FAILURE MAP
← Case archive

FA-85786 / Ride-hailing fare and surge pricing / Open access

Hourly waiting rate applied per minute · case 01

Waiting in traffic costs sixty times the tariff.

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

ROOT CAUSE

Seconds are divided by 60 for an hourly rate.

VERIFIED REPAIR

Divide seconds by 3600 for per-hour rates.

Unsuccessful approach: Flooring each time segment to whole cents loses fractional waiting charges.

Case contract

A single-tariff taximeter bills each segment [seconds, meters] by distance when its speed is at least v m/s (meters >= v*seconds, so a zero-duration movement bills distance) and by time otherwise, never both. Charges accumulate exactly (per_km per 1000 m, per_hour per 3600 s) and the total is rounded half up to a cent once, then the flag fall is added.

Why this case matters

Ride-hailing prices are computed per trip at scale; ordering, unit and boundary slips become systematic over- or under-charging.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
from fractions import Fraction
N = 1
observations = []
def solve(segments, rate):
    acc = Fraction(0)
    for dt, dm in segments:
        if dm >= rate['v'] * dt:
            acc += Fraction(dm * rate['per_km'], 1000)
        else:
            acc += Fraction(dt * rate['per_hour'], 60)
    cents = int(acc * 2 + 1) // 2
    return rate['flag'] + cents
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: hourly rate unit',
   [[[0, 7], [30, 150], [10, 50], [10, 0], [10, 49], [1, 7]],
    {'flag': 390, 'per_hour': 3600, 'per_km': 199, 'v': 5}],
   453),
  ('partial repair probe: hourly rate unit',
   [[[30, 7], [5, 7], [0, 0]], {'flag': 390, 'per_hour': 4150, 'per_km': 230, 'v': 5}], 430),
  ('second regression', [[[5, 24], [10, 0]], {'flag': 300, 'per_hour': 3600, 'per_km': 199, 'v': 5}], 315),
  ('normal control 1', [[[0, 0], [1, 7]], {'flag': 300, 'per_hour': 4150, 'per_km': 245, 'v': 5}], 302),
  ('normal control 2', [[[0, 3], [10, 110], [1, 5]], {'flag': 300, 'per_hour': 3900, 'per_km': 230, 'v': 5}],
   327),
  ('normal control 3', [[[30, 330]], {'flag': 300, 'per_hour': 4150, 'per_km': 245, 'v': 5}], 381),
  ('normal control 4', [[[5, 28], [1, 5]], {'flag': 390, 'per_hour': 4150, 'per_km': 199, 'v': 5}], 397)],
 [('regression: hourly rate unit',
   [[[10, 20], [0, 0], [30, 330], [5, 25], [1, 0], [0, 0]],
    {'flag': 390, 'per_hour': 3900, 'per_km': 245, 'v': 5}],
   489),
  ('partial repair probe: hourly rate unit',
   [[[30, 149], [1, 11], [5, 25]], {'flag': 300, 'per_hour': 4150, 'per_km': 199, 'v': 5}], 342),
  ('second regression',
   [[[10, 0], [30, 0], [10, 50], [30, 150], [10, 110], [1, 11]],
    {'flag': 390, 'per_hour': 4150, 'per_km': 230, 'v': 5}],
   510),
  ('normal control 1', [[[1, 5], [1, 11]], {'flag': 300, 'per_hour': 3600, 'per_km': 245, 'v': 5}], 304),
  ('normal control 2', [[[5, 25], [30, 330]], {'flag': 300, 'per_hour': 3900, 'per_km': 245, 'v': 5}], 387),
  ('normal control 3', [[[5, 28]], {'flag': 390, 'per_hour': 3900, 'per_km': 230, 'v': 5}], 396),
  ('normal control 4', [[[0, 0]], {'flag': 300, 'per_hour': 4150, 'per_km': 230, 'v': 5}], 300)],
 [('regression: hourly rate unit',
   [[[10, 0], [1, 11], [0, 0], [0, 7], [0, 0], [10, 7]],
    {'flag': 300, 'per_hour': 3600, 'per_km': 199, 'v': 5}],
   324),
  ('partial repair probe: hourly rate unit',
   [[[0, 0], [30, 330], [5, 10], [30, 330]], {'flag': 390, 'per_hour': 4150, 'per_km': 199, 'v': 5}], 527),
  ('second regression', [[[0, 0], [10, 20]], {'flag': 300, 'per_hour': 3600, 'per_km': 230, 'v': 5}], 310),
  ('normal control 1', [[[1, 7], [1, 8], [0, 3]], {'flag': 300, 'per_hour': 4150, 'per_km': 199, 'v': 5}],
   304),
  ('normal control 2', [[[1, 5]], {'flag': 390, 'per_hour': 3900, 'per_km': 199, 'v': 5}], 391),
  ('normal control 3', [[[0, 0]], {'flag': 390, 'per_hour': 4150, 'per_km': 199, 'v': 5}], 390),
  ('normal control 4', [[[30, 150]], {'flag': 300, 'per_hour': 3600, 'per_km': 230, 'v': 5}], 335)],
 [('regression: hourly rate unit',
   [[[30, 153], [30, 330], [30, 149], [1, 7], [30, 149]],
    {'flag': 390, 'per_hour': 3600, 'per_km': 199, 'v': 5}],
   548),
  ('partial repair probe: hourly rate unit',
   [[[0, 0], [10, 0], [10, 50], [10, 7], [10, 110], [1, 8]],
    {'flag': 300, 'per_hour': 3900, 'per_km': 245, 'v': 5}],
   363),
  ('second regression',
   [[[5, 0], [10, 110], [0, 0], [10, 53], [0, 0], [10, 7]],
    {'flag': 390, 'per_hour': 3600, 'per_km': 199, 'v': 5}],
   437),
  ('normal control 1', [[[0, 0], [10, 53]], {'flag': 300, 'per_hour': 3600, 'per_km': 245, 'v': 5}], 313),
  ('normal control 2', [[[30, 150]], {'flag': 300, 'per_hour': 4150, 'per_km': 245, 'v': 5}], 337),
  ('normal control 3',
   [[[0, 0], [10, 110], [0, 0], [0, 0]], {'flag': 390, 'per_hour': 4150, 'per_km': 199, 'v': 5}], 412),
  ('normal control 4', [[[10, 53], [1, 5]], {'flag': 390, 'per_hour': 3900, 'per_km': 230, 'v': 5}], 403)],
 [('regression: hourly rate unit',
   [[[0, 0], [10, 0], [1, 7], [1, 2]], {'flag': 300, 'per_hour': 3600, 'per_km': 199, 'v': 5}], 312),
  ('partial repair probe: hourly rate unit',
   [[[30, 153], [5, 10], [30, 149], [1, 8]], {'flag': 390, 'per_hour': 3900, 'per_km': 199, 'v': 5}], 460),
  ('second regression',
   [[[1, 11], [1, 5], [1, 7], [10, 0], [30, 150]], {'flag': 390, 'per_hour': 4150, 'per_km': 245, 'v': 5}],
   444),
  ('normal control 1',
   [[[1, 7], [30, 150], [10, 53], [0, 0]], {'flag': 390, 'per_hour': 4150, 'per_km': 245, 'v': 5}], 441),
  ('normal control 2', [[[0, 0]], {'flag': 300, 'per_hour': 3600, 'per_km': 199, 'v': 5}], 300),
  ('normal control 3', [[[10, 50]], {'flag': 300, 'per_hour': 3900, 'per_km': 245, 'v': 5}], 312),
  ('normal control 4', [[[0, 0]], {'flag': 390, 'per_hour': 4150, 'per_km': 245, 'v': 5}], 390)]]
for label, args, expected in fixtures[N-1]:
    check(label, 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
regression: hourly rate unit1633453Failed
partial repair probe: hourly rate unit2811430Failed
second regression1200315Failed
normal control 1302302Passed
normal control 2327327Passed
normal control 3381381Passed
normal control 4397397Passed

SHA-256 / 311ff52e570b0dcfabf9876a0386906c3f29d044c3ec7a5c956be211ac340eaa

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
from fractions import Fraction
N = 1
observations = []
def solve(segments, rate):
    acc = Fraction(0)
    for dt, dm in segments:
        if dm >= rate['v'] * dt:
            acc += Fraction(dm * rate['per_km'], 1000)
        else:
            acc += dt * rate['per_hour'] // 3600
    cents = int(acc * 2 + 1) // 2
    return rate['flag'] + cents
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: hourly rate unit',
   [[[0, 7], [30, 150], [10, 50], [10, 0], [10, 49], [1, 7]],
    {'flag': 390, 'per_hour': 3600, 'per_km': 199, 'v': 5}],
   453),
  ('partial repair probe: hourly rate unit',
   [[[30, 7], [5, 7], [0, 0]], {'flag': 390, 'per_hour': 4150, 'per_km': 230, 'v': 5}], 430),
  ('second regression', [[[5, 24], [10, 0]], {'flag': 300, 'per_hour': 3600, 'per_km': 199, 'v': 5}], 315),
  ('normal control 1', [[[0, 0], [1, 7]], {'flag': 300, 'per_hour': 4150, 'per_km': 245, 'v': 5}], 302),
  ('normal control 2', [[[0, 3], [10, 110], [1, 5]], {'flag': 300, 'per_hour': 3900, 'per_km': 230, 'v': 5}],
   327),
  ('normal control 3', [[[30, 330]], {'flag': 300, 'per_hour': 4150, 'per_km': 245, 'v': 5}], 381),
  ('normal control 4', [[[5, 28], [1, 5]], {'flag': 390, 'per_hour': 4150, 'per_km': 199, 'v': 5}], 397)],
 [('regression: hourly rate unit',
   [[[10, 20], [0, 0], [30, 330], [5, 25], [1, 0], [0, 0]],
    {'flag': 390, 'per_hour': 3900, 'per_km': 245, 'v': 5}],
   489),
  ('partial repair probe: hourly rate unit',
   [[[30, 149], [1, 11], [5, 25]], {'flag': 300, 'per_hour': 4150, 'per_km': 199, 'v': 5}], 342),
  ('second regression',
   [[[10, 0], [30, 0], [10, 50], [30, 150], [10, 110], [1, 11]],
    {'flag': 390, 'per_hour': 4150, 'per_km': 230, 'v': 5}],
   510),
  ('normal control 1', [[[1, 5], [1, 11]], {'flag': 300, 'per_hour': 3600, 'per_km': 245, 'v': 5}], 304),
  ('normal control 2', [[[5, 25], [30, 330]], {'flag': 300, 'per_hour': 3900, 'per_km': 245, 'v': 5}], 387),
  ('normal control 3', [[[5, 28]], {'flag': 390, 'per_hour': 3900, 'per_km': 230, 'v': 5}], 396),
  ('normal control 4', [[[0, 0]], {'flag': 300, 'per_hour': 4150, 'per_km': 230, 'v': 5}], 300)],
 [('regression: hourly rate unit',
   [[[10, 0], [1, 11], [0, 0], [0, 7], [0, 0], [10, 7]],
    {'flag': 300, 'per_hour': 3600, 'per_km': 199, 'v': 5}],
   324),
  ('partial repair probe: hourly rate unit',
   [[[0, 0], [30, 330], [5, 10], [30, 330]], {'flag': 390, 'per_hour': 4150, 'per_km': 199, 'v': 5}], 527),
  ('second regression', [[[0, 0], [10, 20]], {'flag': 300, 'per_hour': 3600, 'per_km': 230, 'v': 5}], 310),
  ('normal control 1', [[[1, 7], [1, 8], [0, 3]], {'flag': 300, 'per_hour': 4150, 'per_km': 199, 'v': 5}],
   304),
  ('normal control 2', [[[1, 5]], {'flag': 390, 'per_hour': 3900, 'per_km': 199, 'v': 5}], 391),
  ('normal control 3', [[[0, 0]], {'flag': 390, 'per_hour': 4150, 'per_km': 199, 'v': 5}], 390),
  ('normal control 4', [[[30, 150]], {'flag': 300, 'per_hour': 3600, 'per_km': 230, 'v': 5}], 335)],
 [('regression: hourly rate unit',
   [[[30, 153], [30, 330], [30, 149], [1, 7], [30, 149]],
    {'flag': 390, 'per_hour': 3600, 'per_km': 199, 'v': 5}],
   548),
  ('partial repair probe: hourly rate unit',
   [[[0, 0], [10, 0], [10, 50], [10, 7], [10, 110], [1, 8]],
    {'flag': 300, 'per_hour': 3900, 'per_km': 245, 'v': 5}],
   363),
  ('second regression',
   [[[5, 0], [10, 110], [0, 0], [10, 53], [0, 0], [10, 7]],
    {'flag': 390, 'per_hour': 3600, 'per_km': 199, 'v': 5}],
   437),
  ('normal control 1', [[[0, 0], [10, 53]], {'flag': 300, 'per_hour': 3600, 'per_km': 245, 'v': 5}], 313),
  ('normal control 2', [[[30, 150]], {'flag': 300, 'per_hour': 4150, 'per_km': 245, 'v': 5}], 337),
  ('normal control 3',
   [[[0, 0], [10, 110], [0, 0], [0, 0]], {'flag': 390, 'per_hour': 4150, 'per_km': 199, 'v': 5}], 412),
  ('normal control 4', [[[10, 53], [1, 5]], {'flag': 390, 'per_hour': 3900, 'per_km': 230, 'v': 5}], 403)],
 [('regression: hourly rate unit',
   [[[0, 0], [10, 0], [1, 7], [1, 2]], {'flag': 300, 'per_hour': 3600, 'per_km': 199, 'v': 5}], 312),
  ('partial repair probe: hourly rate unit',
   [[[30, 153], [5, 10], [30, 149], [1, 8]], {'flag': 390, 'per_hour': 3900, 'per_km': 199, 'v': 5}], 460),
  ('second regression',
   [[[1, 11], [1, 5], [1, 7], [10, 0], [30, 150]], {'flag': 390, 'per_hour': 4150, 'per_km': 245, 'v': 5}],
   444),
  ('normal control 1',
   [[[1, 7], [30, 150], [10, 53], [0, 0]], {'flag': 390, 'per_hour': 4150, 'per_km': 245, 'v': 5}], 441),
  ('normal control 2', [[[0, 0]], {'flag': 300, 'per_hour': 3600, 'per_km': 199, 'v': 5}], 300),
  ('normal control 3', [[[10, 50]], {'flag': 300, 'per_hour': 3900, 'per_km': 245, 'v': 5}], 312),
  ('normal control 4', [[[0, 0]], {'flag': 390, 'per_hour': 4150, 'per_km': 245, 'v': 5}], 390)]]
for label, args, expected in fixtures[N-1]:
    check(label, 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
regression: hourly rate unit453453Passed
partial repair probe: hourly rate unit429430Failed
second regression315315Passed
normal control 1302302Passed
normal control 2327327Passed
normal control 3381381Passed
normal control 4397397Passed

SHA-256 / 84cdb236bdf32fbb89a197e14513c75a1bb4d3c08fc21673656f5ba120d4b89b

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json
from fractions import Fraction
N = 1
observations = []
def solve(segments, rate):
    acc = Fraction(0)
    for dt, dm in segments:
        if dm >= rate['v'] * dt:
            acc += Fraction(dm * rate['per_km'], 1000)
        else:
            acc += Fraction(dt * rate['per_hour'], 3600)
    cents = int(acc * 2 + 1) // 2
    return rate['flag'] + cents
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: hourly rate unit',
   [[[0, 7], [30, 150], [10, 50], [10, 0], [10, 49], [1, 7]],
    {'flag': 390, 'per_hour': 3600, 'per_km': 199, 'v': 5}],
   453),
  ('partial repair probe: hourly rate unit',
   [[[30, 7], [5, 7], [0, 0]], {'flag': 390, 'per_hour': 4150, 'per_km': 230, 'v': 5}], 430),
  ('second regression', [[[5, 24], [10, 0]], {'flag': 300, 'per_hour': 3600, 'per_km': 199, 'v': 5}], 315),
  ('normal control 1', [[[0, 0], [1, 7]], {'flag': 300, 'per_hour': 4150, 'per_km': 245, 'v': 5}], 302),
  ('normal control 2', [[[0, 3], [10, 110], [1, 5]], {'flag': 300, 'per_hour': 3900, 'per_km': 230, 'v': 5}],
   327),
  ('normal control 3', [[[30, 330]], {'flag': 300, 'per_hour': 4150, 'per_km': 245, 'v': 5}], 381),
  ('normal control 4', [[[5, 28], [1, 5]], {'flag': 390, 'per_hour': 4150, 'per_km': 199, 'v': 5}], 397)],
 [('regression: hourly rate unit',
   [[[10, 20], [0, 0], [30, 330], [5, 25], [1, 0], [0, 0]],
    {'flag': 390, 'per_hour': 3900, 'per_km': 245, 'v': 5}],
   489),
  ('partial repair probe: hourly rate unit',
   [[[30, 149], [1, 11], [5, 25]], {'flag': 300, 'per_hour': 4150, 'per_km': 199, 'v': 5}], 342),
  ('second regression',
   [[[10, 0], [30, 0], [10, 50], [30, 150], [10, 110], [1, 11]],
    {'flag': 390, 'per_hour': 4150, 'per_km': 230, 'v': 5}],
   510),
  ('normal control 1', [[[1, 5], [1, 11]], {'flag': 300, 'per_hour': 3600, 'per_km': 245, 'v': 5}], 304),
  ('normal control 2', [[[5, 25], [30, 330]], {'flag': 300, 'per_hour': 3900, 'per_km': 245, 'v': 5}], 387),
  ('normal control 3', [[[5, 28]], {'flag': 390, 'per_hour': 3900, 'per_km': 230, 'v': 5}], 396),
  ('normal control 4', [[[0, 0]], {'flag': 300, 'per_hour': 4150, 'per_km': 230, 'v': 5}], 300)],
 [('regression: hourly rate unit',
   [[[10, 0], [1, 11], [0, 0], [0, 7], [0, 0], [10, 7]],
    {'flag': 300, 'per_hour': 3600, 'per_km': 199, 'v': 5}],
   324),
  ('partial repair probe: hourly rate unit',
   [[[0, 0], [30, 330], [5, 10], [30, 330]], {'flag': 390, 'per_hour': 4150, 'per_km': 199, 'v': 5}], 527),
  ('second regression', [[[0, 0], [10, 20]], {'flag': 300, 'per_hour': 3600, 'per_km': 230, 'v': 5}], 310),
  ('normal control 1', [[[1, 7], [1, 8], [0, 3]], {'flag': 300, 'per_hour': 4150, 'per_km': 199, 'v': 5}],
   304),
  ('normal control 2', [[[1, 5]], {'flag': 390, 'per_hour': 3900, 'per_km': 199, 'v': 5}], 391),
  ('normal control 3', [[[0, 0]], {'flag': 390, 'per_hour': 4150, 'per_km': 199, 'v': 5}], 390),
  ('normal control 4', [[[30, 150]], {'flag': 300, 'per_hour': 3600, 'per_km': 230, 'v': 5}], 335)],
 [('regression: hourly rate unit',
   [[[30, 153], [30, 330], [30, 149], [1, 7], [30, 149]],
    {'flag': 390, 'per_hour': 3600, 'per_km': 199, 'v': 5}],
   548),
  ('partial repair probe: hourly rate unit',
   [[[0, 0], [10, 0], [10, 50], [10, 7], [10, 110], [1, 8]],
    {'flag': 300, 'per_hour': 3900, 'per_km': 245, 'v': 5}],
   363),
  ('second regression',
   [[[5, 0], [10, 110], [0, 0], [10, 53], [0, 0], [10, 7]],
    {'flag': 390, 'per_hour': 3600, 'per_km': 199, 'v': 5}],
   437),
  ('normal control 1', [[[0, 0], [10, 53]], {'flag': 300, 'per_hour': 3600, 'per_km': 245, 'v': 5}], 313),
  ('normal control 2', [[[30, 150]], {'flag': 300, 'per_hour': 4150, 'per_km': 245, 'v': 5}], 337),
  ('normal control 3',
   [[[0, 0], [10, 110], [0, 0], [0, 0]], {'flag': 390, 'per_hour': 4150, 'per_km': 199, 'v': 5}], 412),
  ('normal control 4', [[[10, 53], [1, 5]], {'flag': 390, 'per_hour': 3900, 'per_km': 230, 'v': 5}], 403)],
 [('regression: hourly rate unit',
   [[[0, 0], [10, 0], [1, 7], [1, 2]], {'flag': 300, 'per_hour': 3600, 'per_km': 199, 'v': 5}], 312),
  ('partial repair probe: hourly rate unit',
   [[[30, 153], [5, 10], [30, 149], [1, 8]], {'flag': 390, 'per_hour': 3900, 'per_km': 199, 'v': 5}], 460),
  ('second regression',
   [[[1, 11], [1, 5], [1, 7], [10, 0], [30, 150]], {'flag': 390, 'per_hour': 4150, 'per_km': 245, 'v': 5}],
   444),
  ('normal control 1',
   [[[1, 7], [30, 150], [10, 53], [0, 0]], {'flag': 390, 'per_hour': 4150, 'per_km': 245, 'v': 5}], 441),
  ('normal control 2', [[[0, 0]], {'flag': 300, 'per_hour': 3600, 'per_km': 199, 'v': 5}], 300),
  ('normal control 3', [[[10, 50]], {'flag': 300, 'per_hour': 3900, 'per_km': 245, 'v': 5}], 312),
  ('normal control 4', [[[0, 0]], {'flag': 390, 'per_hour': 4150, 'per_km': 245, 'v': 5}], 390)]]
for label, args, expected in fixtures[N-1]:
    check(label, 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
regression: hourly rate unit453453Passed
partial repair probe: hourly rate unit430430Passed
second regression315315Passed
normal control 1302302Passed
normal control 2327327Passed
normal control 3381381Passed
normal control 4397397Passed

SHA-256 / cdaf4ee9a2f53ecc03dbbbb53a1e7ee8983eb12f1c8e152f2db5e1a2bfb37c03

Verification & scope

A deterministic toy pricing contract stipulated for this example; it does not reproduce the pricing of any real ride-hailing operator or regulator. 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:50:43.563841+00:00.

Case digest / ad5b28cde0bc6954d31dee0c5bd8d3dca75ec59f92d6eedd21de007bddddafd7