use std::collections::HashSet;
use crate::core::tokens::count_tokens;
#[derive(Debug, Clone)]
pub struct EchoRatioReport {
pub input_tokens: usize,
pub output_tokens: usize,
pub echo_words: usize,
pub output_words: usize,
pub ratio: f64,
pub verdict: &'static str,
}
pub fn compute_echo_ratio(input: &str, output: &str) -> EchoRatioReport {
let input_tokens_count = count_tokens(input);
let output_tokens_count = count_tokens(output);
if output_tokens_count == 0 {
return EchoRatioReport {
input_tokens: input_tokens_count,
output_tokens: 0,
echo_words: 0,
output_words: 0,
ratio: 0.0,
verdict: "low",
};
}
let input_words: HashSet<&str> = input.split_whitespace().collect();
let output_word_list: Vec<&str> = output.split_whitespace().collect();
let output_word_count = output_word_list.len();
let echo_count = output_word_list
.iter()
.filter(|word| input_words.contains(*word))
.count();
let ratio = echo_count as f64 / output_word_count.max(1) as f64;
let verdict = if ratio < 0.3 {
"low"
} else if ratio < 0.6 {
"moderate"
} else {
"high"
};
EchoRatioReport {
input_tokens: input_tokens_count,
output_tokens: output_tokens_count,
echo_words: echo_count,
output_words: output_word_count,
ratio,
verdict,
}
}
impl EchoRatioReport {
pub fn summary(&self) -> String {
format!(
"Echo: {:.0}% ({}) — {}/{} words echoed",
self.ratio * 100.0,
self.verdict,
self.echo_words,
self.output_words,
)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn empty_output_gives_zero_ratio() {
let report = compute_echo_ratio("input context", "");
assert_eq!(report.output_tokens, 0);
assert_eq!(report.echo_words, 0);
assert_eq!(report.ratio, 0.0);
assert_eq!(report.verdict, "low");
}
#[test]
fn no_overlap_gives_zero_ratio() {
let report = compute_echo_ratio("alpha beta", "gamma delta");
assert_eq!(report.echo_words, 0);
assert_eq!(report.ratio, 0.0);
assert_eq!(report.verdict, "low");
}
#[test]
fn complete_echo_gives_high_ratio() {
let report = compute_echo_ratio("alpha beta", "alpha beta");
assert_eq!(report.echo_words, 2);
assert_eq!(report.ratio, 1.0);
assert_eq!(report.verdict, "high");
}
#[test]
fn partial_echo_gives_moderate_ratio() {
let report = compute_echo_ratio("alpha beta", "alpha gamma");
assert_eq!(report.echo_words, 1);
assert_eq!(report.ratio, 0.5);
assert_eq!(report.verdict, "moderate");
}
#[test]
fn summary_format() {
let report = compute_echo_ratio("alpha beta", "alpha beta");
assert_eq!(report.summary(), "Echo: 100% (high) — 2/2 words echoed");
}
}