The LP was producing visually unintuitive schedules: when several surplus
hours had identical cost benefit (true with constant export_rate), the
solver picked an arbitrary subset, which the user couldn't read as 'this
is the battery doing its job'. Worse, the daily-LP variant drained to 0
every midnight because it placed zero value on next-day SoC.
Replaced oracle_daily_schedule() with a one-pass greedy dispatcher that
matches what every plug-in battery in the catalog (Marstek, Zendure,
EcoFlow, HomeWizard) actually does in 'self-consumption mode':
for each hour:
if exporting at meter: charge as fast as power+capacity allows
if importing at meter: discharge to cover net demand
Trade-offs:
- Greedy doesn't do grid arbitrage (charge cheap → discharge expensive
without a surplus source). The LP would; real plug-in firmware
doesn't, so greedy is more honest about what dad's battery would do.
- Charts now show 'fill in the morning, overflow at midday' which is
what users expect to see.
- Updated tests: dropped LP-arbitrage assertion, added a greedy-fills-
from-surplus-then-overflows test that locks the new behaviour in.