mod analysis;
mod health;
mod quality;
pub use analysis::{
calculate_activity_timeline, calculate_file_heatmap, calculate_ownership, calculate_stats,
ActivityTimeline, AuthorStats, CodeOwnership, CodeOwnershipEntry, FileHeatmap,
FileHeatmapEntry, RepoStats,
};
pub use quality::{
calculate_change_coupling, calculate_impact_scores, calculate_quality_scores,
ChangeCouplingAnalysis, CommitImpactAnalysis, CommitImpactScore, CommitQualityAnalysis,
CommitQualityScore, FileCoupling,
};
pub use health::{
calculate_bus_factor, calculate_project_health, calculate_tech_debt, is_test_file,
AlertSeverity, ConfidenceLevel, HealthAlert, HealthAlertKind, HealthConfidence,
HealthScoreComponent, ProjectHealth,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum AggregationLevel {
#[default]
Files,
Shallow,
Deep,
}
impl AggregationLevel {
pub fn next(&self) -> Self {
match self {
AggregationLevel::Files => AggregationLevel::Shallow,
AggregationLevel::Shallow => AggregationLevel::Deep,
AggregationLevel::Deep => AggregationLevel::Files,
}
}
pub fn prev(&self) -> Self {
match self {
AggregationLevel::Files => AggregationLevel::Deep,
AggregationLevel::Shallow => AggregationLevel::Files,
AggregationLevel::Deep => AggregationLevel::Shallow,
}
}
pub fn display_name(&self) -> &'static str {
match self {
AggregationLevel::Files => "Files",
AggregationLevel::Shallow => "Directories (2 levels)",
AggregationLevel::Deep => "Directories (top level)",
}
}
}
#[derive(Debug, Clone)]
pub struct BusFactorEntry {
pub path: String,
pub bus_factor: usize,
pub contributors: Vec<ContributorInfo>,
pub total_commits: usize,
pub risk_level: BusFactorRisk,
pub is_directory: bool,
}
#[derive(Debug, Clone)]
pub struct ContributorInfo {
pub name: String,
pub commit_count: usize,
pub contribution_percent: f64,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BusFactorRisk {
High,
Medium,
Low,
}
impl BusFactorRisk {
pub fn display_name(&self) -> &'static str {
match self {
BusFactorRisk::High => "High Risk",
BusFactorRisk::Medium => "Medium Risk",
BusFactorRisk::Low => "Low Risk",
}
}
pub fn color(&self) -> &'static str {
match self {
BusFactorRisk::High => "red",
BusFactorRisk::Medium => "yellow",
BusFactorRisk::Low => "green",
}
}
}
#[derive(Debug, Clone, Default)]
pub struct BusFactorAnalysis {
pub entries: Vec<BusFactorEntry>,
pub high_risk_count: usize,
pub medium_risk_count: usize,
pub total_paths_analyzed: usize,
}
impl BusFactorAnalysis {
pub fn entry_count(&self) -> usize {
self.entries.len()
}
}
#[derive(Debug, Clone)]
pub struct TechDebtEntry {
pub path: String,
pub score: f64,
pub churn_score: f64,
pub complexity_score: f64,
pub age_score: f64,
pub change_count: usize,
pub total_changes: usize,
pub debt_level: TechDebtLevel,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TechDebtLevel {
High,
Medium,
Low,
}
impl TechDebtLevel {
pub fn display_name(&self) -> &'static str {
match self {
TechDebtLevel::High => "High Debt",
TechDebtLevel::Medium => "Medium Debt",
TechDebtLevel::Low => "Low Debt",
}
}
pub fn color(&self) -> &'static str {
match self {
TechDebtLevel::High => "red",
TechDebtLevel::Medium => "yellow",
TechDebtLevel::Low => "green",
}
}
}
#[derive(Debug, Clone, Default)]
pub struct TechDebtAnalysis {
pub entries: Vec<TechDebtEntry>,
pub avg_score: f64,
pub high_debt_count: usize,
pub total_files_analyzed: usize,
}
impl TechDebtAnalysis {
pub fn entry_count(&self) -> usize {
self.entries.len()
}
}