comparison 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
comparison
equal deleted inserted replaced
609:7bda01659426 610:af0dac00d40b
1 use std::collections::HashMap; 1 use std::collections::HashMap;
2 use std::time::{Duration,Instant}; 2 use std::time::{Duration,Instant};
3 use std::error::Error; 3 use std::error::Error;
4 use std::fmt; 4 use std::fmt;
5 use std::cmp;
5 use std::cell::Cell; 6 use std::cell::Cell;
7 use std::iter::FromIterator;
6 8
7 use serde::{Deserialize,Serialize}; 9 use serde::{Deserialize,Serialize};
8 10
9 #[derive(Deserialize, Serialize, Debug)] 11 #[derive(Deserialize, Serialize, Debug)]
10 pub struct Params { 12 pub struct Params {
124 op(); 126 op();
125 } 127 }
126 } 128 }
127 } 129 }
128 130
129 131 struct Period {
132 start: Instant,
133 end: Option<Instant>,
134 }
135
136 pub struct StepIntegrator {
137 on_periods: Vec<Period>,
138 limit: Duration,
139 }
140
141 impl StepIntegrator {
142 pub fn new(limit: Duration) -> Self {
143 StepIntegrator {
144 on_periods: Vec::new(),
145 limit: limit,
146 }
147 }
148
149 pub fn turn(&mut self, on: bool) {
150 self.trim();
151
152 if self.on_periods.is_empty() {
153 self.on_periods.push( Period { start: Instant::now(), end: None });
154 return;
155 }
156
157 let current_on = self.on_periods.last().unwrap().end.is_none();
158 if on == current_on {
159 // state is unchanged
160 return;
161 }
162
163 if on {
164 self.on_periods.push( Period { start: Instant::now(), end: None });
165 } else {
166 self.on_periods.last_mut().unwrap().end = Some(Instant::now());
167 }
168 }
169
170 pub fn set_limit(&mut self, limit: Duration) {
171 self.limit = limit;
172 self.trim();
173 }
174
175 fn integrate(&self) -> Duration {
176 let durs = self.on_periods.iter().map(|p| {
177 let end = p.end.unwrap_or_else(|| Instant::now());
178 end - p.start
179 });
180 // TODO rust 1.16: impl Sum for Duration
181 // durs.sum()
182 durs.fold(Duration::new(0,0), |acc, d| acc + d)
183 }
184
185 fn trim(&mut self) {
186 let begin = Instant::now() - self.limit;
187
188 self.on_periods.retain(|p| {
189 // remove expired endtimes
190 if let Some(e) = p.end {
191 e >= begin && e != p.start
192 } else {
193 true
194 }
195 });
196
197 for p in &mut self.on_periods {
198 p.start = cmp::max(p.start, begin);
199 }
200 }
201 }
202