use git2::{Commit, DiffLine, Repository};
use crate::error::Error;
use crate::git_blame::GitBlame;
use crate::line_analyzer::LineAnalyzer;
use crate::work_stats::WorkStats;
pub struct HunkAnalyzer<'a> {
repo: &'a Repository,
commit: &'a Commit<'a>,
blame: Option<GitBlame>,
result: WorkStats,
weight: f64,
}
impl<'a> HunkAnalyzer<'a> {
pub fn new(
repo: &'a Repository,
commit: &'a Commit<'a>,
blame: Option<GitBlame>,
weight: f64,
) -> HunkAnalyzer<'a> {
HunkAnalyzer {
repo,
commit,
blame,
weight,
result: WorkStats::empty(),
}
}
pub fn analyze_line(&mut self, diff_line: &DiffLine) -> Result<(), Error> {
let analyzer = LineAnalyzer::new(self.repo, self.commit, diff_line, self.blame.as_ref());
let result = analyzer.analyze()?;
self.result += result;
Ok(())
}
pub fn finish(self) -> (Option<GitBlame>, WorkStats) {
let mut result = self.result;
result.impact = calculate_impact(&result, self.weight);
(self.blame, result)
}
}
fn calculate_impact(work_stats: &WorkStats, weight: f64) -> u64 {
let line_value =
work_stats.legacy_refactor * 4 + work_stats.help_others * 2 + work_stats.new_work;
let scaled_line_value = (line_value as f64).powf(0.5);
(scaled_line_value * weight).round() as u64
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_impact() {
assert_eq!(
calculate_impact(
&WorkStats {
new_work: 100,
..Default::default()
},
1.0
),
10
);
assert_eq!(
calculate_impact(
&WorkStats {
legacy_refactor: 100,
..Default::default()
},
1.0
),
20
);
assert_eq!(
calculate_impact(
&WorkStats {
churn: 100,
..Default::default()
},
1.0
),
0
);
}
}