pub struct HaddenDetector {
history: Vec<f64>,
max_history: usize,
}
impl HaddenDetector {
pub fn new(max_history: usize) -> Self {
Self {
history: Vec::with_capacity(max_history),
max_history,
}
}
pub fn add_value(&mut self, value: f64) {
self.history.push(value);
if self.history.len() > self.max_history {
self.history.remove(0);
}
}
pub fn detect_peak(&self, dt_secs: f64) -> Option<(f64, f64)> {
if self.history.len() < 3 { return None; }
let len = self.history.len();
let y1 = self.history[len - 3];
let y2 = self.history[len - 2];
let y3 = self.history[len - 1];
let a = (y3 - 2.0 * y2 + y1) / (2.0 * dt_secs * dt_secs);
if a >= 0.0 { return None; }
let b = (y3 - y1) / (2.0 * dt_secs);
let t_peak = -b / (2.0 * a);
if t_peak < -dt_secs || t_peak > dt_secs { return None; }
let peak_value = a * t_peak * t_peak + b * t_peak + y2;
let avg_value = (y1 + y2 + y3) / 3.0;
let severity = if avg_value > 0.0 { peak_value / avg_value } else { 1.0 };
Some((severity, peak_value))
}
}