pub struct Stats {
pub received: usize,
pub lost: usize,
pub min_rtt: u64,
pub max_rtt: u64,
pub avg_rtt: f64,
pub mad_rtt: f64,
}
pub fn compute_stats(states: &[crate::state::State]) -> Option<Stats> {
let mut rtts: Vec<u64> = Vec::new();
let received = states
.iter()
.filter(|state| matches!(state, crate::state::State::Received { .. } | crate::state::State::NotYetReceived { .. } ))
.count();
let lost = states.len() - received;
if received == 0 {
return None;
}
for state in states {
if let crate::state::State::Received { rtt } = state {
rtts.push(*rtt);
}
}
let min_rtt = rtts.iter().min().copied().unwrap_or(0);
let max_rtt = rtts.iter().max().copied().unwrap_or(0);
let sum_rtt: u64 = rtts.iter().sum();
let avg_rtt = sum_rtt as f64 / rtts.len() as f64;
let mad_rtt: f64 = rtts
.iter()
.map(|&x| (x as f64 - avg_rtt).abs())
.sum::<f64>()
/ rtts.len() as f64;
Some(Stats {
received,
lost,
min_rtt,
max_rtt,
avg_rtt,
mad_rtt,
})
}