#![allow(unused_variables)]
#[derive(Debug, Copy, Clone, Default)]
pub struct MinMaxSample {
time: u64,
value: u64,
}
#[derive(Debug)]
pub struct MinMax {
window: u64,
samples: [MinMaxSample; 3],
}
impl MinMax {
pub fn new(window: u64) -> Self {
Self {
window,
samples: [Default::default(); 3],
}
}
pub fn set_window(&mut self, window: u64) {
self.window = window;
}
pub fn reset(&mut self, sample: MinMaxSample) {
self.samples.fill(sample)
}
fn subwin_update(&mut self, sample: MinMaxSample) {
let dt = sample.time.saturating_sub(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.saturating_sub(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_u64 {
self.samples[2] = sample;
self.samples[1] = sample;
} else if self.samples[2].time == self.samples[1].time && dt > self.window / 2_u64 {
self.samples[2] = sample;
}
}
pub fn update_max(&mut self, time: u64, value: u64) {
if time < self.samples[2].time {
return;
}
let sample = MinMaxSample { time, value };
if self.samples[0].value == 0 || sample.value >= self.samples[0].value || sample.time.saturating_sub(self.samples[2].time) > self.window
{
self.reset(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);
}
pub fn update_min(&mut self, time: u64, value: u64) {
if time < self.samples[2].time {
return;
}
let sample = MinMaxSample { time, value };
if self.samples[0].value == 0 || sample.value <= self.samples[0].value || sample.time.saturating_sub(self.samples[2].time) > self.window
{
self.reset(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);
}
pub fn get(&self) -> u64 {
self.samples[0].value
}
}
impl Default for MinMax {
fn default() -> Self {
Self {
window: 10,
samples: [Default::default(); 3],
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn minmax_update_max() {
let mut min_max = MinMax::new(15);
let round: u64 = 20;
min_max.set_window(10);
assert_eq!(min_max.window, 10);
min_max.update_max(1, 200);
assert_eq!(min_max.get(), 200);
min_max.update_max(round, 120);
assert_eq!(min_max.get(), 120);
min_max.update_max(round + 1, 150);
assert_eq!(min_max.get(), 150);
min_max.update_max(round, 180);
assert_eq!(min_max.get(), 150);
min_max.update_max(round + 2, 120);
assert_eq!(min_max.get(), 150);
min_max.update_max(round + 4, 110);
assert_eq!(min_max.get(), 150);
min_max.update_max(round + 8, 100);
assert_eq!(min_max.get(), 150);
min_max.update_max(round + 9, 105);
assert_eq!(min_max.get(), 150);
assert_eq!(min_max.samples[1].value, 110);
assert_eq!(min_max.samples[2].value, 105);
min_max.update_max(round + 15, 90);
assert_eq!(min_max.get(), 105);
min_max.update_max(round + 17, 95);
assert_eq!(min_max.get(), 105);
assert_eq!(min_max.samples[1].value, 95);
assert_eq!(min_max.samples[2].value, 95);
}
#[test]
fn minmax_update_min() {
let mut min_max = MinMax::default();
assert_eq!(min_max.window, 10);
let round: u64 = 20;
min_max.update_min(1, 100);
assert_eq!(min_max.get(), 100);
min_max.update_min(round, 120);
assert_eq!(min_max.get(), 120);
min_max.update_min(round + 1, 110);
assert_eq!(min_max.get(), 110);
min_max.update_min(round, 90);
assert_eq!(min_max.get(), 110);
min_max.update_min(round + 4, 120);
assert_eq!(min_max.get(), 110);
min_max.update_min(round + 8, 115);
assert_eq!(min_max.samples[1].value, 115);
min_max.update_min(round + 9, 120);
assert_eq!(min_max.samples[2].value, 120);
min_max.update_min(round + 10, 118);
assert_eq!(min_max.samples[2].value, 118);
}
}