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