use std::time::Duration;
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct LatencyStats {
pub average_ms: f64,
pub jitter_ms: f64,
pub min_ms: f64,
pub max_ms: f64,
pub samples: usize,
pub packet_loss_pct: f64,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct TransferStats {
pub bytes: u64,
pub duration: Duration,
pub average_bps: f64,
pub peak_bps: f64,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum BufferbloatGrade {
APlus,
A,
B,
C,
D,
F,
}
impl BufferbloatGrade {
#[must_use]
pub fn from_increase_ms(increase_ms: f64) -> Self {
match increase_ms {
x if x < 5.0 => Self::APlus,
x if x < 30.0 => Self::A,
x if x < 60.0 => Self::B,
x if x < 200.0 => Self::C,
x if x < 400.0 => Self::D,
_ => Self::F,
}
}
#[must_use]
pub fn label(self) -> &'static str {
match self {
Self::APlus => "A+",
Self::A => "A",
Self::B => "B",
Self::C => "C",
Self::D => "D",
Self::F => "F",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Bufferbloat {
pub download_ms: f64,
pub upload_ms: f64,
pub idle_ms: f64,
pub grade: BufferbloatGrade,
}
impl Bufferbloat {
#[must_use]
pub fn new(idle_ms: f64, download_ms: f64, upload_ms: f64) -> Self {
let worst = (download_ms - idle_ms).max(upload_ms - idle_ms).max(0.0);
Self {
download_ms,
upload_ms,
idle_ms,
grade: BufferbloatGrade::from_increase_ms(worst),
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct TestReport {
pub server_name: String,
pub latency: LatencyStats,
pub download: TransferStats,
pub upload: TransferStats,
pub bufferbloat: Option<Bufferbloat>,
}