1mod analysis;
6mod health;
7mod quality;
8
9pub use analysis::{
13 calculate_activity_timeline, calculate_file_heatmap, calculate_ownership, calculate_stats,
14 ActivityTimeline, AuthorStats, CodeOwnership, CodeOwnershipEntry, FileHeatmap,
15 FileHeatmapEntry, RepoStats,
16};
17
18pub use quality::{
22 calculate_change_coupling, calculate_impact_scores, calculate_quality_scores,
23 ChangeCouplingAnalysis, CommitImpactAnalysis, CommitImpactScore, CommitQualityAnalysis,
24 CommitQualityScore, FileCoupling,
25};
26
27pub use health::{
31 calculate_bus_factor, calculate_project_health, calculate_tech_debt, is_test_file,
32 AlertSeverity, ConfidenceLevel, HealthAlert, HealthAlertKind, HealthConfidence,
33 HealthScoreComponent, ProjectHealth,
34};
35
36#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
42pub enum AggregationLevel {
43 #[default]
45 Files,
46 Shallow,
48 Deep,
50}
51
52impl AggregationLevel {
53 pub fn next(&self) -> Self {
55 match self {
56 AggregationLevel::Files => AggregationLevel::Shallow,
57 AggregationLevel::Shallow => AggregationLevel::Deep,
58 AggregationLevel::Deep => AggregationLevel::Files,
59 }
60 }
61
62 pub fn prev(&self) -> Self {
64 match self {
65 AggregationLevel::Files => AggregationLevel::Deep,
66 AggregationLevel::Shallow => AggregationLevel::Files,
67 AggregationLevel::Deep => AggregationLevel::Shallow,
68 }
69 }
70
71 pub fn display_name(&self) -> &'static str {
73 match self {
74 AggregationLevel::Files => "Files",
75 AggregationLevel::Shallow => "Directories (2 levels)",
76 AggregationLevel::Deep => "Directories (top level)",
77 }
78 }
79}
80
81#[derive(Debug, Clone)]
87pub struct BusFactorEntry {
88 pub path: String,
90 pub bus_factor: usize,
92 pub contributors: Vec<ContributorInfo>,
94 pub total_commits: usize,
96 pub risk_level: BusFactorRisk,
98 pub is_directory: bool,
100}
101
102#[derive(Debug, Clone)]
104pub struct ContributorInfo {
105 pub name: String,
107 pub commit_count: usize,
109 pub contribution_percent: f64,
111}
112
113#[derive(Debug, Clone, Copy, PartialEq, Eq)]
115pub enum BusFactorRisk {
116 High,
118 Medium,
120 Low,
122}
123
124impl BusFactorRisk {
125 pub fn display_name(&self) -> &'static str {
127 match self {
128 BusFactorRisk::High => "High Risk",
129 BusFactorRisk::Medium => "Medium Risk",
130 BusFactorRisk::Low => "Low Risk",
131 }
132 }
133
134 pub fn color(&self) -> &'static str {
136 match self {
137 BusFactorRisk::High => "red",
138 BusFactorRisk::Medium => "yellow",
139 BusFactorRisk::Low => "green",
140 }
141 }
142}
143
144#[derive(Debug, Clone, Default)]
146pub struct BusFactorAnalysis {
147 pub entries: Vec<BusFactorEntry>,
149 pub high_risk_count: usize,
151 pub medium_risk_count: usize,
153 pub total_paths_analyzed: usize,
155}
156
157impl BusFactorAnalysis {
158 pub fn entry_count(&self) -> usize {
160 self.entries.len()
161 }
162}
163
164#[derive(Debug, Clone)]
170pub struct TechDebtEntry {
171 pub path: String,
173 pub score: f64,
175 pub churn_score: f64,
177 pub complexity_score: f64,
179 pub age_score: f64,
181 pub change_count: usize,
183 pub total_changes: usize,
185 pub debt_level: TechDebtLevel,
187}
188
189#[derive(Debug, Clone, Copy, PartialEq, Eq)]
191pub enum TechDebtLevel {
192 High,
194 Medium,
196 Low,
198}
199
200impl TechDebtLevel {
201 pub fn display_name(&self) -> &'static str {
203 match self {
204 TechDebtLevel::High => "High Debt",
205 TechDebtLevel::Medium => "Medium Debt",
206 TechDebtLevel::Low => "Low Debt",
207 }
208 }
209
210 pub fn color(&self) -> &'static str {
212 match self {
213 TechDebtLevel::High => "red",
214 TechDebtLevel::Medium => "yellow",
215 TechDebtLevel::Low => "green",
216 }
217 }
218}
219
220#[derive(Debug, Clone, Default)]
222pub struct TechDebtAnalysis {
223 pub entries: Vec<TechDebtEntry>,
225 pub avg_score: f64,
227 pub high_debt_count: usize,
229 pub total_files_analyzed: usize,
231}
232
233impl TechDebtAnalysis {
234 pub fn entry_count(&self) -> usize {
236 self.entries.len()
237 }
238}