Mercurial > templog
diff rust/src/types.rs @ 610:af0dac00d40b rust
untested step integrator
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Thu, 23 Feb 2017 23:27:09 +0800 |
parents | 7bda01659426 |
children | f3e39e2107fd |
line wrap: on
line diff
--- a/rust/src/types.rs Sat Feb 18 00:21:10 2017 +0800 +++ b/rust/src/types.rs Thu Feb 23 23:27:09 2017 +0800 @@ -2,7 +2,9 @@ use std::time::{Duration,Instant}; use std::error::Error; use std::fmt; +use std::cmp; use std::cell::Cell; +use std::iter::FromIterator; use serde::{Deserialize,Serialize}; @@ -126,4 +128,75 @@ } } +struct Period { + start: Instant, + end: Option<Instant>, +} +pub struct StepIntegrator { + on_periods: Vec<Period>, + limit: Duration, +} + +impl StepIntegrator { + pub fn new(limit: Duration) -> Self { + StepIntegrator { + on_periods: Vec::new(), + limit: limit, + } + } + + pub fn turn(&mut self, on: bool) { + self.trim(); + + if self.on_periods.is_empty() { + self.on_periods.push( Period { start: Instant::now(), end: None }); + return; + } + + let current_on = self.on_periods.last().unwrap().end.is_none(); + if on == current_on { + // state is unchanged + return; + } + + if on { + self.on_periods.push( Period { start: Instant::now(), end: None }); + } else { + self.on_periods.last_mut().unwrap().end = Some(Instant::now()); + } + } + + pub fn set_limit(&mut self, limit: Duration) { + self.limit = limit; + self.trim(); + } + + fn integrate(&self) -> Duration { + let durs = self.on_periods.iter().map(|p| { + let end = p.end.unwrap_or_else(|| Instant::now()); + end - p.start + }); + // TODO rust 1.16: impl Sum for Duration + // durs.sum() + durs.fold(Duration::new(0,0), |acc, d| acc + d) + } + + fn trim(&mut self) { + let begin = Instant::now() - self.limit; + + self.on_periods.retain(|p| { + // remove expired endtimes + if let Some(e) = p.end { + e >= begin && e != p.start + } else { + true + } + }); + + for p in &mut self.on_periods { + p.start = cmp::max(p.start, begin); + } + } +} +