rkik 2.2.0

Rusty Klock Inspection Kit - NTP Query and Compare Tool
Documentation
use crate::domain::ntp::ProbeResult;
#[cfg(all(feature = "ptp", target_os = "linux"))]
use crate::domain::ptp::PtpProbeResult;
#[cfg(feature = "json")]
use serde::Serialize;

#[derive(Debug, Clone)]
#[cfg_attr(feature = "json", derive(Serialize))]
pub struct Stats {
    pub count: usize,
    pub offset_avg: f64,
    pub offset_min: f64,
    pub offset_max: f64,
    pub rtt_avg: f64,
}

pub fn compute_stats(results: &[ProbeResult]) -> Stats {
    if results.is_empty() {
        return Stats {
            count: 0,
            offset_avg: 0.0,
            offset_min: 0.0,
            offset_max: 0.0,
            rtt_avg: 0.0,
        };
    }

    let count = results.len();
    let offset_avg = results.iter().map(|r| r.offset_ms).sum::<f64>() / count as f64;
    let offset_min = results
        .iter()
        .map(|r| r.offset_ms)
        .fold(f64::INFINITY, f64::min);
    let offset_max = results
        .iter()
        .map(|r| r.offset_ms)
        .fold(f64::NEG_INFINITY, f64::max);
    let rtt_avg = results.iter().map(|r| r.rtt_ms).sum::<f64>() / count as f64;
    Stats {
        count,
        offset_avg,
        offset_min,
        offset_max,
        rtt_avg,
    }
}

#[cfg(all(feature = "ptp", target_os = "linux"))]
#[derive(Debug, Clone)]
#[cfg_attr(feature = "json", derive(Serialize))]
pub struct PtpStats {
    pub count: usize,
    pub offset_avg_ns: f64,
    pub offset_min_ns: f64,
    pub offset_max_ns: f64,
    pub mean_path_delay_avg_ns: f64,
}

#[cfg(all(feature = "ptp", target_os = "linux"))]
pub fn compute_ptp_stats(results: &[PtpProbeResult]) -> PtpStats {
    if results.is_empty() {
        return PtpStats {
            count: 0,
            offset_avg_ns: 0.0,
            offset_min_ns: 0.0,
            offset_max_ns: 0.0,
            mean_path_delay_avg_ns: 0.0,
        };
    }

    let count = results.len();
    let offset_avg_ns = results.iter().map(|r| r.offset_ns as f64).sum::<f64>() / count as f64;
    let offset_min_ns = results
        .iter()
        .map(|r| r.offset_ns as f64)
        .fold(f64::INFINITY, f64::min);
    let offset_max_ns = results
        .iter()
        .map(|r| r.offset_ns as f64)
        .fold(f64::NEG_INFINITY, f64::max);
    let mean_path_delay_avg_ns = results
        .iter()
        .map(|r| r.mean_path_delay_ns as f64)
        .sum::<f64>()
        / count as f64;

    PtpStats {
        count,
        offset_avg_ns,
        offset_min_ns,
        offset_max_ns,
        mean_path_delay_avg_ns,
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn compute_stats_empty_results() {
        let results: Vec<ProbeResult> = Vec::new();

        let stats = compute_stats(&results);

        assert_eq!(stats.count, 0);
        assert_eq!(stats.offset_avg, 0.0);
        assert_eq!(stats.offset_min, 0.0);
        assert_eq!(stats.offset_max, 0.0);
        assert_eq!(stats.rtt_avg, 0.0);
    }
}