1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
// RichReporter analysis methods: analyze(), generate_recommendations()
// Runs data science pipeline (K-Means, PageRank, Louvain, Isolation Forest, trends)
// and generates prioritized recommendations from results.
impl RichReporter {
/// Run data science analysis on findings
pub fn analyze(&mut self) {
// 1. Cluster findings (K-means)
self.report.clusters = self.analyzer.cluster_findings(&mut self.report.findings);
// 2. Calculate PageRank centrality
self.analyzer
.calculate_pagerank(&mut self.report.findings, &self.dependencies);
// 3. Detect communities (Louvain)
self.report.communities = self
.analyzer
.detect_communities(&mut self.report.findings, &self.dependencies);
// 4. Detect anomalies (Isolation Forest)
self.report.anomalies = self.analyzer.detect_anomalies(&mut self.report.findings);
// 5. Analyze trends
self.report.trends = self.analyzer.analyze_trends(&self.metric_history);
// 6. Calculate Andon status
self.report.calculate_andon_status();
// 7. Generate recommendations based on analysis
self.generate_recommendations();
}
/// Generate recommendations based on analysis
fn generate_recommendations(&mut self) {
// Clear existing recommendations
self.report.recommendations.clear();
// Recommend based on clusters
for cluster in &self.report.clusters {
if cluster.size >= 3 {
self.report.recommendations.push(format!(
"Batch fix {} {} issues (cluster cohesion: {:.0}%)",
cluster.size,
cluster.primary_category,
cluster.cohesion * 100.0
));
}
}
// Recommend based on high-PageRank findings
let mut high_pagerank: Vec<_> = self
.report
.findings
.iter()
.filter(|f| f.pagerank.unwrap_or(0.0) > 0.1)
.collect();
high_pagerank.sort_by(|a, b| {
b.pagerank
.unwrap_or(0.0)
.partial_cmp(&a.pagerank.unwrap_or(0.0))
.expect("internal error")
});
for finding in high_pagerank.iter().take(3) {
self.report.recommendations.push(format!(
"Priority: Fix {} in {} (high centrality: {:.2})",
finding.category,
finding.location,
finding.pagerank.unwrap_or(0.0)
));
}
// Recommend based on anomalies
for anomaly in &self.report.anomalies {
self.report.recommendations.push(format!(
"Investigate anomaly: {} (score: {:.2}) - {}",
anomaly.finding_id, anomaly.score, anomaly.action
));
}
// Recommend based on degrading trends
for trend in &self.report.trends {
if trend.direction == TrendDirection::Degrading && trend.change_percent.abs() > 10.0 {
self.report.recommendations.push(format!(
"Address {} regression: {:.1}% degradation over window",
trend.name,
trend.change_percent.abs()
));
}
}
}
}