use super::tracker::{prevented_counts, session_interruptions};
#[derive(Debug, Clone)]
pub struct CognitiveImpactReport {
pub interruptions_prevented: u64,
pub context_switches_saved: u64,
pub echo_tokens_saved: u64,
pub cognitive_load_reduction: f64,
pub focus_time_saved_minutes: f64,
pub score: f64,
}
pub fn compute_impact() -> CognitiveImpactReport {
let counts = prevented_counts();
let events = session_interruptions();
let total_events = events.len() as u64;
let total_prevented = events.iter().filter(|(_, prevented)| *prevented).count() as u64;
let score = if total_events == 0 {
1.0
} else {
total_prevented as f64 / total_events as f64
};
let focus_minutes = counts.context_switches_prevented as f64 * 23.0;
let load_reduction = (total_prevented as f64 * 0.02).min(1.0);
CognitiveImpactReport {
interruptions_prevented: total_prevented,
context_switches_saved: counts.context_switches_prevented,
echo_tokens_saved: counts.echo_prevented,
cognitive_load_reduction: load_reduction,
focus_time_saved_minutes: focus_minutes,
score,
}
}
pub fn render_impact_summary(report: &CognitiveImpactReport) -> String {
format!(
"Anti-Interruption Score: {:.0}%\n\
Interruptions prevented: {}\n\
Focus time saved: {:.0} min\n\
Echo tokens saved: {}\n\
Cognitive load reduction: {:.0}%",
report.score * 100.0,
report.interruptions_prevented,
report.focus_time_saved_minutes,
report.echo_tokens_saved,
report.cognitive_load_reduction * 100.0,
)
}
#[cfg(test)]
pub mod tests {
use super::{compute_impact, render_impact_summary};
use crate::core::anti_interrupt::tracker::{
InterruptionEvent, TEST_LOCK, record_interruption, reset_session,
};
#[test]
fn empty_session_has_perfect_score() {
let _guard = TEST_LOCK.lock().expect("test lock should be available");
reset_session();
let report = compute_impact();
assert_eq!(report.interruptions_prevented, 0);
assert_eq!(report.score, 1.0);
assert_eq!(report.cognitive_load_reduction, 0.0);
}
#[test]
fn all_prevented_gives_perfect_score() {
let _guard = TEST_LOCK.lock().expect("test lock should be available");
reset_session();
record_interruption(InterruptionEvent::EchoRepetition { tokens: 50 }, true);
record_interruption(
InterruptionEvent::ContextSwitch {
from: "parser".to_string(),
to: "storage".to_string(),
},
true,
);
let report = compute_impact();
assert_eq!(report.interruptions_prevented, 2);
assert_eq!(report.context_switches_saved, 1);
assert_eq!(report.echo_tokens_saved, 50);
assert_eq!(report.focus_time_saved_minutes, 23.0);
assert_eq!(report.score, 1.0);
}
#[test]
fn mixed_events_calculates_correctly() {
let _guard = TEST_LOCK.lock().expect("test lock should be available");
reset_session();
record_interruption(InterruptionEvent::EchoRepetition { tokens: 80 }, true);
record_interruption(
InterruptionEvent::RedundantRead {
path: "src/main.rs".to_string(),
},
false,
);
record_interruption(InterruptionEvent::BounceWaste { tokens: 10 }, true);
let report = compute_impact();
assert_eq!(report.interruptions_prevented, 2);
assert!((report.score - (2.0 / 3.0)).abs() < f64::EPSILON);
assert_eq!(report.cognitive_load_reduction, 0.04);
}
#[test]
fn render_summary_format() {
let _guard = TEST_LOCK.lock().expect("test lock should be available");
reset_session();
record_interruption(
InterruptionEvent::ContextSwitch {
from: "core".to_string(),
to: "tests".to_string(),
},
true,
);
let summary = render_impact_summary(&compute_impact());
assert_eq!(
summary,
"Anti-Interruption Score: 100%\n\
Interruptions prevented: 1\n\
Focus time saved: 23 min\n\
Echo tokens saved: 0\n\
Cognitive load reduction: 2%"
);
}
}