FA-68701 / Toll and parking fee computation / Open access
EV charging session and idle fee: the grace period is only a threshold · case 01
EV charging session and idle fee returns a wrong result when the grace period is only a threshold.
ROOT CAUSE
Idle fees start the instant charging completes.
VERIFIED REPAIR
Restore the idle grace rule so that the step reads `max(0, x['unplug'] - x['charge_end'] - x['idle_grace'])`.
Unsuccessful approach: Once the grace is exceeded the whole idle period is billed, so grace minutes are charged.
Case contract
Input {plug_in, charge_end, unplug (minutes), wh, price_per_kwh, idle_grace, idle_rate (per started 10 min), idle_cap, session_fee, min_fee}. Energy = ceil(wh*price/1000). Idle minutes = max(0, unplug - charge_end - grace); idle fee = min(idle_cap, started 10-minute blocks * idle_rate). Total = max(min_fee, session_fee + energy + idle). Return {energy, idle, total}.
Why this case matters
Fee engines bill customers in integer cents; a wrong boundary, rounding stage or cap scope silently over- or under-charges.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
energy = -(-x['wh'] * x['price_per_kwh'] // 1000)
idle = max(0, x['unplug'] - x['charge_end'])
idle_fee = min(x['idle_cap'], -(-idle // 10) * x['idle_rate'])
total = x['session_fee'] + energy + idle_fee
return {'energy': energy, 'idle': idle_fee, 'total': max(x['min_fee'], total)}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[({'plug_in': 400, 'charge_end': 430, 'unplug': 440, 'wh': 26712, 'price_per_kwh': 35, 'idle_grace': 10, 'idle_rate': 40, 'idle_cap': 1000, 'session_fee': 150, 'min_fee': 200}, {'energy': 935, 'idle': 0, 'total': 1085}), ({'plug_in': 443, 'charge_end': 621, 'unplug': 1021, 'wh': 32003, 'price_per_kwh': 35, 'idle_grace': 10, 'idle_rate': 100, 'idle_cap': 3000, 'session_fee': 100, 'min_fee': 500}, {'energy': 1121, 'idle': 3000, 'total': 4221}), ({'plug_in': 178, 'charge_end': 431, 'unplug': 831, 'wh': 23652, 'price_per_kwh': 35, 'idle_grace': 15, 'idle_rate': 50, 'idle_cap': 1000, 'session_fee': 100, 'min_fee': 200}, {'energy': 828, 'idle': 1000, 'total': 1928}), ({'plug_in': 0, 'charge_end': 90, 'unplug': 106, 'wh': 12500, 'price_per_kwh': 35, 'idle_grace': 15, 'idle_rate': 50, 'idle_cap': 2000, 'session_fee': 100, 'min_fee': 300}, {'energy': 438, 'idle': 50, 'total': 588}), ({'plug_in': 24, 'charge_end': 82, 'unplug': 82, 'wh': 29231, 'price_per_kwh': 45, 'idle_grace': 15, 'idle_rate': 100, 'idle_cap': 3000, 'session_fee': 100, 'min_fee': 300}, {'energy': 1316, 'idle': 0, 'total': 1416}), ({'plug_in': 30, 'charge_end': 45, 'unplug': 400, 'wh': 800, 'price_per_kwh': 29, 'idle_grace': 10, 'idle_rate': 100, 'idle_cap': 1000, 'session_fee': 0, 'min_fee': 500}, {'energy': 24, 'idle': 1000, 'total': 1024}), ({'plug_in': 321, 'charge_end': 549, 'unplug': 949, 'wh': 16186, 'price_per_kwh': 29, 'idle_grace': 10, 'idle_rate': 50, 'idle_cap': 3000, 'session_fee': 0, 'min_fee': 300}, {'energy': 470, 'idle': 1950, 'total': 2420}), ({'plug_in': 445, 'charge_end': 719, 'unplug': 744, 'wh': 13785, 'price_per_kwh': 29, 'idle_grace': 10, 'idle_rate': 100, 'idle_cap': 2000, 'session_fee': 0, 'min_fee': 500}, {'energy': 400, 'idle': 200, 'total': 600})], [({'plug_in': 143, 'charge_end': 442, 'unplug': 842, 'wh': 33904, 'price_per_kwh': 29, 'idle_grace': 15, 'idle_rate': 40, 'idle_cap': 1000, 'session_fee': 150, 'min_fee': 200}, {'energy': 984, 'idle': 1000, 'total': 2134}), ({'plug_in': 468, 'charge_end': 648, 'unplug': 648, 'wh': 29211, 'price_per_kwh': 45, 'idle_grace': 15, 'idle_rate': 100, 'idle_cap': 2000, 'session_fee': 150, 'min_fee': 500}, {'energy': 1315, 'idle': 0, 'total': 1465}), ({'plug_in': 244, 'charge_end': 536, 'unplug': 736, 'wh': 50241, 'price_per_kwh': 29, 'idle_grace': 15, 'idle_rate': 100, 'idle_cap': 1000, 'session_fee': 150, 'min_fee': 200}, {'energy': 1457, 'idle': 1000, 'total': 2607}), ({'plug_in': 217, 'charge_end': 487, 'unplug': 687, 'wh': 40392, 'price_per_kwh': 52, 'idle_grace': 10, 'idle_rate': 50, 'idle_cap': 3000, 'session_fee': 0, 'min_fee': 300}, {'energy': 2101, 'idle': 950, 'total': 3051}), ({'plug_in': 30, 'charge_end': 45, 'unplug': 400, 'wh': 800, 'price_per_kwh': 29, 'idle_grace': 10, 'idle_rate': 100, 'idle_cap': 1000, 'session_fee': 0, 'min_fee': 500}, {'energy': 24, 'idle': 1000, 'total': 1024}), ({'plug_in': 0, 'charge_end': 90, 'unplug': 106, 'wh': 12500, 'price_per_kwh': 35, 'idle_grace': 15, 'idle_rate': 50, 'idle_cap': 2000, 'session_fee': 100, 'min_fee': 300}, {'energy': 438, 'idle': 50, 'total': 588}), ({'plug_in': 417, 'charge_end': 599, 'unplug': 604, 'wh': 38888, 'price_per_kwh': 29, 'idle_grace': 10, 'idle_rate': 40, 'idle_cap': 3000, 'session_fee': 150, 'min_fee': 300}, {'energy': 1128, 'idle': 0, 'total': 1278}), ({'plug_in': 468, 'charge_end': 517, 'unplug': 542, 'wh': 35685, 'price_per_kwh': 45, 'idle_grace': 15, 'idle_rate': 100, 'idle_cap': 1000, 'session_fee': 0, 'min_fee': 500}, {'energy': 1606, 'idle': 100, 'total': 1706})], [({'plug_in': 533, 'charge_end': 668, 'unplug': 684, 'wh': 20000, 'price_per_kwh': 52, 'idle_grace': 15, 'idle_rate': 50, 'idle_cap': 2000, 'session_fee': 150, 'min_fee': 500}, {'energy': 1040, 'idle': 50, 'total': 1240}), ({'plug_in': 0, 'charge_end': 90, 'unplug': 106, 'wh': 12500, 'price_per_kwh': 35, 'idle_grace': 15, 'idle_rate': 50, 'idle_cap': 2000, 'session_fee': 100, 'min_fee': 300}, {'energy': 438, 'idle': 50, 'total': 588}), ({'plug_in': 548, 'charge_end': 679, 'unplug': 679, 'wh': 46438, 'price_per_kwh': 52, 'idle_grace': 10, 'idle_rate': 40, 'idle_cap': 2000, 'session_fee': 150, 'min_fee': 200}, {'energy': 2415, 'idle': 0, 'total': 2565}), ({'plug_in': 295, 'charge_end': 514, 'unplug': 539, 'wh': 58607, 'price_per_kwh': 35, 'idle_grace': 10, 'idle_rate': 50, 'idle_cap': 3000, 'session_fee': 100, 'min_fee': 200}, {'energy': 2052, 'idle': 100, 'total': 2252}), ({'plug_in': 270, 'charge_end': 560, 'unplug': 620, 'wh': 13483, 'price_per_kwh': 29, 'idle_grace': 10, 'idle_rate': 50, 'idle_cap': 3000, 'session_fee': 0, 'min_fee': 300}, {'energy': 392, 'idle': 250, 'total': 642}), ({'plug_in': 503, 'charge_end': 781, 'unplug': 1181, 'wh': 23844, 'price_per_kwh': 35, 'idle_grace': 15, 'idle_rate': 100, 'idle_cap': 1000, 'session_fee': 100, 'min_fee': 200}, {'energy': 835, 'idle': 1000, 'total': 1935}), ({'plug_in': 30, 'charge_end': 45, 'unplug': 400, 'wh': 800, 'price_per_kwh': 29, 'idle_grace': 10, 'idle_rate': 100, 'idle_cap': 1000, 'session_fee': 0, 'min_fee': 500}, {'energy': 24, 'idle': 1000, 'total': 1024}), ({'plug_in': 422, 'charge_end': 604, 'unplug': 1004, 'wh': 58741, 'price_per_kwh': 45, 'idle_grace': 10, 'idle_rate': 40, 'idle_cap': 1000, 'session_fee': 0, 'min_fee': 300}, {'energy': 2644, 'idle': 1000, 'total': 3644})], [({'plug_in': 141, 'charge_end': 394, 'unplug': 410, 'wh': 26923, 'price_per_kwh': 52, 'idle_grace': 10, 'idle_rate': 100, 'idle_cap': 2000, 'session_fee': 0, 'min_fee': 500}, {'energy': 1400, 'idle': 100, 'total': 1500}), ({'plug_in': 87, 'charge_end': 194, 'unplug': 194, 'wh': 20119, 'price_per_kwh': 45, 'idle_grace': 10, 'idle_rate': 100, 'idle_cap': 1000, 'session_fee': 100, 'min_fee': 500}, {'energy': 906, 'idle': 0, 'total': 1006}), ({'plug_in': 30, 'charge_end': 45, 'unplug': 400, 'wh': 800, 'price_per_kwh': 29, 'idle_grace': 10, 'idle_rate': 100, 'idle_cap': 1000, 'session_fee': 0, 'min_fee': 500}, {'energy': 24, 'idle': 1000, 'total': 1024}), ({'plug_in': 121, 'charge_end': 230, 'unplug': 230, 'wh': 2855, 'price_per_kwh': 45, 'idle_grace': 10, 'idle_rate': 40, 'idle_cap': 3000, 'session_fee': 100, 'min_fee': 500}, {'energy': 129, 'idle': 0, 'total': 500}), ({'plug_in': 116, 'charge_end': 342, 'unplug': 357, 'wh': 45320, 'price_per_kwh': 45, 'idle_grace': 10, 'idle_rate': 100, 'idle_cap': 1000, 'session_fee': 100, 'min_fee': 200}, {'energy': 2040, 'idle': 100, 'total': 2240}), ({'plug_in': 0, 'charge_end': 90, 'unplug': 106, 'wh': 12500, 'price_per_kwh': 35, 'idle_grace': 15, 'idle_rate': 50, 'idle_cap': 2000, 'session_fee': 100, 'min_fee': 300}, {'energy': 438, 'idle': 50, 'total': 588}), ({'plug_in': 304, 'charge_end': 530, 'unplug': 555, 'wh': 5327, 'price_per_kwh': 45, 'idle_grace': 15, 'idle_rate': 40, 'idle_cap': 2000, 'session_fee': 150, 'min_fee': 500}, {'energy': 240, 'idle': 40, 'total': 500}), ({'plug_in': 338, 'charge_end': 429, 'unplug': 429, 'wh': 18347, 'price_per_kwh': 29, 'idle_grace': 15, 'idle_rate': 40, 'idle_cap': 1000, 'session_fee': 150, 'min_fee': 200}, {'energy': 533, 'idle': 0, 'total': 683})], [({'plug_in': 391, 'charge_end': 417, 'unplug': 432, 'wh': 50407, 'price_per_kwh': 35, 'idle_grace': 10, 'idle_rate': 50, 'idle_cap': 2000, 'session_fee': 0, 'min_fee': 500}, {'energy': 1765, 'idle': 50, 'total': 1815}), ({'plug_in': 30, 'charge_end': 45, 'unplug': 400, 'wh': 800, 'price_per_kwh': 29, 'idle_grace': 10, 'idle_rate': 100, 'idle_cap': 1000, 'session_fee': 0, 'min_fee': 500}, {'energy': 24, 'idle': 1000, 'total': 1024}), ({'plug_in': 547, 'charge_end': 782, 'unplug': 782, 'wh': 23444, 'price_per_kwh': 45, 'idle_grace': 15, 'idle_rate': 50, 'idle_cap': 2000, 'session_fee': 150, 'min_fee': 300}, {'energy': 1055, 'idle': 0, 'total': 1205}), ({'plug_in': 424, 'charge_end': 695, 'unplug': 1095, 'wh': 19996, 'price_per_kwh': 29, 'idle_grace': 15, 'idle_rate': 100, 'idle_cap': 2000, 'session_fee': 150, 'min_fee': 200}, {'energy': 580, 'idle': 2000, 'total': 2730}), ({'plug_in': 596, 'charge_end': 767, 'unplug': 967, 'wh': 39532, 'price_per_kwh': 45, 'idle_grace': 15, 'idle_rate': 100, 'idle_cap': 1000, 'session_fee': 150, 'min_fee': 200}, {'energy': 1779, 'idle': 1000, 'total': 2929}), ({'plug_in': 445, 'charge_end': 682, 'unplug': 698, 'wh': 57925, 'price_per_kwh': 29, 'idle_grace': 10, 'idle_rate': 40, 'idle_cap': 1000, 'session_fee': 150, 'min_fee': 200}, {'energy': 1680, 'idle': 40, 'total': 1870}), ({'plug_in': 555, 'charge_end': 609, 'unplug': 634, 'wh': 10270, 'price_per_kwh': 35, 'idle_grace': 10, 'idle_rate': 100, 'idle_cap': 2000, 'session_fee': 100, 'min_fee': 300}, {'energy': 360, 'idle': 200, 'total': 660}), ({'plug_in': 0, 'charge_end': 90, 'unplug': 106, 'wh': 12500, 'price_per_kwh': 35, 'idle_grace': 15, 'idle_rate': 50, 'idle_cap': 2000, 'session_fee': 100, 'min_fee': 300}, {'energy': 438, 'idle': 50, 'total': 588})]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check('fee oracle' + ' %d' % i, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| fee oracle 0 | {'energy': 935, 'idle': 40, 'total': 1125} | {'energy': 935, 'idle': 0, 'total': 1085} | Failed |
| fee oracle 1 | {'energy': 1121, 'idle': 3000, 'total': 4221} | {'energy': 1121, 'idle': 3000, 'total': 4221} | Passed |
| fee oracle 2 | {'energy': 828, 'idle': 1000, 'total': 1928} | {'energy': 828, 'idle': 1000, 'total': 1928} | Passed |
| fee oracle 3 | {'energy': 438, 'idle': 100, 'total': 638} | {'energy': 438, 'idle': 50, 'total': 588} | Failed |
| fee oracle 4 | {'energy': 1316, 'idle': 0, 'total': 1416} | {'energy': 1316, 'idle': 0, 'total': 1416} | Passed |
| fee oracle 5 | {'energy': 24, 'idle': 1000, 'total': 1024} | {'energy': 24, 'idle': 1000, 'total': 1024} | Passed |
| fee oracle 6 | {'energy': 470, 'idle': 2000, 'total': 2470} | {'energy': 470, 'idle': 1950, 'total': 2420} | Failed |
| fee oracle 7 | {'energy': 400, 'idle': 300, 'total': 700} | {'energy': 400, 'idle': 200, 'total': 600} | Failed |
SHA-256 / 732ec46ebec221fe96f24d60b5b9ac99b81e856eacb263456e93ee5f3278052d
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
energy = -(-x['wh'] * x['price_per_kwh'] // 1000)
idle = (x['unplug'] - x['charge_end'] if x['unplug'] - x['charge_end'] > x['idle_grace'] else 0)
idle_fee = min(x['idle_cap'], -(-idle // 10) * x['idle_rate'])
total = x['session_fee'] + energy + idle_fee
return {'energy': energy, 'idle': idle_fee, 'total': max(x['min_fee'], total)}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[({'plug_in': 400, 'charge_end': 430, 'unplug': 440, 'wh': 26712, 'price_per_kwh': 35, 'idle_grace': 10, 'idle_rate': 40, 'idle_cap': 1000, 'session_fee': 150, 'min_fee': 200}, {'energy': 935, 'idle': 0, 'total': 1085}), ({'plug_in': 443, 'charge_end': 621, 'unplug': 1021, 'wh': 32003, 'price_per_kwh': 35, 'idle_grace': 10, 'idle_rate': 100, 'idle_cap': 3000, 'session_fee': 100, 'min_fee': 500}, {'energy': 1121, 'idle': 3000, 'total': 4221}), ({'plug_in': 178, 'charge_end': 431, 'unplug': 831, 'wh': 23652, 'price_per_kwh': 35, 'idle_grace': 15, 'idle_rate': 50, 'idle_cap': 1000, 'session_fee': 100, 'min_fee': 200}, {'energy': 828, 'idle': 1000, 'total': 1928}), ({'plug_in': 0, 'charge_end': 90, 'unplug': 106, 'wh': 12500, 'price_per_kwh': 35, 'idle_grace': 15, 'idle_rate': 50, 'idle_cap': 2000, 'session_fee': 100, 'min_fee': 300}, {'energy': 438, 'idle': 50, 'total': 588}), ({'plug_in': 24, 'charge_end': 82, 'unplug': 82, 'wh': 29231, 'price_per_kwh': 45, 'idle_grace': 15, 'idle_rate': 100, 'idle_cap': 3000, 'session_fee': 100, 'min_fee': 300}, {'energy': 1316, 'idle': 0, 'total': 1416}), ({'plug_in': 30, 'charge_end': 45, 'unplug': 400, 'wh': 800, 'price_per_kwh': 29, 'idle_grace': 10, 'idle_rate': 100, 'idle_cap': 1000, 'session_fee': 0, 'min_fee': 500}, {'energy': 24, 'idle': 1000, 'total': 1024}), ({'plug_in': 321, 'charge_end': 549, 'unplug': 949, 'wh': 16186, 'price_per_kwh': 29, 'idle_grace': 10, 'idle_rate': 50, 'idle_cap': 3000, 'session_fee': 0, 'min_fee': 300}, {'energy': 470, 'idle': 1950, 'total': 2420}), ({'plug_in': 445, 'charge_end': 719, 'unplug': 744, 'wh': 13785, 'price_per_kwh': 29, 'idle_grace': 10, 'idle_rate': 100, 'idle_cap': 2000, 'session_fee': 0, 'min_fee': 500}, {'energy': 400, 'idle': 200, 'total': 600})], [({'plug_in': 143, 'charge_end': 442, 'unplug': 842, 'wh': 33904, 'price_per_kwh': 29, 'idle_grace': 15, 'idle_rate': 40, 'idle_cap': 1000, 'session_fee': 150, 'min_fee': 200}, {'energy': 984, 'idle': 1000, 'total': 2134}), ({'plug_in': 468, 'charge_end': 648, 'unplug': 648, 'wh': 29211, 'price_per_kwh': 45, 'idle_grace': 15, 'idle_rate': 100, 'idle_cap': 2000, 'session_fee': 150, 'min_fee': 500}, {'energy': 1315, 'idle': 0, 'total': 1465}), ({'plug_in': 244, 'charge_end': 536, 'unplug': 736, 'wh': 50241, 'price_per_kwh': 29, 'idle_grace': 15, 'idle_rate': 100, 'idle_cap': 1000, 'session_fee': 150, 'min_fee': 200}, {'energy': 1457, 'idle': 1000, 'total': 2607}), ({'plug_in': 217, 'charge_end': 487, 'unplug': 687, 'wh': 40392, 'price_per_kwh': 52, 'idle_grace': 10, 'idle_rate': 50, 'idle_cap': 3000, 'session_fee': 0, 'min_fee': 300}, {'energy': 2101, 'idle': 950, 'total': 3051}), ({'plug_in': 30, 'charge_end': 45, 'unplug': 400, 'wh': 800, 'price_per_kwh': 29, 'idle_grace': 10, 'idle_rate': 100, 'idle_cap': 1000, 'session_fee': 0, 'min_fee': 500}, {'energy': 24, 'idle': 1000, 'total': 1024}), ({'plug_in': 0, 'charge_end': 90, 'unplug': 106, 'wh': 12500, 'price_per_kwh': 35, 'idle_grace': 15, 'idle_rate': 50, 'idle_cap': 2000, 'session_fee': 100, 'min_fee': 300}, {'energy': 438, 'idle': 50, 'total': 588}), ({'plug_in': 417, 'charge_end': 599, 'unplug': 604, 'wh': 38888, 'price_per_kwh': 29, 'idle_grace': 10, 'idle_rate': 40, 'idle_cap': 3000, 'session_fee': 150, 'min_fee': 300}, {'energy': 1128, 'idle': 0, 'total': 1278}), ({'plug_in': 468, 'charge_end': 517, 'unplug': 542, 'wh': 35685, 'price_per_kwh': 45, 'idle_grace': 15, 'idle_rate': 100, 'idle_cap': 1000, 'session_fee': 0, 'min_fee': 500}, {'energy': 1606, 'idle': 100, 'total': 1706})], [({'plug_in': 533, 'charge_end': 668, 'unplug': 684, 'wh': 20000, 'price_per_kwh': 52, 'idle_grace': 15, 'idle_rate': 50, 'idle_cap': 2000, 'session_fee': 150, 'min_fee': 500}, {'energy': 1040, 'idle': 50, 'total': 1240}), ({'plug_in': 0, 'charge_end': 90, 'unplug': 106, 'wh': 12500, 'price_per_kwh': 35, 'idle_grace': 15, 'idle_rate': 50, 'idle_cap': 2000, 'session_fee': 100, 'min_fee': 300}, {'energy': 438, 'idle': 50, 'total': 588}), ({'plug_in': 548, 'charge_end': 679, 'unplug': 679, 'wh': 46438, 'price_per_kwh': 52, 'idle_grace': 10, 'idle_rate': 40, 'idle_cap': 2000, 'session_fee': 150, 'min_fee': 200}, {'energy': 2415, 'idle': 0, 'total': 2565}), ({'plug_in': 295, 'charge_end': 514, 'unplug': 539, 'wh': 58607, 'price_per_kwh': 35, 'idle_grace': 10, 'idle_rate': 50, 'idle_cap': 3000, 'session_fee': 100, 'min_fee': 200}, {'energy': 2052, 'idle': 100, 'total': 2252}), ({'plug_in': 270, 'charge_end': 560, 'unplug': 620, 'wh': 13483, 'price_per_kwh': 29, 'idle_grace': 10, 'idle_rate': 50, 'idle_cap': 3000, 'session_fee': 0, 'min_fee': 300}, {'energy': 392, 'idle': 250, 'total': 642}), ({'plug_in': 503, 'charge_end': 781, 'unplug': 1181, 'wh': 23844, 'price_per_kwh': 35, 'idle_grace': 15, 'idle_rate': 100, 'idle_cap': 1000, 'session_fee': 100, 'min_fee': 200}, {'energy': 835, 'idle': 1000, 'total': 1935}), ({'plug_in': 30, 'charge_end': 45, 'unplug': 400, 'wh': 800, 'price_per_kwh': 29, 'idle_grace': 10, 'idle_rate': 100, 'idle_cap': 1000, 'session_fee': 0, 'min_fee': 500}, {'energy': 24, 'idle': 1000, 'total': 1024}), ({'plug_in': 422, 'charge_end': 604, 'unplug': 1004, 'wh': 58741, 'price_per_kwh': 45, 'idle_grace': 10, 'idle_rate': 40, 'idle_cap': 1000, 'session_fee': 0, 'min_fee': 300}, {'energy': 2644, 'idle': 1000, 'total': 3644})], [({'plug_in': 141, 'charge_end': 394, 'unplug': 410, 'wh': 26923, 'price_per_kwh': 52, 'idle_grace': 10, 'idle_rate': 100, 'idle_cap': 2000, 'session_fee': 0, 'min_fee': 500}, {'energy': 1400, 'idle': 100, 'total': 1500}), ({'plug_in': 87, 'charge_end': 194, 'unplug': 194, 'wh': 20119, 'price_per_kwh': 45, 'idle_grace': 10, 'idle_rate': 100, 'idle_cap': 1000, 'session_fee': 100, 'min_fee': 500}, {'energy': 906, 'idle': 0, 'total': 1006}), ({'plug_in': 30, 'charge_end': 45, 'unplug': 400, 'wh': 800, 'price_per_kwh': 29, 'idle_grace': 10, 'idle_rate': 100, 'idle_cap': 1000, 'session_fee': 0, 'min_fee': 500}, {'energy': 24, 'idle': 1000, 'total': 1024}), ({'plug_in': 121, 'charge_end': 230, 'unplug': 230, 'wh': 2855, 'price_per_kwh': 45, 'idle_grace': 10, 'idle_rate': 40, 'idle_cap': 3000, 'session_fee': 100, 'min_fee': 500}, {'energy': 129, 'idle': 0, 'total': 500}), ({'plug_in': 116, 'charge_end': 342, 'unplug': 357, 'wh': 45320, 'price_per_kwh': 45, 'idle_grace': 10, 'idle_rate': 100, 'idle_cap': 1000, 'session_fee': 100, 'min_fee': 200}, {'energy': 2040, 'idle': 100, 'total': 2240}), ({'plug_in': 0, 'charge_end': 90, 'unplug': 106, 'wh': 12500, 'price_per_kwh': 35, 'idle_grace': 15, 'idle_rate': 50, 'idle_cap': 2000, 'session_fee': 100, 'min_fee': 300}, {'energy': 438, 'idle': 50, 'total': 588}), ({'plug_in': 304, 'charge_end': 530, 'unplug': 555, 'wh': 5327, 'price_per_kwh': 45, 'idle_grace': 15, 'idle_rate': 40, 'idle_cap': 2000, 'session_fee': 150, 'min_fee': 500}, {'energy': 240, 'idle': 40, 'total': 500}), ({'plug_in': 338, 'charge_end': 429, 'unplug': 429, 'wh': 18347, 'price_per_kwh': 29, 'idle_grace': 15, 'idle_rate': 40, 'idle_cap': 1000, 'session_fee': 150, 'min_fee': 200}, {'energy': 533, 'idle': 0, 'total': 683})], [({'plug_in': 391, 'charge_end': 417, 'unplug': 432, 'wh': 50407, 'price_per_kwh': 35, 'idle_grace': 10, 'idle_rate': 50, 'idle_cap': 2000, 'session_fee': 0, 'min_fee': 500}, {'energy': 1765, 'idle': 50, 'total': 1815}), ({'plug_in': 30, 'charge_end': 45, 'unplug': 400, 'wh': 800, 'price_per_kwh': 29, 'idle_grace': 10, 'idle_rate': 100, 'idle_cap': 1000, 'session_fee': 0, 'min_fee': 500}, {'energy': 24, 'idle': 1000, 'total': 1024}), ({'plug_in': 547, 'charge_end': 782, 'unplug': 782, 'wh': 23444, 'price_per_kwh': 45, 'idle_grace': 15, 'idle_rate': 50, 'idle_cap': 2000, 'session_fee': 150, 'min_fee': 300}, {'energy': 1055, 'idle': 0, 'total': 1205}), ({'plug_in': 424, 'charge_end': 695, 'unplug': 1095, 'wh': 19996, 'price_per_kwh': 29, 'idle_grace': 15, 'idle_rate': 100, 'idle_cap': 2000, 'session_fee': 150, 'min_fee': 200}, {'energy': 580, 'idle': 2000, 'total': 2730}), ({'plug_in': 596, 'charge_end': 767, 'unplug': 967, 'wh': 39532, 'price_per_kwh': 45, 'idle_grace': 15, 'idle_rate': 100, 'idle_cap': 1000, 'session_fee': 150, 'min_fee': 200}, {'energy': 1779, 'idle': 1000, 'total': 2929}), ({'plug_in': 445, 'charge_end': 682, 'unplug': 698, 'wh': 57925, 'price_per_kwh': 29, 'idle_grace': 10, 'idle_rate': 40, 'idle_cap': 1000, 'session_fee': 150, 'min_fee': 200}, {'energy': 1680, 'idle': 40, 'total': 1870}), ({'plug_in': 555, 'charge_end': 609, 'unplug': 634, 'wh': 10270, 'price_per_kwh': 35, 'idle_grace': 10, 'idle_rate': 100, 'idle_cap': 2000, 'session_fee': 100, 'min_fee': 300}, {'energy': 360, 'idle': 200, 'total': 660}), ({'plug_in': 0, 'charge_end': 90, 'unplug': 106, 'wh': 12500, 'price_per_kwh': 35, 'idle_grace': 15, 'idle_rate': 50, 'idle_cap': 2000, 'session_fee': 100, 'min_fee': 300}, {'energy': 438, 'idle': 50, 'total': 588})]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check('fee oracle' + ' %d' % i, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| fee oracle 0 | {'energy': 935, 'idle': 0, 'total': 1085} | {'energy': 935, 'idle': 0, 'total': 1085} | Passed |
| fee oracle 1 | {'energy': 1121, 'idle': 3000, 'total': 4221} | {'energy': 1121, 'idle': 3000, 'total': 4221} | Passed |
| fee oracle 2 | {'energy': 828, 'idle': 1000, 'total': 1928} | {'energy': 828, 'idle': 1000, 'total': 1928} | Passed |
| fee oracle 3 | {'energy': 438, 'idle': 100, 'total': 638} | {'energy': 438, 'idle': 50, 'total': 588} | Failed |
| fee oracle 4 | {'energy': 1316, 'idle': 0, 'total': 1416} | {'energy': 1316, 'idle': 0, 'total': 1416} | Passed |
| fee oracle 5 | {'energy': 24, 'idle': 1000, 'total': 1024} | {'energy': 24, 'idle': 1000, 'total': 1024} | Passed |
| fee oracle 6 | {'energy': 470, 'idle': 2000, 'total': 2470} | {'energy': 470, 'idle': 1950, 'total': 2420} | Failed |
| fee oracle 7 | {'energy': 400, 'idle': 300, 'total': 700} | {'energy': 400, 'idle': 200, 'total': 600} | Failed |
SHA-256 / 1d0a889154dbddb0d3164b546121f6ff6fae3767165bdc46f1e0b09ff561de3e
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
energy = -(-x['wh'] * x['price_per_kwh'] // 1000)
idle = max(0, x['unplug'] - x['charge_end'] - x['idle_grace'])
idle_fee = min(x['idle_cap'], -(-idle // 10) * x['idle_rate'])
total = x['session_fee'] + energy + idle_fee
return {'energy': energy, 'idle': idle_fee, 'total': max(x['min_fee'], total)}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[({'plug_in': 400, 'charge_end': 430, 'unplug': 440, 'wh': 26712, 'price_per_kwh': 35, 'idle_grace': 10, 'idle_rate': 40, 'idle_cap': 1000, 'session_fee': 150, 'min_fee': 200}, {'energy': 935, 'idle': 0, 'total': 1085}), ({'plug_in': 443, 'charge_end': 621, 'unplug': 1021, 'wh': 32003, 'price_per_kwh': 35, 'idle_grace': 10, 'idle_rate': 100, 'idle_cap': 3000, 'session_fee': 100, 'min_fee': 500}, {'energy': 1121, 'idle': 3000, 'total': 4221}), ({'plug_in': 178, 'charge_end': 431, 'unplug': 831, 'wh': 23652, 'price_per_kwh': 35, 'idle_grace': 15, 'idle_rate': 50, 'idle_cap': 1000, 'session_fee': 100, 'min_fee': 200}, {'energy': 828, 'idle': 1000, 'total': 1928}), ({'plug_in': 0, 'charge_end': 90, 'unplug': 106, 'wh': 12500, 'price_per_kwh': 35, 'idle_grace': 15, 'idle_rate': 50, 'idle_cap': 2000, 'session_fee': 100, 'min_fee': 300}, {'energy': 438, 'idle': 50, 'total': 588}), ({'plug_in': 24, 'charge_end': 82, 'unplug': 82, 'wh': 29231, 'price_per_kwh': 45, 'idle_grace': 15, 'idle_rate': 100, 'idle_cap': 3000, 'session_fee': 100, 'min_fee': 300}, {'energy': 1316, 'idle': 0, 'total': 1416}), ({'plug_in': 30, 'charge_end': 45, 'unplug': 400, 'wh': 800, 'price_per_kwh': 29, 'idle_grace': 10, 'idle_rate': 100, 'idle_cap': 1000, 'session_fee': 0, 'min_fee': 500}, {'energy': 24, 'idle': 1000, 'total': 1024}), ({'plug_in': 321, 'charge_end': 549, 'unplug': 949, 'wh': 16186, 'price_per_kwh': 29, 'idle_grace': 10, 'idle_rate': 50, 'idle_cap': 3000, 'session_fee': 0, 'min_fee': 300}, {'energy': 470, 'idle': 1950, 'total': 2420}), ({'plug_in': 445, 'charge_end': 719, 'unplug': 744, 'wh': 13785, 'price_per_kwh': 29, 'idle_grace': 10, 'idle_rate': 100, 'idle_cap': 2000, 'session_fee': 0, 'min_fee': 500}, {'energy': 400, 'idle': 200, 'total': 600})], [({'plug_in': 143, 'charge_end': 442, 'unplug': 842, 'wh': 33904, 'price_per_kwh': 29, 'idle_grace': 15, 'idle_rate': 40, 'idle_cap': 1000, 'session_fee': 150, 'min_fee': 200}, {'energy': 984, 'idle': 1000, 'total': 2134}), ({'plug_in': 468, 'charge_end': 648, 'unplug': 648, 'wh': 29211, 'price_per_kwh': 45, 'idle_grace': 15, 'idle_rate': 100, 'idle_cap': 2000, 'session_fee': 150, 'min_fee': 500}, {'energy': 1315, 'idle': 0, 'total': 1465}), ({'plug_in': 244, 'charge_end': 536, 'unplug': 736, 'wh': 50241, 'price_per_kwh': 29, 'idle_grace': 15, 'idle_rate': 100, 'idle_cap': 1000, 'session_fee': 150, 'min_fee': 200}, {'energy': 1457, 'idle': 1000, 'total': 2607}), ({'plug_in': 217, 'charge_end': 487, 'unplug': 687, 'wh': 40392, 'price_per_kwh': 52, 'idle_grace': 10, 'idle_rate': 50, 'idle_cap': 3000, 'session_fee': 0, 'min_fee': 300}, {'energy': 2101, 'idle': 950, 'total': 3051}), ({'plug_in': 30, 'charge_end': 45, 'unplug': 400, 'wh': 800, 'price_per_kwh': 29, 'idle_grace': 10, 'idle_rate': 100, 'idle_cap': 1000, 'session_fee': 0, 'min_fee': 500}, {'energy': 24, 'idle': 1000, 'total': 1024}), ({'plug_in': 0, 'charge_end': 90, 'unplug': 106, 'wh': 12500, 'price_per_kwh': 35, 'idle_grace': 15, 'idle_rate': 50, 'idle_cap': 2000, 'session_fee': 100, 'min_fee': 300}, {'energy': 438, 'idle': 50, 'total': 588}), ({'plug_in': 417, 'charge_end': 599, 'unplug': 604, 'wh': 38888, 'price_per_kwh': 29, 'idle_grace': 10, 'idle_rate': 40, 'idle_cap': 3000, 'session_fee': 150, 'min_fee': 300}, {'energy': 1128, 'idle': 0, 'total': 1278}), ({'plug_in': 468, 'charge_end': 517, 'unplug': 542, 'wh': 35685, 'price_per_kwh': 45, 'idle_grace': 15, 'idle_rate': 100, 'idle_cap': 1000, 'session_fee': 0, 'min_fee': 500}, {'energy': 1606, 'idle': 100, 'total': 1706})], [({'plug_in': 533, 'charge_end': 668, 'unplug': 684, 'wh': 20000, 'price_per_kwh': 52, 'idle_grace': 15, 'idle_rate': 50, 'idle_cap': 2000, 'session_fee': 150, 'min_fee': 500}, {'energy': 1040, 'idle': 50, 'total': 1240}), ({'plug_in': 0, 'charge_end': 90, 'unplug': 106, 'wh': 12500, 'price_per_kwh': 35, 'idle_grace': 15, 'idle_rate': 50, 'idle_cap': 2000, 'session_fee': 100, 'min_fee': 300}, {'energy': 438, 'idle': 50, 'total': 588}), ({'plug_in': 548, 'charge_end': 679, 'unplug': 679, 'wh': 46438, 'price_per_kwh': 52, 'idle_grace': 10, 'idle_rate': 40, 'idle_cap': 2000, 'session_fee': 150, 'min_fee': 200}, {'energy': 2415, 'idle': 0, 'total': 2565}), ({'plug_in': 295, 'charge_end': 514, 'unplug': 539, 'wh': 58607, 'price_per_kwh': 35, 'idle_grace': 10, 'idle_rate': 50, 'idle_cap': 3000, 'session_fee': 100, 'min_fee': 200}, {'energy': 2052, 'idle': 100, 'total': 2252}), ({'plug_in': 270, 'charge_end': 560, 'unplug': 620, 'wh': 13483, 'price_per_kwh': 29, 'idle_grace': 10, 'idle_rate': 50, 'idle_cap': 3000, 'session_fee': 0, 'min_fee': 300}, {'energy': 392, 'idle': 250, 'total': 642}), ({'plug_in': 503, 'charge_end': 781, 'unplug': 1181, 'wh': 23844, 'price_per_kwh': 35, 'idle_grace': 15, 'idle_rate': 100, 'idle_cap': 1000, 'session_fee': 100, 'min_fee': 200}, {'energy': 835, 'idle': 1000, 'total': 1935}), ({'plug_in': 30, 'charge_end': 45, 'unplug': 400, 'wh': 800, 'price_per_kwh': 29, 'idle_grace': 10, 'idle_rate': 100, 'idle_cap': 1000, 'session_fee': 0, 'min_fee': 500}, {'energy': 24, 'idle': 1000, 'total': 1024}), ({'plug_in': 422, 'charge_end': 604, 'unplug': 1004, 'wh': 58741, 'price_per_kwh': 45, 'idle_grace': 10, 'idle_rate': 40, 'idle_cap': 1000, 'session_fee': 0, 'min_fee': 300}, {'energy': 2644, 'idle': 1000, 'total': 3644})], [({'plug_in': 141, 'charge_end': 394, 'unplug': 410, 'wh': 26923, 'price_per_kwh': 52, 'idle_grace': 10, 'idle_rate': 100, 'idle_cap': 2000, 'session_fee': 0, 'min_fee': 500}, {'energy': 1400, 'idle': 100, 'total': 1500}), ({'plug_in': 87, 'charge_end': 194, 'unplug': 194, 'wh': 20119, 'price_per_kwh': 45, 'idle_grace': 10, 'idle_rate': 100, 'idle_cap': 1000, 'session_fee': 100, 'min_fee': 500}, {'energy': 906, 'idle': 0, 'total': 1006}), ({'plug_in': 30, 'charge_end': 45, 'unplug': 400, 'wh': 800, 'price_per_kwh': 29, 'idle_grace': 10, 'idle_rate': 100, 'idle_cap': 1000, 'session_fee': 0, 'min_fee': 500}, {'energy': 24, 'idle': 1000, 'total': 1024}), ({'plug_in': 121, 'charge_end': 230, 'unplug': 230, 'wh': 2855, 'price_per_kwh': 45, 'idle_grace': 10, 'idle_rate': 40, 'idle_cap': 3000, 'session_fee': 100, 'min_fee': 500}, {'energy': 129, 'idle': 0, 'total': 500}), ({'plug_in': 116, 'charge_end': 342, 'unplug': 357, 'wh': 45320, 'price_per_kwh': 45, 'idle_grace': 10, 'idle_rate': 100, 'idle_cap': 1000, 'session_fee': 100, 'min_fee': 200}, {'energy': 2040, 'idle': 100, 'total': 2240}), ({'plug_in': 0, 'charge_end': 90, 'unplug': 106, 'wh': 12500, 'price_per_kwh': 35, 'idle_grace': 15, 'idle_rate': 50, 'idle_cap': 2000, 'session_fee': 100, 'min_fee': 300}, {'energy': 438, 'idle': 50, 'total': 588}), ({'plug_in': 304, 'charge_end': 530, 'unplug': 555, 'wh': 5327, 'price_per_kwh': 45, 'idle_grace': 15, 'idle_rate': 40, 'idle_cap': 2000, 'session_fee': 150, 'min_fee': 500}, {'energy': 240, 'idle': 40, 'total': 500}), ({'plug_in': 338, 'charge_end': 429, 'unplug': 429, 'wh': 18347, 'price_per_kwh': 29, 'idle_grace': 15, 'idle_rate': 40, 'idle_cap': 1000, 'session_fee': 150, 'min_fee': 200}, {'energy': 533, 'idle': 0, 'total': 683})], [({'plug_in': 391, 'charge_end': 417, 'unplug': 432, 'wh': 50407, 'price_per_kwh': 35, 'idle_grace': 10, 'idle_rate': 50, 'idle_cap': 2000, 'session_fee': 0, 'min_fee': 500}, {'energy': 1765, 'idle': 50, 'total': 1815}), ({'plug_in': 30, 'charge_end': 45, 'unplug': 400, 'wh': 800, 'price_per_kwh': 29, 'idle_grace': 10, 'idle_rate': 100, 'idle_cap': 1000, 'session_fee': 0, 'min_fee': 500}, {'energy': 24, 'idle': 1000, 'total': 1024}), ({'plug_in': 547, 'charge_end': 782, 'unplug': 782, 'wh': 23444, 'price_per_kwh': 45, 'idle_grace': 15, 'idle_rate': 50, 'idle_cap': 2000, 'session_fee': 150, 'min_fee': 300}, {'energy': 1055, 'idle': 0, 'total': 1205}), ({'plug_in': 424, 'charge_end': 695, 'unplug': 1095, 'wh': 19996, 'price_per_kwh': 29, 'idle_grace': 15, 'idle_rate': 100, 'idle_cap': 2000, 'session_fee': 150, 'min_fee': 200}, {'energy': 580, 'idle': 2000, 'total': 2730}), ({'plug_in': 596, 'charge_end': 767, 'unplug': 967, 'wh': 39532, 'price_per_kwh': 45, 'idle_grace': 15, 'idle_rate': 100, 'idle_cap': 1000, 'session_fee': 150, 'min_fee': 200}, {'energy': 1779, 'idle': 1000, 'total': 2929}), ({'plug_in': 445, 'charge_end': 682, 'unplug': 698, 'wh': 57925, 'price_per_kwh': 29, 'idle_grace': 10, 'idle_rate': 40, 'idle_cap': 1000, 'session_fee': 150, 'min_fee': 200}, {'energy': 1680, 'idle': 40, 'total': 1870}), ({'plug_in': 555, 'charge_end': 609, 'unplug': 634, 'wh': 10270, 'price_per_kwh': 35, 'idle_grace': 10, 'idle_rate': 100, 'idle_cap': 2000, 'session_fee': 100, 'min_fee': 300}, {'energy': 360, 'idle': 200, 'total': 660}), ({'plug_in': 0, 'charge_end': 90, 'unplug': 106, 'wh': 12500, 'price_per_kwh': 35, 'idle_grace': 15, 'idle_rate': 50, 'idle_cap': 2000, 'session_fee': 100, 'min_fee': 300}, {'energy': 438, 'idle': 50, 'total': 588})]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check('fee oracle' + ' %d' % i, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| fee oracle 0 | {'energy': 935, 'idle': 0, 'total': 1085} | {'energy': 935, 'idle': 0, 'total': 1085} | Passed |
| fee oracle 1 | {'energy': 1121, 'idle': 3000, 'total': 4221} | {'energy': 1121, 'idle': 3000, 'total': 4221} | Passed |
| fee oracle 2 | {'energy': 828, 'idle': 1000, 'total': 1928} | {'energy': 828, 'idle': 1000, 'total': 1928} | Passed |
| fee oracle 3 | {'energy': 438, 'idle': 50, 'total': 588} | {'energy': 438, 'idle': 50, 'total': 588} | Passed |
| fee oracle 4 | {'energy': 1316, 'idle': 0, 'total': 1416} | {'energy': 1316, 'idle': 0, 'total': 1416} | Passed |
| fee oracle 5 | {'energy': 24, 'idle': 1000, 'total': 1024} | {'energy': 24, 'idle': 1000, 'total': 1024} | Passed |
| fee oracle 6 | {'energy': 470, 'idle': 1950, 'total': 2420} | {'energy': 470, 'idle': 1950, 'total': 2420} | Passed |
| fee oracle 7 | {'energy': 400, 'idle': 200, 'total': 600} | {'energy': 400, 'idle': 200, 'total': 600} | Passed |
SHA-256 / 3e2583d4f905bcc0e00b887d6077940bb00167c2075f1133fe57eb2339249558
Verification & scope
A deterministic, bounded toy model with a stipulated contract; it makes no claim of conformance to any agency manual or standard. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.
Observations recorded using Python 3.12.14 at 2026-09-29T14:48:04.742485+00:00.
Case digest / 33d44bbd69f2c567d377a838e2fe2ee03eeae378123693aa229c36f69415030a