FAILURE MAP
← Case archive

FA-60811 / Loyalty points ledgers / Open access

Purchased points with volume bonus: price basis · case 01

Members are charged for the bonus points they receive free.

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

ROOT CAUSE

Price is computed on base plus bonus points.

VERIFIED REPAIR

Price only the purchased base thousands.

Unsuccessful approach: Pricing the unfloored request still charges for points that are not delivered.

Case contract

Input {requests:[pts], price_per_1000, tiers:[[min_base, bonus_bp]] ascending, annual_limit, bought_ytd}. Each request is floored to whole thousands ("too small" when that is 0). A request whose base would push purchased base points above annual_limit is rejected whole ("limit"); bonus points never count toward the limit. Bonus = floor(base*bp/10000) with bp from the highest tier whose min_base <= this request base. Price = base/1000*price_per_1000. Return {results:[[base,bonus,price]|reason], bought_ytd}.

Why this case matters

Member point balances, statements and the program liability depend on this ledger rule.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    bought = x['bought_ytd']
    out = []
    for req in x['requests']:
        base = req // 1000 * 1000
        if base == 0:
            out.append('too small')
            continue
        if bought + base > x['annual_limit']:
            out.append('limit')
            continue
        bp = 0
        for mn, b in x['tiers']:
            if base >= mn:
                bp = b
        bonus = base * bp // 10000
        price = (base + bonus) // 1000 * x['price_per_1000']
        bought += base
        out.append([base, bonus, price])
    return {'results': out, 'bought_ytd': bought}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['small buy', {'requests': [3501], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[3000, 0, 3750]], 'bought_ytd': 3000}], ['tier edge', {'requests': [5000], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 1000000, 'bought_ytd': 20000}, {'results': [[5000, 500, 6250]], 'bought_ytd': 25000}], ['big buy', {'requests': [21000], 'price_per_1000': 1100, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[21000, 5250, 23100]], 'bought_ytd': 21000}], ['too small', {'requests': [999, 1001], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': ['too small', [1000, 0, 1000]], 'bought_ytd': 1000}], ['limit hit', {'requests': [30000, 30000, 11000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 70000, 'bought_ytd': 5000}, {'results': [[30000, 7500, 30000], [30000, 7500, 30000], 'limit'], 'bought_ytd': 65000}], ['bonus not limited', {'requests': [20000, 20001], 'price_per_1000': 900, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 40000, 'bought_ytd': 0}, {'results': [[20000, 5000, 18000], [20000, 5000, 18000]], 'bought_ytd': 40000}], ['near limit', {'requests': [7000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 10000, 'bought_ytd': 4001}, {'results': ['limit'], 'bought_ytd': 4001}]], [['small buy', {'requests': [3502], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[3000, 0, 3750]], 'bought_ytd': 3000}], ['tier edge', {'requests': [5000], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 1000000, 'bought_ytd': 40000}, {'results': [[5000, 500, 6250]], 'bought_ytd': 45000}], ['big buy', {'requests': [21001], 'price_per_1000': 1100, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[21000, 5250, 23100]], 'bought_ytd': 21000}], ['too small', {'requests': [999, 1002], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': ['too small', [1000, 0, 1000]], 'bought_ytd': 1000}], ['limit hit', {'requests': [30000, 30000, 12000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 70000, 'bought_ytd': 5000}, {'results': [[30000, 7500, 30000], [30000, 7500, 30000], 'limit'], 'bought_ytd': 65000}], ['bonus not limited', {'requests': [20000, 20002], 'price_per_1000': 900, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 40000, 'bought_ytd': 0}, {'results': [[20000, 5000, 18000], [20000, 5000, 18000]], 'bought_ytd': 40000}], ['near limit', {'requests': [7000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 10000, 'bought_ytd': 4002}, {'results': ['limit'], 'bought_ytd': 4002}]], [['small buy', {'requests': [3503], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[3000, 0, 3750]], 'bought_ytd': 3000}], ['tier edge', {'requests': [5000], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 1000000, 'bought_ytd': 60000}, {'results': [[5000, 500, 6250]], 'bought_ytd': 65000}], ['big buy', {'requests': [21002], 'price_per_1000': 1100, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[21000, 5250, 23100]], 'bought_ytd': 21000}], ['too small', {'requests': [999, 1003], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': ['too small', [1000, 0, 1000]], 'bought_ytd': 1000}], ['limit hit', {'requests': [30000, 30000, 13000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 70000, 'bought_ytd': 5000}, {'results': [[30000, 7500, 30000], [30000, 7500, 30000], 'limit'], 'bought_ytd': 65000}], ['bonus not limited', {'requests': [20000, 20003], 'price_per_1000': 900, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 40000, 'bought_ytd': 0}, {'results': [[20000, 5000, 18000], [20000, 5000, 18000]], 'bought_ytd': 40000}], ['near limit', {'requests': [7000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 10000, 'bought_ytd': 4003}, {'results': ['limit'], 'bought_ytd': 4003}]], [['small buy', {'requests': [3504], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[3000, 0, 3750]], 'bought_ytd': 3000}], ['tier edge', {'requests': [5000], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 1000000, 'bought_ytd': 80000}, {'results': [[5000, 500, 6250]], 'bought_ytd': 85000}], ['big buy', {'requests': [21003], 'price_per_1000': 1100, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[21000, 5250, 23100]], 'bought_ytd': 21000}], ['too small', {'requests': [999, 1004], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': ['too small', [1000, 0, 1000]], 'bought_ytd': 1000}], ['limit hit', {'requests': [30000, 30000, 14000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 70000, 'bought_ytd': 5000}, {'results': [[30000, 7500, 30000], [30000, 7500, 30000], 'limit'], 'bought_ytd': 65000}], ['bonus not limited', {'requests': [20000, 20004], 'price_per_1000': 900, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 40000, 'bought_ytd': 0}, {'results': [[20000, 5000, 18000], [20000, 5000, 18000]], 'bought_ytd': 40000}], ['near limit', {'requests': [7000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 10000, 'bought_ytd': 4004}, {'results': ['limit'], 'bought_ytd': 4004}]], [['small buy', {'requests': [3505], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[3000, 0, 3750]], 'bought_ytd': 3000}], ['tier edge', {'requests': [5000], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 1000000, 'bought_ytd': 100000}, {'results': [[5000, 500, 6250]], 'bought_ytd': 105000}], ['big buy', {'requests': [21004], 'price_per_1000': 1100, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[21000, 5250, 23100]], 'bought_ytd': 21000}], ['too small', {'requests': [999, 1005], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': ['too small', [1000, 0, 1000]], 'bought_ytd': 1000}], ['limit hit', {'requests': [30000, 30000, 15000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 70000, 'bought_ytd': 5000}, {'results': [[30000, 7500, 30000], [30000, 7500, 30000], 'limit'], 'bought_ytd': 65000}], ['bonus not limited', {'requests': [20000, 20005], 'price_per_1000': 900, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 40000, 'bought_ytd': 0}, {'results': [[20000, 5000, 18000], [20000, 5000, 18000]], 'bought_ytd': 40000}], ['near limit', {'requests': [7000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 10000, 'bought_ytd': 4005}, {'results': ['limit'], 'bought_ytd': 4005}]]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
small buy{'bought_ytd': 3000, 'results': [[3000, 0, 3750]]}{'bought_ytd': 3000, 'results': [[3000, 0, 3750]]}Passed
tier edge{'bought_ytd': 25000, 'results': [[5000, 500, 6250]]}{'bought_ytd': 25000, 'results': [[5000, 500, 6250]]}Passed
big buy{'bought_ytd': 21000, 'results': [[21000, 5250, 28600]]}{'bought_ytd': 21000, 'results': [[21000, 5250, 23100]]}Failed
too small{'bought_ytd': 1000, 'results': ['too small', [1000, 0, 1000]]}{'bought_ytd': 1000, 'results': ['too small', [1000, 0, 1000]]}Passed
limit hit{'bought_ytd': 65000, 'results': [[30000, 7500, 37000], [30000, 7500, 37000], 'limit']}{'bought_ytd': 65000, 'results': [[30000, 7500, 30000], [30000, 7500, 30000], 'limit']}Failed
bonus not limited{'bought_ytd': 40000, 'results': [[20000, 5000, 22500], [20000, 5000, 22500]]}{'bought_ytd': 40000, 'results': [[20000, 5000, 18000], [20000, 5000, 18000]]}Failed
near limit{'bought_ytd': 4001, 'results': ['limit']}{'bought_ytd': 4001, 'results': ['limit']}Passed

SHA-256 / f3118e38741912c7234fa26177f0b403193d242aaf2cd0c9171ac79d89fe0d33

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    bought = x['bought_ytd']
    out = []
    for req in x['requests']:
        base = req // 1000 * 1000
        if base == 0:
            out.append('too small')
            continue
        if bought + base > x['annual_limit']:
            out.append('limit')
            continue
        bp = 0
        for mn, b in x['tiers']:
            if base >= mn:
                bp = b
        bonus = base * bp // 10000
        price = req * x['price_per_1000'] // 1000
        bought += base
        out.append([base, bonus, price])
    return {'results': out, 'bought_ytd': bought}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['small buy', {'requests': [3501], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[3000, 0, 3750]], 'bought_ytd': 3000}], ['tier edge', {'requests': [5000], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 1000000, 'bought_ytd': 20000}, {'results': [[5000, 500, 6250]], 'bought_ytd': 25000}], ['big buy', {'requests': [21000], 'price_per_1000': 1100, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[21000, 5250, 23100]], 'bought_ytd': 21000}], ['too small', {'requests': [999, 1001], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': ['too small', [1000, 0, 1000]], 'bought_ytd': 1000}], ['limit hit', {'requests': [30000, 30000, 11000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 70000, 'bought_ytd': 5000}, {'results': [[30000, 7500, 30000], [30000, 7500, 30000], 'limit'], 'bought_ytd': 65000}], ['bonus not limited', {'requests': [20000, 20001], 'price_per_1000': 900, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 40000, 'bought_ytd': 0}, {'results': [[20000, 5000, 18000], [20000, 5000, 18000]], 'bought_ytd': 40000}], ['near limit', {'requests': [7000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 10000, 'bought_ytd': 4001}, {'results': ['limit'], 'bought_ytd': 4001}]], [['small buy', {'requests': [3502], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[3000, 0, 3750]], 'bought_ytd': 3000}], ['tier edge', {'requests': [5000], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 1000000, 'bought_ytd': 40000}, {'results': [[5000, 500, 6250]], 'bought_ytd': 45000}], ['big buy', {'requests': [21001], 'price_per_1000': 1100, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[21000, 5250, 23100]], 'bought_ytd': 21000}], ['too small', {'requests': [999, 1002], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': ['too small', [1000, 0, 1000]], 'bought_ytd': 1000}], ['limit hit', {'requests': [30000, 30000, 12000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 70000, 'bought_ytd': 5000}, {'results': [[30000, 7500, 30000], [30000, 7500, 30000], 'limit'], 'bought_ytd': 65000}], ['bonus not limited', {'requests': [20000, 20002], 'price_per_1000': 900, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 40000, 'bought_ytd': 0}, {'results': [[20000, 5000, 18000], [20000, 5000, 18000]], 'bought_ytd': 40000}], ['near limit', {'requests': [7000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 10000, 'bought_ytd': 4002}, {'results': ['limit'], 'bought_ytd': 4002}]], [['small buy', {'requests': [3503], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[3000, 0, 3750]], 'bought_ytd': 3000}], ['tier edge', {'requests': [5000], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 1000000, 'bought_ytd': 60000}, {'results': [[5000, 500, 6250]], 'bought_ytd': 65000}], ['big buy', {'requests': [21002], 'price_per_1000': 1100, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[21000, 5250, 23100]], 'bought_ytd': 21000}], ['too small', {'requests': [999, 1003], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': ['too small', [1000, 0, 1000]], 'bought_ytd': 1000}], ['limit hit', {'requests': [30000, 30000, 13000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 70000, 'bought_ytd': 5000}, {'results': [[30000, 7500, 30000], [30000, 7500, 30000], 'limit'], 'bought_ytd': 65000}], ['bonus not limited', {'requests': [20000, 20003], 'price_per_1000': 900, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 40000, 'bought_ytd': 0}, {'results': [[20000, 5000, 18000], [20000, 5000, 18000]], 'bought_ytd': 40000}], ['near limit', {'requests': [7000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 10000, 'bought_ytd': 4003}, {'results': ['limit'], 'bought_ytd': 4003}]], [['small buy', {'requests': [3504], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[3000, 0, 3750]], 'bought_ytd': 3000}], ['tier edge', {'requests': [5000], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 1000000, 'bought_ytd': 80000}, {'results': [[5000, 500, 6250]], 'bought_ytd': 85000}], ['big buy', {'requests': [21003], 'price_per_1000': 1100, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[21000, 5250, 23100]], 'bought_ytd': 21000}], ['too small', {'requests': [999, 1004], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': ['too small', [1000, 0, 1000]], 'bought_ytd': 1000}], ['limit hit', {'requests': [30000, 30000, 14000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 70000, 'bought_ytd': 5000}, {'results': [[30000, 7500, 30000], [30000, 7500, 30000], 'limit'], 'bought_ytd': 65000}], ['bonus not limited', {'requests': [20000, 20004], 'price_per_1000': 900, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 40000, 'bought_ytd': 0}, {'results': [[20000, 5000, 18000], [20000, 5000, 18000]], 'bought_ytd': 40000}], ['near limit', {'requests': [7000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 10000, 'bought_ytd': 4004}, {'results': ['limit'], 'bought_ytd': 4004}]], [['small buy', {'requests': [3505], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[3000, 0, 3750]], 'bought_ytd': 3000}], ['tier edge', {'requests': [5000], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 1000000, 'bought_ytd': 100000}, {'results': [[5000, 500, 6250]], 'bought_ytd': 105000}], ['big buy', {'requests': [21004], 'price_per_1000': 1100, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[21000, 5250, 23100]], 'bought_ytd': 21000}], ['too small', {'requests': [999, 1005], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': ['too small', [1000, 0, 1000]], 'bought_ytd': 1000}], ['limit hit', {'requests': [30000, 30000, 15000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 70000, 'bought_ytd': 5000}, {'results': [[30000, 7500, 30000], [30000, 7500, 30000], 'limit'], 'bought_ytd': 65000}], ['bonus not limited', {'requests': [20000, 20005], 'price_per_1000': 900, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 40000, 'bought_ytd': 0}, {'results': [[20000, 5000, 18000], [20000, 5000, 18000]], 'bought_ytd': 40000}], ['near limit', {'requests': [7000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 10000, 'bought_ytd': 4005}, {'results': ['limit'], 'bought_ytd': 4005}]]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
small buy{'bought_ytd': 3000, 'results': [[3000, 0, 4376]]}{'bought_ytd': 3000, 'results': [[3000, 0, 3750]]}Failed
tier edge{'bought_ytd': 25000, 'results': [[5000, 500, 6250]]}{'bought_ytd': 25000, 'results': [[5000, 500, 6250]]}Passed
big buy{'bought_ytd': 21000, 'results': [[21000, 5250, 23100]]}{'bought_ytd': 21000, 'results': [[21000, 5250, 23100]]}Passed
too small{'bought_ytd': 1000, 'results': ['too small', [1000, 0, 1001]]}{'bought_ytd': 1000, 'results': ['too small', [1000, 0, 1000]]}Failed
limit hit{'bought_ytd': 65000, 'results': [[30000, 7500, 30000], [30000, 7500, 30000], 'limit']}{'bought_ytd': 65000, 'results': [[30000, 7500, 30000], [30000, 7500, 30000], 'limit']}Passed
bonus not limited{'bought_ytd': 40000, 'results': [[20000, 5000, 18000], [20000, 5000, 18000]]}{'bought_ytd': 40000, 'results': [[20000, 5000, 18000], [20000, 5000, 18000]]}Passed
near limit{'bought_ytd': 4001, 'results': ['limit']}{'bought_ytd': 4001, 'results': ['limit']}Passed

SHA-256 / d6779b81ae726d74604b0ece98fc999682c19a6438cb09f56e36bfac48abcc3d

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    bought = x['bought_ytd']
    out = []
    for req in x['requests']:
        base = req // 1000 * 1000
        if base == 0:
            out.append('too small')
            continue
        if bought + base > x['annual_limit']:
            out.append('limit')
            continue
        bp = 0
        for mn, b in x['tiers']:
            if base >= mn:
                bp = b
        bonus = base * bp // 10000
        price = base // 1000 * x['price_per_1000']
        bought += base
        out.append([base, bonus, price])
    return {'results': out, 'bought_ytd': bought}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['small buy', {'requests': [3501], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[3000, 0, 3750]], 'bought_ytd': 3000}], ['tier edge', {'requests': [5000], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 1000000, 'bought_ytd': 20000}, {'results': [[5000, 500, 6250]], 'bought_ytd': 25000}], ['big buy', {'requests': [21000], 'price_per_1000': 1100, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[21000, 5250, 23100]], 'bought_ytd': 21000}], ['too small', {'requests': [999, 1001], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': ['too small', [1000, 0, 1000]], 'bought_ytd': 1000}], ['limit hit', {'requests': [30000, 30000, 11000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 70000, 'bought_ytd': 5000}, {'results': [[30000, 7500, 30000], [30000, 7500, 30000], 'limit'], 'bought_ytd': 65000}], ['bonus not limited', {'requests': [20000, 20001], 'price_per_1000': 900, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 40000, 'bought_ytd': 0}, {'results': [[20000, 5000, 18000], [20000, 5000, 18000]], 'bought_ytd': 40000}], ['near limit', {'requests': [7000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 10000, 'bought_ytd': 4001}, {'results': ['limit'], 'bought_ytd': 4001}]], [['small buy', {'requests': [3502], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[3000, 0, 3750]], 'bought_ytd': 3000}], ['tier edge', {'requests': [5000], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 1000000, 'bought_ytd': 40000}, {'results': [[5000, 500, 6250]], 'bought_ytd': 45000}], ['big buy', {'requests': [21001], 'price_per_1000': 1100, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[21000, 5250, 23100]], 'bought_ytd': 21000}], ['too small', {'requests': [999, 1002], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': ['too small', [1000, 0, 1000]], 'bought_ytd': 1000}], ['limit hit', {'requests': [30000, 30000, 12000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 70000, 'bought_ytd': 5000}, {'results': [[30000, 7500, 30000], [30000, 7500, 30000], 'limit'], 'bought_ytd': 65000}], ['bonus not limited', {'requests': [20000, 20002], 'price_per_1000': 900, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 40000, 'bought_ytd': 0}, {'results': [[20000, 5000, 18000], [20000, 5000, 18000]], 'bought_ytd': 40000}], ['near limit', {'requests': [7000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 10000, 'bought_ytd': 4002}, {'results': ['limit'], 'bought_ytd': 4002}]], [['small buy', {'requests': [3503], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[3000, 0, 3750]], 'bought_ytd': 3000}], ['tier edge', {'requests': [5000], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 1000000, 'bought_ytd': 60000}, {'results': [[5000, 500, 6250]], 'bought_ytd': 65000}], ['big buy', {'requests': [21002], 'price_per_1000': 1100, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[21000, 5250, 23100]], 'bought_ytd': 21000}], ['too small', {'requests': [999, 1003], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': ['too small', [1000, 0, 1000]], 'bought_ytd': 1000}], ['limit hit', {'requests': [30000, 30000, 13000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 70000, 'bought_ytd': 5000}, {'results': [[30000, 7500, 30000], [30000, 7500, 30000], 'limit'], 'bought_ytd': 65000}], ['bonus not limited', {'requests': [20000, 20003], 'price_per_1000': 900, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 40000, 'bought_ytd': 0}, {'results': [[20000, 5000, 18000], [20000, 5000, 18000]], 'bought_ytd': 40000}], ['near limit', {'requests': [7000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 10000, 'bought_ytd': 4003}, {'results': ['limit'], 'bought_ytd': 4003}]], [['small buy', {'requests': [3504], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[3000, 0, 3750]], 'bought_ytd': 3000}], ['tier edge', {'requests': [5000], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 1000000, 'bought_ytd': 80000}, {'results': [[5000, 500, 6250]], 'bought_ytd': 85000}], ['big buy', {'requests': [21003], 'price_per_1000': 1100, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[21000, 5250, 23100]], 'bought_ytd': 21000}], ['too small', {'requests': [999, 1004], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': ['too small', [1000, 0, 1000]], 'bought_ytd': 1000}], ['limit hit', {'requests': [30000, 30000, 14000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 70000, 'bought_ytd': 5000}, {'results': [[30000, 7500, 30000], [30000, 7500, 30000], 'limit'], 'bought_ytd': 65000}], ['bonus not limited', {'requests': [20000, 20004], 'price_per_1000': 900, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 40000, 'bought_ytd': 0}, {'results': [[20000, 5000, 18000], [20000, 5000, 18000]], 'bought_ytd': 40000}], ['near limit', {'requests': [7000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 10000, 'bought_ytd': 4004}, {'results': ['limit'], 'bought_ytd': 4004}]], [['small buy', {'requests': [3505], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[3000, 0, 3750]], 'bought_ytd': 3000}], ['tier edge', {'requests': [5000], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 1000000, 'bought_ytd': 100000}, {'results': [[5000, 500, 6250]], 'bought_ytd': 105000}], ['big buy', {'requests': [21004], 'price_per_1000': 1100, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[21000, 5250, 23100]], 'bought_ytd': 21000}], ['too small', {'requests': [999, 1005], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': ['too small', [1000, 0, 1000]], 'bought_ytd': 1000}], ['limit hit', {'requests': [30000, 30000, 15000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 70000, 'bought_ytd': 5000}, {'results': [[30000, 7500, 30000], [30000, 7500, 30000], 'limit'], 'bought_ytd': 65000}], ['bonus not limited', {'requests': [20000, 20005], 'price_per_1000': 900, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 40000, 'bought_ytd': 0}, {'results': [[20000, 5000, 18000], [20000, 5000, 18000]], 'bought_ytd': 40000}], ['near limit', {'requests': [7000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 10000, 'bought_ytd': 4005}, {'results': ['limit'], 'bought_ytd': 4005}]]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
small buy{'bought_ytd': 3000, 'results': [[3000, 0, 3750]]}{'bought_ytd': 3000, 'results': [[3000, 0, 3750]]}Passed
tier edge{'bought_ytd': 25000, 'results': [[5000, 500, 6250]]}{'bought_ytd': 25000, 'results': [[5000, 500, 6250]]}Passed
big buy{'bought_ytd': 21000, 'results': [[21000, 5250, 23100]]}{'bought_ytd': 21000, 'results': [[21000, 5250, 23100]]}Passed
too small{'bought_ytd': 1000, 'results': ['too small', [1000, 0, 1000]]}{'bought_ytd': 1000, 'results': ['too small', [1000, 0, 1000]]}Passed
limit hit{'bought_ytd': 65000, 'results': [[30000, 7500, 30000], [30000, 7500, 30000], 'limit']}{'bought_ytd': 65000, 'results': [[30000, 7500, 30000], [30000, 7500, 30000], 'limit']}Passed
bonus not limited{'bought_ytd': 40000, 'results': [[20000, 5000, 18000], [20000, 5000, 18000]]}{'bought_ytd': 40000, 'results': [[20000, 5000, 18000], [20000, 5000, 18000]]}Passed
near limit{'bought_ytd': 4001, 'results': ['limit']}{'bought_ytd': 4001, 'results': ['limit']}Passed

SHA-256 / 81a17f22fd26ace258d124ec03de8e821856178616e6689b9802a183e81c27c5

Verification & scope

Stipulated bounded loyalty-program model with explicit toy rules; not any real program terms. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.

Observations recorded using Python 3.12.14 at 2026-09-29T14:46:49.176933+00:00.

Case digest / 20139068b80c880f01de81ba9148a7115c6b329aca57a3f9804b61e105d2c20e