FA-68361 / Toll and parking fee computation / Open access
Garage hourly fee with grace and daily maximum: the lost ticket fee replaces a larger computed fee · case 01
Garage hourly fee with grace and daily maximum returns a wrong result when the lost ticket fee replaces a larger computed fee.
ROOT CAUSE
A lost ticket on a long stay pays only the flat lost fee instead of the greater of the two.
VERIFIED REPAIR
Restore the lost ticket rule rule so that the step reads `fee = max(fee, x['lost_fee'])`.
Unsuccessful approach: Adding the lost fee to the computed fee double charges.
Case contract
Input {entry, exit (absolute minutes), grace, hourly, daily_max, lost_ticket, lost_fee}; cents. Exit before entry is 'invalid'. A stay no longer than grace is free (grace is not deducted from longer stays). Otherwise each full 1440-minute block costs daily_max and the remainder costs hourly per started hour, capped at daily_max. A lost ticket pays the greater of the computed fee and lost_fee.
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):
if x['exit'] < x['entry']:
return 'invalid'
dur = x['exit'] - x['entry']
if dur <= x['grace']:
fee = 0
else:
days, rem = divmod(dur, 1440)
fee = days * x['daily_max'] + min(x['daily_max'], -(-rem // 60) * x['hourly'])
if x['lost_ticket']:
fee = x['lost_fee']
return fee
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[({'entry': 1082, 'exit': 5693, 'grace': 10, 'hourly': 450, 'daily_max': 1500, 'lost_ticket': True, 'lost_fee': 2500}, 6000), ({'entry': 60, 'exit': 240, 'grace': 15, 'hourly': 450, 'daily_max': 2400, 'lost_ticket': False, 'lost_fee': 3000}, 1350), ({'entry': 184, 'exit': 280, 'grace': 20, 'hourly': 300, 'daily_max': 2000, 'lost_ticket': True, 'lost_fee': 3000}, 3000), ({'entry': 2107, 'exit': 2568, 'grace': 10, 'hourly': 200, 'daily_max': 2000, 'lost_ticket': True, 'lost_fee': 3000}, 3000), ({'entry': 0, 'exit': 1560, 'grace': 10, 'hourly': 300, 'daily_max': 2000, 'lost_ticket': False, 'lost_fee': 2500}, 2600), ({'entry': 2424, 'exit': 6728, 'grace': 15, 'hourly': 450, 'daily_max': 1500, 'lost_ticket': True, 'lost_fee': 3000}, 4500), ({'entry': 2475, 'exit': 5355, 'grace': 20, 'hourly': 450, 'daily_max': 1500, 'lost_ticket': True, 'lost_fee': 2500}, 3000), ({'entry': 500, 'exit': 500, 'grace': 0, 'hourly': 300, 'daily_max': 2000, 'lost_ticket': True, 'lost_fee': 2500}, 2500)], [({'entry': 124, 'exit': 143, 'grace': 0, 'hourly': 200, 'daily_max': 1500, 'lost_ticket': True, 'lost_fee': 2500}, 2500), ({'entry': 318, 'exit': 5189, 'grace': 0, 'hourly': 300, 'daily_max': 2400, 'lost_ticket': True, 'lost_fee': 2500}, 9600), ({'entry': 927, 'exit': 1380, 'grace': 10, 'hourly': 300, 'daily_max': 2000, 'lost_ticket': True, 'lost_fee': 3000}, 3000), ({'entry': 60, 'exit': 240, 'grace': 15, 'hourly': 450, 'daily_max': 2400, 'lost_ticket': False, 'lost_fee': 3000}, 1350), ({'entry': 500, 'exit': 500, 'grace': 0, 'hourly': 300, 'daily_max': 2000, 'lost_ticket': True, 'lost_fee': 2500}, 2500), ({'entry': 69, 'exit': 4389, 'grace': 10, 'hourly': 450, 'daily_max': 1500, 'lost_ticket': True, 'lost_fee': 3000}, 4500), ({'entry': 648, 'exit': 2644, 'grace': 0, 'hourly': 300, 'daily_max': 2400, 'lost_ticket': True, 'lost_fee': 3000}, 4800), ({'entry': 0, 'exit': 1560, 'grace': 10, 'hourly': 300, 'daily_max': 2000, 'lost_ticket': False, 'lost_fee': 2500}, 2600)], [({'entry': 2135, 'exit': 5612, 'grace': 20, 'hourly': 300, 'daily_max': 2400, 'lost_ticket': True, 'lost_fee': 3000}, 7200), ({'entry': 166, 'exit': 2354, 'grace': 10, 'hourly': 450, 'daily_max': 1500, 'lost_ticket': True, 'lost_fee': 2500}, 3000), ({'entry': 0, 'exit': 1560, 'grace': 10, 'hourly': 300, 'daily_max': 2000, 'lost_ticket': False, 'lost_fee': 2500}, 2600), ({'entry': 1120, 'exit': 1138, 'grace': 10, 'hourly': 300, 'daily_max': 2000, 'lost_ticket': True, 'lost_fee': 2500}, 2500), ({'entry': 60, 'exit': 240, 'grace': 15, 'hourly': 450, 'daily_max': 2400, 'lost_ticket': False, 'lost_fee': 3000}, 1350), ({'entry': 429, 'exit': 683, 'grace': 20, 'hourly': 300, 'daily_max': 1500, 'lost_ticket': True, 'lost_fee': 2500}, 2500), ({'entry': 100, 'exit': 115, 'grace': 15, 'hourly': 300, 'daily_max': 2000, 'lost_ticket': False, 'lost_fee': 2500}, 0), ({'entry': 4, 'exit': 2884, 'grace': 20, 'hourly': 200, 'daily_max': 2400, 'lost_ticket': True, 'lost_fee': 3000}, 4800)], [({'entry': 2108, 'exit': 4988, 'grace': 20, 'hourly': 450, 'daily_max': 2000, 'lost_ticket': True, 'lost_fee': 2500}, 4000), ({'entry': 1675, 'exit': 6410, 'grace': 15, 'hourly': 450, 'daily_max': 1500, 'lost_ticket': True, 'lost_fee': 2500}, 6000), ({'entry': 60, 'exit': 240, 'grace': 15, 'hourly': 450, 'daily_max': 2400, 'lost_ticket': False, 'lost_fee': 3000}, 1350), ({'entry': 2388, 'exit': 2625, 'grace': 15, 'hourly': 200, 'daily_max': 2400, 'lost_ticket': True, 'lost_fee': 2500}, 2500), ({'entry': 903, 'exit': 4042, 'grace': 15, 'hourly': 200, 'daily_max': 1500, 'lost_ticket': True, 'lost_fee': 3000}, 4000), ({'entry': 1659, 'exit': 2168, 'grace': 15, 'hourly': 450, 'daily_max': 2400, 'lost_ticket': True, 'lost_fee': 3000}, 3000), ({'entry': 100, 'exit': 115, 'grace': 15, 'hourly': 300, 'daily_max': 2000, 'lost_ticket': False, 'lost_fee': 2500}, 0), ({'entry': 0, 'exit': 1560, 'grace': 10, 'hourly': 300, 'daily_max': 2000, 'lost_ticket': False, 'lost_fee': 2500}, 2600)], [({'entry': 60, 'exit': 240, 'grace': 15, 'hourly': 450, 'daily_max': 2400, 'lost_ticket': False, 'lost_fee': 3000}, 1350), ({'entry': 445, 'exit': 3325, 'grace': 0, 'hourly': 200, 'daily_max': 2400, 'lost_ticket': True, 'lost_fee': 2500}, 4800), ({'entry': 500, 'exit': 500, 'grace': 0, 'hourly': 300, 'daily_max': 2000, 'lost_ticket': True, 'lost_fee': 2500}, 2500), ({'entry': 1568, 'exit': 2228, 'grace': 15, 'hourly': 300, 'daily_max': 1500, 'lost_ticket': True, 'lost_fee': 2500}, 2500), ({'entry': 100, 'exit': 115, 'grace': 15, 'hourly': 300, 'daily_max': 2000, 'lost_ticket': False, 'lost_fee': 2500}, 0), ({'entry': 2826, 'exit': 7146, 'grace': 0, 'hourly': 300, 'daily_max': 2400, 'lost_ticket': True, 'lost_fee': 3000}, 7200), ({'entry': 2274, 'exit': 5519, 'grace': 15, 'hourly': 300, 'daily_max': 1500, 'lost_ticket': True, 'lost_fee': 2500}, 4500), ({'entry': 1853, 'exit': 1872, 'grace': 10, 'hourly': 200, 'daily_max': 2400, 'lost_ticket': True, 'lost_fee': 3000}, 3000)]]
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 | 2500 | 6000 | Failed |
| fee oracle 1 | 1350 | 1350 | Passed |
| fee oracle 2 | 3000 | 3000 | Passed |
| fee oracle 3 | 3000 | 3000 | Passed |
| fee oracle 4 | 2600 | 2600 | Passed |
| fee oracle 5 | 3000 | 4500 | Failed |
| fee oracle 6 | 2500 | 3000 | Failed |
| fee oracle 7 | 2500 | 2500 | Passed |
SHA-256 / e1559c8de843f36f819f810daacbecaea7048645d4599267c0155a0b54b269d7
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
if x['exit'] < x['entry']:
return 'invalid'
dur = x['exit'] - x['entry']
if dur <= x['grace']:
fee = 0
else:
days, rem = divmod(dur, 1440)
fee = days * x['daily_max'] + min(x['daily_max'], -(-rem // 60) * x['hourly'])
if x['lost_ticket']:
fee = fee + x['lost_fee']
return fee
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[({'entry': 1082, 'exit': 5693, 'grace': 10, 'hourly': 450, 'daily_max': 1500, 'lost_ticket': True, 'lost_fee': 2500}, 6000), ({'entry': 60, 'exit': 240, 'grace': 15, 'hourly': 450, 'daily_max': 2400, 'lost_ticket': False, 'lost_fee': 3000}, 1350), ({'entry': 184, 'exit': 280, 'grace': 20, 'hourly': 300, 'daily_max': 2000, 'lost_ticket': True, 'lost_fee': 3000}, 3000), ({'entry': 2107, 'exit': 2568, 'grace': 10, 'hourly': 200, 'daily_max': 2000, 'lost_ticket': True, 'lost_fee': 3000}, 3000), ({'entry': 0, 'exit': 1560, 'grace': 10, 'hourly': 300, 'daily_max': 2000, 'lost_ticket': False, 'lost_fee': 2500}, 2600), ({'entry': 2424, 'exit': 6728, 'grace': 15, 'hourly': 450, 'daily_max': 1500, 'lost_ticket': True, 'lost_fee': 3000}, 4500), ({'entry': 2475, 'exit': 5355, 'grace': 20, 'hourly': 450, 'daily_max': 1500, 'lost_ticket': True, 'lost_fee': 2500}, 3000), ({'entry': 500, 'exit': 500, 'grace': 0, 'hourly': 300, 'daily_max': 2000, 'lost_ticket': True, 'lost_fee': 2500}, 2500)], [({'entry': 124, 'exit': 143, 'grace': 0, 'hourly': 200, 'daily_max': 1500, 'lost_ticket': True, 'lost_fee': 2500}, 2500), ({'entry': 318, 'exit': 5189, 'grace': 0, 'hourly': 300, 'daily_max': 2400, 'lost_ticket': True, 'lost_fee': 2500}, 9600), ({'entry': 927, 'exit': 1380, 'grace': 10, 'hourly': 300, 'daily_max': 2000, 'lost_ticket': True, 'lost_fee': 3000}, 3000), ({'entry': 60, 'exit': 240, 'grace': 15, 'hourly': 450, 'daily_max': 2400, 'lost_ticket': False, 'lost_fee': 3000}, 1350), ({'entry': 500, 'exit': 500, 'grace': 0, 'hourly': 300, 'daily_max': 2000, 'lost_ticket': True, 'lost_fee': 2500}, 2500), ({'entry': 69, 'exit': 4389, 'grace': 10, 'hourly': 450, 'daily_max': 1500, 'lost_ticket': True, 'lost_fee': 3000}, 4500), ({'entry': 648, 'exit': 2644, 'grace': 0, 'hourly': 300, 'daily_max': 2400, 'lost_ticket': True, 'lost_fee': 3000}, 4800), ({'entry': 0, 'exit': 1560, 'grace': 10, 'hourly': 300, 'daily_max': 2000, 'lost_ticket': False, 'lost_fee': 2500}, 2600)], [({'entry': 2135, 'exit': 5612, 'grace': 20, 'hourly': 300, 'daily_max': 2400, 'lost_ticket': True, 'lost_fee': 3000}, 7200), ({'entry': 166, 'exit': 2354, 'grace': 10, 'hourly': 450, 'daily_max': 1500, 'lost_ticket': True, 'lost_fee': 2500}, 3000), ({'entry': 0, 'exit': 1560, 'grace': 10, 'hourly': 300, 'daily_max': 2000, 'lost_ticket': False, 'lost_fee': 2500}, 2600), ({'entry': 1120, 'exit': 1138, 'grace': 10, 'hourly': 300, 'daily_max': 2000, 'lost_ticket': True, 'lost_fee': 2500}, 2500), ({'entry': 60, 'exit': 240, 'grace': 15, 'hourly': 450, 'daily_max': 2400, 'lost_ticket': False, 'lost_fee': 3000}, 1350), ({'entry': 429, 'exit': 683, 'grace': 20, 'hourly': 300, 'daily_max': 1500, 'lost_ticket': True, 'lost_fee': 2500}, 2500), ({'entry': 100, 'exit': 115, 'grace': 15, 'hourly': 300, 'daily_max': 2000, 'lost_ticket': False, 'lost_fee': 2500}, 0), ({'entry': 4, 'exit': 2884, 'grace': 20, 'hourly': 200, 'daily_max': 2400, 'lost_ticket': True, 'lost_fee': 3000}, 4800)], [({'entry': 2108, 'exit': 4988, 'grace': 20, 'hourly': 450, 'daily_max': 2000, 'lost_ticket': True, 'lost_fee': 2500}, 4000), ({'entry': 1675, 'exit': 6410, 'grace': 15, 'hourly': 450, 'daily_max': 1500, 'lost_ticket': True, 'lost_fee': 2500}, 6000), ({'entry': 60, 'exit': 240, 'grace': 15, 'hourly': 450, 'daily_max': 2400, 'lost_ticket': False, 'lost_fee': 3000}, 1350), ({'entry': 2388, 'exit': 2625, 'grace': 15, 'hourly': 200, 'daily_max': 2400, 'lost_ticket': True, 'lost_fee': 2500}, 2500), ({'entry': 903, 'exit': 4042, 'grace': 15, 'hourly': 200, 'daily_max': 1500, 'lost_ticket': True, 'lost_fee': 3000}, 4000), ({'entry': 1659, 'exit': 2168, 'grace': 15, 'hourly': 450, 'daily_max': 2400, 'lost_ticket': True, 'lost_fee': 3000}, 3000), ({'entry': 100, 'exit': 115, 'grace': 15, 'hourly': 300, 'daily_max': 2000, 'lost_ticket': False, 'lost_fee': 2500}, 0), ({'entry': 0, 'exit': 1560, 'grace': 10, 'hourly': 300, 'daily_max': 2000, 'lost_ticket': False, 'lost_fee': 2500}, 2600)], [({'entry': 60, 'exit': 240, 'grace': 15, 'hourly': 450, 'daily_max': 2400, 'lost_ticket': False, 'lost_fee': 3000}, 1350), ({'entry': 445, 'exit': 3325, 'grace': 0, 'hourly': 200, 'daily_max': 2400, 'lost_ticket': True, 'lost_fee': 2500}, 4800), ({'entry': 500, 'exit': 500, 'grace': 0, 'hourly': 300, 'daily_max': 2000, 'lost_ticket': True, 'lost_fee': 2500}, 2500), ({'entry': 1568, 'exit': 2228, 'grace': 15, 'hourly': 300, 'daily_max': 1500, 'lost_ticket': True, 'lost_fee': 2500}, 2500), ({'entry': 100, 'exit': 115, 'grace': 15, 'hourly': 300, 'daily_max': 2000, 'lost_ticket': False, 'lost_fee': 2500}, 0), ({'entry': 2826, 'exit': 7146, 'grace': 0, 'hourly': 300, 'daily_max': 2400, 'lost_ticket': True, 'lost_fee': 3000}, 7200), ({'entry': 2274, 'exit': 5519, 'grace': 15, 'hourly': 300, 'daily_max': 1500, 'lost_ticket': True, 'lost_fee': 2500}, 4500), ({'entry': 1853, 'exit': 1872, 'grace': 10, 'hourly': 200, 'daily_max': 2400, 'lost_ticket': True, 'lost_fee': 3000}, 3000)]]
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 | 8500 | 6000 | Failed |
| fee oracle 1 | 1350 | 1350 | Passed |
| fee oracle 2 | 3600 | 3000 | Failed |
| fee oracle 3 | 4600 | 3000 | Failed |
| fee oracle 4 | 2600 | 2600 | Passed |
| fee oracle 5 | 7500 | 4500 | Failed |
| fee oracle 6 | 5500 | 3000 | Failed |
| fee oracle 7 | 2500 | 2500 | Passed |
SHA-256 / 6397121356ed714c262a050cdb48a1544ca3cb09430a47543274ec95f10c476f
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
if x['exit'] < x['entry']:
return 'invalid'
dur = x['exit'] - x['entry']
if dur <= x['grace']:
fee = 0
else:
days, rem = divmod(dur, 1440)
fee = days * x['daily_max'] + min(x['daily_max'], -(-rem // 60) * x['hourly'])
if x['lost_ticket']:
fee = max(fee, x['lost_fee'])
return fee
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[({'entry': 1082, 'exit': 5693, 'grace': 10, 'hourly': 450, 'daily_max': 1500, 'lost_ticket': True, 'lost_fee': 2500}, 6000), ({'entry': 60, 'exit': 240, 'grace': 15, 'hourly': 450, 'daily_max': 2400, 'lost_ticket': False, 'lost_fee': 3000}, 1350), ({'entry': 184, 'exit': 280, 'grace': 20, 'hourly': 300, 'daily_max': 2000, 'lost_ticket': True, 'lost_fee': 3000}, 3000), ({'entry': 2107, 'exit': 2568, 'grace': 10, 'hourly': 200, 'daily_max': 2000, 'lost_ticket': True, 'lost_fee': 3000}, 3000), ({'entry': 0, 'exit': 1560, 'grace': 10, 'hourly': 300, 'daily_max': 2000, 'lost_ticket': False, 'lost_fee': 2500}, 2600), ({'entry': 2424, 'exit': 6728, 'grace': 15, 'hourly': 450, 'daily_max': 1500, 'lost_ticket': True, 'lost_fee': 3000}, 4500), ({'entry': 2475, 'exit': 5355, 'grace': 20, 'hourly': 450, 'daily_max': 1500, 'lost_ticket': True, 'lost_fee': 2500}, 3000), ({'entry': 500, 'exit': 500, 'grace': 0, 'hourly': 300, 'daily_max': 2000, 'lost_ticket': True, 'lost_fee': 2500}, 2500)], [({'entry': 124, 'exit': 143, 'grace': 0, 'hourly': 200, 'daily_max': 1500, 'lost_ticket': True, 'lost_fee': 2500}, 2500), ({'entry': 318, 'exit': 5189, 'grace': 0, 'hourly': 300, 'daily_max': 2400, 'lost_ticket': True, 'lost_fee': 2500}, 9600), ({'entry': 927, 'exit': 1380, 'grace': 10, 'hourly': 300, 'daily_max': 2000, 'lost_ticket': True, 'lost_fee': 3000}, 3000), ({'entry': 60, 'exit': 240, 'grace': 15, 'hourly': 450, 'daily_max': 2400, 'lost_ticket': False, 'lost_fee': 3000}, 1350), ({'entry': 500, 'exit': 500, 'grace': 0, 'hourly': 300, 'daily_max': 2000, 'lost_ticket': True, 'lost_fee': 2500}, 2500), ({'entry': 69, 'exit': 4389, 'grace': 10, 'hourly': 450, 'daily_max': 1500, 'lost_ticket': True, 'lost_fee': 3000}, 4500), ({'entry': 648, 'exit': 2644, 'grace': 0, 'hourly': 300, 'daily_max': 2400, 'lost_ticket': True, 'lost_fee': 3000}, 4800), ({'entry': 0, 'exit': 1560, 'grace': 10, 'hourly': 300, 'daily_max': 2000, 'lost_ticket': False, 'lost_fee': 2500}, 2600)], [({'entry': 2135, 'exit': 5612, 'grace': 20, 'hourly': 300, 'daily_max': 2400, 'lost_ticket': True, 'lost_fee': 3000}, 7200), ({'entry': 166, 'exit': 2354, 'grace': 10, 'hourly': 450, 'daily_max': 1500, 'lost_ticket': True, 'lost_fee': 2500}, 3000), ({'entry': 0, 'exit': 1560, 'grace': 10, 'hourly': 300, 'daily_max': 2000, 'lost_ticket': False, 'lost_fee': 2500}, 2600), ({'entry': 1120, 'exit': 1138, 'grace': 10, 'hourly': 300, 'daily_max': 2000, 'lost_ticket': True, 'lost_fee': 2500}, 2500), ({'entry': 60, 'exit': 240, 'grace': 15, 'hourly': 450, 'daily_max': 2400, 'lost_ticket': False, 'lost_fee': 3000}, 1350), ({'entry': 429, 'exit': 683, 'grace': 20, 'hourly': 300, 'daily_max': 1500, 'lost_ticket': True, 'lost_fee': 2500}, 2500), ({'entry': 100, 'exit': 115, 'grace': 15, 'hourly': 300, 'daily_max': 2000, 'lost_ticket': False, 'lost_fee': 2500}, 0), ({'entry': 4, 'exit': 2884, 'grace': 20, 'hourly': 200, 'daily_max': 2400, 'lost_ticket': True, 'lost_fee': 3000}, 4800)], [({'entry': 2108, 'exit': 4988, 'grace': 20, 'hourly': 450, 'daily_max': 2000, 'lost_ticket': True, 'lost_fee': 2500}, 4000), ({'entry': 1675, 'exit': 6410, 'grace': 15, 'hourly': 450, 'daily_max': 1500, 'lost_ticket': True, 'lost_fee': 2500}, 6000), ({'entry': 60, 'exit': 240, 'grace': 15, 'hourly': 450, 'daily_max': 2400, 'lost_ticket': False, 'lost_fee': 3000}, 1350), ({'entry': 2388, 'exit': 2625, 'grace': 15, 'hourly': 200, 'daily_max': 2400, 'lost_ticket': True, 'lost_fee': 2500}, 2500), ({'entry': 903, 'exit': 4042, 'grace': 15, 'hourly': 200, 'daily_max': 1500, 'lost_ticket': True, 'lost_fee': 3000}, 4000), ({'entry': 1659, 'exit': 2168, 'grace': 15, 'hourly': 450, 'daily_max': 2400, 'lost_ticket': True, 'lost_fee': 3000}, 3000), ({'entry': 100, 'exit': 115, 'grace': 15, 'hourly': 300, 'daily_max': 2000, 'lost_ticket': False, 'lost_fee': 2500}, 0), ({'entry': 0, 'exit': 1560, 'grace': 10, 'hourly': 300, 'daily_max': 2000, 'lost_ticket': False, 'lost_fee': 2500}, 2600)], [({'entry': 60, 'exit': 240, 'grace': 15, 'hourly': 450, 'daily_max': 2400, 'lost_ticket': False, 'lost_fee': 3000}, 1350), ({'entry': 445, 'exit': 3325, 'grace': 0, 'hourly': 200, 'daily_max': 2400, 'lost_ticket': True, 'lost_fee': 2500}, 4800), ({'entry': 500, 'exit': 500, 'grace': 0, 'hourly': 300, 'daily_max': 2000, 'lost_ticket': True, 'lost_fee': 2500}, 2500), ({'entry': 1568, 'exit': 2228, 'grace': 15, 'hourly': 300, 'daily_max': 1500, 'lost_ticket': True, 'lost_fee': 2500}, 2500), ({'entry': 100, 'exit': 115, 'grace': 15, 'hourly': 300, 'daily_max': 2000, 'lost_ticket': False, 'lost_fee': 2500}, 0), ({'entry': 2826, 'exit': 7146, 'grace': 0, 'hourly': 300, 'daily_max': 2400, 'lost_ticket': True, 'lost_fee': 3000}, 7200), ({'entry': 2274, 'exit': 5519, 'grace': 15, 'hourly': 300, 'daily_max': 1500, 'lost_ticket': True, 'lost_fee': 2500}, 4500), ({'entry': 1853, 'exit': 1872, 'grace': 10, 'hourly': 200, 'daily_max': 2400, 'lost_ticket': True, 'lost_fee': 3000}, 3000)]]
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 | 6000 | 6000 | Passed |
| fee oracle 1 | 1350 | 1350 | Passed |
| fee oracle 2 | 3000 | 3000 | Passed |
| fee oracle 3 | 3000 | 3000 | Passed |
| fee oracle 4 | 2600 | 2600 | Passed |
| fee oracle 5 | 4500 | 4500 | Passed |
| fee oracle 6 | 3000 | 3000 | Passed |
| fee oracle 7 | 2500 | 2500 | Passed |
SHA-256 / d63ef84b936883bc1dd3f7efa63fa05d00c3fdcd1802b31dbd1bf7ac92c3191e
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:01.527984+00:00.
Case digest / b8d6e917bd48ea548ce9eb6a3e594eb161760203639be9a3e371e9be31ed8d54