1use crate::common_options;
2use crate::subcommands::integration_common::{
3 get_dataset_name, get_numbers_from_input, output_integration_result, parse_analysis_purpose,
4};
5use clap::{ArgMatches, Command};
6use lawkit_core::common::output::{create_output_writer, OutputConfig};
7use lawkit_core::error::Result;
8use lawkit_core::laws::integration::{
9 analyze_all_laws, detect_conflicts_detailed, generate_detailed_recommendations, AnalysisPurpose,
10};
11use std::io::Write;
12
13pub fn command() -> Command {
14 common_options::add_integration_options(common_options::add_common_options(
15 common_options::add_input_arg(
16 Command::new("diagnose").about("Conflict detection and detailed analysis report"),
17 ),
18 ))
19}
20
21pub fn run(matches: &ArgMatches) -> Result<()> {
22 if matches.get_flag("recommend") {
23 return run_recommendation_mode(matches);
24 }
25
26 let report_type = matches.get_one::<String>("report").unwrap();
27 match report_type.as_str() {
28 "conflicting" => run_conflict_analysis_mode(matches),
29 "detailed" => run_detailed_analysis_mode(matches),
30 _ => run_detailed_analysis_mode(matches), }
32}
33
34fn run_detailed_analysis_mode(matches: &ArgMatches) -> Result<()> {
35 let numbers = get_numbers_from_input(matches)?;
36 let dataset_name = get_dataset_name(matches);
37
38 let result = analyze_all_laws(&numbers, &dataset_name)?;
39
40 let mut writer = create_output_writer(matches)?;
41 let output_config = OutputConfig::from_matches(matches);
42
43 output_detailed_integration_result(&mut writer, &result, &output_config)?;
44
45 std::process::exit(result.risk_level.exit_code());
46}
47
48fn run_conflict_analysis_mode(matches: &ArgMatches) -> Result<()> {
49 let numbers = get_numbers_from_input(matches)?;
50 let dataset_name = get_dataset_name(matches);
51 let threshold = *matches.get_one::<f64>("threshold").unwrap();
52
53 let conflict_result = detect_conflicts_detailed(&numbers, &dataset_name, threshold)?;
54
55 let mut writer = create_output_writer(matches)?;
56 let output_config = OutputConfig::from_matches(matches);
57
58 output_conflict_analysis_result(&mut writer, &conflict_result, &output_config)?;
59
60 std::process::exit(conflict_result.integration_result.risk_level.exit_code());
61}
62
63fn run_recommendation_mode(matches: &ArgMatches) -> Result<()> {
64 let numbers = get_numbers_from_input(matches)?;
65 let dataset_name = get_dataset_name(matches);
66
67 let analysis_purpose = matches
68 .get_one::<String>("purpose")
69 .map(|p| parse_analysis_purpose(p))
70 .unwrap_or(AnalysisPurpose::GeneralAnalysis);
71
72 let recommendation_result =
73 generate_detailed_recommendations(&numbers, &dataset_name, analysis_purpose)?;
74
75 let mut writer = create_output_writer(matches)?;
76 let output_config = OutputConfig::from_matches(matches);
77
78 output_recommendation_result(&mut writer, &recommendation_result, &output_config)?;
79
80 std::process::exit(
81 recommendation_result
82 .integration_result
83 .risk_level
84 .exit_code(),
85 );
86}
87
88fn output_detailed_integration_result(
89 writer: &mut Box<dyn Write>,
90 result: &lawkit_core::laws::integration::IntegrationResult,
91 config: &OutputConfig,
92) -> Result<()> {
93 output_integration_result(writer, result, config)?;
94
95 if config.format == "text" {
96 writeln!(writer)?;
97 writeln!(writer, "=== {} ===", get_text("detailed_analysis", "en"))?;
98
99 output_detailed_law_results(writer, result, "en")?;
100 output_data_characteristics(writer, result, "en")?;
101 output_alternative_combinations(writer, result, "en")?;
102 }
103
104 Ok(())
105}
106
107fn output_conflict_analysis_result(
108 writer: &mut Box<dyn Write>,
109 result: &lawkit_core::laws::integration::ConflictAnalysisResult,
110 _config: &OutputConfig,
111) -> Result<()> {
112 writeln!(writer, "{}", get_text("conflict_analysis_title", "en"))?;
113 writeln!(writer)?;
114 writeln!(
115 writer,
116 "{}: {}",
117 get_text("dataset", "en"),
118 result.dataset_name
119 )?;
120 writeln!(
121 writer,
122 "{}: {:.3}",
123 get_text("threshold", "en"),
124 result.threshold
125 )?;
126 writeln!(
127 writer,
128 "{}: {:?}",
129 get_text("conflict_severity", "en"),
130 result.conflict_severity
131 )?;
132 writeln!(writer)?;
133
134 if !result.detailed_conflicts.is_empty() {
135 writeln!(writer, "{}:", get_text("detailed_conflicts", "en"))?;
136 for (i, conflict) in result.detailed_conflicts.iter().enumerate() {
137 writeln!(writer, "{}. {}", i + 1, conflict.base_conflict.description)?;
138 writeln!(
139 writer,
140 " {}: {:.3}",
141 get_text("significance", "en"),
142 conflict.statistical_significance
143 )?;
144 writeln!(
145 writer,
146 " {}: {:?}",
147 get_text("impact", "en"),
148 conflict.impact_assessment
149 )?;
150 writeln!(
151 writer,
152 " {}: {}",
153 get_text("root_cause", "en"),
154 conflict.root_cause_analysis
155 )?;
156 writeln!(writer)?;
157 }
158 }
159
160 if !result.resolution_strategies.is_empty() {
161 writeln!(writer, "{}:", get_text("resolution_strategies", "en"))?;
162 for strategy in &result.resolution_strategies {
163 writeln!(
164 writer,
165 "• {} ({:?})",
166 strategy.strategy_name, strategy.priority
167 )?;
168 writeln!(
169 writer,
170 " {}: {}",
171 get_text("expected_outcome", "en"),
172 strategy.expected_outcome
173 )?;
174 writeln!(
175 writer,
176 " {}: {:.3}",
177 get_text("confidence", "en"),
178 strategy.confidence
179 )?;
180 writeln!(writer)?;
181 }
182 }
183
184 Ok(())
185}
186
187fn output_recommendation_result(
188 writer: &mut Box<dyn Write>,
189 result: &lawkit_core::laws::integration::DetailedRecommendationResult,
190 _config: &OutputConfig,
191) -> Result<()> {
192 writeln!(writer, "{}", get_text("recommendation_title", "en"))?;
193 writeln!(writer)?;
194 writeln!(
195 writer,
196 "{}: {}",
197 get_text("dataset", "en"),
198 result.dataset_name
199 )?;
200 writeln!(
201 writer,
202 "{}: {:?}",
203 get_text("analysis_purpose", "en"),
204 result.analysis_purpose
205 )?;
206 writeln!(writer)?;
207
208 writeln!(writer, "{}:", get_text("purpose_recommendations", "en"))?;
209 for rec in &result.purpose_specific_recommendations {
210 writeln!(
211 writer,
212 "• {:?}: {}",
213 rec.purpose,
214 rec.recommended_laws.join(", ")
215 )?;
216 writeln!(
217 writer,
218 " {}: {}",
219 get_text("rationale", "en"),
220 rec.rationale
221 )?;
222 writeln!(
223 writer,
224 " {}: {:.3}",
225 get_text("effectiveness", "en"),
226 rec.effectiveness
227 )?;
228 writeln!(writer)?;
229 }
230
231 if !result.combination_analysis.is_empty() {
232 writeln!(writer, "{}:", get_text("combination_analysis", "en"))?;
233 for combo in result.combination_analysis.iter().take(3) {
234 writeln!(
235 writer,
236 "• {}: {:.3}",
237 combo.laws.join(" + "),
238 combo.synergy_score
239 )?;
240 }
241 writeln!(writer)?;
242 }
243
244 Ok(())
245}
246
247fn output_detailed_law_results(
248 writer: &mut Box<dyn Write>,
249 result: &lawkit_core::laws::integration::IntegrationResult,
250 _lang: &str,
251) -> Result<()> {
252 writeln!(writer, "{}:", get_text("individual_law_results", "en"))?;
253
254 if let Some(ref benf_result) = result.benford_result {
255 writeln!(
256 writer,
257 "• {}: {:.3} ({:?})",
258 get_law_name("benf", "en"),
259 1.0 - (benf_result.mean_absolute_deviation / 100.0),
260 benf_result.risk_level
261 )?;
262 }
263
264 if let Some(ref pareto_result) = result.pareto_result {
265 writeln!(
266 writer,
267 "• {}: {:.3} ({:?})",
268 get_law_name("pareto", "en"),
269 pareto_result.concentration_index,
270 pareto_result.risk_level
271 )?;
272 }
273
274 if let Some(ref zipf_result) = result.zipf_result {
275 writeln!(
276 writer,
277 "• {}: {:.3} ({:?})",
278 get_law_name("zipf", "en"),
279 zipf_result.distribution_quality,
280 zipf_result.risk_level
281 )?;
282 }
283
284 if let Some(ref normal_result) = result.normal_result {
285 writeln!(
286 writer,
287 "• {}: {:.3} ({:?})",
288 get_law_name("normal", "en"),
289 normal_result.normality_score,
290 normal_result.risk_level
291 )?;
292 }
293
294 if let Some(ref poisson_result) = result.poisson_result {
295 writeln!(
296 writer,
297 "• {}: {:.3} ({:?})",
298 get_law_name("poisson", "en"),
299 poisson_result.goodness_of_fit_score,
300 poisson_result.risk_level
301 )?;
302 }
303
304 writeln!(writer)?;
305 Ok(())
306}
307
308fn output_data_characteristics(
309 writer: &mut Box<dyn Write>,
310 result: &lawkit_core::laws::integration::IntegrationResult,
311 _lang: &str,
312) -> Result<()> {
313 let chars = &result.data_characteristics;
314
315 writeln!(writer, "{}:", get_text("data_characteristics", "en"))?;
316 writeln!(
317 writer,
318 " {}: {:?}",
319 get_text("data_type", "en"),
320 chars.data_type
321 )?;
322 writeln!(
323 writer,
324 " {}: {:?}",
325 get_text("distribution_shape", "en"),
326 chars.distribution_shape
327 )?;
328 writeln!(
329 writer,
330 " {}: {:?}",
331 get_text("outlier_presence", "en"),
332 chars.outlier_presence
333 )?;
334 writeln!(
335 writer,
336 " {}: {:?}",
337 get_text("scale_range", "en"),
338 chars.scale_range
339 )?;
340 writeln!(
341 writer,
342 " {}: {:?}",
343 get_text("sample_size_category", "en"),
344 chars.sample_size_category
345 )?;
346 writeln!(writer)?;
347
348 Ok(())
349}
350
351fn output_alternative_combinations(
352 writer: &mut Box<dyn Write>,
353 result: &lawkit_core::laws::integration::IntegrationResult,
354 _lang: &str,
355) -> Result<()> {
356 writeln!(writer, "{}:", get_text("alternative_combinations", "en"))?;
357
358 for combo in &result.recommendations.alternative_combinations {
359 writeln!(writer, "• {} ({})", combo.purpose, combo.laws.join(" + "))?;
360 writeln!(
361 writer,
362 " {}: {:.3}",
363 get_text("effectiveness", "en"),
364 combo.effectiveness_score
365 )?;
366 writeln!(
367 writer,
368 " {}: {}",
369 get_text("description", "en"),
370 combo.description
371 )?;
372 writeln!(writer)?;
373 }
374
375 Ok(())
376}
377
378fn get_text(key: &str, _lang: &str) -> String {
379 match key {
380 "detailed_analysis" => "Detailed Analysis",
381 "conflict_analysis_title" => "Conflict Analysis",
382 "threshold" => "Threshold",
383 "conflict_severity" => "Conflict Severity",
384 "detailed_conflicts" => "Detailed Conflicts",
385 "significance" => "Significance",
386 "impact" => "Impact",
387 "root_cause" => "Root Cause",
388 "resolution_strategies" => "Resolution Strategies",
389 "expected_outcome" => "Expected Outcome",
390 "confidence" => "Confidence",
391 "recommendation_title" => "Recommendations",
392 "analysis_purpose" => "Analysis Purpose",
393 "purpose_recommendations" => "Purpose-Based Recommendations",
394 "combination_analysis" => "Combination Analysis",
395 "individual_law_results" => "Individual Law Results",
396 "data_characteristics" => "Data Characteristics",
397 "data_type" => "Data Type",
398 "distribution_shape" => "Distribution Shape",
399 "outlier_presence" => "Outlier Presence",
400 "scale_range" => "Scale Range",
401 "sample_size_category" => "Sample Size Category",
402 "alternative_combinations" => "Alternative Combinations",
403 "effectiveness" => "Effectiveness",
404 "rationale" => "Rationale",
405 "dataset" => "Dataset",
406 _ => key,
407 }
408 .to_string()
409}
410
411fn get_law_name(law: &str, _lang: &str) -> String {
412 match law {
413 "benf" => "Benford's Law",
414 "pareto" => "Pareto Principle",
415 "zipf" => "Zipf's Law",
416 "normal" => "Normal Distribution",
417 "poisson" => "Poisson Distribution",
418 _ => law,
419 }
420 .to_string()
421}