broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    base = x['base']
    if x['resident']:
        base -= base * x['resident_pct'] // 100
    tax = (x['base'] * x['tax_bp'] + 5000) // 10000
    total = base + tax + x['surcharge']
    if x['app']:
        total += x['app_fee'] + (x['app_fee'] * x['tax_bp'] + 5000) // 10000
    return {'base': base, 'tax': tax, 'total': total}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[({'base': 2637, 'resident': False, 'resident_pct': 20, 'tax_bp': 625, 'surcharge': 0, 'app': True, 'app_fee': 45}, {'base': 2637, 'tax': 165, 'total': 2850}), ({'base': 1530, 'resident': False, 'resident_pct': 20, 'tax_bp': 2250, 'surcharge': 0, 'app': False, 'app_fee': 35}, {'base': 1530, 'tax': 344, 'total': 1874}), ({'base': 3784, 'resident': False, 'resident_pct': 25, 'tax_bp': 2250, 'surcharge': 0, 'app': False, 'app_fee': 25}, {'base': 3784, 'tax': 851, 'total': 4635}), ({'base': 1000, 'resident': True, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 150, 'app': True, 'app_fee': 35}, {'base': 750, 'tax': 139, 'total': 1080}), ({'base': 2503, 'resident': True, 'resident_pct': 50, 'tax_bp': 1850, 'surcharge': 50, 'app': True, 'app_fee': 35}, {'base': 1252, 'tax': 232, 'total': 1575}), ({'base': 2025, 'resident': False, 'resident_pct': 25, 'tax_bp': 2250, 'surcharge': 0, 'app': True, 'app_fee': 25}, {'base': 2025, 'tax': 456, 'total': 2512}), ({'base': 2199, 'resident': True, 'resident_pct': 50, 'tax_bp': 1000, 'surcharge': 50, 'app': False, 'app_fee': 45}, {'base': 1100, 'tax': 110, 'total': 1260}), ({'base': 3824, 'resident': False, 'resident_pct': 50, 'tax_bp': 1850, 'surcharge': 50, 'app': True, 'app_fee': 45}, {'base': 3824, 'tax': 707, 'total': 4634})], [({'base': 1899, 'resident': False, 'resident_pct': 20, 'tax_bp': 2250, 'surcharge': 0, 'app': True, 'app_fee': 35}, {'base': 1899, 'tax': 427, 'total': 2369}), ({'base': 1080, 'resident': True, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 150, 'app': False, 'app_fee': 35}, {'base': 810, 'tax': 150, 'total': 1110}), ({'base': 586, 'resident': False, 'resident_pct': 20, 'tax_bp': 2250, 'surcharge': 0, 'app': False, 'app_fee': 25}, {'base': 586, 'tax': 132, 'total': 718}), ({'base': 1000, 'resident': True, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 150, 'app': True, 'app_fee': 35}, {'base': 750, 'tax': 139, 'total': 1080}), ({'base': 2094, 'resident': False, 'resident_pct': 25, 'tax_bp': 2250, 'surcharge': 150, 'app': True, 'app_fee': 45}, {'base': 2094, 'tax': 471, 'total': 2770}), ({'base': 2383, 'resident': True, 'resident_pct': 50, 'tax_bp': 1000, 'surcharge': 50, 'app': True, 'app_fee': 25}, {'base': 1192, 'tax': 119, 'total': 1389}), ({'base': 554, 'resident': False, 'resident_pct': 50, 'tax_bp': 1850, 'surcharge': 0, 'app': True, 'app_fee': 25}, {'base': 554, 'tax': 102, 'total': 686}), ({'base': 4806, 'resident': False, 'resident_pct': 20, 'tax_bp': 1000, 'surcharge': 0, 'app': True, 'app_fee': 25}, {'base': 4806, 'tax': 481, 'total': 5315})], [({'base': 2199, 'resident': False, 'resident_pct': 25, 'tax_bp': 1000, 'surcharge': 0, 'app': True, 'app_fee': 35}, {'base': 2199, 'tax': 220, 'total': 2458}), ({'base': 4132, 'resident': True, 'resident_pct': 50, 'tax_bp': 2250, 'surcharge': 150, 'app': False, 'app_fee': 35}, {'base': 2066, 'tax': 465, 'total': 2681}), ({'base': 2238, 'resident': False, 'resident_pct': 20, 'tax_bp': 1850, 'surcharge': 0, 'app': True, 'app_fee': 25}, {'base': 2238, 'tax': 414, 'total': 2682}), ({'base': 4457, 'resident': True, 'resident_pct': 25, 'tax_bp': 2250, 'surcharge': 50, 'app': True, 'app_fee': 35}, {'base': 3343, 'tax': 752, 'total': 4188}), ({'base': 4324, 'resident': False, 'resident_pct': 25, 'tax_bp': 1000, 'surcharge': 0, 'app': True, 'app_fee': 25}, {'base': 4324, 'tax': 432, 'total': 4784}), ({'base': 2603, 'resident': False, 'resident_pct': 20, 'tax_bp': 2250, 'surcharge': 0, 'app': False, 'app_fee': 35}, {'base': 2603, 'tax': 586, 'total': 3189}), ({'base': 985, 'resident': True, 'resident_pct': 25, 'tax_bp': 2250, 'surcharge': 150, 'app': True, 'app_fee': 25}, {'base': 739, 'tax': 166, 'total': 1086}), ({'base': 1000, 'resident': True, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 150, 'app': True, 'app_fee': 35}, {'base': 750, 'tax': 139, 'total': 1080})], [({'base': 2930, 'resident': False, 'resident_pct': 50, 'tax_bp': 2250, 'surcharge': 150, 'app': True, 'app_fee': 25}, {'base': 2930, 'tax': 659, 'total': 3770}), ({'base': 1844, 'resident': False, 'resident_pct': 20, 'tax_bp': 1850, 'surcharge': 0, 'app': False, 'app_fee': 25}, {'base': 1844, 'tax': 341, 'total': 2185}), ({'base': 1000, 'resident': True, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 150, 'app': True, 'app_fee': 35}, {'base': 750, 'tax': 139, 'total': 1080}), ({'base': 4678, 'resident': True, 'resident_pct': 25, 'tax_bp': 625, 'surcharge': 150, 'app': True, 'app_fee': 35}, {'base': 3509, 'tax': 219, 'total': 3915}), ({'base': 4200, 'resident': False, 'resident_pct': 20, 'tax_bp': 625, 'surcharge': 0, 'app': True, 'app_fee': 25}, {'base': 4200, 'tax': 263, 'total': 4490}), ({'base': 4301, 'resident': True, 'resident_pct': 25, 'tax_bp': 625, 'surcharge': 0, 'app': False, 'app_fee': 45}, {'base': 3226, 'tax': 202, 'total': 3428}), ({'base': 3641, 'resident': False, 'resident_pct': 20, 'tax_bp': 1850, 'surcharge': 0, 'app': True, 'app_fee': 35}, {'base': 3641, 'tax': 674, 'total': 4356}), ({'base': 1783, 'resident': False, 'resident_pct': 50, 'tax_bp': 1000, 'surcharge': 0, 'app': False, 'app_fee': 45}, {'base': 1783, 'tax': 178, 'total': 1961})], [({'base': 4884, 'resident': False, 'resident_pct': 20, 'tax_bp': 1000, 'surcharge': 150, 'app': True, 'app_fee': 35}, {'base': 4884, 'tax': 488, 'total': 5561}), ({'base': 1000, 'resident': True, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 150, 'app': True, 'app_fee': 35}, {'base': 750, 'tax': 139, 'total': 1080}), ({'base': 2807, 'resident': True, 'resident_pct': 25, 'tax_bp': 1000, 'surcharge': 0, 'app': False, 'app_fee': 25}, {'base': 2106, 'tax': 211, 'total': 2317}), ({'base': 1234, 'resident': False, 'resident_pct': 20, 'tax_bp': 2250, 'surcharge': 0, 'app': False, 'app_fee': 35}, {'base': 1234, 'tax': 278, 'total': 1512}), ({'base': 398, 'resident': False, 'resident_pct': 20, 'tax_bp': 2250, 'surcharge': 0, 'app': False, 'app_fee': 45}, {'base': 398, 'tax': 90, 'total': 488}), ({'base': 1292, 'resident': True, 'resident_pct': 25, 'tax_bp': 2250, 'surcharge': 0, 'app': False, 'app_fee': 25}, {'base': 969, 'tax': 218, 'total': 1187}), ({'base': 3586, 'resident': False, 'resident_pct': 50, 'tax_bp': 1850, 'surcharge': 0, 'app': True, 'app_fee': 45}, {'base': 3586, 'tax': 663, 'total': 4302}), ({'base': 4846, 'resident': False, 'resident_pct': 50, 'tax_bp': 1000, 'surcharge': 0, 'app': False, 'app_fee': 25}, {'base': 4846, 'tax': 485, 'total': 5331})]]
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)

source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    base = x['base']
    if x['resident']:
        base -= base * x['resident_pct'] // 100
    tax = ((base + x['surcharge']) * x['tax_bp'] + 5000) // 10000
    total = base + tax + x['surcharge']
    if x['app']:
        total += x['app_fee'] + (x['app_fee'] * x['tax_bp'] + 5000) // 10000
    return {'base': base, 'tax': tax, 'total': total}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[({'base': 2637, 'resident': False, 'resident_pct': 20, 'tax_bp': 625, 'surcharge': 0, 'app': True, 'app_fee': 45}, {'base': 2637, 'tax': 165, 'total': 2850}), ({'base': 1530, 'resident': False, 'resident_pct': 20, 'tax_bp': 2250, 'surcharge': 0, 'app': False, 'app_fee': 35}, {'base': 1530, 'tax': 344, 'total': 1874}), ({'base': 3784, 'resident': False, 'resident_pct': 25, 'tax_bp': 2250, 'surcharge': 0, 'app': False, 'app_fee': 25}, {'base': 3784, 'tax': 851, 'total': 4635}), ({'base': 1000, 'resident': True, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 150, 'app': True, 'app_fee': 35}, {'base': 750, 'tax': 139, 'total': 1080}), ({'base': 2503, 'resident': True, 'resident_pct': 50, 'tax_bp': 1850, 'surcharge': 50, 'app': True, 'app_fee': 35}, {'base': 1252, 'tax': 232, 'total': 1575}), ({'base': 2025, 'resident': False, 'resident_pct': 25, 'tax_bp': 2250, 'surcharge': 0, 'app': True, 'app_fee': 25}, {'base': 2025, 'tax': 456, 'total': 2512}), ({'base': 2199, 'resident': True, 'resident_pct': 50, 'tax_bp': 1000, 'surcharge': 50, 'app': False, 'app_fee': 45}, {'base': 1100, 'tax': 110, 'total': 1260}), ({'base': 3824, 'resident': False, 'resident_pct': 50, 'tax_bp': 1850, 'surcharge': 50, 'app': True, 'app_fee': 45}, {'base': 3824, 'tax': 707, 'total': 4634})], [({'base': 1899, 'resident': False, 'resident_pct': 20, 'tax_bp': 2250, 'surcharge': 0, 'app': True, 'app_fee': 35}, {'base': 1899, 'tax': 427, 'total': 2369}), ({'base': 1080, 'resident': True, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 150, 'app': False, 'app_fee': 35}, {'base': 810, 'tax': 150, 'total': 1110}), ({'base': 586, 'resident': False, 'resident_pct': 20, 'tax_bp': 2250, 'surcharge': 0, 'app': False, 'app_fee': 25}, {'base': 586, 'tax': 132, 'total': 718}), ({'base': 1000, 'resident': True, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 150, 'app': True, 'app_fee': 35}, {'base': 750, 'tax': 139, 'total': 1080}), ({'base': 2094, 'resident': False, 'resident_pct': 25, 'tax_bp': 2250, 'surcharge': 150, 'app': True, 'app_fee': 45}, {'base': 2094, 'tax': 471, 'total': 2770}), ({'base': 2383, 'resident': True, 'resident_pct': 50, 'tax_bp': 1000, 'surcharge': 50, 'app': True, 'app_fee': 25}, {'base': 1192, 'tax': 119, 'total': 1389}), ({'base': 554, 'resident': False, 'resident_pct': 50, 'tax_bp': 1850, 'surcharge': 0, 'app': True, 'app_fee': 25}, {'base': 554, 'tax': 102, 'total': 686}), ({'base': 4806, 'resident': False, 'resident_pct': 20, 'tax_bp': 1000, 'surcharge': 0, 'app': True, 'app_fee': 25}, {'base': 4806, 'tax': 481, 'total': 5315})], [({'base': 2199, 'resident': False, 'resident_pct': 25, 'tax_bp': 1000, 'surcharge': 0, 'app': True, 'app_fee': 35}, {'base': 2199, 'tax': 220, 'total': 2458}), ({'base': 4132, 'resident': True, 'resident_pct': 50, 'tax_bp': 2250, 'surcharge': 150, 'app': False, 'app_fee': 35}, {'base': 2066, 'tax': 465, 'total': 2681}), ({'base': 2238, 'resident': False, 'resident_pct': 20, 'tax_bp': 1850, 'surcharge': 0, 'app': True, 'app_fee': 25}, {'base': 2238, 'tax': 414, 'total': 2682}), ({'base': 4457, 'resident': True, 'resident_pct': 25, 'tax_bp': 2250, 'surcharge': 50, 'app': True, 'app_fee': 35}, {'base': 3343, 'tax': 752, 'total': 4188}), ({'base': 4324, 'resident': False, 'resident_pct': 25, 'tax_bp': 1000, 'surcharge': 0, 'app': True, 'app_fee': 25}, {'base': 4324, 'tax': 432, 'total': 4784}), ({'base': 2603, 'resident': False, 'resident_pct': 20, 'tax_bp': 2250, 'surcharge': 0, 'app': False, 'app_fee': 35}, {'base': 2603, 'tax': 586, 'total': 3189}), ({'base': 985, 'resident': True, 'resident_pct': 25, 'tax_bp': 2250, 'surcharge': 150, 'app': True, 'app_fee': 25}, {'base': 739, 'tax': 166, 'total': 1086}), ({'base': 1000, 'resident': True, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 150, 'app': True, 'app_fee': 35}, {'base': 750, 'tax': 139, 'total': 1080})], [({'base': 2930, 'resident': False, 'resident_pct': 50, 'tax_bp': 2250, 'surcharge': 150, 'app': True, 'app_fee': 25}, {'base': 2930, 'tax': 659, 'total': 3770}), ({'base': 1844, 'resident': False, 'resident_pct': 20, 'tax_bp': 1850, 'surcharge': 0, 'app': False, 'app_fee': 25}, {'base': 1844, 'tax': 341, 'total': 2185}), ({'base': 1000, 'resident': True, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 150, 'app': True, 'app_fee': 35}, {'base': 750, 'tax': 139, 'total': 1080}), ({'base': 4678, 'resident': True, 'resident_pct': 25, 'tax_bp': 625, 'surcharge': 150, 'app': True, 'app_fee': 35}, {'base': 3509, 'tax': 219, 'total': 3915}), ({'base': 4200, 'resident': False, 'resident_pct': 20, 'tax_bp': 625, 'surcharge': 0, 'app': True, 'app_fee': 25}, {'base': 4200, 'tax': 263, 'total': 4490}), ({'base': 4301, 'resident': True, 'resident_pct': 25, 'tax_bp': 625, 'surcharge': 0, 'app': False, 'app_fee': 45}, {'base': 3226, 'tax': 202, 'total': 3428}), ({'base': 3641, 'resident': False, 'resident_pct': 20, 'tax_bp': 1850, 'surcharge': 0, 'app': True, 'app_fee': 35}, {'base': 3641, 'tax': 674, 'total': 4356}), ({'base': 1783, 'resident': False, 'resident_pct': 50, 'tax_bp': 1000, 'surcharge': 0, 'app': False, 'app_fee': 45}, {'base': 1783, 'tax': 178, 'total': 1961})], [({'base': 4884, 'resident': False, 'resident_pct': 20, 'tax_bp': 1000, 'surcharge': 150, 'app': True, 'app_fee': 35}, {'base': 4884, 'tax': 488, 'total': 5561}), ({'base': 1000, 'resident': True, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 150, 'app': True, 'app_fee': 35}, {'base': 750, 'tax': 139, 'total': 1080}), ({'base': 2807, 'resident': True, 'resident_pct': 25, 'tax_bp': 1000, 'surcharge': 0, 'app': False, 'app_fee': 25}, {'base': 2106, 'tax': 211, 'total': 2317}), ({'base': 1234, 'resident': False, 'resident_pct': 20, 'tax_bp': 2250, 'surcharge': 0, 'app': False, 'app_fee': 35}, {'base': 1234, 'tax': 278, 'total': 1512}), ({'base': 398, 'resident': False, 'resident_pct': 20, 'tax_bp': 2250, 'surcharge': 0, 'app': False, 'app_fee': 45}, {'base': 398, 'tax': 90, 'total': 488}), ({'base': 1292, 'resident': True, 'resident_pct': 25, 'tax_bp': 2250, 'surcharge': 0, 'app': False, 'app_fee': 25}, {'base': 969, 'tax': 218, 'total': 1187}), ({'base': 3586, 'resident': False, 'resident_pct': 50, 'tax_bp': 1850, 'surcharge': 0, 'app': True, 'app_fee': 45}, {'base': 3586, 'tax': 663, 'total': 4302}), ({'base': 4846, 'resident': False, 'resident_pct': 50, 'tax_bp': 1000, 'surcharge': 0, 'app': False, 'app_fee': 25}, {'base': 4846, 'tax': 485, 'total': 5331})]]
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)

prompt:
Parking tax and fee composition returns a wrong result when tax is computed on the undiscounted price.

Input {base, resident, resident_pct, tax_bp (basis points), surcharge, app, app_fee}. Residents get resident_pct off (discount floored). Parking tax on the discounted base is rounded half up per transaction. The surcharge is untaxed. App payments add app_fee plus its own tax rounded half up. Return {base, tax, total}.

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    base = x['base']
    if x['resident']:
        base -= base * x['resident_pct'] // 100
    tax = base * x['tax_bp'] // 10000
    total = base + tax + x['surcharge']
    if x['app']:
        total += x['app_fee'] + (x['app_fee'] * x['tax_bp'] + 5000) // 10000
    return {'base': base, 'tax': tax, 'total': total}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[({'base': 4607, 'resident': True, 'resident_pct': 25, 'tax_bp': 625, 'surcharge': 50, 'app': True, 'app_fee': 25}, {'base': 3456, 'tax': 216, 'total': 3749}), ({'base': 1000, 'resident': True, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 150, 'app': True, 'app_fee': 35}, {'base': 750, 'tax': 139, 'total': 1080}), ({'base': 340, 'resident': False, 'resident_pct': 20, 'tax_bp': 1000, 'surcharge': 0, 'app': False, 'app_fee': 25}, {'base': 340, 'tax': 34, 'total': 374}), ({'base': 775, 'resident': True, 'resident_pct': 50, 'tax_bp': 1000, 'surcharge': 0, 'app': True, 'app_fee': 35}, {'base': 388, 'tax': 39, 'total': 466}), ({'base': 2257, 'resident': True, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 50, 'app': False, 'app_fee': 45}, {'base': 1693, 'tax': 313, 'total': 2056}), ({'base': 1884, 'resident': True, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 50, 'app': False, 'app_fee': 45}, {'base': 1413, 'tax': 261, 'total': 1724}), ({'base': 3965, 'resident': False, 'resident_pct': 20, 'tax_bp': 625, 'surcharge': 150, 'app': True, 'app_fee': 45}, {'base': 3965, 'tax': 248, 'total': 4411}), ({'base': 3730, 'resident': False, 'resident_pct': 20, 'tax_bp': 1000, 'surcharge': 0, 'app': False, 'app_fee': 45}, {'base': 3730, 'tax': 373, 'total': 4103})], [({'base': 1000, 'resident': True, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 150, 'app': True, 'app_fee': 35}, {'base': 750, 'tax': 139, 'total': 1080}), ({'base': 3820, 'resident': False, 'resident_pct': 50, 'tax_bp': 1000, 'surcharge': 0, 'app': True, 'app_fee': 25}, {'base': 3820, 'tax': 382, 'total': 4230}), ({'base': 3488, 'resident': False, 'resident_pct': 20, 'tax_bp': 2250, 'surcharge': 0, 'app': False, 'app_fee': 35}, {'base': 3488, 'tax': 785, 'total': 4273}), ({'base': 1584, 'resident': False, 'resident_pct': 50, 'tax_bp': 625, 'surcharge': 50, 'app': False, 'app_fee': 35}, {'base': 1584, 'tax': 99, 'total': 1733}), ({'base': 1360, 'resident': False, 'resident_pct': 25, 'tax_bp': 1000, 'surcharge': 50, 'app': True, 'app_fee': 25}, {'base': 1360, 'tax': 136, 'total': 1574}), ({'base': 3857, 'resident': False, 'resident_pct': 25, 'tax_bp': 625, 'surcharge': 50, 'app': False, 'app_fee': 25}, {'base': 3857, 'tax': 241, 'total': 4148}), ({'base': 146, 'resident': False, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 0, 'app': True, 'app_fee': 25}, {'base': 146, 'tax': 27, 'total': 203}), ({'base': 4289, 'resident': False, 'resident_pct': 20, 'tax_bp': 1000, 'surcharge': 150, 'app': True, 'app_fee': 25}, {'base': 4289, 'tax': 429, 'total': 4896})], [({'base': 1490, 'resident': False, 'resident_pct': 25, 'tax_bp': 1000, 'surcharge': 150, 'app': True, 'app_fee': 25}, {'base': 1490, 'tax': 149, 'total': 1817}), ({'base': 4064, 'resident': False, 'resident_pct': 20, 'tax_bp': 625, 'surcharge': 150, 'app': True, 'app_fee': 25}, {'base': 4064, 'tax': 254, 'total': 4495}), ({'base': 4016, 'resident': False, 'resident_pct': 25, 'tax_bp': 625, 'surcharge': 150, 'app': True, 'app_fee': 35}, {'base': 4016, 'tax': 251, 'total': 4454}), ({'base': 1390, 'resident': False, 'resident_pct': 50, 'tax_bp': 625, 'surcharge': 50, 'app': False, 'app_fee': 25}, {'base': 1390, 'tax': 87, 'total': 1527}), ({'base': 1783, 'resident': False, 'resident_pct': 50, 'tax_bp': 2250, 'surcharge': 50, 'app': True, 'app_fee': 45}, {'base': 1783, 'tax': 401, 'total': 2289}), ({'base': 1000, 'resident': True, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 150, 'app': True, 'app_fee': 35}, {'base': 750, 'tax': 139, 'total': 1080}), ({'base': 4398, 'resident': False, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 50, 'app': False, 'app_fee': 35}, {'base': 4398, 'tax': 814, 'total': 5262}), ({'base': 2093, 'resident': True, 'resident_pct': 25, 'tax_bp': 625, 'surcharge': 150, 'app': False, 'app_fee': 45}, {'base': 1570, 'tax': 98, 'total': 1818})], [({'base': 2840, 'resident': False, 'resident_pct': 50, 'tax_bp': 1000, 'surcharge': 50, 'app': True, 'app_fee': 45}, {'base': 2840, 'tax': 284, 'total': 3224}), ({'base': 2280, 'resident': False, 'resident_pct': 50, 'tax_bp': 2250, 'surcharge': 50, 'app': True, 'app_fee': 25}, {'base': 2280, 'tax': 513, 'total': 2874}), ({'base': 689, 'resident': False, 'resident_pct': 25, 'tax_bp': 625, 'surcharge': 150, 'app': False, 'app_fee': 35}, {'base': 689, 'tax': 43, 'total': 882}), ({'base': 900, 'resident': True, 'resident_pct': 20, 'tax_bp': 2250, 'surcharge': 50, 'app': True, 'app_fee': 45}, {'base': 720, 'tax': 162, 'total': 987}), ({'base': 1018, 'resident': False, 'resident_pct': 20, 'tax_bp': 2250, 'surcharge': 0, 'app': True, 'app_fee': 35}, {'base': 1018, 'tax': 229, 'total': 1290}), ({'base': 3121, 'resident': True, 'resident_pct': 50, 'tax_bp': 1850, 'surcharge': 150, 'app': False, 'app_fee': 25}, {'base': 1561, 'tax': 289, 'total': 2000}), ({'base': 923, 'resident': False, 'resident_pct': 50, 'tax_bp': 1850, 'surcharge': 0, 'app': True, 'app_fee': 45}, {'base': 923, 'tax': 171, 'total': 1147}), ({'base': 1000, 'resident': True, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 150, 'app': True, 'app_fee': 35}, {'base': 750, 'tax': 139, 'total': 1080})], [({'base': 1000, 'resident': True, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 150, 'app': True, 'app_fee': 35}, {'base': 750, 'tax': 139, 'total': 1080}), ({'base': 4242, 'resident': False, 'resident_pct': 50, 'tax_bp': 625, 'surcharge': 150, 'app': True, 'app_fee': 45}, {'base': 4242, 'tax': 265, 'total': 4705}), ({'base': 2612, 'resident': False, 'resident_pct': 50, 'tax_bp': 1850, 'surcharge': 0, 'app': False, 'app_fee': 45}, {'base': 2612, 'tax': 483, 'total': 3095}), ({'base': 4896, 'resident': False, 'resident_pct': 20, 'tax_bp': 625, 'surcharge': 0, 'app': True, 'app_fee': 45}, {'base': 4896, 'tax': 306, 'total': 5250}), ({'base': 3293, 'resident': True, 'resident_pct': 20, 'tax_bp': 1000, 'surcharge': 50, 'app': True, 'app_fee': 25}, {'base': 2635, 'tax': 264, 'total': 2977}), ({'base': 2690, 'resident': False, 'resident_pct': 20, 'tax_bp': 1000, 'surcharge': 150, 'app': True, 'app_fee': 45}, {'base': 2690, 'tax': 269, 'total': 3159}), ({'base': 4760, 'resident': False, 'resident_pct': 50, 'tax_bp': 2250, 'surcharge': 150, 'app': True, 'app_fee': 45}, {'base': 4760, 'tax': 1071, 'total': 6036}), ({'base': 115, 'resident': False, 'resident_pct': 20, 'tax_bp': 2250, 'surcharge': 150, 'app': False, 'app_fee': 45}, {'base': 115, 'tax': 26, 'total': 291})]]
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)

meaning: Fixture-count band, not measured model difficulty

deps: stdlib

source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    base = x['base']
    if x['resident']:
        base -= base * x['resident_pct'] // 100
    tax = -(-base * x['tax_bp'] // 10000)
    total = base + tax + x['surcharge']
    if x['app']:
        total += x['app_fee'] + (x['app_fee'] * x['tax_bp'] + 5000) // 10000
    return {'base': base, 'tax': tax, 'total': total}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[({'base': 4607, 'resident': True, 'resident_pct': 25, 'tax_bp': 625, 'surcharge': 50, 'app': True, 'app_fee': 25}, {'base': 3456, 'tax': 216, 'total': 3749}), ({'base': 1000, 'resident': True, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 150, 'app': True, 'app_fee': 35}, {'base': 750, 'tax': 139, 'total': 1080}), ({'base': 340, 'resident': False, 'resident_pct': 20, 'tax_bp': 1000, 'surcharge': 0, 'app': False, 'app_fee': 25}, {'base': 340, 'tax': 34, 'total': 374}), ({'base': 775, 'resident': True, 'resident_pct': 50, 'tax_bp': 1000, 'surcharge': 0, 'app': True, 'app_fee': 35}, {'base': 388, 'tax': 39, 'total': 466}), ({'base': 2257, 'resident': True, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 50, 'app': False, 'app_fee': 45}, {'base': 1693, 'tax': 313, 'total': 2056}), ({'base': 1884, 'resident': True, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 50, 'app': False, 'app_fee': 45}, {'base': 1413, 'tax': 261, 'total': 1724}), ({'base': 3965, 'resident': False, 'resident_pct': 20, 'tax_bp': 625, 'surcharge': 150, 'app': True, 'app_fee': 45}, {'base': 3965, 'tax': 248, 'total': 4411}), ({'base': 3730, 'resident': False, 'resident_pct': 20, 'tax_bp': 1000, 'surcharge': 0, 'app': False, 'app_fee': 45}, {'base': 3730, 'tax': 373, 'total': 4103})], [({'base': 1000, 'resident': True, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 150, 'app': True, 'app_fee': 35}, {'base': 750, 'tax': 139, 'total': 1080}), ({'base': 3820, 'resident': False, 'resident_pct': 50, 'tax_bp': 1000, 'surcharge': 0, 'app': True, 'app_fee': 25}, {'base': 3820, 'tax': 382, 'total': 4230}), ({'base': 3488, 'resident': False, 'resident_pct': 20, 'tax_bp': 2250, 'surcharge': 0, 'app': False, 'app_fee': 35}, {'base': 3488, 'tax': 785, 'total': 4273}), ({'base': 1584, 'resident': False, 'resident_pct': 50, 'tax_bp': 625, 'surcharge': 50, 'app': False, 'app_fee': 35}, {'base': 1584, 'tax': 99, 'total': 1733}), ({'base': 1360, 'resident': False, 'resident_pct': 25, 'tax_bp': 1000, 'surcharge': 50, 'app': True, 'app_fee': 25}, {'base': 1360, 'tax': 136, 'total': 1574}), ({'base': 3857, 'resident': False, 'resident_pct': 25, 'tax_bp': 625, 'surcharge': 50, 'app': False, 'app_fee': 25}, {'base': 3857, 'tax': 241, 'total': 4148}), ({'base': 146, 'resident': False, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 0, 'app': True, 'app_fee': 25}, {'base': 146, 'tax': 27, 'total': 203}), ({'base': 4289, 'resident': False, 'resident_pct': 20, 'tax_bp': 1000, 'surcharge': 150, 'app': True, 'app_fee': 25}, {'base': 4289, 'tax': 429, 'total': 4896})], [({'base': 1490, 'resident': False, 'resident_pct': 25, 'tax_bp': 1000, 'surcharge': 150, 'app': True, 'app_fee': 25}, {'base': 1490, 'tax': 149, 'total': 1817}), ({'base': 4064, 'resident': False, 'resident_pct': 20, 'tax_bp': 625, 'surcharge': 150, 'app': True, 'app_fee': 25}, {'base': 4064, 'tax': 254, 'total': 4495}), ({'base': 4016, 'resident': False, 'resident_pct': 25, 'tax_bp': 625, 'surcharge': 150, 'app': True, 'app_fee': 35}, {'base': 4016, 'tax': 251, 'total': 4454}), ({'base': 1390, 'resident': False, 'resident_pct': 50, 'tax_bp': 625, 'surcharge': 50, 'app': False, 'app_fee': 25}, {'base': 1390, 'tax': 87, 'total': 1527}), ({'base': 1783, 'resident': False, 'resident_pct': 50, 'tax_bp': 2250, 'surcharge': 50, 'app': True, 'app_fee': 45}, {'base': 1783, 'tax': 401, 'total': 2289}), ({'base': 1000, 'resident': True, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 150, 'app': True, 'app_fee': 35}, {'base': 750, 'tax': 139, 'total': 1080}), ({'base': 4398, 'resident': False, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 50, 'app': False, 'app_fee': 35}, {'base': 4398, 'tax': 814, 'total': 5262}), ({'base': 2093, 'resident': True, 'resident_pct': 25, 'tax_bp': 625, 'surcharge': 150, 'app': False, 'app_fee': 45}, {'base': 1570, 'tax': 98, 'total': 1818})], [({'base': 2840, 'resident': False, 'resident_pct': 50, 'tax_bp': 1000, 'surcharge': 50, 'app': True, 'app_fee': 45}, {'base': 2840, 'tax': 284, 'total': 3224}), ({'base': 2280, 'resident': False, 'resident_pct': 50, 'tax_bp': 2250, 'surcharge': 50, 'app': True, 'app_fee': 25}, {'base': 2280, 'tax': 513, 'total': 2874}), ({'base': 689, 'resident': False, 'resident_pct': 25, 'tax_bp': 625, 'surcharge': 150, 'app': False, 'app_fee': 35}, {'base': 689, 'tax': 43, 'total': 882}), ({'base': 900, 'resident': True, 'resident_pct': 20, 'tax_bp': 2250, 'surcharge': 50, 'app': True, 'app_fee': 45}, {'base': 720, 'tax': 162, 'total': 987}), ({'base': 1018, 'resident': False, 'resident_pct': 20, 'tax_bp': 2250, 'surcharge': 0, 'app': True, 'app_fee': 35}, {'base': 1018, 'tax': 229, 'total': 1290}), ({'base': 3121, 'resident': True, 'resident_pct': 50, 'tax_bp': 1850, 'surcharge': 150, 'app': False, 'app_fee': 25}, {'base': 1561, 'tax': 289, 'total': 2000}), ({'base': 923, 'resident': False, 'resident_pct': 50, 'tax_bp': 1850, 'surcharge': 0, 'app': True, 'app_fee': 45}, {'base': 923, 'tax': 171, 'total': 1147}), ({'base': 1000, 'resident': True, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 150, 'app': True, 'app_fee': 35}, {'base': 750, 'tax': 139, 'total': 1080})], [({'base': 1000, 'resident': True, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 150, 'app': True, 'app_fee': 35}, {'base': 750, 'tax': 139, 'total': 1080}), ({'base': 4242, 'resident': False, 'resident_pct': 50, 'tax_bp': 625, 'surcharge': 150, 'app': True, 'app_fee': 45}, {'base': 4242, 'tax': 265, 'total': 4705}), ({'base': 2612, 'resident': False, 'resident_pct': 50, 'tax_bp': 1850, 'surcharge': 0, 'app': False, 'app_fee': 45}, {'base': 2612, 'tax': 483, 'total': 3095}), ({'base': 4896, 'resident': False, 'resident_pct': 20, 'tax_bp': 625, 'surcharge': 0, 'app': True, 'app_fee': 45}, {'base': 4896, 'tax': 306, 'total': 5250}), ({'base': 3293, 'resident': True, 'resident_pct': 20, 'tax_bp': 1000, 'surcharge': 50, 'app': True, 'app_fee': 25}, {'base': 2635, 'tax': 264, 'total': 2977}), ({'base': 2690, 'resident': False, 'resident_pct': 20, 'tax_bp': 1000, 'surcharge': 150, 'app': True, 'app_fee': 45}, {'base': 2690, 'tax': 269, 'total': 3159}), ({'base': 4760, 'resident': False, 'resident_pct': 50, 'tax_bp': 2250, 'surcharge': 150, 'app': True, 'app_fee': 45}, {'base': 4760, 'tax': 1071, 'total': 6036}), ({'base': 115, 'resident': False, 'resident_pct': 20, 'tax_bp': 2250, 'surcharge': 150, 'app': False, 'app_fee': 45}, {'base': 115, 'tax': 26, 'total': 291})]]
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)

prompt:
Parking tax and fee composition returns a wrong result when parking tax is truncated.

Input {base, resident, resident_pct, tax_bp (basis points), surcharge, app, app_fee}. Residents get resident_pct off (discount floored). Parking tax on the discounted base is rounded half up per transaction. The surcharge is untaxed. App payments add app_fee plus its own tax rounded half up. Return {base, tax, total}.

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    base = x['base']
    if x['resident']:
        base -= base * x['resident_pct'] // 100
    tax = (base * x['tax_bp'] + 5000) // 10000
    total = base + tax + x['surcharge']
    if x['app']:
        total += x['app_fee']
    return {'base': base, 'tax': tax, 'total': total}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[({'base': 3638, 'resident': False, 'resident_pct': 50, 'tax_bp': 1000, 'surcharge': 0, 'app': False, 'app_fee': 45}, {'base': 3638, 'tax': 364, 'total': 4002}), ({'base': 407, 'resident': False, 'resident_pct': 25, 'tax_bp': 1000, 'surcharge': 50, 'app': False, 'app_fee': 25}, {'base': 407, 'tax': 41, 'total': 498}), ({'base': 3231, 'resident': False, 'resident_pct': 50, 'tax_bp': 1850, 'surcharge': 50, 'app': True, 'app_fee': 25}, {'base': 3231, 'tax': 598, 'total': 3909}), ({'base': 3732, 'resident': False, 'resident_pct': 20, 'tax_bp': 1000, 'surcharge': 0, 'app': True, 'app_fee': 25}, {'base': 3732, 'tax': 373, 'total': 4133}), ({'base': 363, 'resident': True, 'resident_pct': 20, 'tax_bp': 1850, 'surcharge': 150, 'app': False, 'app_fee': 35}, {'base': 291, 'tax': 54, 'total': 495}), ({'base': 3002, 'resident': True, 'resident_pct': 20, 'tax_bp': 625, 'surcharge': 50, 'app': True, 'app_fee': 25}, {'base': 2402, 'tax': 150, 'total': 2629}), ({'base': 1000, 'resident': True, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 150, 'app': True, 'app_fee': 35}, {'base': 750, 'tax': 139, 'total': 1080}), ({'base': 3434, 'resident': True, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 150, 'app': False, 'app_fee': 25}, {'base': 2576, 'tax': 477, 'total': 3203})], [({'base': 1981, 'resident': True, 'resident_pct': 20, 'tax_bp': 1850, 'surcharge': 150, 'app': True, 'app_fee': 45}, {'base': 1585, 'tax': 293, 'total': 2081}), ({'base': 3279, 'resident': False, 'resident_pct': 20, 'tax_bp': 2250, 'surcharge': 150, 'app': False, 'app_fee': 45}, {'base': 3279, 'tax': 738, 'total': 4167}), ({'base': 2460, 'resident': False, 'resident_pct': 25, 'tax_bp': 625, 'surcharge': 150, 'app': True, 'app_fee': 25}, {'base': 2460, 'tax': 154, 'total': 2791}), ({'base': 1000, 'resident': True, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 150, 'app': True, 'app_fee': 35}, {'base': 750, 'tax': 139, 'total': 1080}), ({'base': 3803, 'resident': False, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 50, 'app': False, 'app_fee': 35}, {'base': 3803, 'tax': 704, 'total': 4557}), ({'base': 4360, 'resident': False, 'resident_pct': 50, 'tax_bp': 625, 'surcharge': 50, 'app': True, 'app_fee': 45}, {'base': 4360, 'tax': 273, 'total': 4731}), ({'base': 4204, 'resident': False, 'resident_pct': 20, 'tax_bp': 1850, 'surcharge': 50, 'app': False, 'app_fee': 25}, {'base': 4204, 'tax': 778, 'total': 5032}), ({'base': 2514, 'resident': False, 'resident_pct': 20, 'tax_bp': 1850, 'surcharge': 150, 'app': False, 'app_fee': 25}, {'base': 2514, 'tax': 465, 'total': 3129})], [({'base': 4611, 'resident': False, 'resident_pct': 20, 'tax_bp': 2250, 'surcharge': 50, 'app': False, 'app_fee': 45}, {'base': 4611, 'tax': 1037, 'total': 5698}), ({'base': 1000, 'resident': True, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 150, 'app': True, 'app_fee': 35}, {'base': 750, 'tax': 139, 'total': 1080}), ({'base': 3136, 'resident': False, 'resident_pct': 20, 'tax_bp': 1000, 'surcharge': 50, 'app': True, 'app_fee': 25}, {'base': 3136, 'tax': 314, 'total': 3528}), ({'base': 3785, 'resident': False, 'resident_pct': 50, 'tax_bp': 1000, 'surcharge': 50, 'app': False, 'app_fee': 45}, {'base': 3785, 'tax': 379, 'total': 4214}), ({'base': 3524, 'resident': False, 'resident_pct': 25, 'tax_bp': 1000, 'surcharge': 150, 'app': False, 'app_fee': 35}, {'base': 3524, 'tax': 352, 'total': 4026}), ({'base': 2889, 'resident': True, 'resident_pct': 20, 'tax_bp': 2250, 'surcharge': 0, 'app': False, 'app_fee': 35}, {'base': 2312, 'tax': 520, 'total': 2832}), ({'base': 4399, 'resident': True, 'resident_pct': 50, 'tax_bp': 1850, 'surcharge': 150, 'app': True, 'app_fee': 25}, {'base': 2200, 'tax': 407, 'total': 2787}), ({'base': 520, 'resident': False, 'resident_pct': 20, 'tax_bp': 2250, 'surcharge': 150, 'app': False, 'app_fee': 25}, {'base': 520, 'tax': 117, 'total': 787})], [({'base': 1169, 'resident': False, 'resident_pct': 20, 'tax_bp': 1000, 'surcharge': 150, 'app': True, 'app_fee': 45}, {'base': 1169, 'tax': 117, 'total': 1486}), ({'base': 262, 'resident': False, 'resident_pct': 25, 'tax_bp': 2250, 'surcharge': 50, 'app': False, 'app_fee': 35}, {'base': 262, 'tax': 59, 'total': 371}), ({'base': 112, 'resident': True, 'resident_pct': 20, 'tax_bp': 1850, 'surcharge': 0, 'app': False, 'app_fee': 25}, {'base': 90, 'tax': 17, 'total': 107}), ({'base': 3364, 'resident': True, 'resident_pct': 20, 'tax_bp': 1850, 'surcharge': 0, 'app': False, 'app_fee': 45}, {'base': 2692, 'tax': 498, 'total': 3190}), ({'base': 2377, 'resident': True, 'resident_pct': 20, 'tax_bp': 1850, 'surcharge': 50, 'app': False, 'app_fee': 25}, {'base': 1902, 'tax': 352, 'total': 2304}), ({'base': 1000, 'resident': True, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 150, 'app': True, 'app_fee': 35}, {'base': 750, 'tax': 139, 'total': 1080}), ({'base': 2393, 'resident': False, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 150, 'app': True, 'app_fee': 25}, {'base': 2393, 'tax': 443, 'total': 3016}), ({'base': 933, 'resident': True, 'resident_pct': 20, 'tax_bp': 1000, 'surcharge': 0, 'app': True, 'app_fee': 45}, {'base': 747, 'tax': 75, 'total': 872})], [({'base': 1000, 'resident': True, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 150, 'app': True, 'app_fee': 35}, {'base': 750, 'tax': 139, 'total': 1080}), ({'base': 968, 'resident': False, 'resident_pct': 20, 'tax_bp': 2250, 'surcharge': 0, 'app': False, 'app_fee': 35}, {'base': 968, 'tax': 218, 'total': 1186}), ({'base': 2247, 'resident': False, 'resident_pct': 50, 'tax_bp': 1850, 'surcharge': 150, 'app': False, 'app_fee': 35}, {'base': 2247, 'tax': 416, 'total': 2813}), ({'base': 549, 'resident': False, 'resident_pct': 50, 'tax_bp': 2250, 'surcharge': 50, 'app': True, 'app_fee': 35}, {'base': 549, 'tax': 124, 'total': 766}), ({'base': 4563, 'resident': True, 'resident_pct': 50, 'tax_bp': 2250, 'surcharge': 50, 'app': True, 'app_fee': 45}, {'base': 2282, 'tax': 513, 'total': 2900}), ({'base': 885, 'resident': True, 'resident_pct': 25, 'tax_bp': 625, 'surcharge': 50, 'app': False, 'app_fee': 35}, {'base': 664, 'tax': 42, 'total': 756}), ({'base': 4948, 'resident': False, 'resident_pct': 50, 'tax_bp': 2250, 'surcharge': 50, 'app': True, 'app_fee': 35}, {'base': 4948, 'tax': 1113, 'total': 6154}), ({'base': 1984, 'resident': True, 'resident_pct': 25, 'tax_bp': 1000, 'surcharge': 150, 'app': False, 'app_fee': 45}, {'base': 1488, 'tax': 149, 'total': 1787})]]
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)

source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    base = x['base']
    if x['resident']:
        base -= base * x['resident_pct'] // 100
    tax = (base * x['tax_bp'] + 5000) // 10000
    total = base + tax + x['surcharge']
    if x['app']:
        total += x['app_fee'] * (10000 + x['tax_bp']) // 10000
    return {'base': base, 'tax': tax, 'total': total}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[({'base': 3638, 'resident': False, 'resident_pct': 50, 'tax_bp': 1000, 'surcharge': 0, 'app': False, 'app_fee': 45}, {'base': 3638, 'tax': 364, 'total': 4002}), ({'base': 407, 'resident': False, 'resident_pct': 25, 'tax_bp': 1000, 'surcharge': 50, 'app': False, 'app_fee': 25}, {'base': 407, 'tax': 41, 'total': 498}), ({'base': 3231, 'resident': False, 'resident_pct': 50, 'tax_bp': 1850, 'surcharge': 50, 'app': True, 'app_fee': 25}, {'base': 3231, 'tax': 598, 'total': 3909}), ({'base': 3732, 'resident': False, 'resident_pct': 20, 'tax_bp': 1000, 'surcharge': 0, 'app': True, 'app_fee': 25}, {'base': 3732, 'tax': 373, 'total': 4133}), ({'base': 363, 'resident': True, 'resident_pct': 20, 'tax_bp': 1850, 'surcharge': 150, 'app': False, 'app_fee': 35}, {'base': 291, 'tax': 54, 'total': 495}), ({'base': 3002, 'resident': True, 'resident_pct': 20, 'tax_bp': 625, 'surcharge': 50, 'app': True, 'app_fee': 25}, {'base': 2402, 'tax': 150, 'total': 2629}), ({'base': 1000, 'resident': True, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 150, 'app': True, 'app_fee': 35}, {'base': 750, 'tax': 139, 'total': 1080}), ({'base': 3434, 'resident': True, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 150, 'app': False, 'app_fee': 25}, {'base': 2576, 'tax': 477, 'total': 3203})], [({'base': 1981, 'resident': True, 'resident_pct': 20, 'tax_bp': 1850, 'surcharge': 150, 'app': True, 'app_fee': 45}, {'base': 1585, 'tax': 293, 'total': 2081}), ({'base': 3279, 'resident': False, 'resident_pct': 20, 'tax_bp': 2250, 'surcharge': 150, 'app': False, 'app_fee': 45}, {'base': 3279, 'tax': 738, 'total': 4167}), ({'base': 2460, 'resident': False, 'resident_pct': 25, 'tax_bp': 625, 'surcharge': 150, 'app': True, 'app_fee': 25}, {'base': 2460, 'tax': 154, 'total': 2791}), ({'base': 1000, 'resident': True, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 150, 'app': True, 'app_fee': 35}, {'base': 750, 'tax': 139, 'total': 1080}), ({'base': 3803, 'resident': False, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 50, 'app': False, 'app_fee': 35}, {'base': 3803, 'tax': 704, 'total': 4557}), ({'base': 4360, 'resident': False, 'resident_pct': 50, 'tax_bp': 625, 'surcharge': 50, 'app': True, 'app_fee': 45}, {'base': 4360, 'tax': 273, 'total': 4731}), ({'base': 4204, 'resident': False, 'resident_pct': 20, 'tax_bp': 1850, 'surcharge': 50, 'app': False, 'app_fee': 25}, {'base': 4204, 'tax': 778, 'total': 5032}), ({'base': 2514, 'resident': False, 'resident_pct': 20, 'tax_bp': 1850, 'surcharge': 150, 'app': False, 'app_fee': 25}, {'base': 2514, 'tax': 465, 'total': 3129})], [({'base': 4611, 'resident': False, 'resident_pct': 20, 'tax_bp': 2250, 'surcharge': 50, 'app': False, 'app_fee': 45}, {'base': 4611, 'tax': 1037, 'total': 5698}), ({'base': 1000, 'resident': True, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 150, 'app': True, 'app_fee': 35}, {'base': 750, 'tax': 139, 'total': 1080}), ({'base': 3136, 'resident': False, 'resident_pct': 20, 'tax_bp': 1000, 'surcharge': 50, 'app': True, 'app_fee': 25}, {'base': 3136, 'tax': 314, 'total': 3528}), ({'base': 3785, 'resident': False, 'resident_pct': 50, 'tax_bp': 1000, 'surcharge': 50, 'app': False, 'app_fee': 45}, {'base': 3785, 'tax': 379, 'total': 4214}), ({'base': 3524, 'resident': False, 'resident_pct': 25, 'tax_bp': 1000, 'surcharge': 150, 'app': False, 'app_fee': 35}, {'base': 3524, 'tax': 352, 'total': 4026}), ({'base': 2889, 'resident': True, 'resident_pct': 20, 'tax_bp': 2250, 'surcharge': 0, 'app': False, 'app_fee': 35}, {'base': 2312, 'tax': 520, 'total': 2832}), ({'base': 4399, 'resident': True, 'resident_pct': 50, 'tax_bp': 1850, 'surcharge': 150, 'app': True, 'app_fee': 25}, {'base': 2200, 'tax': 407, 'total': 2787}), ({'base': 520, 'resident': False, 'resident_pct': 20, 'tax_bp': 2250, 'surcharge': 150, 'app': False, 'app_fee': 25}, {'base': 520, 'tax': 117, 'total': 787})], [({'base': 1169, 'resident': False, 'resident_pct': 20, 'tax_bp': 1000, 'surcharge': 150, 'app': True, 'app_fee': 45}, {'base': 1169, 'tax': 117, 'total': 1486}), ({'base': 262, 'resident': False, 'resident_pct': 25, 'tax_bp': 2250, 'surcharge': 50, 'app': False, 'app_fee': 35}, {'base': 262, 'tax': 59, 'total': 371}), ({'base': 112, 'resident': True, 'resident_pct': 20, 'tax_bp': 1850, 'surcharge': 0, 'app': False, 'app_fee': 25}, {'base': 90, 'tax': 17, 'total': 107}), ({'base': 3364, 'resident': True, 'resident_pct': 20, 'tax_bp': 1850, 'surcharge': 0, 'app': False, 'app_fee': 45}, {'base': 2692, 'tax': 498, 'total': 3190}), ({'base': 2377, 'resident': True, 'resident_pct': 20, 'tax_bp': 1850, 'surcharge': 50, 'app': False, 'app_fee': 25}, {'base': 1902, 'tax': 352, 'total': 2304}), ({'base': 1000, 'resident': True, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 150, 'app': True, 'app_fee': 35}, {'base': 750, 'tax': 139, 'total': 1080}), ({'base': 2393, 'resident': False, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 150, 'app': True, 'app_fee': 25}, {'base': 2393, 'tax': 443, 'total': 3016}), ({'base': 933, 'resident': True, 'resident_pct': 20, 'tax_bp': 1000, 'surcharge': 0, 'app': True, 'app_fee': 45}, {'base': 747, 'tax': 75, 'total': 872})], [({'base': 1000, 'resident': True, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 150, 'app': True, 'app_fee': 35}, {'base': 750, 'tax': 139, 'total': 1080}), ({'base': 968, 'resident': False, 'resident_pct': 20, 'tax_bp': 2250, 'surcharge': 0, 'app': False, 'app_fee': 35}, {'base': 968, 'tax': 218, 'total': 1186}), ({'base': 2247, 'resident': False, 'resident_pct': 50, 'tax_bp': 1850, 'surcharge': 150, 'app': False, 'app_fee': 35}, {'base': 2247, 'tax': 416, 'total': 2813}), ({'base': 549, 'resident': False, 'resident_pct': 50, 'tax_bp': 2250, 'surcharge': 50, 'app': True, 'app_fee': 35}, {'base': 549, 'tax': 124, 'total': 766}), ({'base': 4563, 'resident': True, 'resident_pct': 50, 'tax_bp': 2250, 'surcharge': 50, 'app': True, 'app_fee': 45}, {'base': 2282, 'tax': 513, 'total': 2900}), ({'base': 885, 'resident': True, 'resident_pct': 25, 'tax_bp': 625, 'surcharge': 50, 'app': False, 'app_fee': 35}, {'base': 664, 'tax': 42, 'total': 756}), ({'base': 4948, 'resident': False, 'resident_pct': 50, 'tax_bp': 2250, 'surcharge': 50, 'app': True, 'app_fee': 35}, {'base': 4948, 'tax': 1113, 'total': 6154}), ({'base': 1984, 'resident': True, 'resident_pct': 25, 'tax_bp': 1000, 'surcharge': 150, 'app': False, 'app_fee': 45}, {'base': 1488, 'tax': 149, 'total': 1787})]]
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)

prompt:
Parking tax and fee composition returns a wrong result when the app fee is left untaxed.

Input {base, resident, resident_pct, tax_bp (basis points), surcharge, app, app_fee}. Residents get resident_pct off (discount floored). Parking tax on the discounted base is rounded half up per transaction. The surcharge is untaxed. App payments add app_fee plus its own tax rounded half up. Return {base, tax, total}.

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    base = x['base']
    if x['resident']:
        base = base * x['resident_pct'] // 100
    tax = (base * x['tax_bp'] + 5000) // 10000
    total = base + tax + x['surcharge']
    if x['app']:
        total += x['app_fee'] + (x['app_fee'] * x['tax_bp'] + 5000) // 10000
    return {'base': base, 'tax': tax, 'total': total}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[({'base': 2437, 'resident': True, 'resident_pct': 50, 'tax_bp': 1000, 'surcharge': 150, 'app': False, 'app_fee': 35}, {'base': 1219, 'tax': 122, 'total': 1491}), ({'base': 122, 'resident': True, 'resident_pct': 20, 'tax_bp': 1850, 'surcharge': 150, 'app': False, 'app_fee': 25}, {'base': 98, 'tax': 18, 'total': 266}), ({'base': 4927, 'resident': False, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 0, 'app': False, 'app_fee': 35}, {'base': 4927, 'tax': 911, 'total': 5838}), ({'base': 2805, 'resident': False, 'resident_pct': 20, 'tax_bp': 1000, 'surcharge': 0, 'app': True, 'app_fee': 35}, {'base': 2805, 'tax': 281, 'total': 3125}), ({'base': 1795, 'resident': False, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 0, 'app': True, 'app_fee': 25}, {'base': 1795, 'tax': 332, 'total': 2157}), ({'base': 2304, 'resident': False, 'resident_pct': 20, 'tax_bp': 625, 'surcharge': 0, 'app': True, 'app_fee': 45}, {'base': 2304, 'tax': 144, 'total': 2496}), ({'base': 622, 'resident': True, 'resident_pct': 20, 'tax_bp': 625, 'surcharge': 0, 'app': True, 'app_fee': 25}, {'base': 498, 'tax': 31, 'total': 556}), ({'base': 1000, 'resident': True, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 150, 'app': True, 'app_fee': 35}, {'base': 750, 'tax': 139, 'total': 1080})], [({'base': 4756, 'resident': True, 'resident_pct': 25, 'tax_bp': 625, 'surcharge': 50, 'app': False, 'app_fee': 35}, {'base': 3567, 'tax': 223, 'total': 3840}), ({'base': 1000, 'resident': True, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 150, 'app': True, 'app_fee': 35}, {'base': 750, 'tax': 139, 'total': 1080}), ({'base': 4135, 'resident': False, 'resident_pct': 25, 'tax_bp': 625, 'surcharge': 50, 'app': True, 'app_fee': 45}, {'base': 4135, 'tax': 258, 'total': 4491}), ({'base': 4117, 'resident': False, 'resident_pct': 20, 'tax_bp': 1850, 'surcharge': 0, 'app': True, 'app_fee': 35}, {'base': 4117, 'tax': 762, 'total': 4920}), ({'base': 1189, 'resident': False, 'resident_pct': 50, 'tax_bp': 2250, 'surcharge': 150, 'app': False, 'app_fee': 45}, {'base': 1189, 'tax': 268, 'total': 1607}), ({'base': 815, 'resident': False, 'resident_pct': 50, 'tax_bp': 1850, 'surcharge': 150, 'app': False, 'app_fee': 35}, {'base': 815, 'tax': 151, 'total': 1116}), ({'base': 816, 'resident': False, 'resident_pct': 20, 'tax_bp': 1850, 'surcharge': 50, 'app': False, 'app_fee': 35}, {'base': 816, 'tax': 151, 'total': 1017}), ({'base': 4473, 'resident': True, 'resident_pct': 50, 'tax_bp': 1000, 'surcharge': 150, 'app': True, 'app_fee': 25}, {'base': 2237, 'tax': 224, 'total': 2639})], [({'base': 3532, 'resident': False, 'resident_pct': 50, 'tax_bp': 1000, 'surcharge': 0, 'app': True, 'app_fee': 35}, {'base': 3532, 'tax': 353, 'total': 3924}), ({'base': 4127, 'resident': False, 'resident_pct': 50, 'tax_bp': 1850, 'surcharge': 150, 'app': False, 'app_fee': 35}, {'base': 4127, 'tax': 763, 'total': 5040}), ({'base': 4285, 'resident': False, 'resident_pct': 50, 'tax_bp': 1850, 'surcharge': 150, 'app': False, 'app_fee': 25}, {'base': 4285, 'tax': 793, 'total': 5228}), ({'base': 2775, 'resident': False, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 50, 'app': True, 'app_fee': 35}, {'base': 2775, 'tax': 513, 'total': 3379}), ({'base': 3543, 'resident': True, 'resident_pct': 50, 'tax_bp': 1000, 'surcharge': 150, 'app': False, 'app_fee': 25}, {'base': 1772, 'tax': 177, 'total': 2099}), ({'base': 4552, 'resident': True, 'resident_pct': 50, 'tax_bp': 625, 'surcharge': 0, 'app': True, 'app_fee': 35}, {'base': 2276, 'tax': 142, 'total': 2455}), ({'base': 2846, 'resident': True, 'resident_pct': 20, 'tax_bp': 2250, 'surcharge': 150, 'app': True, 'app_fee': 45}, {'base': 2277, 'tax': 512, 'total': 2994}), ({'base': 1000, 'resident': True, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 150, 'app': True, 'app_fee': 35}, {'base': 750, 'tax': 139, 'total': 1080})], [({'base': 4467, 'resident': True, 'resident_pct': 20, 'tax_bp': 1000, 'surcharge': 50, 'app': False, 'app_fee': 25}, {'base': 3574, 'tax': 357, 'total': 3981}), ({'base': 3746, 'resident': False, 'resident_pct': 25, 'tax_bp': 1000, 'surcharge': 150, 'app': False, 'app_fee': 45}, {'base': 3746, 'tax': 375, 'total': 4271}), ({'base': 3485, 'resident': True, 'resident_pct': 20, 'tax_bp': 2250, 'surcharge': 0, 'app': True, 'app_fee': 25}, {'base': 2788, 'tax': 627, 'total': 3446}), ({'base': 1000, 'resident': True, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 150, 'app': True, 'app_fee': 35}, {'base': 750, 'tax': 139, 'total': 1080}), ({'base': 4961, 'resident': False, 'resident_pct': 50, 'tax_bp': 2250, 'surcharge': 150, 'app': True, 'app_fee': 35}, {'base': 4961, 'tax': 1116, 'total': 6270}), ({'base': 3383, 'resident': False, 'resident_pct': 50, 'tax_bp': 2250, 'surcharge': 150, 'app': True, 'app_fee': 25}, {'base': 3383, 'tax': 761, 'total': 4325}), ({'base': 2453, 'resident': True, 'resident_pct': 25, 'tax_bp': 1000, 'surcharge': 0, 'app': False, 'app_fee': 35}, {'base': 1840, 'tax': 184, 'total': 2024}), ({'base': 1002, 'resident': False, 'resident_pct': 20, 'tax_bp': 625, 'surcharge': 50, 'app': False, 'app_fee': 45}, {'base': 1002, 'tax': 63, 'total': 1115})], [({'base': 1986, 'resident': False, 'resident_pct': 25, 'tax_bp': 2250, 'surcharge': 150, 'app': True, 'app_fee': 25}, {'base': 1986, 'tax': 447, 'total': 2614}), ({'base': 781, 'resident': False, 'resident_pct': 20, 'tax_bp': 1000, 'surcharge': 50, 'app': True, 'app_fee': 25}, {'base': 781, 'tax': 78, 'total': 937}), ({'base': 1000, 'resident': True, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 150, 'app': True, 'app_fee': 35}, {'base': 750, 'tax': 139, 'total': 1080}), ({'base': 2384, 'resident': True, 'resident_pct': 25, 'tax_bp': 1000, 'surcharge': 0, 'app': False, 'app_fee': 45}, {'base': 1788, 'tax': 179, 'total': 1967}), ({'base': 1756, 'resident': False, 'resident_pct': 20, 'tax_bp': 2250, 'surcharge': 0, 'app': True, 'app_fee': 25}, {'base': 1756, 'tax': 395, 'total': 2182}), ({'base': 2491, 'resident': True, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 50, 'app': False, 'app_fee': 45}, {'base': 1869, 'tax': 346, 'total': 2265}), ({'base': 3567, 'resident': False, 'resident_pct': 20, 'tax_bp': 2250, 'surcharge': 0, 'app': True, 'app_fee': 35}, {'base': 3567, 'tax': 803, 'total': 4413}), ({'base': 3650, 'resident': True, 'resident_pct': 50, 'tax_bp': 1000, 'surcharge': 150, 'app': False, 'app_fee': 25}, {'base': 1825, 'tax': 183, 'total': 2158})]]
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)

source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    base = x['base']
    if x['resident']:
        base -= x['resident_pct']
    tax = (base * x['tax_bp'] + 5000) // 10000
    total = base + tax + x['surcharge']
    if x['app']:
        total += x['app_fee'] + (x['app_fee'] * x['tax_bp'] + 5000) // 10000
    return {'base': base, 'tax': tax, 'total': total}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[({'base': 2437, 'resident': True, 'resident_pct': 50, 'tax_bp': 1000, 'surcharge': 150, 'app': False, 'app_fee': 35}, {'base': 1219, 'tax': 122, 'total': 1491}), ({'base': 122, 'resident': True, 'resident_pct': 20, 'tax_bp': 1850, 'surcharge': 150, 'app': False, 'app_fee': 25}, {'base': 98, 'tax': 18, 'total': 266}), ({'base': 4927, 'resident': False, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 0, 'app': False, 'app_fee': 35}, {'base': 4927, 'tax': 911, 'total': 5838}), ({'base': 2805, 'resident': False, 'resident_pct': 20, 'tax_bp': 1000, 'surcharge': 0, 'app': True, 'app_fee': 35}, {'base': 2805, 'tax': 281, 'total': 3125}), ({'base': 1795, 'resident': False, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 0, 'app': True, 'app_fee': 25}, {'base': 1795, 'tax': 332, 'total': 2157}), ({'base': 2304, 'resident': False, 'resident_pct': 20, 'tax_bp': 625, 'surcharge': 0, 'app': True, 'app_fee': 45}, {'base': 2304, 'tax': 144, 'total': 2496}), ({'base': 622, 'resident': True, 'resident_pct': 20, 'tax_bp': 625, 'surcharge': 0, 'app': True, 'app_fee': 25}, {'base': 498, 'tax': 31, 'total': 556}), ({'base': 1000, 'resident': True, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 150, 'app': True, 'app_fee': 35}, {'base': 750, 'tax': 139, 'total': 1080})], [({'base': 4756, 'resident': True, 'resident_pct': 25, 'tax_bp': 625, 'surcharge': 50, 'app': False, 'app_fee': 35}, {'base': 3567, 'tax': 223, 'total': 3840}), ({'base': 1000, 'resident': True, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 150, 'app': True, 'app_fee': 35}, {'base': 750, 'tax': 139, 'total': 1080}), ({'base': 4135, 'resident': False, 'resident_pct': 25, 'tax_bp': 625, 'surcharge': 50, 'app': True, 'app_fee': 45}, {'base': 4135, 'tax': 258, 'total': 4491}), ({'base': 4117, 'resident': False, 'resident_pct': 20, 'tax_bp': 1850, 'surcharge': 0, 'app': True, 'app_fee': 35}, {'base': 4117, 'tax': 762, 'total': 4920}), ({'base': 1189, 'resident': False, 'resident_pct': 50, 'tax_bp': 2250, 'surcharge': 150, 'app': False, 'app_fee': 45}, {'base': 1189, 'tax': 268, 'total': 1607}), ({'base': 815, 'resident': False, 'resident_pct': 50, 'tax_bp': 1850, 'surcharge': 150, 'app': False, 'app_fee': 35}, {'base': 815, 'tax': 151, 'total': 1116}), ({'base': 816, 'resident': False, 'resident_pct': 20, 'tax_bp': 1850, 'surcharge': 50, 'app': False, 'app_fee': 35}, {'base': 816, 'tax': 151, 'total': 1017}), ({'base': 4473, 'resident': True, 'resident_pct': 50, 'tax_bp': 1000, 'surcharge': 150, 'app': True, 'app_fee': 25}, {'base': 2237, 'tax': 224, 'total': 2639})], [({'base': 3532, 'resident': False, 'resident_pct': 50, 'tax_bp': 1000, 'surcharge': 0, 'app': True, 'app_fee': 35}, {'base': 3532, 'tax': 353, 'total': 3924}), ({'base': 4127, 'resident': False, 'resident_pct': 50, 'tax_bp': 1850, 'surcharge': 150, 'app': False, 'app_fee': 35}, {'base': 4127, 'tax': 763, 'total': 5040}), ({'base': 4285, 'resident': False, 'resident_pct': 50, 'tax_bp': 1850, 'surcharge': 150, 'app': False, 'app_fee': 25}, {'base': 4285, 'tax': 793, 'total': 5228}), ({'base': 2775, 'resident': False, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 50, 'app': True, 'app_fee': 35}, {'base': 2775, 'tax': 513, 'total': 3379}), ({'base': 3543, 'resident': True, 'resident_pct': 50, 'tax_bp': 1000, 'surcharge': 150, 'app': False, 'app_fee': 25}, {'base': 1772, 'tax': 177, 'total': 2099}), ({'base': 4552, 'resident': True, 'resident_pct': 50, 'tax_bp': 625, 'surcharge': 0, 'app': True, 'app_fee': 35}, {'base': 2276, 'tax': 142, 'total': 2455}), ({'base': 2846, 'resident': True, 'resident_pct': 20, 'tax_bp': 2250, 'surcharge': 150, 'app': True, 'app_fee': 45}, {'base': 2277, 'tax': 512, 'total': 2994}), ({'base': 1000, 'resident': True, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 150, 'app': True, 'app_fee': 35}, {'base': 750, 'tax': 139, 'total': 1080})], [({'base': 4467, 'resident': True, 'resident_pct': 20, 'tax_bp': 1000, 'surcharge': 50, 'app': False, 'app_fee': 25}, {'base': 3574, 'tax': 357, 'total': 3981}), ({'base': 3746, 'resident': False, 'resident_pct': 25, 'tax_bp': 1000, 'surcharge': 150, 'app': False, 'app_fee': 45}, {'base': 3746, 'tax': 375, 'total': 4271}), ({'base': 3485, 'resident': True, 'resident_pct': 20, 'tax_bp': 2250, 'surcharge': 0, 'app': True, 'app_fee': 25}, {'base': 2788, 'tax': 627, 'total': 3446}), ({'base': 1000, 'resident': True, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 150, 'app': True, 'app_fee': 35}, {'base': 750, 'tax': 139, 'total': 1080}), ({'base': 4961, 'resident': False, 'resident_pct': 50, 'tax_bp': 2250, 'surcharge': 150, 'app': True, 'app_fee': 35}, {'base': 4961, 'tax': 1116, 'total': 6270}), ({'base': 3383, 'resident': False, 'resident_pct': 50, 'tax_bp': 2250, 'surcharge': 150, 'app': True, 'app_fee': 25}, {'base': 3383, 'tax': 761, 'total': 4325}), ({'base': 2453, 'resident': True, 'resident_pct': 25, 'tax_bp': 1000, 'surcharge': 0, 'app': False, 'app_fee': 35}, {'base': 1840, 'tax': 184, 'total': 2024}), ({'base': 1002, 'resident': False, 'resident_pct': 20, 'tax_bp': 625, 'surcharge': 50, 'app': False, 'app_fee': 45}, {'base': 1002, 'tax': 63, 'total': 1115})], [({'base': 1986, 'resident': False, 'resident_pct': 25, 'tax_bp': 2250, 'surcharge': 150, 'app': True, 'app_fee': 25}, {'base': 1986, 'tax': 447, 'total': 2614}), ({'base': 781, 'resident': False, 'resident_pct': 20, 'tax_bp': 1000, 'surcharge': 50, 'app': True, 'app_fee': 25}, {'base': 781, 'tax': 78, 'total': 937}), ({'base': 1000, 'resident': True, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 150, 'app': True, 'app_fee': 35}, {'base': 750, 'tax': 139, 'total': 1080}), ({'base': 2384, 'resident': True, 'resident_pct': 25, 'tax_bp': 1000, 'surcharge': 0, 'app': False, 'app_fee': 45}, {'base': 1788, 'tax': 179, 'total': 1967}), ({'base': 1756, 'resident': False, 'resident_pct': 20, 'tax_bp': 2250, 'surcharge': 0, 'app': True, 'app_fee': 25}, {'base': 1756, 'tax': 395, 'total': 2182}), ({'base': 2491, 'resident': True, 'resident_pct': 25, 'tax_bp': 1850, 'surcharge': 50, 'app': False, 'app_fee': 45}, {'base': 1869, 'tax': 346, 'total': 2265}), ({'base': 3567, 'resident': False, 'resident_pct': 20, 'tax_bp': 2250, 'surcharge': 0, 'app': True, 'app_fee': 35}, {'base': 3567, 'tax': 803, 'total': 4413}), ({'base': 3650, 'resident': True, 'resident_pct': 50, 'tax_bp': 1000, 'surcharge': 150, 'app': False, 'app_fee': 25}, {'base': 1825, 'tax': 183, 'total': 2158})]]
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)

prompt:
Parking tax and fee composition returns a wrong result when the resident percentage is kept instead of removed.

Input {base, resident, resident_pct, tax_bp (basis points), surcharge, app, app_fee}. Residents get resident_pct off (discount floored). Parking tax on the discounted base is rounded half up per transaction. The surcharge is untaxed. App payments add app_fee plus its own tax rounded half up. Return {base, tax, total}.

split: open-access


prompt:
Mid-flood heights stay far too low and the tide never reaches high water.

Input [t1,h1,t2,h2,t] in hours/metres for consecutive turning points t1<t2 (rise or fall). The interval is split into six equal tide hours with cumulative twelfths 0,1,3,6,9,11,12 and linear interpolation inside a tide hour. Return height rounded to 4 decimals, or None when t2<=t1 or t lies outside [t1,t2].

split: open-access


prompt:
Heights between whole tide hours jump by a whole twelfth-step early.

Input [t1,h1,t2,h2,t] in hours/metres for consecutive turning points t1<t2 (rise or fall). The interval is split into six equal tide hours with cumulative twelfths 0,1,3,6,9,11,12 and linear interpolation inside a tide hour. Return height rounded to 4 decimals, or None when t2<=t1 or t lies outside [t1,t2].

split: open-access


prompt:
Ebb predictions climb above the preceding high water.

Input [t1,h1,t2,h2,t] in hours/metres for consecutive turning points t1<t2 (rise or fall). The interval is split into six equal tide hours with cumulative twelfths 0,1,3,6,9,11,12 and linear interpolation inside a tide hour. Return height rounded to 4 decimals, or None when t2<=t1 or t lies outside [t1,t2].

split: open-access


prompt:
Queries past high water return heights above the high water itself.

Input [t1,h1,t2,h2,t] in hours/metres for consecutive turning points t1<t2 (rise or fall). The interval is split into six equal tide hours with cumulative twelfths 0,1,3,6,9,11,12 and linear interpolation inside a tide hour. Return height rounded to 4 decimals, or None when t2<=t1 or t lies outside [t1,t2].

split: open-access


prompt:
Predictions are only right when the rise lasts exactly six hours.

Input [t1,h1,t2,h2,t] in hours/metres for consecutive turning points t1<t2 (rise or fall). The interval is split into six equal tide hours with cumulative twelfths 0,1,3,6,9,11,12 and linear interpolation inside a tide hour. Return height rounded to 4 decimals, or None when t2<=t1 or t lies outside [t1,t2].

split: open-access


prompt:
Predicted high waters arrive early by twice the phase lag.

Input [t_minutes, z0, constituents]; each constituent is [H metres, g phase lag deg, speed deg/hour, nodal factor f, nodal phase u deg, equilibrium argument V0 deg]. Height above chart datum is z0 + sum f*H*cos(V0+u+speed*t_hours-g). Return rounded to 4 decimals.

split: open-access


prompt:
Predicted ranges are too small in years of strong lunar declination.

Input [t_minutes, z0, constituents]; each constituent is [H metres, g phase lag deg, speed deg/hour, nodal factor f, nodal phase u deg, equilibrium argument V0 deg]. Height above chart datum is z0 + sum f*H*cos(V0+u+speed*t_hours-g). Return rounded to 4 decimals.

split: open-access


prompt:
Predictions oscillate erratically with no semidiurnal pattern.

Input [t_minutes, z0, constituents]; each constituent is [H metres, g phase lag deg, speed deg/hour, nodal factor f, nodal phase u deg, equilibrium argument V0 deg]. Height above chart datum is z0 + sum f*H*cos(V0+u+speed*t_hours-g). Return rounded to 4 decimals.

split: open-access


prompt:
Only the epoch prediction is right; later times drift wildly.

Input [t_minutes, z0, constituents]; each constituent is [H metres, g phase lag deg, speed deg/hour, nodal factor f, nodal phase u deg, equilibrium argument V0 deg]. Height above chart datum is z0 + sum f*H*cos(V0+u+speed*t_hours-g). Return rounded to 4 decimals.

split: open-access


prompt:
All heights are low by the datum offset and many are negative.

Input [t_minutes, z0, constituents]; each constituent is [H metres, g phase lag deg, speed deg/hour, nodal factor f, nodal phase u deg, equilibrium argument V0 deg]. Height above chart datum is z0 + sum f*H*cos(V0+u+speed*t_hours-g). Return rounded to 4 decimals.

split: open-access


prompt:
Heights near low water are reached at the wrong end of the half-cycle.

Input [t1,h1,t2,h2,h] (hours, metres) for consecutive turning points with t2>t1 and h1!=h2. Height follows h1+(h2-h1)*(1-cos(pi*s/T))/2 with s elapsed and T=t2-t1. Return the time in whole minutes (rounded half up) when the height h is first reached on that half-cycle, or None when h lies outside the closed range of h1..h2.

split: open-access


prompt:
On the ebb the target height is reached at a mirrored time.

Input [t1,h1,t2,h2,h] (hours, metres) for consecutive turning points with t2>t1 and h1!=h2. Height follows h1+(h2-h1)*(1-cos(pi*s/T))/2 with s elapsed and T=t2-t1. Return the time in whole minutes (rounded half up) when the height h is first reached on that half-cycle, or None when h lies outside the closed range of h1..h2.

split: open-access


prompt:
Asking when high water height is reached returns None.

Input [t1,h1,t2,h2,h] (hours, metres) for consecutive turning points with t2>t1 and h1!=h2. Height follows h1+(h2-h1)*(1-cos(pi*s/T))/2 with s elapsed and T=t2-t1. Return the time in whole minutes (rounded half up) when the height h is first reached on that half-cycle, or None when h lies outside the closed range of h1..h2.

split: open-access


prompt:
Times are always reported on the whole hour.

Input [t1,h1,t2,h2,h] (hours, metres) for consecutive turning points with t2>t1 and h1!=h2. Height follows h1+(h2-h1)*(1-cos(pi*s/T))/2 with s elapsed and T=t2-t1. Return the time in whole minutes (rounded half up) when the height h is first reached on that half-cycle, or None when h lies outside the closed range of h1..h2.

split: open-access


prompt:
Computed times fall far beyond the second turning point.

Input [t1,h1,t2,h2,h] (hours, metres) for consecutive turning points with t2>t1 and h1!=h2. Height follows h1+(h2-h1)*(1-cos(pi*s/T))/2 with s elapsed and T=t2-t1. Return the time in whole minutes (rounded half up) when the height h is first reached on that half-cycle, or None when h lies outside the closed range of h1..h2.

split: open-access


prompt:
Near-neap days get spring corrections and vice versa.

Input dict: standard port HW time hw (minutes of day), height hh, today range rng, mean spring/neap ranges sr/nr, time differences ts/tn (spring/neap, minutes) and height differences hs/hn. Interpolation factor k=(rng-nr)/(sr-nr) clamped to [0,1]; difference = neap+(spring-neap)*k. Time is wrapped to [0,1440) and rounded to whole minutes half up; height rounded to 2 decimals. Return [minutes, height].

split: open-access


prompt:
Exceptional ranges produce time differences outside the published pair.

Input dict: standard port HW time hw (minutes of day), height hh, today range rng, mean spring/neap ranges sr/nr, time differences ts/tn (spring/neap, minutes) and height differences hs/hn. Interpolation factor k=(rng-nr)/(sr-nr) clamped to [0,1]; difference = neap+(spring-neap)*k. Time is wrapped to [0,1440) and rounded to whole minutes half up; height rounded to 2 decimals. Return [minutes, height].

split: open-access


prompt:
A correction just after midnight yields a negative time of day.

Input dict: standard port HW time hw (minutes of day), height hh, today range rng, mean spring/neap ranges sr/nr, time differences ts/tn (spring/neap, minutes) and height differences hs/hn. Interpolation factor k=(rng-nr)/(sr-nr) clamped to [0,1]; difference = neap+(spring-neap)*k. Time is wrapped to [0,1440) and rounded to whole minutes half up; height rounded to 2 decimals. Return [minutes, height].

split: open-access


prompt:
Corrected times are a minute off when the interpolated difference has a half minute.

Input dict: standard port HW time hw (minutes of day), height hh, today range rng, mean spring/neap ranges sr/nr, time differences ts/tn (spring/neap, minutes) and height differences hs/hn. Interpolation factor k=(rng-nr)/(sr-nr) clamped to [0,1]; difference = neap+(spring-neap)*k. Time is wrapped to [0,1440) and rounded to whole minutes half up; height rounded to 2 decimals. Return [minutes, height].

split: open-access


prompt:
Heights are corrected with the neap difference on spring days.

Input dict: standard port HW time hw (minutes of day), height hh, today range rng, mean spring/neap ranges sr/nr, time differences ts/tn (spring/neap, minutes) and height differences hs/hn. Interpolation factor k=(rng-nr)/(sr-nr) clamped to [0,1]; difference = neap+(spring-neap)*k. Time is wrapped to [0,1440) and rounded to whole minutes half up; height rounded to 2 decimals. Return [minutes, height].

split: open-access


prompt:
Clearance in narrow channels is overstated.

Input [charted, tide, draft, speed_kn, cb, confined, margin]. Charted value is depth below chart datum (negative means a drying height above datum). Squat = cb*speed^2/100 metres in open water and twice that when confined. UKC = charted+tide-draft-squat. Required clearance is margin*draft. Return [round(ukc,3), ukc>=required].

split: open-access


prompt:
Vessels are cleared over banks that dry at low water.

Input [charted, tide, draft, speed_kn, cb, confined, margin]. Charted value is depth below chart datum (negative means a drying height above datum). Squat = cb*speed^2/100 metres in open water and twice that when confined. UKC = charted+tide-draft-squat. Required clearance is margin*draft. Return [round(ukc,3), ukc>=required].

split: open-access


prompt:
Fast transits get far too little squat allowance.

Input [charted, tide, draft, speed_kn, cb, confined, margin]. Charted value is depth below chart datum (negative means a drying height above datum). Squat = cb*speed^2/100 metres in open water and twice that when confined. UKC = charted+tide-draft-squat. Required clearance is margin*draft. Return [round(ukc,3), ukc>=required].

split: open-access


prompt:
Deep berths demand an excessive clearance and refuse safe ships.

Input [charted, tide, draft, speed_kn, cb, confined, margin]. Charted value is depth below chart datum (negative means a drying height above datum). Squat = cb*speed^2/100 metres in open water and twice that when confined. UKC = charted+tide-draft-squat. Required clearance is margin*draft. Return [round(ukc,3), ukc>=required].

split: open-access


prompt:
A transit meeting the requirement exactly is refused.

Input [charted, tide, draft, speed_kn, cb, confined, margin]. Charted value is depth below chart datum (negative means a drying height above datum). Squat = cb*speed^2/100 metres in open water and twice that when confined. UKC = charted+tide-draft-squat. Required clearance is margin*draft. Return [round(ukc,3), ukc>=required].

split: open-access


prompt:
Clearance appears to grow as the tide rises, approving transits at high water.

Input [c, mhws, tide, air, safety]: charted vertical clearance c is measured above MHWS; mhws and tide are heights above chart datum; air is the vessel air draft. Available clearance = c+(mhws-tide) (it shrinks when the tide exceeds MHWS). Return [round(avail,2), round(avail-air,2), avail-air>=safety].

split: open-access


prompt:
Available clearance is short by the MHWS height at every tide.

Input [c, mhws, tide, air, safety]: charted vertical clearance c is measured above MHWS; mhws and tide are heights above chart datum; air is the vessel air draft. Available clearance = c+(mhws-tide) (it shrinks when the tide exceeds MHWS). Return [round(avail,2), round(avail-air,2), avail-air>=safety].

split: open-access


prompt:
During a surge the bridge is reported with its full charted clearance.

Input [c, mhws, tide, air, safety]: charted vertical clearance c is measured above MHWS; mhws and tide are heights above chart datum; air is the vessel air draft. Available clearance = c+(mhws-tide) (it shrinks when the tide exceeds MHWS). Return [round(avail,2), round(avail-air,2), avail-air>=safety].

split: open-access


prompt:
The displayed clearance is tide-corrected but the go decision is not.

Input [c, mhws, tide, air, safety]: charted vertical clearance c is measured above MHWS; mhws and tide are heights above chart datum; air is the vessel air draft. Available clearance = c+(mhws-tide) (it shrinks when the tide exceeds MHWS). Return [round(avail,2), round(avail-air,2), avail-air>=safety].

split: open-access


prompt:
A margin a few centimetres short of the allowance is approved.

Input [c, mhws, tide, air, safety]: charted vertical clearance c is measured above MHWS; mhws and tide are heights above chart datum; air is the vessel air draft. Available clearance = c+(mhws-tide) (it shrinks when the tide exceeds MHWS). Return [round(avail,2), round(avail-air,2), avail-air>=safety].

split: open-access


prompt:
At exactly half past an hour the stream is read from alternating rows.

Input [hrel, rng, sr, nr, rows]: hrel is hours relative to standard-port HW; rows lists 13 entries for HW-6..HW+6 as [direction, spring rate, neap rate] in tenths of a knot. The row is chosen by rounding hrel half up (floor(hrel+0.5)); hrel outside [-6.5,6.5) returns None. Rate = neap+(spring-neap)*k with k=(rng-nr)/(sr-nr) (not clamped), converted to knots, floored at zero and rounded to 2 decimals. Return [direction, knots].

split: open-access


prompt:
Before high water the ebb rows are returned for the flood.

Input [hrel, rng, sr, nr, rows]: hrel is hours relative to standard-port HW; rows lists 13 entries for HW-6..HW+6 as [direction, spring rate, neap rate] in tenths of a knot. The row is chosen by rounding hrel half up (floor(hrel+0.5)); hrel outside [-6.5,6.5) returns None. Rate = neap+(spring-neap)*k with k=(rng-nr)/(sr-nr) (not clamped), converted to knots, floored at zero and rounded to 2 decimals. Return [direction, knots].

split: open-access


prompt:
On very small ranges the stream rate becomes negative.

Input [hrel, rng, sr, nr, rows]: hrel is hours relative to standard-port HW; rows lists 13 entries for HW-6..HW+6 as [direction, spring rate, neap rate] in tenths of a knot. The row is chosen by rounding hrel half up (floor(hrel+0.5)); hrel outside [-6.5,6.5) returns None. Rate = neap+(spring-neap)*k with k=(rng-nr)/(sr-nr) (not clamped), converted to knots, floored at zero and rounded to 2 decimals. Return [direction, knots].

split: open-access


prompt:
Between HW+6 and HW+6.5 no stream is reported although a row applies.

Input [hrel, rng, sr, nr, rows]: hrel is hours relative to standard-port HW; rows lists 13 entries for HW-6..HW+6 as [direction, spring rate, neap rate] in tenths of a knot. The row is chosen by rounding hrel half up (floor(hrel+0.5)); hrel outside [-6.5,6.5) returns None. Rate = neap+(spring-neap)*k with k=(rng-nr)/(sr-nr) (not clamped), converted to knots, floored at zero and rounded to 2 decimals. Return [direction, knots].

split: open-access


prompt:
Stream rates are ten times too large.

Input [hrel, rng, sr, nr, rows]: hrel is hours relative to standard-port HW; rows lists 13 entries for HW-6..HW+6 as [direction, spring rate, neap rate] in tenths of a knot. The row is chosen by rounding hrel half up (floor(hrel+0.5)); hrel outside [-6.5,6.5) returns None. Rate = neap+(spring-neap)*k with k=(rng-nr)/(sr-nr) (not clamped), converted to knots, floored at zero and rounded to 2 decimals. Return [direction, knots].

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    track,bs,setd,drift=x
    rel=math.radians(setd-track)
    cross=drift*math.sin(rel)
    if abs(cross)>bs: return None
    a=math.asin(cross/bs)
    sog=bs*math.cos(a)+drift*math.cos(rel)
    if sog<=0: return None
    return [round(math.degrees(math.radians(track)+a)%360,1),round(sog,2)]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('course to steer across a stream [90, 6, 180, 1.5]', [90, 6, 180, 1.5], [75.5, 5.81]), ('course to steer across a stream [90, 6, 0, 1.5]', [90, 6, 0, 1.5], [104.5, 5.81]), ('course to steer across a stream [10, 5, 100, 2]', [10, 5, 100, 2], [346.4, 4.58]), ('course to steer across a stream [350, 5, 80, 2]', [350, 5, 80, 2], [326.4, 4.58]), ('course to steer across a stream [200, 4, 200, 3]', [200, 4, 200, 3], [200.0, 7.0]), ('course to steer across a stream [200, 4, 20, 3]', [200, 4, 20, 3], [200.0, 1.0]), ('course to steer across a stream [45, 5, 135, 6]', [45, 5, 135, 6], None)], [('course to steer across a stream [90, 6, 0, 1.5]', [90, 6, 0, 1.5], [104.5, 5.81]), ('course to steer across a stream [350, 5, 80, 2]', [350, 5, 80, 2], [326.4, 4.58]), ('course to steer across a stream [200, 4, 200, 3]', [200, 4, 200, 3], [200.0, 7.0]), ('course to steer across a stream [200, 4, 20, 3]', [200, 4, 20, 3], [200.0, 1.0]), ('course to steer across a stream [45, 5, 135, 6]', [45, 5, 135, 6], None), ('course to steer across a stream [45, 5, 60, 7]', [45, 5, 60, 7], [23.8, 11.42]), ('course to steer across a stream [120, 5, 300, 5.5]', [120, 5, 300, 5.5], None)], [('course to steer across a stream [10, 5, 100, 2]', [10, 5, 100, 2], [346.4, 4.58]), ('course to steer across a stream [45, 5, 135, 6]', [45, 5, 135, 6], None), ('course to steer across a stream [45, 5, 60, 7]', [45, 5, 60, 7], [23.8, 11.42]), ('course to steer across a stream [120, 5, 300, 5.5]', [120, 5, 300, 5.5], None), ('course to steer across a stream [0, 5, 90, 0]', [0, 5, 90, 0], [0.0, 5.0]), ('course to steer across a stream [270, 8, 315, 2.5]', [270, 8, 315, 2.5], [257.2, 9.57]), ('course to steer across a stream [5, 6, 275, 1.2]', [5, 6, 275, 1.2], [16.5, 5.88])], [('course to steer across a stream [350, 5, 80, 2]', [350, 5, 80, 2], [326.4, 4.58]), ('course to steer across a stream [0, 5, 90, 0]', [0, 5, 90, 0], [0.0, 5.0]), ('course to steer across a stream [270, 8, 315, 2.5]', [270, 8, 315, 2.5], [257.2, 9.57]), ('course to steer across a stream [5, 6, 275, 1.2]', [5, 6, 275, 1.2], [16.5, 5.88]), ('course to steer across a stream [180, 3, 90, 2.9]', [180, 3, 90, 2.9], [255.2, 0.77]), ('course to steer across a stream [300, 7, 120, 2]', [300, 7, 120, 2], [300.0, 5.0]), ('course to steer across a stream [5, 6, 90, 1.5]', [5, 6, 90, 1.5], [350.6, 5.94])], [('course to steer across a stream [45, 5, 60, 7]', [45, 5, 60, 7], [23.8, 11.42]), ('course to steer across a stream [180, 3, 90, 2.9]', [180, 3, 90, 2.9], [255.2, 0.77]), ('course to steer across a stream [300, 7, 120, 2]', [300, 7, 120, 2], [300.0, 5.0]), ('course to steer across a stream [5, 6, 90, 1.5]', [5, 6, 90, 1.5], [350.6, 5.94]), ('course to steer across a stream [355, 6, 260, 1.5]', [355, 6, 260, 1.5], [9.4, 5.68]), ('course to steer across a stream [0, 5, 10, 7]', [0, 5, 10, 7], [345.9, 11.74]), ('course to steer across a stream [90, 4, 100, 4.5]', [90, 4, 100, 4.5], [78.7, 8.35])]]
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)

source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    track,bs,setd,drift=x
    rel=math.radians(setd-track)
    cross=drift*math.sin(rel)
    if abs(cross)>bs: return None
    a=-math.atan2(cross,bs)
    sog=bs*math.cos(a)+drift*math.cos(rel)
    if sog<=0: return None
    return [round(math.degrees(math.radians(track)+a)%360,1),round(sog,2)]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('course to steer across a stream [90, 6, 180, 1.5]', [90, 6, 180, 1.5], [75.5, 5.81]), ('course to steer across a stream [90, 6, 0, 1.5]', [90, 6, 0, 1.5], [104.5, 5.81]), ('course to steer across a stream [10, 5, 100, 2]', [10, 5, 100, 2], [346.4, 4.58]), ('course to steer across a stream [350, 5, 80, 2]', [350, 5, 80, 2], [326.4, 4.58]), ('course to steer across a stream [200, 4, 200, 3]', [200, 4, 200, 3], [200.0, 7.0]), ('course to steer across a stream [200, 4, 20, 3]', [200, 4, 20, 3], [200.0, 1.0]), ('course to steer across a stream [45, 5, 135, 6]', [45, 5, 135, 6], None)], [('course to steer across a stream [90, 6, 0, 1.5]', [90, 6, 0, 1.5], [104.5, 5.81]), ('course to steer across a stream [350, 5, 80, 2]', [350, 5, 80, 2], [326.4, 4.58]), ('course to steer across a stream [200, 4, 200, 3]', [200, 4, 200, 3], [200.0, 7.0]), ('course to steer across a stream [200, 4, 20, 3]', [200, 4, 20, 3], [200.0, 1.0]), ('course to steer across a stream [45, 5, 135, 6]', [45, 5, 135, 6], None), ('course to steer across a stream [45, 5, 60, 7]', [45, 5, 60, 7], [23.8, 11.42]), ('course to steer across a stream [120, 5, 300, 5.5]', [120, 5, 300, 5.5], None)], [('course to steer across a stream [10, 5, 100, 2]', [10, 5, 100, 2], [346.4, 4.58]), ('course to steer across a stream [45, 5, 135, 6]', [45, 5, 135, 6], None), ('course to steer across a stream [45, 5, 60, 7]', [45, 5, 60, 7], [23.8, 11.42]), ('course to steer across a stream [120, 5, 300, 5.5]', [120, 5, 300, 5.5], None), ('course to steer across a stream [0, 5, 90, 0]', [0, 5, 90, 0], [0.0, 5.0]), ('course to steer across a stream [270, 8, 315, 2.5]', [270, 8, 315, 2.5], [257.2, 9.57]), ('course to steer across a stream [5, 6, 275, 1.2]', [5, 6, 275, 1.2], [16.5, 5.88])], [('course to steer across a stream [350, 5, 80, 2]', [350, 5, 80, 2], [326.4, 4.58]), ('course to steer across a stream [0, 5, 90, 0]', [0, 5, 90, 0], [0.0, 5.0]), ('course to steer across a stream [270, 8, 315, 2.5]', [270, 8, 315, 2.5], [257.2, 9.57]), ('course to steer across a stream [5, 6, 275, 1.2]', [5, 6, 275, 1.2], [16.5, 5.88]), ('course to steer across a stream [180, 3, 90, 2.9]', [180, 3, 90, 2.9], [255.2, 0.77]), ('course to steer across a stream [300, 7, 120, 2]', [300, 7, 120, 2], [300.0, 5.0]), ('course to steer across a stream [5, 6, 90, 1.5]', [5, 6, 90, 1.5], [350.6, 5.94])], [('course to steer across a stream [45, 5, 60, 7]', [45, 5, 60, 7], [23.8, 11.42]), ('course to steer across a stream [180, 3, 90, 2.9]', [180, 3, 90, 2.9], [255.2, 0.77]), ('course to steer across a stream [300, 7, 120, 2]', [300, 7, 120, 2], [300.0, 5.0]), ('course to steer across a stream [5, 6, 90, 1.5]', [5, 6, 90, 1.5], [350.6, 5.94]), ('course to steer across a stream [355, 6, 260, 1.5]', [355, 6, 260, 1.5], [9.4, 5.68]), ('course to steer across a stream [0, 5, 10, 7]', [0, 5, 10, 7], [345.9, 11.74]), ('course to steer across a stream [90, 4, 100, 4.5]', [90, 4, 100, 4.5], [78.7, 8.35])]]
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)

prompt:
The vessel is set twice as far off track.

Input [track, boat_speed, set, drift] with degrees true (set is the direction the stream flows toward) and knots. Cross-track stream c=drift*sin(set-track); heading = track+asin(-c/boat); SOG=boat*cos(asin(-c/boat))+drift*cos(set-track). Return None when |c|>boat or SOG<=0, else [heading mod 360 rounded to 0.1, SOG rounded to 0.01].

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    track,bs,setd,drift=x
    rel=math.radians(setd-track)
    cross=drift*math.sin(rel)
    if abs(cross)>bs: return None
    a=math.asin(-cross/bs)
    sog=bs*math.cos(a)+drift*math.cos(rel)
    if sog<=0: return None
    return [round(math.degrees(math.radians(track)+a),1),round(sog,2)]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('course to steer across a stream [10, 5, 100, 2]', [10, 5, 100, 2], [346.4, 4.58]), ('course to steer across a stream [90, 6, 180, 1.5]', [90, 6, 180, 1.5], [75.5, 5.81]), ('course to steer across a stream [90, 6, 0, 1.5]', [90, 6, 0, 1.5], [104.5, 5.81]), ('course to steer across a stream [350, 5, 80, 2]', [350, 5, 80, 2], [326.4, 4.58]), ('course to steer across a stream [200, 4, 200, 3]', [200, 4, 200, 3], [200.0, 7.0]), ('course to steer across a stream [200, 4, 20, 3]', [200, 4, 20, 3], [200.0, 1.0]), ('course to steer across a stream [45, 5, 135, 6]', [45, 5, 135, 6], None)], [('course to steer across a stream [5, 6, 90, 1.5]', [5, 6, 90, 1.5], [350.6, 5.94]), ('course to steer across a stream [350, 5, 80, 2]', [350, 5, 80, 2], [326.4, 4.58]), ('course to steer across a stream [200, 4, 200, 3]', [200, 4, 200, 3], [200.0, 7.0]), ('course to steer across a stream [200, 4, 20, 3]', [200, 4, 20, 3], [200.0, 1.0]), ('course to steer across a stream [45, 5, 135, 6]', [45, 5, 135, 6], None), ('course to steer across a stream [45, 5, 60, 7]', [45, 5, 60, 7], [23.8, 11.42]), ('course to steer across a stream [120, 5, 300, 5.5]', [120, 5, 300, 5.5], None)], [('course to steer across a stream [355, 6, 260, 1.5]', [355, 6, 260, 1.5], [9.4, 5.68]), ('course to steer across a stream [45, 5, 135, 6]', [45, 5, 135, 6], None), ('course to steer across a stream [45, 5, 60, 7]', [45, 5, 60, 7], [23.8, 11.42]), ('course to steer across a stream [120, 5, 300, 5.5]', [120, 5, 300, 5.5], None), ('course to steer across a stream [0, 5, 90, 0]', [0, 5, 90, 0], [0.0, 5.0]), ('course to steer across a stream [270, 8, 315, 2.5]', [270, 8, 315, 2.5], [257.2, 9.57]), ('course to steer across a stream [5, 6, 275, 1.2]', [5, 6, 275, 1.2], [16.5, 5.88])], [('course to steer across a stream [0, 5, 10, 7]', [0, 5, 10, 7], [345.9, 11.74]), ('course to steer across a stream [0, 5, 90, 0]', [0, 5, 90, 0], [0.0, 5.0]), ('course to steer across a stream [270, 8, 315, 2.5]', [270, 8, 315, 2.5], [257.2, 9.57]), ('course to steer across a stream [5, 6, 275, 1.2]', [5, 6, 275, 1.2], [16.5, 5.88]), ('course to steer across a stream [180, 3, 90, 2.9]', [180, 3, 90, 2.9], [255.2, 0.77]), ('course to steer across a stream [300, 7, 120, 2]', [300, 7, 120, 2], [300.0, 5.0]), ('course to steer across a stream [5, 6, 90, 1.5]', [5, 6, 90, 1.5], [350.6, 5.94])], [('course to steer across a stream [10, 5, 100, 2]', [10, 5, 100, 2], [346.4, 4.58]), ('course to steer across a stream [180, 3, 90, 2.9]', [180, 3, 90, 2.9], [255.2, 0.77]), ('course to steer across a stream [300, 7, 120, 2]', [300, 7, 120, 2], [300.0, 5.0]), ('course to steer across a stream [5, 6, 90, 1.5]', [5, 6, 90, 1.5], [350.6, 5.94]), ('course to steer across a stream [355, 6, 260, 1.5]', [355, 6, 260, 1.5], [9.4, 5.68]), ('course to steer across a stream [0, 5, 10, 7]', [0, 5, 10, 7], [345.9, 11.74]), ('course to steer across a stream [90, 4, 100, 4.5]', [90, 4, 100, 4.5], [78.7, 8.35])]]
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)

source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    track,bs,setd,drift=x
    rel=math.radians(setd-track)
    cross=drift*math.sin(rel)
    if abs(cross)>bs: return None
    a=math.asin(-cross/bs)
    sog=bs*math.cos(a)+drift*math.cos(rel)
    if sog<=0: return None
    return [round(abs(math.degrees(math.radians(track)+a)),1),round(sog,2)]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('course to steer across a stream [10, 5, 100, 2]', [10, 5, 100, 2], [346.4, 4.58]), ('course to steer across a stream [90, 6, 180, 1.5]', [90, 6, 180, 1.5], [75.5, 5.81]), ('course to steer across a stream [90, 6, 0, 1.5]', [90, 6, 0, 1.5], [104.5, 5.81]), ('course to steer across a stream [350, 5, 80, 2]', [350, 5, 80, 2], [326.4, 4.58]), ('course to steer across a stream [200, 4, 200, 3]', [200, 4, 200, 3], [200.0, 7.0]), ('course to steer across a stream [200, 4, 20, 3]', [200, 4, 20, 3], [200.0, 1.0]), ('course to steer across a stream [45, 5, 135, 6]', [45, 5, 135, 6], None)], [('course to steer across a stream [5, 6, 90, 1.5]', [5, 6, 90, 1.5], [350.6, 5.94]), ('course to steer across a stream [350, 5, 80, 2]', [350, 5, 80, 2], [326.4, 4.58]), ('course to steer across a stream [200, 4, 200, 3]', [200, 4, 200, 3], [200.0, 7.0]), ('course to steer across a stream [200, 4, 20, 3]', [200, 4, 20, 3], [200.0, 1.0]), ('course to steer across a stream [45, 5, 135, 6]', [45, 5, 135, 6], None), ('course to steer across a stream [45, 5, 60, 7]', [45, 5, 60, 7], [23.8, 11.42]), ('course to steer across a stream [120, 5, 300, 5.5]', [120, 5, 300, 5.5], None)], [('course to steer across a stream [355, 6, 260, 1.5]', [355, 6, 260, 1.5], [9.4, 5.68]), ('course to steer across a stream [45, 5, 135, 6]', [45, 5, 135, 6], None), ('course to steer across a stream [45, 5, 60, 7]', [45, 5, 60, 7], [23.8, 11.42]), ('course to steer across a stream [120, 5, 300, 5.5]', [120, 5, 300, 5.5], None), ('course to steer across a stream [0, 5, 90, 0]', [0, 5, 90, 0], [0.0, 5.0]), ('course to steer across a stream [270, 8, 315, 2.5]', [270, 8, 315, 2.5], [257.2, 9.57]), ('course to steer across a stream [5, 6, 275, 1.2]', [5, 6, 275, 1.2], [16.5, 5.88])], [('course to steer across a stream [0, 5, 10, 7]', [0, 5, 10, 7], [345.9, 11.74]), ('course to steer across a stream [0, 5, 90, 0]', [0, 5, 90, 0], [0.0, 5.0]), ('course to steer across a stream [270, 8, 315, 2.5]', [270, 8, 315, 2.5], [257.2, 9.57]), ('course to steer across a stream [5, 6, 275, 1.2]', [5, 6, 275, 1.2], [16.5, 5.88]), ('course to steer across a stream [180, 3, 90, 2.9]', [180, 3, 90, 2.9], [255.2, 0.77]), ('course to steer across a stream [300, 7, 120, 2]', [300, 7, 120, 2], [300.0, 5.0]), ('course to steer across a stream [5, 6, 90, 1.5]', [5, 6, 90, 1.5], [350.6, 5.94])], [('course to steer across a stream [10, 5, 100, 2]', [10, 5, 100, 2], [346.4, 4.58]), ('course to steer across a stream [180, 3, 90, 2.9]', [180, 3, 90, 2.9], [255.2, 0.77]), ('course to steer across a stream [300, 7, 120, 2]', [300, 7, 120, 2], [300.0, 5.0]), ('course to steer across a stream [5, 6, 90, 1.5]', [5, 6, 90, 1.5], [350.6, 5.94]), ('course to steer across a stream [355, 6, 260, 1.5]', [355, 6, 260, 1.5], [9.4, 5.68]), ('course to steer across a stream [0, 5, 10, 7]', [0, 5, 10, 7], [345.9, 11.74]), ('course to steer across a stream [90, 4, 100, 4.5]', [90, 4, 100, 4.5], [78.7, 8.35])]]
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)

prompt:
Courses left of north come out negative or above 360.

Input [track, boat_speed, set, drift] with degrees true (set is the direction the stream flows toward) and knots. Cross-track stream c=drift*sin(set-track); heading = track+asin(-c/boat); SOG=boat*cos(asin(-c/boat))+drift*cos(set-track). Return None when |c|>boat or SOG<=0, else [heading mod 360 rounded to 0.1, SOG rounded to 0.01].

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    track,bs,setd,drift=x
    rel=math.radians(setd+180-track)
    cross=drift*math.sin(rel)
    if abs(cross)>bs: return None
    a=math.asin(-cross/bs)
    sog=bs*math.cos(a)+drift*math.cos(rel)
    if sog<=0: return None
    return [round(math.degrees(math.radians(track)+a)%360,1),round(sog,2)]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('course to steer across a stream [90, 6, 180, 1.5]', [90, 6, 180, 1.5], [75.5, 5.81]), ('course to steer across a stream [90, 6, 0, 1.5]', [90, 6, 0, 1.5], [104.5, 5.81]), ('course to steer across a stream [10, 5, 100, 2]', [10, 5, 100, 2], [346.4, 4.58]), ('course to steer across a stream [350, 5, 80, 2]', [350, 5, 80, 2], [326.4, 4.58]), ('course to steer across a stream [200, 4, 200, 3]', [200, 4, 200, 3], [200.0, 7.0]), ('course to steer across a stream [200, 4, 20, 3]', [200, 4, 20, 3], [200.0, 1.0]), ('course to steer across a stream [45, 5, 135, 6]', [45, 5, 135, 6], None)], [('course to steer across a stream [90, 6, 0, 1.5]', [90, 6, 0, 1.5], [104.5, 5.81]), ('course to steer across a stream [350, 5, 80, 2]', [350, 5, 80, 2], [326.4, 4.58]), ('course to steer across a stream [200, 4, 200, 3]', [200, 4, 200, 3], [200.0, 7.0]), ('course to steer across a stream [200, 4, 20, 3]', [200, 4, 20, 3], [200.0, 1.0]), ('course to steer across a stream [45, 5, 135, 6]', [45, 5, 135, 6], None), ('course to steer across a stream [45, 5, 60, 7]', [45, 5, 60, 7], [23.8, 11.42]), ('course to steer across a stream [120, 5, 300, 5.5]', [120, 5, 300, 5.5], None)], [('course to steer across a stream [10, 5, 100, 2]', [10, 5, 100, 2], [346.4, 4.58]), ('course to steer across a stream [45, 5, 135, 6]', [45, 5, 135, 6], None), ('course to steer across a stream [45, 5, 60, 7]', [45, 5, 60, 7], [23.8, 11.42]), ('course to steer across a stream [120, 5, 300, 5.5]', [120, 5, 300, 5.5], None), ('course to steer across a stream [0, 5, 90, 0]', [0, 5, 90, 0], [0.0, 5.0]), ('course to steer across a stream [270, 8, 315, 2.5]', [270, 8, 315, 2.5], [257.2, 9.57]), ('course to steer across a stream [5, 6, 275, 1.2]', [5, 6, 275, 1.2], [16.5, 5.88])], [('course to steer across a stream [350, 5, 80, 2]', [350, 5, 80, 2], [326.4, 4.58]), ('course to steer across a stream [0, 5, 90, 0]', [0, 5, 90, 0], [0.0, 5.0]), ('course to steer across a stream [270, 8, 315, 2.5]', [270, 8, 315, 2.5], [257.2, 9.57]), ('course to steer across a stream [5, 6, 275, 1.2]', [5, 6, 275, 1.2], [16.5, 5.88]), ('course to steer across a stream [180, 3, 90, 2.9]', [180, 3, 90, 2.9], [255.2, 0.77]), ('course to steer across a stream [300, 7, 120, 2]', [300, 7, 120, 2], [300.0, 5.0]), ('course to steer across a stream [5, 6, 90, 1.5]', [5, 6, 90, 1.5], [350.6, 5.94])], [('course to steer across a stream [200, 4, 200, 3]', [200, 4, 200, 3], [200.0, 7.0]), ('course to steer across a stream [45, 5, 60, 7]', [45, 5, 60, 7], [23.8, 11.42]), ('course to steer across a stream [180, 3, 90, 2.9]', [180, 3, 90, 2.9], [255.2, 0.77]), ('course to steer across a stream [300, 7, 120, 2]', [300, 7, 120, 2], [300.0, 5.0]), ('course to steer across a stream [5, 6, 90, 1.5]', [5, 6, 90, 1.5], [350.6, 5.94]), ('course to steer across a stream [355, 6, 260, 1.5]', [355, 6, 260, 1.5], [9.4, 5.68]), ('course to steer across a stream [0, 5, 10, 7]', [0, 5, 10, 7], [345.9, 11.74])]]
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)

source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    track,bs,setd,drift=x
    rel=math.radians(track-setd)
    cross=drift*math.sin(rel)
    if abs(cross)>bs: return None
    a=math.asin(-cross/bs)
    sog=bs*math.cos(a)+drift*math.cos(rel)
    if sog<=0: return None
    return [round(math.degrees(math.radians(track)+a)%360,1),round(sog,2)]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('course to steer across a stream [90, 6, 180, 1.5]', [90, 6, 180, 1.5], [75.5, 5.81]), ('course to steer across a stream [90, 6, 0, 1.5]', [90, 6, 0, 1.5], [104.5, 5.81]), ('course to steer across a stream [10, 5, 100, 2]', [10, 5, 100, 2], [346.4, 4.58]), ('course to steer across a stream [350, 5, 80, 2]', [350, 5, 80, 2], [326.4, 4.58]), ('course to steer across a stream [200, 4, 200, 3]', [200, 4, 200, 3], [200.0, 7.0]), ('course to steer across a stream [200, 4, 20, 3]', [200, 4, 20, 3], [200.0, 1.0]), ('course to steer across a stream [45, 5, 135, 6]', [45, 5, 135, 6], None)], [('course to steer across a stream [90, 6, 0, 1.5]', [90, 6, 0, 1.5], [104.5, 5.81]), ('course to steer across a stream [350, 5, 80, 2]', [350, 5, 80, 2], [326.4, 4.58]), ('course to steer across a stream [200, 4, 200, 3]', [200, 4, 200, 3], [200.0, 7.0]), ('course to steer across a stream [200, 4, 20, 3]', [200, 4, 20, 3], [200.0, 1.0]), ('course to steer across a stream [45, 5, 135, 6]', [45, 5, 135, 6], None), ('course to steer across a stream [45, 5, 60, 7]', [45, 5, 60, 7], [23.8, 11.42]), ('course to steer across a stream [120, 5, 300, 5.5]', [120, 5, 300, 5.5], None)], [('course to steer across a stream [10, 5, 100, 2]', [10, 5, 100, 2], [346.4, 4.58]), ('course to steer across a stream [45, 5, 135, 6]', [45, 5, 135, 6], None), ('course to steer across a stream [45, 5, 60, 7]', [45, 5, 60, 7], [23.8, 11.42]), ('course to steer across a stream [120, 5, 300, 5.5]', [120, 5, 300, 5.5], None), ('course to steer across a stream [0, 5, 90, 0]', [0, 5, 90, 0], [0.0, 5.0]), ('course to steer across a stream [270, 8, 315, 2.5]', [270, 8, 315, 2.5], [257.2, 9.57]), ('course to steer across a stream [5, 6, 275, 1.2]', [5, 6, 275, 1.2], [16.5, 5.88])], [('course to steer across a stream [350, 5, 80, 2]', [350, 5, 80, 2], [326.4, 4.58]), ('course to steer across a stream [0, 5, 90, 0]', [0, 5, 90, 0], [0.0, 5.0]), ('course to steer across a stream [270, 8, 315, 2.5]', [270, 8, 315, 2.5], [257.2, 9.57]), ('course to steer across a stream [5, 6, 275, 1.2]', [5, 6, 275, 1.2], [16.5, 5.88]), ('course to steer across a stream [180, 3, 90, 2.9]', [180, 3, 90, 2.9], [255.2, 0.77]), ('course to steer across a stream [300, 7, 120, 2]', [300, 7, 120, 2], [300.0, 5.0]), ('course to steer across a stream [5, 6, 90, 1.5]', [5, 6, 90, 1.5], [350.6, 5.94])], [('course to steer across a stream [200, 4, 200, 3]', [200, 4, 200, 3], [200.0, 7.0]), ('course to steer across a stream [45, 5, 60, 7]', [45, 5, 60, 7], [23.8, 11.42]), ('course to steer across a stream [180, 3, 90, 2.9]', [180, 3, 90, 2.9], [255.2, 0.77]), ('course to steer across a stream [300, 7, 120, 2]', [300, 7, 120, 2], [300.0, 5.0]), ('course to steer across a stream [5, 6, 90, 1.5]', [5, 6, 90, 1.5], [350.6, 5.94]), ('course to steer across a stream [355, 6, 260, 1.5]', [355, 6, 260, 1.5], [9.4, 5.68]), ('course to steer across a stream [0, 5, 10, 7]', [0, 5, 10, 7], [345.9, 11.74])]]
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)

prompt:
The boat is steered downstream and fair streams look foul.

Input [track, boat_speed, set, drift] with degrees true (set is the direction the stream flows toward) and knots. Cross-track stream c=drift*sin(set-track); heading = track+asin(-c/boat); SOG=boat*cos(asin(-c/boat))+drift*cos(set-track). Return None when |c|>boat or SOG<=0, else [heading mod 360 rounded to 0.1, SOG rounded to 0.01].

split: open-access