pub struct RollingAverage { index: usize, data: Vec, } 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]); } }