107 lines
2.4 KiB
Rust
107 lines
2.4 KiB
Rust
pub struct RollingAverage {
|
|
index: usize,
|
|
data: Vec<f64>,
|
|
}
|
|
|
|
impl RollingAverage {
|
|
pub fn new(size: usize) -> Self {
|
|
RollingAverage {
|
|
index: 0,
|
|
data: Vec::with_capacity(size),
|
|
}
|
|
}
|
|
|
|
pub fn value(&self) -> f64 {
|
|
if self.data.is_empty() {
|
|
0.0
|
|
} else {
|
|
let mut max = self.data[0];
|
|
|
|
for v in self.data.iter() {
|
|
if *v > max {
|
|
max = *v;
|
|
}
|
|
}
|
|
|
|
let mut sum: f64 = self.data.iter().sum();
|
|
let mut count = self.data.len();
|
|
|
|
if self.data.len() >= 3 {
|
|
sum -= max;
|
|
count -= 1;
|
|
}
|
|
|
|
sum / count as f64
|
|
}
|
|
}
|
|
|
|
pub fn add(&mut self, val: f64) {
|
|
if self.data.capacity() == self.data.len() {
|
|
self.data[self.index] = val;
|
|
|
|
self.index += 1;
|
|
if self.index >= self.data.capacity() {
|
|
self.index = 0;
|
|
}
|
|
} else {
|
|
self.data.push(val);
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn rolling_average() {
|
|
let mut ra = RollingAverage::new(3);
|
|
|
|
assert_eq!(0, ra.data.len());
|
|
assert_eq!(3, ra.data.capacity());
|
|
|
|
assert_eq!(0.0, ra.value());
|
|
|
|
// 10 / 1 = 10
|
|
ra.add(10.0);
|
|
assert_eq!(1, ra.data.len());
|
|
assert_eq!(10.0, ra.value());
|
|
|
|
// (10 + 20) / 2 = 15
|
|
ra.add(20.0);
|
|
assert_eq!(2, ra.data.len());
|
|
assert_eq!(15.0, ra.value());
|
|
|
|
// (10 + 20 + 30) / 3 = 20
|
|
ra.add(30.0);
|
|
assert_eq!(3, ra.data.len());
|
|
assert_eq!(20.0, ra.value());
|
|
|
|
assert_eq!(10.0, ra.data[0]);
|
|
assert_eq!(20.0, ra.data[1]);
|
|
assert_eq!(30.0, ra.data[2]);
|
|
|
|
// This should replace the oldest value (index 1)
|
|
ra.add(40.0);
|
|
|
|
assert_eq!(3, ra.data.len());
|
|
assert_eq!(3, ra.data.capacity());
|
|
|
|
// (40 + 20 + 30) / 3 = 30
|
|
assert_eq!(30.0, ra.value());
|
|
|
|
assert_eq!(40.0, ra.data[0]);
|
|
assert_eq!(20.0, ra.data[1]);
|
|
assert_eq!(30.0, ra.data[2]);
|
|
|
|
ra.add(50.0);
|
|
ra.add(60.0);
|
|
ra.add(70.0);
|
|
|
|
assert_eq!(70.0, ra.data[0]);
|
|
assert_eq!(50.0, ra.data[1]);
|
|
assert_eq!(60.0, ra.data[2]);
|
|
}
|
|
}
|