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, "=== Detailed Analysis ===")?;
98 writeln!(writer, "Additional analysis details would be shown here.")?;
99 }
100
101 Ok(())
102}
103
104fn output_conflict_analysis_result(
105 writer: &mut Box<dyn Write>,
106 result: &lawkit_core::laws::integration::ConflictAnalysisResult,
107 _config: &OutputConfig,
108) -> Result<()> {
109 writeln!(writer, "Conflict Analysis Results")?;
110 writeln!(writer)?;
111 writeln!(writer, "Dataset: {}", result.dataset_name)?;
112 writeln!(writer, "Threshold: {:.3}", result.threshold)?;
113 writeln!(writer, "Conflict Severity: {:?}", result.conflict_severity)?;
114 writeln!(writer)?;
115
116 if !result.detailed_conflicts.is_empty() {
117 writeln!(writer, "Detailed Conflicts:")?;
118 for (i, conflict) in result.detailed_conflicts.iter().enumerate() {
119 writeln!(writer, "{}. {}", i + 1, conflict.base_conflict.description)?;
120 writeln!(
121 writer,
122 " Significance: {:.3}",
123 conflict.statistical_significance
124 )?;
125 writeln!(writer, " Impact: {:?}", conflict.impact_assessment)?;
126 writeln!(writer, " Root Cause: {}", conflict.root_cause_analysis)?;
127 writeln!(writer)?;
128 }
129 }
130
131 if !result.resolution_strategies.is_empty() {
132 writeln!(writer, "Resolution Strategies:")?;
133 for strategy in &result.resolution_strategies {
134 writeln!(
135 writer,
136 "• {} ({:?})",
137 strategy.strategy_name, strategy.priority
138 )?;
139 writeln!(writer, " Expected Outcome: {}", strategy.expected_outcome)?;
140 writeln!(writer, " Confidence: {:.3}", strategy.confidence)?;
141 writeln!(writer)?;
142 }
143 }
144
145 Ok(())
146}
147
148fn output_recommendation_result(
149 writer: &mut Box<dyn Write>,
150 result: &lawkit_core::laws::integration::DetailedRecommendationResult,
151 _config: &OutputConfig,
152) -> Result<()> {
153 writeln!(writer, "{}", get_text("recommendation_title", "en"))?;
154 writeln!(writer)?;
155 writeln!(
156 writer,
157 "{}: {}",
158 get_text("dataset", "en"),
159 result.dataset_name
160 )?;
161 writeln!(
162 writer,
163 "{}: {:?}",
164 get_text("analysis_purpose", "en"),
165 result.analysis_purpose
166 )?;
167 writeln!(writer)?;
168
169 writeln!(writer, "{}:", get_text("purpose_recommendations", "en"))?;
170 for rec in &result.purpose_specific_recommendations {
171 writeln!(
172 writer,
173 "• {:?}: {}",
174 rec.purpose,
175 rec.recommended_laws.join(", ")
176 )?;
177 writeln!(
178 writer,
179 " {}: {}",
180 get_text("rationale", "en"),
181 rec.rationale
182 )?;
183 writeln!(
184 writer,
185 " {}: {:.3}",
186 get_text("effectiveness", "en"),
187 rec.effectiveness
188 )?;
189 writeln!(writer)?;
190 }
191
192 if !result.combination_analysis.is_empty() {
193 writeln!(writer, "{}:", get_text("combination_analysis", "en"))?;
194 for combo in result.combination_analysis.iter().take(3) {
195 writeln!(
196 writer,
197 "• {}: {:.3}",
198 combo.laws.join(" + "),
199 combo.synergy_score
200 )?;
201 }
202 writeln!(writer)?;
203 }
204
205 Ok(())
206}
207
208#[allow(dead_code)]
209fn output_detailed_law_results(
210 writer: &mut Box<dyn Write>,
211 result: &lawkit_core::laws::integration::IntegrationResult,
212 _lang: &str,
213) -> Result<()> {
214 writeln!(writer, "{}:", get_text("individual_law_results", "en"))?;
215
216 if let Some(ref benf_result) = result.benford_result {
217 writeln!(
218 writer,
219 "• {}: {:.3} ({:?})",
220 get_law_name("benf", "en"),
221 1.0 - (benf_result.mean_absolute_deviation / 100.0),
222 benf_result.risk_level
223 )?;
224 }
225
226 if let Some(ref pareto_result) = result.pareto_result {
227 writeln!(
228 writer,
229 "• {}: {:.3} ({:?})",
230 get_law_name("pareto", "en"),
231 pareto_result.concentration_index,
232 pareto_result.risk_level
233 )?;
234 }
235
236 if let Some(ref zipf_result) = result.zipf_result {
237 writeln!(
238 writer,
239 "• {}: {:.3} ({:?})",
240 get_law_name("zipf", "en"),
241 zipf_result.distribution_quality,
242 zipf_result.risk_level
243 )?;
244 }
245
246 if let Some(ref normal_result) = result.normal_result {
247 writeln!(
248 writer,
249 "• {}: {:.3} ({:?})",
250 get_law_name("normal", "en"),
251 normal_result.normality_score,
252 normal_result.risk_level
253 )?;
254 }
255
256 if let Some(ref poisson_result) = result.poisson_result {
257 writeln!(
258 writer,
259 "• {}: {:.3} ({:?})",
260 get_law_name("poisson", "en"),
261 poisson_result.goodness_of_fit_score,
262 poisson_result.risk_level
263 )?;
264 }
265
266 writeln!(writer)?;
267 Ok(())
268}
269
270#[allow(dead_code)]
271fn output_data_characteristics(
272 writer: &mut Box<dyn Write>,
273 result: &lawkit_core::laws::integration::IntegrationResult,
274 _lang: &str,
275) -> Result<()> {
276 let chars = &result.data_characteristics;
277
278 writeln!(writer, "{}:", get_text("data_characteristics", "en"))?;
279 writeln!(
280 writer,
281 " {}: {:?}",
282 get_text("data_type", "en"),
283 chars.data_type
284 )?;
285 writeln!(
286 writer,
287 " {}: {:?}",
288 get_text("distribution_shape", "en"),
289 chars.distribution_shape
290 )?;
291 writeln!(
292 writer,
293 " {}: {:?}",
294 get_text("outlier_presence", "en"),
295 chars.outlier_presence
296 )?;
297 writeln!(
298 writer,
299 " {}: {:?}",
300 get_text("scale_range", "en"),
301 chars.scale_range
302 )?;
303 writeln!(
304 writer,
305 " {}: {:?}",
306 get_text("sample_size_category", "en"),
307 chars.sample_size_category
308 )?;
309 writeln!(writer)?;
310
311 Ok(())
312}
313
314#[allow(dead_code)]
315fn output_alternative_combinations(
316 writer: &mut Box<dyn Write>,
317 result: &lawkit_core::laws::integration::IntegrationResult,
318 _lang: &str,
319) -> Result<()> {
320 writeln!(writer, "{}:", get_text("alternative_combinations", "en"))?;
321
322 for combo in &result.recommendations.alternative_combinations {
323 writeln!(writer, "• {} ({})", combo.purpose, combo.laws.join(" + "))?;
324 writeln!(
325 writer,
326 " {}: {:.3}",
327 get_text("effectiveness", "en"),
328 combo.effectiveness_score
329 )?;
330 writeln!(
331 writer,
332 " {}: {}",
333 get_text("description", "en"),
334 combo.description
335 )?;
336 writeln!(writer)?;
337 }
338
339 Ok(())
340}
341
342fn get_text(key: &str, _lang: &str) -> String {
343 match key {
344 "detailed_analysis" => "Detailed Analysis",
345 "conflict_analysis_title" => "Conflict Analysis",
346 "threshold" => "Threshold",
347 "conflict_severity" => "Conflict Severity",
348 "detailed_conflicts" => "Detailed Conflicts",
349 "significance" => "Significance",
350 "impact" => "Impact",
351 "root_cause" => "Root Cause",
352 "resolution_strategies" => "Resolution Strategies",
353 "expected_outcome" => "Expected Outcome",
354 "confidence" => "Confidence",
355 "recommendation_title" => "Recommendations",
356 "analysis_purpose" => "Analysis Purpose",
357 "purpose_recommendations" => "Purpose-Based Recommendations",
358 "combination_analysis" => "Combination Analysis",
359 "individual_law_results" => "Individual Law Results",
360 "data_characteristics" => "Data Characteristics",
361 "data_type" => "Data Type",
362 "distribution_shape" => "Distribution Shape",
363 "outlier_presence" => "Outlier Presence",
364 "scale_range" => "Scale Range",
365 "sample_size_category" => "Sample Size Category",
366 "alternative_combinations" => "Alternative Combinations",
367 "effectiveness" => "Effectiveness",
368 "rationale" => "Rationale",
369 "dataset" => "Dataset",
370 _ => key,
371 }
372 .to_string()
373}
374
375#[allow(dead_code)]
376fn get_law_name(law: &str, _lang: &str) -> String {
377 match law {
378 "benf" => "Benford's Law",
379 "pareto" => "Pareto Principle",
380 "zipf" => "Zipf's Law",
381 "normal" => "Normal Distribution",
382 "poisson" => "Poisson Distribution",
383 _ => law,
384 }
385 .to_string()
386}