#![allow(dead_code)]
use std::time::Duration;
pub fn format_speed_mbps(bytes_per_sec: f64) -> f64 {
(bytes_per_sec * 8.0) / 1_000_000.0
}
pub fn format_duration(duration: Duration) -> String {
let secs = duration.as_secs();
if secs < 60 {
format!("{}s", secs)
} else if secs < 3600 {
format!("{}m {}s", secs / 60, secs % 60)
} else {
format!("{}h {}m", secs / 3600, (secs % 3600) / 60)
}
}
pub fn lerp(start: f64, end: f64, t: f64) -> f64 {
start + (end - start) * t.clamp(0.0, 1.0)
}
pub fn ease_out_cubic(t: f64) -> f64 {
let t = t.clamp(0.0, 1.0);
1.0 - (1.0 - t).powi(3)
}
pub fn calculate_gauge_scale(speed_mbps: f64) -> f64 {
const SCALES: [f64; 9] = [
10.0, 50.0, 100.0, 250.0, 500.0, 1000.0, 2500.0, 5000.0, 10000.0,
];
for scale in SCALES {
if speed_mbps <= scale * 0.8 {
return scale;
}
}
SCALES[SCALES.len() - 1]
}
pub fn calculate_jitter(samples: &[f64]) -> f64 {
if samples.len() < 2 {
return 0.0;
}
let mean = samples.iter().sum::<f64>() / samples.len() as f64;
let variance = samples.iter().map(|x| (x - mean).powi(2)).sum::<f64>() / samples.len() as f64;
variance.sqrt()
}
pub fn format_bytes(bytes: u64) -> String {
humansize::format_size(bytes, humansize::BINARY)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_format_speed_mbps() {
assert!((format_speed_mbps(125_000_000.0) - 1000.0).abs() < 0.001);
assert!((format_speed_mbps(12_500_000.0) - 100.0).abs() < 0.001);
}
#[test]
fn test_calculate_gauge_scale() {
assert_eq!(calculate_gauge_scale(5.0), 10.0);
assert_eq!(calculate_gauge_scale(45.0), 100.0);
assert_eq!(calculate_gauge_scale(800.0), 1000.0);
}
#[test]
fn test_calculate_jitter() {
let samples = vec![10.0, 12.0, 11.0, 10.5, 11.5];
let jitter = calculate_jitter(&samples);
assert!(jitter > 0.0 && jitter < 2.0);
}
}