Skip to content

Commit 2e9f191

Browse files
fix: address Copilot review on #4644 - kwh precision in split slots
dp2() on both sides of the cap-boundary split let low_kwh + high_kwh drift from the original kwh via double-rounding, and made the split path's kwh precision inconsistent with this function's non-split chunks, which already carry full-precision kwh (dp2() only applied to cost/soc downstream). Kept full precision for the split kwh values instead, matching the rest of the function. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
1 parent d2063ba commit 2e9f191

2 files changed

Lines changed: 8 additions & 4 deletions

File tree

apps/predbat/octopus.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2666,12 +2666,15 @@ def load_octopus_slots(self, car_n, octopus_slots, octopus_intelligent_consider_
26662666
elif available_blocks <= 0:
26672667
chunks = [(start_minutes, end_minutes, kwh, self.rate_max_base)]
26682668
else:
2669+
# Full precision here - rounding to dp2() on both sides can make low_kwh + high_kwh
2670+
# drift from the original kwh, and this function's non-split chunks already carry
2671+
# kwh at full precision too (dp2() is only applied downstream, to cost/soc).
26692672
split_minute = min(slot_block_start + available_blocks * 30, end_minutes)
26702673
span = end_minutes - start_minutes
2671-
low_kwh = dp2(kwh * (split_minute - start_minutes) / span) if span > 0 else 0.0
2674+
low_kwh = kwh * (split_minute - start_minutes) / span if span > 0 else 0.0
26722675
chunks = [
26732676
(start_minutes, split_minute, low_kwh, self.rate_min_base),
2674-
(split_minute, end_minutes, dp2(kwh - low_kwh), self.rate_max_base),
2677+
(split_minute, end_minutes, kwh - low_kwh, self.rate_max_base),
26752678
]
26762679

26772680
for chunk_start, chunk_end, chunk_kwh, slot_average in chunks:

apps/predbat/tests/test_octopus_slots.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,9 @@ def run_load_octopus_slots_tests(my_predbat):
120120
# flipping to the max rate (batpred#4624).
121121
slot_block_start = (minutes_start // 30) * 30
122122
split_minute = slot_block_start + 2 * 30 # 2 blocks (12 - 10) remain in the daily budget
123-
low_kwh = dp2(5.0 * (split_minute - minutes_start) / 60)
124-
high_kwh = dp2(5.0 - low_kwh)
123+
# Full precision to match production - only cost is rounded (batpred#4644 review).
124+
low_kwh = 5.0 * (split_minute - minutes_start) / 60
125+
high_kwh = 5.0 - low_kwh
125126
for target in (expected_slots5, expected_slots8):
126127
target.append({"start": minutes_start, "end": split_minute, "kwh": low_kwh, "average": 4, "cost": dp2(4 * low_kwh), "soc": 10, "octopus": True})
127128
target.append({"start": split_minute, "end": minutes_end, "kwh": high_kwh, "average": 10, "cost": dp2(10 * high_kwh), "soc": 10, "octopus": True})

0 commit comments

Comments
 (0)