FA-68391 / Toll and parking fee computation / Open access
Tiered parking rate table: the maximum caps only the additional blocks · case 01
Tiered parking rate table returns a wrong result when the maximum caps only the additional blocks.
ROOT CAUSE
The maximum limits only the add-on charge, so long stays exceed the posted maximum.
VERIFIED REPAIR
Restore the overall maximum rule so that the step reads `min(last_price + extra * add, x['max'])`.
Unsuccessful approach: Capping the base tier then adding blocks uncapped still exceeds the maximum.
Case contract
Input {minutes, tiers: [[upto minutes, cumulative price]] in any order, extra_per: [block minutes, cents], max}. A stay of 0 minutes is free. Tiers are applied in ascending upto order and a stay of exactly upto minutes belongs to that tier (price capped at max). Beyond the last tier each started block after its upto adds the block price; the whole fee is capped at max.
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):
m = x['minutes']
tiers = sorted(x['tiers'])
if m <= 0:
return 0
for upto, price in tiers:
if m <= upto:
return min(price, x['max'])
last_upto, last_price = tiers[-1]
blk, add = x['extra_per']
extra = -(-(m - last_upto) // blk)
return last_price + min(extra * add, x['max'])
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[({'minutes': 207, 'tiers': [[210, 400], [270, 950]], 'extra_per': [30, 50], 'max': 4000}, 400), ({'minutes': 1, 'tiers': [[30, 150], [60, 300]], 'extra_per': [30, 100], 'max': 1500}, 150), ({'minutes': 553, 'tiers': [[180, 800], [240, 1350], [120, 600]], 'extra_per': [15, 150], 'max': 1500}, 1500), ({'minutes': 171, 'tiers': [[150, 700], [270, 1150], [360, 1250], [210, 800]], 'extra_per': [30, 100], 'max': 4000}, 800), ({'minutes': 151, 'tiers': [[60, 1200], [120, 1750], [150, 1900]], 'extra_per': [20, 50], 'max': 1500}, 1500), ({'minutes': 0, 'tiers': [[60, 300]], 'extra_per': [30, 100], 'max': 1500}, 0), ({'minutes': 250, 'tiers': [[240, 800], [60, 300], [120, 500]], 'extra_per': [60, 200], 'max': 2000}, 1000), ({'minutes': 259, 'tiers': [[30, 200]], 'extra_per': [15, 150], 'max': 2500}, 2500)], [({'minutes': 241, 'tiers': [[60, 300], [240, 1150]], 'extra_per': [60, 50], 'max': 1500}, 1200), ({'minutes': 180, 'tiers': [[180, 150], [360, 1900]], 'extra_per': [20, 50], 'max': 1500}, 150), ({'minutes': 677, 'tiers': [[210, 1400]], 'extra_per': [20, 150], 'max': 4000}, 4000), ({'minutes': 61, 'tiers': [[240, 550], [210, 300], [60, 250], [330, 750]], 'extra_per': [60, 100], 'max': 2500}, 300), ({'minutes': 1000, 'tiers': [[90, 400], [180, 700]], 'extra_per': [45, 150], 'max': 2500}, 2500), ({'minutes': 250, 'tiers': [[240, 800], [60, 300], [120, 500]], 'extra_per': [60, 200], 'max': 2000}, 1000), ({'minutes': 802, 'tiers': [[300, 1950]], 'extra_per': [20, 50], 'max': 2500}, 2500), ({'minutes': 60, 'tiers': [[60, 300], [120, 500], [240, 800]], 'extra_per': [60, 200], 'max': 2000}, 300)], [({'minutes': 328, 'tiers': [[30, 100], [360, 1450]], 'extra_per': [20, 150], 'max': 2500}, 1450), ({'minutes': 60, 'tiers': [[60, 300], [120, 500], [240, 800]], 'extra_per': [60, 200], 'max': 2000}, 300), ({'minutes': 250, 'tiers': [[240, 800], [60, 300], [120, 500]], 'extra_per': [60, 200], 'max': 2000}, 1000), ({'minutes': 782, 'tiers': [[180, 250], [30, 100]], 'extra_per': [60, 100], 'max': 4000}, 1350), ({'minutes': 1000, 'tiers': [[90, 400], [180, 700]], 'extra_per': [45, 150], 'max': 2500}, 2500), ({'minutes': 601, 'tiers': [[60, 900], [270, 1350]], 'extra_per': [30, 50], 'max': 1500}, 1500), ({'minutes': 555, 'tiers': [[210, 500], [240, 850], [300, 1500], [270, 950]], 'extra_per': [60, 100], 'max': 1500}, 1500), ({'minutes': 180, 'tiers': [[180, 750], [30, 600], [240, 1600]], 'extra_per': [20, 100], 'max': 1500}, 750)], [({'minutes': 1, 'tiers': [[30, 150], [60, 300]], 'extra_per': [30, 100], 'max': 1500}, 150), ({'minutes': 60, 'tiers': [[60, 300], [120, 500], [240, 800]], 'extra_per': [60, 200], 'max': 2000}, 300), ({'minutes': 308, 'tiers': [[210, 650], [180, 150], [300, 1050], [330, 1300]], 'extra_per': [60, 150], 'max': 4000}, 1300), ({'minutes': 762, 'tiers': [[300, 1900]], 'extra_per': [30, 100], 'max': 1500}, 1500), ({'minutes': 91, 'tiers': [[300, 1000], [90, 200]], 'extra_per': [60, 150], 'max': 1500}, 1000), ({'minutes': 1000, 'tiers': [[90, 400], [180, 700]], 'extra_per': [45, 150], 'max': 2500}, 2500), ({'minutes': 361, 'tiers': [[90, 600], [360, 1350]], 'extra_per': [15, 50], 'max': 2500}, 1400), ({'minutes': 241, 'tiers': [[150, 1300], [240, 1700]], 'extra_per': [30, 100], 'max': 1500}, 1500)], [({'minutes': 1, 'tiers': [[30, 150], [60, 300]], 'extra_per': [30, 100], 'max': 1500}, 150), ({'minutes': 50, 'tiers': [[60, 200], [210, 850], [270, 900], [300, 1850]], 'extra_per': [30, 150], 'max': 1500}, 200), ({'minutes': 241, 'tiers': [[90, 900], [120, 1350], [240, 1800]], 'extra_per': [30, 150], 'max': 1500}, 1500), ({'minutes': 120, 'tiers': [[180, 950], [150, 500], [120, 300], [300, 1500]], 'extra_per': [15, 50], 'max': 1500}, 300), ({'minutes': 1000, 'tiers': [[90, 400], [180, 700]], 'extra_per': [45, 150], 'max': 2500}, 2500), ({'minutes': 658, 'tiers': [[150, 850]], 'extra_per': [20, 150], 'max': 1500}, 1500), ({'minutes': 60, 'tiers': [[60, 300], [120, 500], [240, 800]], 'extra_per': [60, 200], 'max': 2000}, 300), ({'minutes': 151, 'tiers': [[150, 600]], 'extra_per': [20, 100], 'max': 1500}, 700)]]
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 | 400 | 400 | Passed |
| fee oracle 1 | 150 | 150 | Passed |
| fee oracle 2 | 2850 | 1500 | Failed |
| fee oracle 3 | 800 | 800 | Passed |
| fee oracle 4 | 1950 | 1500 | Failed |
| fee oracle 5 | 0 | 0 | Passed |
| fee oracle 6 | 1000 | 1000 | Passed |
| fee oracle 7 | 2600 | 2500 | Failed |
SHA-256 / 5bf02e13580ea68f7507b15b1142304156179dfcddc1daa48223fd8c5db78219
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
m = x['minutes']
tiers = sorted(x['tiers'])
if m <= 0:
return 0
for upto, price in tiers:
if m <= upto:
return min(price, x['max'])
last_upto, last_price = tiers[-1]
blk, add = x['extra_per']
extra = -(-(m - last_upto) // blk)
return min(last_price, x['max']) + extra * add
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[({'minutes': 207, 'tiers': [[210, 400], [270, 950]], 'extra_per': [30, 50], 'max': 4000}, 400), ({'minutes': 1, 'tiers': [[30, 150], [60, 300]], 'extra_per': [30, 100], 'max': 1500}, 150), ({'minutes': 553, 'tiers': [[180, 800], [240, 1350], [120, 600]], 'extra_per': [15, 150], 'max': 1500}, 1500), ({'minutes': 171, 'tiers': [[150, 700], [270, 1150], [360, 1250], [210, 800]], 'extra_per': [30, 100], 'max': 4000}, 800), ({'minutes': 151, 'tiers': [[60, 1200], [120, 1750], [150, 1900]], 'extra_per': [20, 50], 'max': 1500}, 1500), ({'minutes': 0, 'tiers': [[60, 300]], 'extra_per': [30, 100], 'max': 1500}, 0), ({'minutes': 250, 'tiers': [[240, 800], [60, 300], [120, 500]], 'extra_per': [60, 200], 'max': 2000}, 1000), ({'minutes': 259, 'tiers': [[30, 200]], 'extra_per': [15, 150], 'max': 2500}, 2500)], [({'minutes': 241, 'tiers': [[60, 300], [240, 1150]], 'extra_per': [60, 50], 'max': 1500}, 1200), ({'minutes': 180, 'tiers': [[180, 150], [360, 1900]], 'extra_per': [20, 50], 'max': 1500}, 150), ({'minutes': 677, 'tiers': [[210, 1400]], 'extra_per': [20, 150], 'max': 4000}, 4000), ({'minutes': 61, 'tiers': [[240, 550], [210, 300], [60, 250], [330, 750]], 'extra_per': [60, 100], 'max': 2500}, 300), ({'minutes': 1000, 'tiers': [[90, 400], [180, 700]], 'extra_per': [45, 150], 'max': 2500}, 2500), ({'minutes': 250, 'tiers': [[240, 800], [60, 300], [120, 500]], 'extra_per': [60, 200], 'max': 2000}, 1000), ({'minutes': 802, 'tiers': [[300, 1950]], 'extra_per': [20, 50], 'max': 2500}, 2500), ({'minutes': 60, 'tiers': [[60, 300], [120, 500], [240, 800]], 'extra_per': [60, 200], 'max': 2000}, 300)], [({'minutes': 328, 'tiers': [[30, 100], [360, 1450]], 'extra_per': [20, 150], 'max': 2500}, 1450), ({'minutes': 60, 'tiers': [[60, 300], [120, 500], [240, 800]], 'extra_per': [60, 200], 'max': 2000}, 300), ({'minutes': 250, 'tiers': [[240, 800], [60, 300], [120, 500]], 'extra_per': [60, 200], 'max': 2000}, 1000), ({'minutes': 782, 'tiers': [[180, 250], [30, 100]], 'extra_per': [60, 100], 'max': 4000}, 1350), ({'minutes': 1000, 'tiers': [[90, 400], [180, 700]], 'extra_per': [45, 150], 'max': 2500}, 2500), ({'minutes': 601, 'tiers': [[60, 900], [270, 1350]], 'extra_per': [30, 50], 'max': 1500}, 1500), ({'minutes': 555, 'tiers': [[210, 500], [240, 850], [300, 1500], [270, 950]], 'extra_per': [60, 100], 'max': 1500}, 1500), ({'minutes': 180, 'tiers': [[180, 750], [30, 600], [240, 1600]], 'extra_per': [20, 100], 'max': 1500}, 750)], [({'minutes': 1, 'tiers': [[30, 150], [60, 300]], 'extra_per': [30, 100], 'max': 1500}, 150), ({'minutes': 60, 'tiers': [[60, 300], [120, 500], [240, 800]], 'extra_per': [60, 200], 'max': 2000}, 300), ({'minutes': 308, 'tiers': [[210, 650], [180, 150], [300, 1050], [330, 1300]], 'extra_per': [60, 150], 'max': 4000}, 1300), ({'minutes': 762, 'tiers': [[300, 1900]], 'extra_per': [30, 100], 'max': 1500}, 1500), ({'minutes': 91, 'tiers': [[300, 1000], [90, 200]], 'extra_per': [60, 150], 'max': 1500}, 1000), ({'minutes': 1000, 'tiers': [[90, 400], [180, 700]], 'extra_per': [45, 150], 'max': 2500}, 2500), ({'minutes': 361, 'tiers': [[90, 600], [360, 1350]], 'extra_per': [15, 50], 'max': 2500}, 1400), ({'minutes': 241, 'tiers': [[150, 1300], [240, 1700]], 'extra_per': [30, 100], 'max': 1500}, 1500)], [({'minutes': 1, 'tiers': [[30, 150], [60, 300]], 'extra_per': [30, 100], 'max': 1500}, 150), ({'minutes': 50, 'tiers': [[60, 200], [210, 850], [270, 900], [300, 1850]], 'extra_per': [30, 150], 'max': 1500}, 200), ({'minutes': 241, 'tiers': [[90, 900], [120, 1350], [240, 1800]], 'extra_per': [30, 150], 'max': 1500}, 1500), ({'minutes': 120, 'tiers': [[180, 950], [150, 500], [120, 300], [300, 1500]], 'extra_per': [15, 50], 'max': 1500}, 300), ({'minutes': 1000, 'tiers': [[90, 400], [180, 700]], 'extra_per': [45, 150], 'max': 2500}, 2500), ({'minutes': 658, 'tiers': [[150, 850]], 'extra_per': [20, 150], 'max': 1500}, 1500), ({'minutes': 60, 'tiers': [[60, 300], [120, 500], [240, 800]], 'extra_per': [60, 200], 'max': 2000}, 300), ({'minutes': 151, 'tiers': [[150, 600]], 'extra_per': [20, 100], 'max': 1500}, 700)]]
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 | 400 | 400 | Passed |
| fee oracle 1 | 150 | 150 | Passed |
| fee oracle 2 | 4500 | 1500 | Failed |
| fee oracle 3 | 800 | 800 | Passed |
| fee oracle 4 | 1550 | 1500 | Failed |
| fee oracle 5 | 0 | 0 | Passed |
| fee oracle 6 | 1000 | 1000 | Passed |
| fee oracle 7 | 2600 | 2500 | Failed |
SHA-256 / 8cf5d689d852d1d323300344534f0fecab7bfb4b45c98d37138baf28c6baeec7
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
m = x['minutes']
tiers = sorted(x['tiers'])
if m <= 0:
return 0
for upto, price in tiers:
if m <= upto:
return min(price, x['max'])
last_upto, last_price = tiers[-1]
blk, add = x['extra_per']
extra = -(-(m - last_upto) // blk)
return min(last_price + extra * add, x['max'])
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[({'minutes': 207, 'tiers': [[210, 400], [270, 950]], 'extra_per': [30, 50], 'max': 4000}, 400), ({'minutes': 1, 'tiers': [[30, 150], [60, 300]], 'extra_per': [30, 100], 'max': 1500}, 150), ({'minutes': 553, 'tiers': [[180, 800], [240, 1350], [120, 600]], 'extra_per': [15, 150], 'max': 1500}, 1500), ({'minutes': 171, 'tiers': [[150, 700], [270, 1150], [360, 1250], [210, 800]], 'extra_per': [30, 100], 'max': 4000}, 800), ({'minutes': 151, 'tiers': [[60, 1200], [120, 1750], [150, 1900]], 'extra_per': [20, 50], 'max': 1500}, 1500), ({'minutes': 0, 'tiers': [[60, 300]], 'extra_per': [30, 100], 'max': 1500}, 0), ({'minutes': 250, 'tiers': [[240, 800], [60, 300], [120, 500]], 'extra_per': [60, 200], 'max': 2000}, 1000), ({'minutes': 259, 'tiers': [[30, 200]], 'extra_per': [15, 150], 'max': 2500}, 2500)], [({'minutes': 241, 'tiers': [[60, 300], [240, 1150]], 'extra_per': [60, 50], 'max': 1500}, 1200), ({'minutes': 180, 'tiers': [[180, 150], [360, 1900]], 'extra_per': [20, 50], 'max': 1500}, 150), ({'minutes': 677, 'tiers': [[210, 1400]], 'extra_per': [20, 150], 'max': 4000}, 4000), ({'minutes': 61, 'tiers': [[240, 550], [210, 300], [60, 250], [330, 750]], 'extra_per': [60, 100], 'max': 2500}, 300), ({'minutes': 1000, 'tiers': [[90, 400], [180, 700]], 'extra_per': [45, 150], 'max': 2500}, 2500), ({'minutes': 250, 'tiers': [[240, 800], [60, 300], [120, 500]], 'extra_per': [60, 200], 'max': 2000}, 1000), ({'minutes': 802, 'tiers': [[300, 1950]], 'extra_per': [20, 50], 'max': 2500}, 2500), ({'minutes': 60, 'tiers': [[60, 300], [120, 500], [240, 800]], 'extra_per': [60, 200], 'max': 2000}, 300)], [({'minutes': 328, 'tiers': [[30, 100], [360, 1450]], 'extra_per': [20, 150], 'max': 2500}, 1450), ({'minutes': 60, 'tiers': [[60, 300], [120, 500], [240, 800]], 'extra_per': [60, 200], 'max': 2000}, 300), ({'minutes': 250, 'tiers': [[240, 800], [60, 300], [120, 500]], 'extra_per': [60, 200], 'max': 2000}, 1000), ({'minutes': 782, 'tiers': [[180, 250], [30, 100]], 'extra_per': [60, 100], 'max': 4000}, 1350), ({'minutes': 1000, 'tiers': [[90, 400], [180, 700]], 'extra_per': [45, 150], 'max': 2500}, 2500), ({'minutes': 601, 'tiers': [[60, 900], [270, 1350]], 'extra_per': [30, 50], 'max': 1500}, 1500), ({'minutes': 555, 'tiers': [[210, 500], [240, 850], [300, 1500], [270, 950]], 'extra_per': [60, 100], 'max': 1500}, 1500), ({'minutes': 180, 'tiers': [[180, 750], [30, 600], [240, 1600]], 'extra_per': [20, 100], 'max': 1500}, 750)], [({'minutes': 1, 'tiers': [[30, 150], [60, 300]], 'extra_per': [30, 100], 'max': 1500}, 150), ({'minutes': 60, 'tiers': [[60, 300], [120, 500], [240, 800]], 'extra_per': [60, 200], 'max': 2000}, 300), ({'minutes': 308, 'tiers': [[210, 650], [180, 150], [300, 1050], [330, 1300]], 'extra_per': [60, 150], 'max': 4000}, 1300), ({'minutes': 762, 'tiers': [[300, 1900]], 'extra_per': [30, 100], 'max': 1500}, 1500), ({'minutes': 91, 'tiers': [[300, 1000], [90, 200]], 'extra_per': [60, 150], 'max': 1500}, 1000), ({'minutes': 1000, 'tiers': [[90, 400], [180, 700]], 'extra_per': [45, 150], 'max': 2500}, 2500), ({'minutes': 361, 'tiers': [[90, 600], [360, 1350]], 'extra_per': [15, 50], 'max': 2500}, 1400), ({'minutes': 241, 'tiers': [[150, 1300], [240, 1700]], 'extra_per': [30, 100], 'max': 1500}, 1500)], [({'minutes': 1, 'tiers': [[30, 150], [60, 300]], 'extra_per': [30, 100], 'max': 1500}, 150), ({'minutes': 50, 'tiers': [[60, 200], [210, 850], [270, 900], [300, 1850]], 'extra_per': [30, 150], 'max': 1500}, 200), ({'minutes': 241, 'tiers': [[90, 900], [120, 1350], [240, 1800]], 'extra_per': [30, 150], 'max': 1500}, 1500), ({'minutes': 120, 'tiers': [[180, 950], [150, 500], [120, 300], [300, 1500]], 'extra_per': [15, 50], 'max': 1500}, 300), ({'minutes': 1000, 'tiers': [[90, 400], [180, 700]], 'extra_per': [45, 150], 'max': 2500}, 2500), ({'minutes': 658, 'tiers': [[150, 850]], 'extra_per': [20, 150], 'max': 1500}, 1500), ({'minutes': 60, 'tiers': [[60, 300], [120, 500], [240, 800]], 'extra_per': [60, 200], 'max': 2000}, 300), ({'minutes': 151, 'tiers': [[150, 600]], 'extra_per': [20, 100], 'max': 1500}, 700)]]
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 | 400 | 400 | Passed |
| fee oracle 1 | 150 | 150 | Passed |
| fee oracle 2 | 1500 | 1500 | Passed |
| fee oracle 3 | 800 | 800 | Passed |
| fee oracle 4 | 1500 | 1500 | Passed |
| fee oracle 5 | 0 | 0 | Passed |
| fee oracle 6 | 1000 | 1000 | Passed |
| fee oracle 7 | 2500 | 2500 | Passed |
SHA-256 / 19fb4e9d7165ef4a07e160af832e479044110e252537b7903913aa0b15a7c51c
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.798686+00:00.
Case digest / 80128c283ac22eacf2810f3b37ee26771313837e26c42d8bbfd90750ce0ba838