Shadow-mode client script and cutover doc correction
This commit is contained in:
@@ -29,6 +29,13 @@ MIN_POINTS_FOR_ESTIMATE = 4
|
||||
# says "never", which is worse than saying nothing.
|
||||
MIN_DROP_FOR_ESTIMATE = 2
|
||||
|
||||
# At or below this, the cartridge is done and the arithmetic stops being the
|
||||
# useful answer. A supply sitting at 1% that drains a tenth of a point a day
|
||||
# computes to ten days; a printer at 1% is out of toner as far as anyone
|
||||
# standing at it is concerned, and it is what should be ordered first. Rate is
|
||||
# still reported - only the days-left figure is floored.
|
||||
EMPTY_LEVEL = 5
|
||||
|
||||
|
||||
def _asfloat(value):
|
||||
try:
|
||||
@@ -101,11 +108,17 @@ def burn_rate(points):
|
||||
return drop / days
|
||||
|
||||
|
||||
def analyse(points, rise=REPLACEMENT_RISE):
|
||||
def analyse(points, rise=REPLACEMENT_RISE, currentlevel=None):
|
||||
"""Everything the report needs about one supply.
|
||||
|
||||
`currentlevel` is the live reading from the printer, when the caller has
|
||||
one. It is what the days-left figure is computed against, because it is
|
||||
what the report displays: taking the level from the display and the
|
||||
countdown from the last stored history point lets the two disagree, and a
|
||||
row reading "20% - 4 days left" is read as a broken report, correctly.
|
||||
|
||||
Returns:
|
||||
currentlevel latest reading, or None
|
||||
currentlevel live reading if given, else the latest stored one
|
||||
daysleft at the current rate, or None when there is no estimate
|
||||
burnrateperday percent per day, or None
|
||||
reason why there is no estimate - shown rather than hidden, so
|
||||
@@ -117,12 +130,16 @@ def analyse(points, rise=REPLACEMENT_RISE):
|
||||
"""
|
||||
points = normalise(points)
|
||||
result = {
|
||||
'currentlevel': None, 'daysleft': None, 'burnrateperday': None,
|
||||
'currentlevel': currentlevel, 'daysleft': None, 'burnrateperday': None,
|
||||
'reason': None, 'replacements': 0, 'lastreplaced': None,
|
||||
'basisdays': 0, 'points': [],
|
||||
}
|
||||
if not points:
|
||||
result['reason'] = 'no history'
|
||||
# A live level with no history is still worth acting on when it is low.
|
||||
if currentlevel is not None and currentlevel <= EMPTY_LEVEL:
|
||||
result['daysleft'] = 0
|
||||
else:
|
||||
result['reason'] = 'no history'
|
||||
return result
|
||||
|
||||
replacements = find_replacements(points, rise=rise)
|
||||
@@ -130,13 +147,30 @@ def analyse(points, rise=REPLACEMENT_RISE):
|
||||
result['lastreplaced'] = replacements[-1].isoformat() if replacements else None
|
||||
|
||||
run = current_run(points, rise=rise)
|
||||
result['currentlevel'] = run[-1][1]
|
||||
stored = run[-1][1]
|
||||
level = stored if currentlevel is None else currentlevel
|
||||
result['currentlevel'] = level
|
||||
result['points'] = [(when.isoformat(), level) for when, level in run]
|
||||
if len(run) >= 2:
|
||||
result['basisdays'] = round(
|
||||
(run[-1][0] - run[0][0]).total_seconds() / 86400, 1)
|
||||
|
||||
# A live level well above the stored run means it was swapped since the
|
||||
# last stored reading. The run describes the cartridge that came out.
|
||||
if currentlevel is not None and currentlevel - stored >= rise:
|
||||
result['replacements'] += 1
|
||||
result['reason'] = 'replaced recently'
|
||||
return result
|
||||
|
||||
rate = burn_rate(run)
|
||||
|
||||
# Empty is empty. Ordering by a rate below this level ranks a dead
|
||||
# cartridge behind a healthy one that happens to be draining faster.
|
||||
if level <= EMPTY_LEVEL:
|
||||
result['daysleft'] = 0
|
||||
result['burnrateperday'] = round(rate, 2) if rate is not None else None
|
||||
return result
|
||||
|
||||
if rate is None:
|
||||
# Say which of the three it is; "no estimate" alone invites a bug report.
|
||||
if len(run) < MIN_POINTS_FOR_ESTIMATE:
|
||||
@@ -147,7 +181,7 @@ def analyse(points, rise=REPLACEMENT_RISE):
|
||||
return result
|
||||
|
||||
result['burnrateperday'] = round(rate, 2)
|
||||
result['daysleft'] = max(0, int(run[-1][1] / rate))
|
||||
result['daysleft'] = max(0, int(level / rate))
|
||||
return result
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user