FAILURE MAP
← Case archive

FA-68386 / Toll and parking fee computation / Open access

Tiered parking rate table: a zero-minute stay pays the first tier · case 01

Tiered parking rate table returns a wrong result when a zero-minute stay pays the first tier.

Verified by executionVariant 1 · 8 checks per implementationDownload source bundle ↓JSON ↗

ROOT CAUSE

Entry and exit in the same minute is charged the first tier.

VERIFIED REPAIR

Restore the zero-length stay rule so that the step reads `if m <= 0:`.

Unsuccessful approach: Making one-minute stays free extends the free window beyond the contract.

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 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': 1000, 'tiers': [[90, 400], [180, 700]], 'extra_per': [45, 150], 'max': 2500}, 2500), ({'minutes': 1, 'tiers': [[30, 150], [60, 300]], 'extra_per': [30, 100], 'max': 1500}, 150), ({'minutes': 301, 'tiers': [[180, 800], [300, 1350]], 'extra_per': [20, 100], 'max': 2500}, 1450), ({'minutes': 183, 'tiers': [[30, 450], [300, 900], [330, 1550]], 'extra_per': [30, 50], 'max': 4000}, 900), ({'minutes': 241, 'tiers': [[240, 1350]], 'extra_per': [30, 50], 'max': 1500}, 1400), ({'minutes': 0, 'tiers': [[60, 300]], 'extra_per': [30, 100], 'max': 1500}, 0), ({'minutes': 150, 'tiers': [[150, 200], [360, 450]], 'extra_per': [15, 150], 'max': 1500}, 200), ({'minutes': 345, 'tiers': [[300, 1350], [150, 1150], [360, 1800], [180, 1200]], 'extra_per': [15, 150], 'max': 2500}, 1800)], [({'minutes': 185, 'tiers': [[90, 1200], [150, 1800]], 'extra_per': [20, 50], 'max': 2500}, 1900), ({'minutes': 67, 'tiers': [[60, 500], [90, 1400], [210, 1800]], 'extra_per': [15, 150], 'max': 2500}, 1400), ({'minutes': 1, 'tiers': [[30, 150], [60, 300]], 'extra_per': [30, 100], 'max': 1500}, 150), ({'minutes': 360, 'tiers': [[90, 450], [330, 1500], [360, 1900]], 'extra_per': [20, 150], 'max': 2500}, 1900), ({'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': 0, 'tiers': [[60, 300]], 'extra_per': [30, 100], 'max': 1500}, 0), ({'minutes': 233, 'tiers': [[270, 550], [120, 350], [330, 1600], [180, 500]], 'extra_per': [60, 50], 'max': 2500}, 550)], [({'minutes': 60, 'tiers': [[60, 750]], 'extra_per': [30, 150], 'max': 1500}, 750), ({'minutes': 350, 'tiers': [[150, 250]], 'extra_per': [15, 150], 'max': 2500}, 2350), ({'minutes': 425, 'tiers': [[120, 500], [180, 1250], [240, 1950], [90, 150]], 'extra_per': [30, 50], 'max': 4000}, 2300), ({'minutes': 250, 'tiers': [[240, 800], [60, 300], [120, 500]], 'extra_per': [60, 200], 'max': 2000}, 1000), ({'minutes': 0, 'tiers': [[60, 300]], 'extra_per': [30, 100], 'max': 1500}, 0), ({'minutes': 184, 'tiers': [[360, 1200], [90, 300], [300, 1100], [120, 1050]], 'extra_per': [30, 50], 'max': 1500}, 1100), ({'minutes': 302, 'tiers': [[30, 150], [90, 500], [270, 650], [360, 1500]], 'extra_per': [30, 50], 'max': 4000}, 1500), ({'minutes': 1, 'tiers': [[30, 150], [60, 300]], 'extra_per': [30, 100], 'max': 1500}, 150)], [({'minutes': 1000, 'tiers': [[90, 400], [180, 700]], 'extra_per': [45, 150], 'max': 2500}, 2500), ({'minutes': 181, 'tiers': [[120, 550], [180, 1800], [210, 1850]], 'extra_per': [60, 150], 'max': 4000}, 1850), ({'minutes': 82, 'tiers': [[150, 1900]], 'extra_per': [20, 150], 'max': 2500}, 1900), ({'minutes': 241, 'tiers': [[60, 350], [240, 1350]], 'extra_per': [20, 50], 'max': 2500}, 1400), ({'minutes': 0, 'tiers': [[300, 1750], [150, 650], [210, 1250]], 'extra_per': [30, 150], 'max': 2500}, 0), ({'minutes': 250, 'tiers': [[240, 800], [60, 300], [120, 500]], 'extra_per': [60, 200], 'max': 2000}, 1000), ({'minutes': 1, 'tiers': [[30, 150], [60, 300]], 'extra_per': [30, 100], 'max': 1500}, 150), ({'minutes': 0, 'tiers': [[60, 300]], 'extra_per': [30, 100], 'max': 1500}, 0)], [({'minutes': 594, 'tiers': [[90, 250], [120, 1400]], 'extra_per': [15, 100], 'max': 1500}, 1500), ({'minutes': 1, 'tiers': [[270, 1150]], 'extra_per': [20, 150], 'max': 4000}, 1150), ({'minutes': 250, 'tiers': [[240, 800], [60, 300], [120, 500]], 'extra_per': [60, 200], 'max': 2000}, 1000), ({'minutes': 0, 'tiers': [[60, 300]], 'extra_per': [30, 100], 'max': 1500}, 0), ({'minutes': 1, 'tiers': [[30, 150], [60, 300]], 'extra_per': [30, 100], 'max': 1500}, 150), ({'minutes': 151, 'tiers': [[30, 200], [240, 1250]], 'extra_per': [15, 100], 'max': 1500}, 1250), ({'minutes': 291, 'tiers': [[300, 1700], [30, 500], [150, 1400]], 'extra_per': [30, 150], 'max': 4000}, 1700), ({'minutes': 68, 'tiers': [[120, 1100], [330, 1550]], 'extra_per': [30, 150], 'max': 4000}, 1100)]]
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 fixtureActualExpectedOutcome
fee oracle 025002500Passed
fee oracle 1150150Passed
fee oracle 214501450Passed
fee oracle 3900900Passed
fee oracle 414001400Passed
fee oracle 53000Failed
fee oracle 6200200Passed
fee oracle 718001800Passed

SHA-256 / d1f4b467c18f9fc45bdbb83ee569bd8956728ae913f6af7a90fc33ab34c7f7b6

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 <= 1:
        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': 1000, 'tiers': [[90, 400], [180, 700]], 'extra_per': [45, 150], 'max': 2500}, 2500), ({'minutes': 1, 'tiers': [[30, 150], [60, 300]], 'extra_per': [30, 100], 'max': 1500}, 150), ({'minutes': 301, 'tiers': [[180, 800], [300, 1350]], 'extra_per': [20, 100], 'max': 2500}, 1450), ({'minutes': 183, 'tiers': [[30, 450], [300, 900], [330, 1550]], 'extra_per': [30, 50], 'max': 4000}, 900), ({'minutes': 241, 'tiers': [[240, 1350]], 'extra_per': [30, 50], 'max': 1500}, 1400), ({'minutes': 0, 'tiers': [[60, 300]], 'extra_per': [30, 100], 'max': 1500}, 0), ({'minutes': 150, 'tiers': [[150, 200], [360, 450]], 'extra_per': [15, 150], 'max': 1500}, 200), ({'minutes': 345, 'tiers': [[300, 1350], [150, 1150], [360, 1800], [180, 1200]], 'extra_per': [15, 150], 'max': 2500}, 1800)], [({'minutes': 185, 'tiers': [[90, 1200], [150, 1800]], 'extra_per': [20, 50], 'max': 2500}, 1900), ({'minutes': 67, 'tiers': [[60, 500], [90, 1400], [210, 1800]], 'extra_per': [15, 150], 'max': 2500}, 1400), ({'minutes': 1, 'tiers': [[30, 150], [60, 300]], 'extra_per': [30, 100], 'max': 1500}, 150), ({'minutes': 360, 'tiers': [[90, 450], [330, 1500], [360, 1900]], 'extra_per': [20, 150], 'max': 2500}, 1900), ({'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': 0, 'tiers': [[60, 300]], 'extra_per': [30, 100], 'max': 1500}, 0), ({'minutes': 233, 'tiers': [[270, 550], [120, 350], [330, 1600], [180, 500]], 'extra_per': [60, 50], 'max': 2500}, 550)], [({'minutes': 60, 'tiers': [[60, 750]], 'extra_per': [30, 150], 'max': 1500}, 750), ({'minutes': 350, 'tiers': [[150, 250]], 'extra_per': [15, 150], 'max': 2500}, 2350), ({'minutes': 425, 'tiers': [[120, 500], [180, 1250], [240, 1950], [90, 150]], 'extra_per': [30, 50], 'max': 4000}, 2300), ({'minutes': 250, 'tiers': [[240, 800], [60, 300], [120, 500]], 'extra_per': [60, 200], 'max': 2000}, 1000), ({'minutes': 0, 'tiers': [[60, 300]], 'extra_per': [30, 100], 'max': 1500}, 0), ({'minutes': 184, 'tiers': [[360, 1200], [90, 300], [300, 1100], [120, 1050]], 'extra_per': [30, 50], 'max': 1500}, 1100), ({'minutes': 302, 'tiers': [[30, 150], [90, 500], [270, 650], [360, 1500]], 'extra_per': [30, 50], 'max': 4000}, 1500), ({'minutes': 1, 'tiers': [[30, 150], [60, 300]], 'extra_per': [30, 100], 'max': 1500}, 150)], [({'minutes': 1000, 'tiers': [[90, 400], [180, 700]], 'extra_per': [45, 150], 'max': 2500}, 2500), ({'minutes': 181, 'tiers': [[120, 550], [180, 1800], [210, 1850]], 'extra_per': [60, 150], 'max': 4000}, 1850), ({'minutes': 82, 'tiers': [[150, 1900]], 'extra_per': [20, 150], 'max': 2500}, 1900), ({'minutes': 241, 'tiers': [[60, 350], [240, 1350]], 'extra_per': [20, 50], 'max': 2500}, 1400), ({'minutes': 0, 'tiers': [[300, 1750], [150, 650], [210, 1250]], 'extra_per': [30, 150], 'max': 2500}, 0), ({'minutes': 250, 'tiers': [[240, 800], [60, 300], [120, 500]], 'extra_per': [60, 200], 'max': 2000}, 1000), ({'minutes': 1, 'tiers': [[30, 150], [60, 300]], 'extra_per': [30, 100], 'max': 1500}, 150), ({'minutes': 0, 'tiers': [[60, 300]], 'extra_per': [30, 100], 'max': 1500}, 0)], [({'minutes': 594, 'tiers': [[90, 250], [120, 1400]], 'extra_per': [15, 100], 'max': 1500}, 1500), ({'minutes': 1, 'tiers': [[270, 1150]], 'extra_per': [20, 150], 'max': 4000}, 1150), ({'minutes': 250, 'tiers': [[240, 800], [60, 300], [120, 500]], 'extra_per': [60, 200], 'max': 2000}, 1000), ({'minutes': 0, 'tiers': [[60, 300]], 'extra_per': [30, 100], 'max': 1500}, 0), ({'minutes': 1, 'tiers': [[30, 150], [60, 300]], 'extra_per': [30, 100], 'max': 1500}, 150), ({'minutes': 151, 'tiers': [[30, 200], [240, 1250]], 'extra_per': [15, 100], 'max': 1500}, 1250), ({'minutes': 291, 'tiers': [[300, 1700], [30, 500], [150, 1400]], 'extra_per': [30, 150], 'max': 4000}, 1700), ({'minutes': 68, 'tiers': [[120, 1100], [330, 1550]], 'extra_per': [30, 150], 'max': 4000}, 1100)]]
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 fixtureActualExpectedOutcome
fee oracle 025002500Passed
fee oracle 10150Failed
fee oracle 214501450Passed
fee oracle 3900900Passed
fee oracle 414001400Passed
fee oracle 500Passed
fee oracle 6200200Passed
fee oracle 718001800Passed

SHA-256 / 6a7262ee25f63b44df9ff6b18bbf4b91174889a49d4531df6e40a417652a073a

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': 1000, 'tiers': [[90, 400], [180, 700]], 'extra_per': [45, 150], 'max': 2500}, 2500), ({'minutes': 1, 'tiers': [[30, 150], [60, 300]], 'extra_per': [30, 100], 'max': 1500}, 150), ({'minutes': 301, 'tiers': [[180, 800], [300, 1350]], 'extra_per': [20, 100], 'max': 2500}, 1450), ({'minutes': 183, 'tiers': [[30, 450], [300, 900], [330, 1550]], 'extra_per': [30, 50], 'max': 4000}, 900), ({'minutes': 241, 'tiers': [[240, 1350]], 'extra_per': [30, 50], 'max': 1500}, 1400), ({'minutes': 0, 'tiers': [[60, 300]], 'extra_per': [30, 100], 'max': 1500}, 0), ({'minutes': 150, 'tiers': [[150, 200], [360, 450]], 'extra_per': [15, 150], 'max': 1500}, 200), ({'minutes': 345, 'tiers': [[300, 1350], [150, 1150], [360, 1800], [180, 1200]], 'extra_per': [15, 150], 'max': 2500}, 1800)], [({'minutes': 185, 'tiers': [[90, 1200], [150, 1800]], 'extra_per': [20, 50], 'max': 2500}, 1900), ({'minutes': 67, 'tiers': [[60, 500], [90, 1400], [210, 1800]], 'extra_per': [15, 150], 'max': 2500}, 1400), ({'minutes': 1, 'tiers': [[30, 150], [60, 300]], 'extra_per': [30, 100], 'max': 1500}, 150), ({'minutes': 360, 'tiers': [[90, 450], [330, 1500], [360, 1900]], 'extra_per': [20, 150], 'max': 2500}, 1900), ({'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': 0, 'tiers': [[60, 300]], 'extra_per': [30, 100], 'max': 1500}, 0), ({'minutes': 233, 'tiers': [[270, 550], [120, 350], [330, 1600], [180, 500]], 'extra_per': [60, 50], 'max': 2500}, 550)], [({'minutes': 60, 'tiers': [[60, 750]], 'extra_per': [30, 150], 'max': 1500}, 750), ({'minutes': 350, 'tiers': [[150, 250]], 'extra_per': [15, 150], 'max': 2500}, 2350), ({'minutes': 425, 'tiers': [[120, 500], [180, 1250], [240, 1950], [90, 150]], 'extra_per': [30, 50], 'max': 4000}, 2300), ({'minutes': 250, 'tiers': [[240, 800], [60, 300], [120, 500]], 'extra_per': [60, 200], 'max': 2000}, 1000), ({'minutes': 0, 'tiers': [[60, 300]], 'extra_per': [30, 100], 'max': 1500}, 0), ({'minutes': 184, 'tiers': [[360, 1200], [90, 300], [300, 1100], [120, 1050]], 'extra_per': [30, 50], 'max': 1500}, 1100), ({'minutes': 302, 'tiers': [[30, 150], [90, 500], [270, 650], [360, 1500]], 'extra_per': [30, 50], 'max': 4000}, 1500), ({'minutes': 1, 'tiers': [[30, 150], [60, 300]], 'extra_per': [30, 100], 'max': 1500}, 150)], [({'minutes': 1000, 'tiers': [[90, 400], [180, 700]], 'extra_per': [45, 150], 'max': 2500}, 2500), ({'minutes': 181, 'tiers': [[120, 550], [180, 1800], [210, 1850]], 'extra_per': [60, 150], 'max': 4000}, 1850), ({'minutes': 82, 'tiers': [[150, 1900]], 'extra_per': [20, 150], 'max': 2500}, 1900), ({'minutes': 241, 'tiers': [[60, 350], [240, 1350]], 'extra_per': [20, 50], 'max': 2500}, 1400), ({'minutes': 0, 'tiers': [[300, 1750], [150, 650], [210, 1250]], 'extra_per': [30, 150], 'max': 2500}, 0), ({'minutes': 250, 'tiers': [[240, 800], [60, 300], [120, 500]], 'extra_per': [60, 200], 'max': 2000}, 1000), ({'minutes': 1, 'tiers': [[30, 150], [60, 300]], 'extra_per': [30, 100], 'max': 1500}, 150), ({'minutes': 0, 'tiers': [[60, 300]], 'extra_per': [30, 100], 'max': 1500}, 0)], [({'minutes': 594, 'tiers': [[90, 250], [120, 1400]], 'extra_per': [15, 100], 'max': 1500}, 1500), ({'minutes': 1, 'tiers': [[270, 1150]], 'extra_per': [20, 150], 'max': 4000}, 1150), ({'minutes': 250, 'tiers': [[240, 800], [60, 300], [120, 500]], 'extra_per': [60, 200], 'max': 2000}, 1000), ({'minutes': 0, 'tiers': [[60, 300]], 'extra_per': [30, 100], 'max': 1500}, 0), ({'minutes': 1, 'tiers': [[30, 150], [60, 300]], 'extra_per': [30, 100], 'max': 1500}, 150), ({'minutes': 151, 'tiers': [[30, 200], [240, 1250]], 'extra_per': [15, 100], 'max': 1500}, 1250), ({'minutes': 291, 'tiers': [[300, 1700], [30, 500], [150, 1400]], 'extra_per': [30, 150], 'max': 4000}, 1700), ({'minutes': 68, 'tiers': [[120, 1100], [330, 1550]], 'extra_per': [30, 150], 'max': 4000}, 1100)]]
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 fixtureActualExpectedOutcome
fee oracle 025002500Passed
fee oracle 1150150Passed
fee oracle 214501450Passed
fee oracle 3900900Passed
fee oracle 414001400Passed
fee oracle 500Passed
fee oracle 6200200Passed
fee oracle 718001800Passed

SHA-256 / 1181acefc4e817ebb47d9a0e0ede0caf1eb383909c969a0b3aefbe7fd2d054f1

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.696836+00:00.

Case digest / 71a94692614aa29fcee4d9f732fd47b02c998543045bda269b594f72aca0dc33