batuta/stack/quality/
summary.rs1use serde::{Deserialize, Serialize};
6
7use super::component::ComponentQuality;
8use super::types::QualityGrade;
9
10#[derive(Debug, Clone, Serialize, Deserialize)]
16pub struct QualitySummary {
17 pub total_components: usize,
19 pub a_plus_count: usize,
21 pub a_count: usize,
23 pub a_minus_count: usize,
25 pub below_threshold_count: usize,
27 pub missing_hero_count: usize,
29 pub avg_rust_score: f64,
31 pub avg_repo_score: f64,
33 pub avg_readme_score: f64,
35}
36
37impl QualitySummary {
38 pub fn from_components(components: &[ComponentQuality]) -> Self {
40 let total = components.len();
41 if total == 0 {
42 return Self {
43 total_components: 0,
44 a_plus_count: 0,
45 a_count: 0,
46 a_minus_count: 0,
47 below_threshold_count: 0,
48 missing_hero_count: 0,
49 avg_rust_score: 0.0,
50 avg_repo_score: 0.0,
51 avg_readme_score: 0.0,
52 };
53 }
54
55 let a_plus_count = components.iter().filter(|c| c.grade == QualityGrade::APlus).count();
56 let a_count = components.iter().filter(|c| c.grade == QualityGrade::A).count();
57 let a_minus_count = components.iter().filter(|c| c.grade == QualityGrade::AMinus).count();
58 let below_threshold_count =
59 components.iter().filter(|c| !c.grade.is_release_ready()).count();
60 let missing_hero_count = components.iter().filter(|c| !c.hero_image.valid).count();
61
62 let avg_rust_score =
63 components.iter().map(|c| c.rust_score.value as f64).sum::<f64>() / total as f64;
64 let avg_repo_score =
65 components.iter().map(|c| c.repo_score.value as f64).sum::<f64>() / total as f64;
66 let avg_readme_score =
67 components.iter().map(|c| c.readme_score.value as f64).sum::<f64>() / total as f64;
68
69 Self {
70 total_components: total,
71 a_plus_count,
72 a_count,
73 a_minus_count,
74 below_threshold_count,
75 missing_hero_count,
76 avg_rust_score,
77 avg_repo_score,
78 avg_readme_score,
79 }
80 }
81}