OPT-27: test_modes_p4 says what a covered sensor does; test_opt27 guards
test_modes_p4.py: 'the forecast is lost mid-run' now loses it for good (a hold that never covers); a second scenario is the same loss with the hold, which keeps Leftover solar charging. test_opt27.py: a failing check no longer hides the ones after it. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude
parent
cdcbe7dbb6
commit
1eb572f513
@@ -672,9 +672,24 @@ check("Cheap hours with a sun forecast charges as with none (P3)",
|
||||
and top > 80.0)
|
||||
|
||||
# The forecast goes away mid-run: Leftover solar stops at once (P3 option A).
|
||||
# OPT-27: a sensor that is unavailable is covered by its last fresh reading
|
||||
# for up to 3 h (`solarfc.Hold`), so "lost" here is a hold that never covers;
|
||||
# the next scenario is the same loss with the hold (test_opt27.py).
|
||||
DROP = UTC0 + timedelta(hours=1, minutes=30)
|
||||
|
||||
|
||||
class _NoHold(solarfc.Hold):
|
||||
def stand_in(self, *a, **k):
|
||||
return None
|
||||
|
||||
|
||||
def seed_profile_no_hold(c):
|
||||
seed_profile(c)
|
||||
c.fc_hold = _NoHold()
|
||||
|
||||
|
||||
rows, st_, c = run_day(SF_LS, fc=lambda now: 1.0 if now < DROP else None,
|
||||
soc0={"a": 60.0, "b": 10.0})
|
||||
soc0={"a": 60.0, "b": 10.0}, patch=seed_profile_no_hold)
|
||||
invariants("forecast lost mid-run", rows, c)
|
||||
before = [r for r in rows if r["now"] < DROP and r["action"]
|
||||
== arbitrage.CHARGE]
|
||||
@@ -682,6 +697,15 @@ late = [r for r in rows if r["now"] > DROP + timedelta(
|
||||
seconds=2 * 60 + 10) and r["action"] == arbitrage.CHARGE]
|
||||
check("forecast lost mid-run: Leftover solar was charging, and stops within "
|
||||
"a forecast read (60 s) and a cycle", before and not late)
|
||||
rows, st_, c = run_day(SF_LS, fc=lambda now: 1.0 if now < DROP else None,
|
||||
soc0={"a": 60.0, "b": 10.0})
|
||||
invariants("forecast unavailable mid-run, covered", rows, c)
|
||||
check("forecast unavailable mid-run (OPT-27): the last reading covers it, so "
|
||||
"Leftover solar goes on charging past the point where it was lost",
|
||||
[r for r in rows if r["now"] < DROP and r["action"]
|
||||
== arbitrage.CHARGE]
|
||||
and [r for r in rows if r["now"] > DROP + timedelta(
|
||||
seconds=2 * 60 + 10) and r["action"] == arbitrage.CHARGE])
|
||||
|
||||
# The forecast is far too high (40 kWh, and there is no sun at all): no grid
|
||||
# charge, so B covers less of the evening - a money risk, never a safety one.
|
||||
|
||||
@@ -100,7 +100,7 @@ check("22:00 with the sensors stale since 17:05: the 17:05 figures are used",
|
||||
fc is not None and fc.kept and fc.tomorrow.kwh == 12.0
|
||||
and fc.at == D1_READ and gaps == ())
|
||||
check("... today has no sun left in it, tomorrow's is counted from 06:00",
|
||||
fc.between(EVE, at(4, 7, 0)) is not None
|
||||
fc is not None and fc.between(EVE, at(4, 7, 0)) is not None
|
||||
and 0.0 < fc.between(EVE, at(4, 7, 0)) < 0.5
|
||||
and fc.today.kwh == 0.4)
|
||||
fc2, _w, _g = rs(GONE, GONE, EVE, h)
|
||||
@@ -146,12 +146,16 @@ check("02:59: tomorrow's 12.0 kWh is now today's, there is no tomorrow",
|
||||
fmid is not None and fmid.today.kwh == 12.0 and fmid.tomorrow is None
|
||||
and fmid.kept and fmid.today.day0 == at(4, 0, 0))
|
||||
check("... its sun is counted on the day it is for (06:00-20:00 on the 4th)",
|
||||
fmid.between(at(4, 3, 0), at(4, 7, 0)) is not None
|
||||
fmid is not None and fmid.between(at(4, 3, 0), at(4, 7, 0)) is not None
|
||||
and fmid.between(at(4, 3, 0), at(4, 7, 0)) > 0.0)
|
||||
check("03:01 (midnight + 3 h): not used any more",
|
||||
rs(GONE, GONE, at(4, 3, 1), h2)[0] is None)
|
||||
check("... and not the next evening either (older than one night)",
|
||||
rs(GONE, GONE, at(4, 22, 0), h2)[0] is None)
|
||||
fe = rs(st(0.1, at(4, 21, 50)), GONE, at(4, 22, 0), h2)[0]
|
||||
check("... the next evening, with today fresh and tomorrow's sensor down, "
|
||||
"there is no tomorrow: the 4th's figure is not the 5th's",
|
||||
fe is not None and fe.today.kwh == 0.1 and fe.tomorrow is None)
|
||||
# Never today's figure for tomorrow.
|
||||
h4 = solarfc.Hold()
|
||||
rs(st(3.0, at(3, 17, 0)), st(12.0, at(3, 17, 0)), at(3, 17, 5), h4)
|
||||
|
||||
Reference in New Issue
Block a user