comparison py/utils.py @ 569:d7575050e4be

StepIntegrator
author Matt Johnston <matt@ucc.asn.au>
date Wed, 11 Nov 2015 00:07:21 +0800
parents 59cb8449ef97
children 11cebd6f0bfb
comparison
equal deleted inserted replaced
568:8eb16d97ed2b 569:d7575050e4be
169 """ 169 """
170 if self(): 170 if self():
171 L(msg + " (log interval %s)" % str(self.limit)) 171 L(msg + " (log interval %s)" % str(self.limit))
172 else: 172 else:
173 D(msg) 173 D(msg)
174
175 class StepIntegrator(object):
176 """
177 >>> s = StepIntegrator(lambda: t, 40)
178 >>> t = 1
179 >>> s.turn(1)
180 >>> t = 10
181 >>> s.turn(0)
182 >>> t = 20
183 >>> s.turn(1)
184 >>> t = 30
185 >>> print(s.integrate())
186 19
187 >>> s.turn(0)
188 >>> print(s.integrate())
189 19
190 >>> t = 35
191 >>> print(s.integrate())
192 19
193 >>> t = 42
194 >>> print(s.integrate())
195 18
196 >>> t = 52
197 >>> print(s.integrate())
198 10
199 >>> t = 69
200 >>> print(s.integrate())
201 1
202 >>> t = 70
203 >>> print(s.integrate())
204 0
205 >>> t = 170
206 >>> print(s.integrate())
207 0
208 """
209 def __init__(self, timefn, limittime):
210 # _on_periods is a list of [[start, end]]. End is None if still on
211 self._on_periods = []
212 self._timefn = timefn
213 self._limittime = limittime
214
215 def turn(self, value):
216 if not self._on_periods:
217 if value:
218 self._on_periods.append([self._timefn(), None])
219 return
220
221 # state hasn't changed
222 on_now = (self._on_periods[-1][1] is None)
223 if value == on_now:
224 return
225
226 if value:
227 self._on_periods.append([self._timefn(), None])
228 else:
229 self._on_periods[-1][1] = self._timefn()
230
231 def _trim(self):
232 begin = self._timefn() - self._limittime
233 # shortcut, first start is after begin
234 if not self._on_periods or self._on_periods[0][0] >= begin:
235 return
236
237 new_periods = []
238 for s, e in self._on_periods:
239 if s == e:
240 continue
241 elif s >= begin:
242 new_periods.append([s,e])
243 elif e is not None and e < begin:
244 continue
245 else:
246 new_periods.append([begin, e])
247 self._on_periods = new_periods
248
249 def integrate(self):
250 self._trim()
251 tot = 0
252 for s, e in self._on_periods:
253 if e is None:
254 e = self._timefn()
255 tot += (e-s)
256 return tot
257
258
259
260
261
262
263