use std::fmt::Debug;
#[derive(Copy, Clone, Debug)]
pub(super) struct MinMax {
window: u64,
samples: [MinMaxSample; 3],
}
impl MinMax {
pub(super) fn get(&self) -> u64 {
self.samples[0].value
}
fn fill(&mut self, sample: MinMaxSample) {
self.samples.fill(sample);
}
pub(super) fn reset(&mut self) {
self.fill(Default::default())
}
pub(super) fn update_max(&mut self, current_round: u64, measurement: u64) {
let sample = MinMaxSample {
time: current_round,
value: measurement,
};
if self.samples[0].value == 0
|| sample.value >= self.samples[0].value
|| sample.time - self.samples[2].time > self.window
{
self.fill(sample);
return;
}
if sample.value >= self.samples[1].value {
self.samples[2] = sample;
self.samples[1] = sample;
} else if sample.value >= self.samples[2].value {
self.samples[2] = sample;
}
self.subwin_update(sample);
}
fn subwin_update(&mut self, sample: MinMaxSample) {
let dt = sample.time - self.samples[0].time;
if dt > self.window {
self.samples[0] = self.samples[1];
self.samples[1] = self.samples[2];
self.samples[2] = sample;
if sample.time - self.samples[0].time > self.window {
self.samples[0] = self.samples[1];
self.samples[1] = self.samples[2];
self.samples[2] = sample;
}
} else if self.samples[1].time == self.samples[0].time && dt > self.window / 4 {
self.samples[2] = sample;
self.samples[1] = sample;
} else if self.samples[2].time == self.samples[1].time && dt > self.window / 2 {
self.samples[2] = sample;
}
}
}
impl Default for MinMax {
fn default() -> Self {
Self {
window: 10,
samples: [Default::default(); 3],
}
}
}
#[derive(Debug, Copy, Clone, Default)]
struct MinMaxSample {
time: u64,
value: u64,
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test() {
let round = 25;
let mut min_max = MinMax::default();
min_max.update_max(round + 1, 100);
assert_eq!(100, min_max.get());
min_max.update_max(round + 3, 120);
assert_eq!(120, min_max.get());
min_max.update_max(round + 5, 160);
assert_eq!(160, min_max.get());
min_max.update_max(round + 7, 100);
assert_eq!(160, min_max.get());
min_max.update_max(round + 10, 100);
assert_eq!(160, min_max.get());
min_max.update_max(round + 14, 100);
assert_eq!(160, min_max.get());
min_max.update_max(round + 16, 100);
assert_eq!(100, min_max.get());
min_max.update_max(round + 18, 130);
assert_eq!(130, min_max.get());
}
}