FA-84761 / Betting odds conversion / Open access
Teaser reduced to one leg is paid or lost · case 01
A two-team teaser with one push crashes or is graded a loss.
ROOT CAUSE
Only zero remaining winners are refunded, so one winner looks up a missing table row.
VERIFIED REPAIR
Refund when fewer than two winning legs remain.
Unsuccessful approach: Grading a single remaining leg as a loss is not the stated rule.
Case contract
Point-spread teaser. legs rows are [team spread line, team margin of victory]; every line is moved in the bettor's favour by points (adjusted = line + points). A leg wins if margin + adjusted > 0, pushes if = 0, loses if < 0. Any losing leg loses the ticket. Pushed legs are dropped; fewer than 2 remaining winners refunds the stake. Payout by winning legs from the American table {2: -120, 3: +160, 4: +260, 5: +400} (5 or more pay +400). Return [status, return cents rounded down].
Why this case matters
Sportsbooks grade teasers with shifted lines, push reduction and a tiered payout table.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
from fractions import Fraction
import math
N = 1
observations = []
def solve(legs, points, stake_cents):
TABLE = {2: -120, 3: 160, 4: 260, 5: 400}
wins = 0
for line, margin in legs:
adj = Fraction(line) + Fraction(points)
v = margin + adj
if v < 0:
return ['lose', 0]
if v > 0:
wins += 1
if wins < 1:
return ['refund', stake_cents]
am = TABLE[min(wins, 5)]
dec = 1 + (Fraction(am, 100) if am > 0 else Fraction(100, -am))
return ['win', math.floor(stake_cents * dec)]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
def run(args):
try:
return solve(*args)
except Exception as exc:
return 'raised ' + type(exc).__name__
cases = [[('control two-team teaser', ([['-7.5', 3], ['+2.5', -5]], '6', 1200), ['win', 2200]),
('boundary push drops a leg', ([['-7', 1], ['+3', 0], ['-1', 2]], '6', 1000), ['win', 1833]),
('boundary reduced to one leg', ([['-7', 1], ['+3', 5]], '6', 1000), ['refund', 1000]),
('control losing leg', ([['-10', 2], ['+3', 5], ['+7', 0]], '6', 1000), ['lose', 0]),
('control three winners', ([['-3', 1], ['+3', 0], ['-1', 0]], '6', 1000), ['win', 2600]),
('regression: reduction to one', ([['-7', 1], ['+3', 5]], '6', 1000), ['refund', 1000]),
('variant scenario 1',
([['+7', -3], ['-6', -11], ['+2.5', 8], ['-7', -7], ['+3', -5]], '7', 1100),
['lose', 0]),
('variant scenario 2', ([['+7', -13], ['+3', -5], ['+1.5', 2]], '6.5', 1000), ['win', 2600])],
[('control two-team teaser', ([['-7.5', 3], ['+2.5', -5]], '6', 1200), ['win', 2200]),
('boundary push drops a leg', ([['-7', 1], ['+3', 0], ['-1', 2]], '6', 1000), ['win', 1833]),
('boundary reduced to one leg', ([['-7', 1], ['+3', 5]], '6', 1000), ['refund', 1000]),
('control losing leg', ([['-10', 2], ['+3', 5], ['+7', 0]], '6', 1000), ['lose', 0]),
('control three winners', ([['-3', 1], ['+3', 0], ['-1', 0]], '6', 1000), ['win', 2600]),
('regression: reduction to one', ([['+2.5', 5], ['+2.5', -9]], '6.5', 1000), ['refund', 1000]),
('variant scenario 1', ([['-6', 7], ['-7', 7], ['-7', 14]], '6.5', 1100), ['win', 2860]),
('variant scenario 2', ([['+7', 10], ['+7', 11]], '6.5', 1100), ['win', 2016])],
[('control two-team teaser', ([['-7.5', 3], ['+2.5', -5]], '6', 1200), ['win', 2200]),
('boundary push drops a leg', ([['-7', 1], ['+3', 0], ['-1', 2]], '6', 1000), ['win', 1833]),
('boundary reduced to one leg', ([['-7', 1], ['+3', 5]], '6', 1000), ['refund', 1000]),
('control losing leg', ([['-10', 2], ['+3', 5], ['+7', 0]], '6', 1000), ['lose', 0]),
('control three winners', ([['-3', 1], ['+3', 0], ['-1', 0]], '6', 1000), ['win', 2600]),
('regression: reduction to one', ([['+7', 10], ['-10', 3]], '7', 500), ['refund', 500]),
('variant scenario 1', ([['-10', -2], ['-1', -5], ['+1.5', -7]], '6', 500), ['lose', 0]),
('variant scenario 2',
([['-7.5', 14], ['-10', 1], ['-3', 1], ['+1.5', -4]], '6.5', 500),
['lose', 0])],
[('control two-team teaser', ([['-7.5', 3], ['+2.5', -5]], '6', 1200), ['win', 2200]),
('boundary push drops a leg', ([['-7', 1], ['+3', 0], ['-1', 2]], '6', 1000), ['win', 1833]),
('boundary reduced to one leg', ([['-7', 1], ['+3', 5]], '6', 1000), ['refund', 1000]),
('control losing leg', ([['-10', 2], ['+3', 5], ['+7', 0]], '6', 1000), ['lose', 0]),
('control three winners', ([['-3', 1], ['+3', 0], ['-1', 0]], '6', 1000), ['win', 2600]),
('regression: reduction to one', ([['-6', 10], ['-1', -6]], '7', 1100), ['refund', 1100]),
('variant scenario 1',
([['+3', 2], ['+1.5', 8], ['+1.5', -3], ['+7', 10], ['-3', -3]], '6.5', 1100),
['win', 5500]),
('variant scenario 2',
([['+1.5', -4], ['-7', 9], ['-7.5', -10], ['-6', -7]], '7', 500),
['lose', 0])],
[('control two-team teaser', ([['-7.5', 3], ['+2.5', -5]], '6', 1200), ['win', 2200]),
('boundary push drops a leg', ([['-7', 1], ['+3', 0], ['-1', 2]], '6', 1000), ['win', 1833]),
('boundary reduced to one leg', ([['-7', 1], ['+3', 5]], '6', 1000), ['refund', 1000]),
('control losing leg', ([['-10', 2], ['+3', 5], ['+7', 0]], '6', 1000), ['lose', 0]),
('control three winners', ([['-3', 1], ['+3', 0], ['-1', 0]], '6', 1000), ['win', 2600]),
('regression: reduction to one', ([['-1', -5], ['+3', 6]], '6', 1000), ['refund', 1000]),
('variant scenario 1',
([['+2.5', 7], ['-6', 10], ['-1', -5], ['+7', 7]], '6', 1000),
['win', 2600]),
('variant scenario 2', ([['-7.5', -3], ['+2.5', -11]], '6', 1100), ['lose', 0])]]
for label, args, expected in cases[N - 1]:
check(label, run(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| control two-team teaser | ['win', 2200] | ['win', 2200] | Passed |
| boundary push drops a leg | ['win', 1833] | ['win', 1833] | Passed |
| boundary reduced to one leg | raised KeyError | ['refund', 1000] | Failed |
| control losing leg | ['lose', 0] | ['lose', 0] | Passed |
| control three winners | ['win', 2600] | ['win', 2600] | Passed |
| regression: reduction to one | raised KeyError | ['refund', 1000] | Failed |
| variant scenario 1 | ['lose', 0] | ['lose', 0] | Passed |
| variant scenario 2 | ['win', 2600] | ['win', 2600] | Passed |
SHA-256 / 9e847e3b7b4092c847ce1e1cb41b4ba660ea3ee6916483e31d0a375ffa0a37ef
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
from fractions import Fraction
import math
N = 1
observations = []
def solve(legs, points, stake_cents):
TABLE = {2: -120, 3: 160, 4: 260, 5: 400}
wins = 0
for line, margin in legs:
adj = Fraction(line) + Fraction(points)
v = margin + adj
if v < 0:
return ['lose', 0]
if v > 0:
wins += 1
if wins < 2:
return ['lose', 0]
am = TABLE[min(wins, 5)]
dec = 1 + (Fraction(am, 100) if am > 0 else Fraction(100, -am))
return ['win', math.floor(stake_cents * dec)]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
def run(args):
try:
return solve(*args)
except Exception as exc:
return 'raised ' + type(exc).__name__
cases = [[('control two-team teaser', ([['-7.5', 3], ['+2.5', -5]], '6', 1200), ['win', 2200]),
('boundary push drops a leg', ([['-7', 1], ['+3', 0], ['-1', 2]], '6', 1000), ['win', 1833]),
('boundary reduced to one leg', ([['-7', 1], ['+3', 5]], '6', 1000), ['refund', 1000]),
('control losing leg', ([['-10', 2], ['+3', 5], ['+7', 0]], '6', 1000), ['lose', 0]),
('control three winners', ([['-3', 1], ['+3', 0], ['-1', 0]], '6', 1000), ['win', 2600]),
('regression: reduction to one', ([['-7', 1], ['+3', 5]], '6', 1000), ['refund', 1000]),
('variant scenario 1',
([['+7', -3], ['-6', -11], ['+2.5', 8], ['-7', -7], ['+3', -5]], '7', 1100),
['lose', 0]),
('variant scenario 2', ([['+7', -13], ['+3', -5], ['+1.5', 2]], '6.5', 1000), ['win', 2600])],
[('control two-team teaser', ([['-7.5', 3], ['+2.5', -5]], '6', 1200), ['win', 2200]),
('boundary push drops a leg', ([['-7', 1], ['+3', 0], ['-1', 2]], '6', 1000), ['win', 1833]),
('boundary reduced to one leg', ([['-7', 1], ['+3', 5]], '6', 1000), ['refund', 1000]),
('control losing leg', ([['-10', 2], ['+3', 5], ['+7', 0]], '6', 1000), ['lose', 0]),
('control three winners', ([['-3', 1], ['+3', 0], ['-1', 0]], '6', 1000), ['win', 2600]),
('regression: reduction to one', ([['+2.5', 5], ['+2.5', -9]], '6.5', 1000), ['refund', 1000]),
('variant scenario 1', ([['-6', 7], ['-7', 7], ['-7', 14]], '6.5', 1100), ['win', 2860]),
('variant scenario 2', ([['+7', 10], ['+7', 11]], '6.5', 1100), ['win', 2016])],
[('control two-team teaser', ([['-7.5', 3], ['+2.5', -5]], '6', 1200), ['win', 2200]),
('boundary push drops a leg', ([['-7', 1], ['+3', 0], ['-1', 2]], '6', 1000), ['win', 1833]),
('boundary reduced to one leg', ([['-7', 1], ['+3', 5]], '6', 1000), ['refund', 1000]),
('control losing leg', ([['-10', 2], ['+3', 5], ['+7', 0]], '6', 1000), ['lose', 0]),
('control three winners', ([['-3', 1], ['+3', 0], ['-1', 0]], '6', 1000), ['win', 2600]),
('regression: reduction to one', ([['+7', 10], ['-10', 3]], '7', 500), ['refund', 500]),
('variant scenario 1', ([['-10', -2], ['-1', -5], ['+1.5', -7]], '6', 500), ['lose', 0]),
('variant scenario 2',
([['-7.5', 14], ['-10', 1], ['-3', 1], ['+1.5', -4]], '6.5', 500),
['lose', 0])],
[('control two-team teaser', ([['-7.5', 3], ['+2.5', -5]], '6', 1200), ['win', 2200]),
('boundary push drops a leg', ([['-7', 1], ['+3', 0], ['-1', 2]], '6', 1000), ['win', 1833]),
('boundary reduced to one leg', ([['-7', 1], ['+3', 5]], '6', 1000), ['refund', 1000]),
('control losing leg', ([['-10', 2], ['+3', 5], ['+7', 0]], '6', 1000), ['lose', 0]),
('control three winners', ([['-3', 1], ['+3', 0], ['-1', 0]], '6', 1000), ['win', 2600]),
('regression: reduction to one', ([['-6', 10], ['-1', -6]], '7', 1100), ['refund', 1100]),
('variant scenario 1',
([['+3', 2], ['+1.5', 8], ['+1.5', -3], ['+7', 10], ['-3', -3]], '6.5', 1100),
['win', 5500]),
('variant scenario 2',
([['+1.5', -4], ['-7', 9], ['-7.5', -10], ['-6', -7]], '7', 500),
['lose', 0])],
[('control two-team teaser', ([['-7.5', 3], ['+2.5', -5]], '6', 1200), ['win', 2200]),
('boundary push drops a leg', ([['-7', 1], ['+3', 0], ['-1', 2]], '6', 1000), ['win', 1833]),
('boundary reduced to one leg', ([['-7', 1], ['+3', 5]], '6', 1000), ['refund', 1000]),
('control losing leg', ([['-10', 2], ['+3', 5], ['+7', 0]], '6', 1000), ['lose', 0]),
('control three winners', ([['-3', 1], ['+3', 0], ['-1', 0]], '6', 1000), ['win', 2600]),
('regression: reduction to one', ([['-1', -5], ['+3', 6]], '6', 1000), ['refund', 1000]),
('variant scenario 1',
([['+2.5', 7], ['-6', 10], ['-1', -5], ['+7', 7]], '6', 1000),
['win', 2600]),
('variant scenario 2', ([['-7.5', -3], ['+2.5', -11]], '6', 1100), ['lose', 0])]]
for label, args, expected in cases[N - 1]:
check(label, run(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| control two-team teaser | ['win', 2200] | ['win', 2200] | Passed |
| boundary push drops a leg | ['win', 1833] | ['win', 1833] | Passed |
| boundary reduced to one leg | ['lose', 0] | ['refund', 1000] | Failed |
| control losing leg | ['lose', 0] | ['lose', 0] | Passed |
| control three winners | ['win', 2600] | ['win', 2600] | Passed |
| regression: reduction to one | ['lose', 0] | ['refund', 1000] | Failed |
| variant scenario 1 | ['lose', 0] | ['lose', 0] | Passed |
| variant scenario 2 | ['win', 2600] | ['win', 2600] | Passed |
SHA-256 / 810ca5d97ccefa00c367df383fa48226e47cd626a4a592ad0e674f274f1bf69d
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
from fractions import Fraction
import math
N = 1
observations = []
def solve(legs, points, stake_cents):
TABLE = {2: -120, 3: 160, 4: 260, 5: 400}
wins = 0
for line, margin in legs:
adj = Fraction(line) + Fraction(points)
v = margin + adj
if v < 0:
return ['lose', 0]
if v > 0:
wins += 1
if wins < 2:
return ['refund', stake_cents]
am = TABLE[min(wins, 5)]
dec = 1 + (Fraction(am, 100) if am > 0 else Fraction(100, -am))
return ['win', math.floor(stake_cents * dec)]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
def run(args):
try:
return solve(*args)
except Exception as exc:
return 'raised ' + type(exc).__name__
cases = [[('control two-team teaser', ([['-7.5', 3], ['+2.5', -5]], '6', 1200), ['win', 2200]),
('boundary push drops a leg', ([['-7', 1], ['+3', 0], ['-1', 2]], '6', 1000), ['win', 1833]),
('boundary reduced to one leg', ([['-7', 1], ['+3', 5]], '6', 1000), ['refund', 1000]),
('control losing leg', ([['-10', 2], ['+3', 5], ['+7', 0]], '6', 1000), ['lose', 0]),
('control three winners', ([['-3', 1], ['+3', 0], ['-1', 0]], '6', 1000), ['win', 2600]),
('regression: reduction to one', ([['-7', 1], ['+3', 5]], '6', 1000), ['refund', 1000]),
('variant scenario 1',
([['+7', -3], ['-6', -11], ['+2.5', 8], ['-7', -7], ['+3', -5]], '7', 1100),
['lose', 0]),
('variant scenario 2', ([['+7', -13], ['+3', -5], ['+1.5', 2]], '6.5', 1000), ['win', 2600])],
[('control two-team teaser', ([['-7.5', 3], ['+2.5', -5]], '6', 1200), ['win', 2200]),
('boundary push drops a leg', ([['-7', 1], ['+3', 0], ['-1', 2]], '6', 1000), ['win', 1833]),
('boundary reduced to one leg', ([['-7', 1], ['+3', 5]], '6', 1000), ['refund', 1000]),
('control losing leg', ([['-10', 2], ['+3', 5], ['+7', 0]], '6', 1000), ['lose', 0]),
('control three winners', ([['-3', 1], ['+3', 0], ['-1', 0]], '6', 1000), ['win', 2600]),
('regression: reduction to one', ([['+2.5', 5], ['+2.5', -9]], '6.5', 1000), ['refund', 1000]),
('variant scenario 1', ([['-6', 7], ['-7', 7], ['-7', 14]], '6.5', 1100), ['win', 2860]),
('variant scenario 2', ([['+7', 10], ['+7', 11]], '6.5', 1100), ['win', 2016])],
[('control two-team teaser', ([['-7.5', 3], ['+2.5', -5]], '6', 1200), ['win', 2200]),
('boundary push drops a leg', ([['-7', 1], ['+3', 0], ['-1', 2]], '6', 1000), ['win', 1833]),
('boundary reduced to one leg', ([['-7', 1], ['+3', 5]], '6', 1000), ['refund', 1000]),
('control losing leg', ([['-10', 2], ['+3', 5], ['+7', 0]], '6', 1000), ['lose', 0]),
('control three winners', ([['-3', 1], ['+3', 0], ['-1', 0]], '6', 1000), ['win', 2600]),
('regression: reduction to one', ([['+7', 10], ['-10', 3]], '7', 500), ['refund', 500]),
('variant scenario 1', ([['-10', -2], ['-1', -5], ['+1.5', -7]], '6', 500), ['lose', 0]),
('variant scenario 2',
([['-7.5', 14], ['-10', 1], ['-3', 1], ['+1.5', -4]], '6.5', 500),
['lose', 0])],
[('control two-team teaser', ([['-7.5', 3], ['+2.5', -5]], '6', 1200), ['win', 2200]),
('boundary push drops a leg', ([['-7', 1], ['+3', 0], ['-1', 2]], '6', 1000), ['win', 1833]),
('boundary reduced to one leg', ([['-7', 1], ['+3', 5]], '6', 1000), ['refund', 1000]),
('control losing leg', ([['-10', 2], ['+3', 5], ['+7', 0]], '6', 1000), ['lose', 0]),
('control three winners', ([['-3', 1], ['+3', 0], ['-1', 0]], '6', 1000), ['win', 2600]),
('regression: reduction to one', ([['-6', 10], ['-1', -6]], '7', 1100), ['refund', 1100]),
('variant scenario 1',
([['+3', 2], ['+1.5', 8], ['+1.5', -3], ['+7', 10], ['-3', -3]], '6.5', 1100),
['win', 5500]),
('variant scenario 2',
([['+1.5', -4], ['-7', 9], ['-7.5', -10], ['-6', -7]], '7', 500),
['lose', 0])],
[('control two-team teaser', ([['-7.5', 3], ['+2.5', -5]], '6', 1200), ['win', 2200]),
('boundary push drops a leg', ([['-7', 1], ['+3', 0], ['-1', 2]], '6', 1000), ['win', 1833]),
('boundary reduced to one leg', ([['-7', 1], ['+3', 5]], '6', 1000), ['refund', 1000]),
('control losing leg', ([['-10', 2], ['+3', 5], ['+7', 0]], '6', 1000), ['lose', 0]),
('control three winners', ([['-3', 1], ['+3', 0], ['-1', 0]], '6', 1000), ['win', 2600]),
('regression: reduction to one', ([['-1', -5], ['+3', 6]], '6', 1000), ['refund', 1000]),
('variant scenario 1',
([['+2.5', 7], ['-6', 10], ['-1', -5], ['+7', 7]], '6', 1000),
['win', 2600]),
('variant scenario 2', ([['-7.5', -3], ['+2.5', -11]], '6', 1100), ['lose', 0])]]
for label, args, expected in cases[N - 1]:
check(label, run(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| control two-team teaser | ['win', 2200] | ['win', 2200] | Passed |
| boundary push drops a leg | ['win', 1833] | ['win', 1833] | Passed |
| boundary reduced to one leg | ['refund', 1000] | ['refund', 1000] | Passed |
| control losing leg | ['lose', 0] | ['lose', 0] | Passed |
| control three winners | ['win', 2600] | ['win', 2600] | Passed |
| regression: reduction to one | ['refund', 1000] | ['refund', 1000] | Passed |
| variant scenario 1 | ['lose', 0] | ['lose', 0] | Passed |
| variant scenario 2 | ['win', 2600] | ['win', 2600] | Passed |
SHA-256 / 6a36e8f8bf1d7ca17bf551a145f0d5cef1171e29d60cf889725b439ef246c5b6
Verification & scope
Stipulated, bounded toy contract stated in the contract field; not a claim of conformance with any operator, exchange or regulator rule set. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.
Observations recorded using Python 3.12.14 at 2026-09-29T14:50:33.996963+00:00.
Case digest / 4b560e8fe5757f56ecb222b36c146460a83a69e2a0f7b8e662a12cd06ac66e0d