#![cfg_attr(coverage_nightly, coverage(off))]
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
use super::grade::{Grade, MetricCategory, PenaltyAttribution};
use super::language_simple::Language;
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct TdgScore {
pub structural_complexity: f32,
pub semantic_complexity: f32,
pub duplication_ratio: f32,
pub coupling_score: f32,
pub doc_coverage: f32,
pub consistency_score: f32,
pub entropy_score: f32, pub total: f32,
pub grade: Grade,
pub confidence: f32,
pub language: Language,
pub file_path: Option<PathBuf>,
pub penalties_applied: Vec<PenaltyAttribution>,
pub critical_defects_count: usize, pub has_critical_defects: bool, }
impl Default for TdgScore {
fn default() -> Self {
Self {
structural_complexity: 25.0,
semantic_complexity: 20.0,
duplication_ratio: 20.0,
coupling_score: 15.0,
doc_coverage: 10.0,
consistency_score: 10.0,
entropy_score: 0.0, total: 100.0,
grade: Grade::APLus,
confidence: 1.0,
language: Language::Unknown,
file_path: None,
penalties_applied: Vec::new(),
critical_defects_count: 0,
has_critical_defects: false,
}
}
}
impl TdgScore {
pub fn calculate_total(&mut self) {
self.structural_complexity = self.structural_complexity.clamp(0.0, 25.0);
self.semantic_complexity = self.semantic_complexity.clamp(0.0, 20.0);
self.duplication_ratio = self.duplication_ratio.clamp(0.0, 20.0);
self.coupling_score = self.coupling_score.clamp(0.0, 15.0);
self.doc_coverage = self.doc_coverage.clamp(0.0, 10.0);
self.consistency_score = self.consistency_score.clamp(0.0, 10.0);
self.entropy_score = self.entropy_score.clamp(0.0, 10.0);
let raw_total = self.structural_complexity
+ self.semantic_complexity
+ self.duplication_ratio
+ self.coupling_score
+ self.doc_coverage
+ self.consistency_score
+ self.entropy_score;
if raw_total <= 100.0 {
self.total = raw_total.clamp(0.0, 100.0);
} else {
const THEORETICAL_MAX: f32 = 110.0; self.total = (raw_total / THEORETICAL_MAX * 100.0).clamp(0.0, 100.0);
}
if self.has_critical_defects {
self.total = 0.0;
self.grade = Grade::F;
} else {
self.grade = Grade::from_score(self.total);
}
}
pub fn set_metric(&mut self, category: MetricCategory, value: f32) {
match category {
MetricCategory::StructuralComplexity => self.structural_complexity = value,
MetricCategory::SemanticComplexity => self.semantic_complexity = value,
MetricCategory::Duplication => self.duplication_ratio = value,
MetricCategory::Coupling => self.coupling_score = value,
MetricCategory::Documentation => self.doc_coverage = value,
MetricCategory::Consistency => self.consistency_score = value,
}
}
}