pub struct Stats { /// Number of received packets (better names: `packets_received` or `received_count`) pub received: usize, /// Number of lost packets (total - received) (better names: `packets_lost` or `lost_count`) pub lost: usize, // Round-Time Trip pub min_rtt: u64, pub max_rtt: u64, pub avg_rtt: f64, /// Mean absolute difference (deviation) from the average pub mad_rtt: f64, // Time To Live pub min_ttl: u32, pub max_ttl: u32, pub avg_ttl: f64, /// Mean absolute difference (deviation) from the average pub mad_ttl: f64, } pub fn compute_stats(states: &[crate::state::State]) -> Option { let mut rtts: Vec = Vec::new(); let mut ttls: Vec = Vec::new(); let received = states.iter().filter(|state| matches!(state, crate::state::State::Received { .. })).count(); let lost = states.len() - received; if received == 0 { return None; } for state in states { if let crate::state::State::Received { rtt, ttl } = state { rtts.push(*rtt); ttls.push(*ttl); } } // RTT stats let min_rtt = rtts.iter().min().copied().unwrap(); let max_rtt = rtts.iter().max().copied().unwrap(); 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::() / rtts.len() as f64; // TTL stats let min_ttl = ttls.iter().min().copied().unwrap(); let max_ttl = ttls.iter().max().copied().unwrap(); let sum_ttl: u32 = ttls.iter().sum(); let avg_ttl = sum_ttl as f64 / ttls.len() as f64; let mad_ttl: f64 = ttls.iter().map(|&x| (x as f64 - avg_ttl).abs()).sum::() / ttls.len() as f64; Some(Stats { received, lost, min_rtt, max_rtt, avg_rtt, mad_rtt, min_ttl, max_ttl, avg_ttl, mad_ttl }) }