use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct ScanSummary {
pub total_count: usize,
pub files_with_todos: usize,
pub files_scanned: usize,
pub tag_counts: HashMap<String, usize>,
#[serde(default)]
pub duration_ms: u128,
}
impl ScanSummary {
pub fn avg_items_per_file(&self) -> f64 {
if self.files_with_todos > 0 {
self.total_count as f64 / self.files_with_todos as f64
} else {
0.0
}
}
pub fn tag_percentage(&self, count: usize) -> f64 {
if self.total_count > 0 {
(count as f64 / self.total_count as f64) * 100.0
} else {
0.0
}
}
}
#[cfg(test)]
mod tests {
use super::*;
fn summary(total_count: usize, files_with_todos: usize) -> ScanSummary {
ScanSummary {
total_count,
files_with_todos,
files_scanned: files_with_todos + 1,
tag_counts: HashMap::new(),
duration_ms: 0,
}
}
#[test]
fn avg_items_per_file_divides_when_files_present() {
assert_eq!(summary(10, 4).avg_items_per_file(), 2.5);
}
#[test]
fn avg_items_per_file_is_zero_when_no_files_with_todos() {
assert_eq!(summary(0, 0).avg_items_per_file(), 0.0);
}
#[test]
fn tag_percentage_divides_when_total_present() {
assert_eq!(summary(4, 1).tag_percentage(1), 25.0);
}
#[test]
fn tag_percentage_is_zero_when_total_is_zero() {
assert_eq!(summary(0, 0).tag_percentage(0), 0.0);
}
}