FA-85306 / Fantasy sports scoring / Open access
Live projection prorated by elapsed time · case 01
A player at kickoff shows no remaining projection while a nearly finished game shows the whole projection.
ROOT CAUSE
The projection is scaled by elapsed rather than remaining seconds.
VERIFIED REPAIR
Scale the projection by remaining seconds over 3600.
Unsuccessful approach: Subtracting the floored elapsed share rounds the remaining share up instead of down.
Case contract
Projected final lineup score in tenths. Each player is [actual, full-game projection, status, game seconds left]. Final games count actual points; not-started games count the full projection; live games count actual plus the projection prorated by remaining time over 3600 seconds (floored per player; overtime reports negative seconds, treated as 0 remaining); postponed (ppd) games count 0.
Why this case matters
Live projections are shown to millions of users during games; status handling and proration must be exact.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(players):
total = 0
for actual, proj, status, left in players:
if status == 'final':
total += actual
elif status == 'pre':
total += proj
elif status == 'live':
left = max(left, 0)
total += actual + proj * (3600 - left) // 3600
return total
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: remaining time proration',
[[[213, 180, 'final', 3600], [200, 180, 'live', -300], [102, 95, 'live', 1800]]], 562),
('partial repair probe: remaining time proration',
[[[36, 0, 'live', 1800], [17, 180, 'live', 900], [72, 0, 'live', 1800], [137, 180, 'pre', -300],
[221, 180, 'live', 1], [154, 0, 'live', 1800]]],
725),
('second regression', [[[237, 95, 'live', 900], [48, 95, 'live', 3600], [237, 180, 'live', 1800]]], 730),
('normal control 1', [[[110, 0, 'final', 900], [154, 95, 'ppd', 3600]]], 110),
('normal control 2',
[[[130, 0, 'live', 0], [150, 120, 'final', 3600], [231, 0, 'live', 1800], [86, 0, 'ppd', 1],
[148, 0, 'live', -300], [234, 0, 'final', -300]]],
893),
('normal control 3', [[[173, 180, 'pre', 1], [126, 180, 'ppd', 0], [32, 0, 'final', 0]]], 212),
('normal control 4',
[[[101, 120, 'ppd', 900], [78, 180, 'ppd', 0], [57, 180, 'final', 900], [220, 120, 'pre', 1800],
[192, 120, 'live', 1800]]],
429)],
[('regression: remaining time proration',
[[[115, 120, 'live', 1800], [221, 180, 'live', 900], [144, 95, 'ppd', 900], [237, 180, 'live', 3600],
[48, 180, 'ppd', 1], [92, 180, 'pre', -300]]],
1038),
('partial repair probe: remaining time proration', [[[113, 180, 'pre', 3600], [57, 95, 'live', 1]]], 237),
('second regression', [[[172, 120, 'live', 900], [5, 0, 'final', 3600]]], 207),
('normal control 1',
[[[18, 120, 'ppd', 900], [72, 120, 'ppd', 3600], [129, 120, 'pre', 1800], [3, 120, 'pre', 3600],
[224, 180, 'pre', 1800]]],
420),
('normal control 2',
[[[145, 180, 'final', 900], [133, 120, 'pre', 0], [42, 120, 'live', 1800], [39, 120, 'final', -300]]],
406),
('normal control 3',
[[[250, 180, 'ppd', 1], [227, 0, 'live', 0], [205, 180, 'pre', 1800], [89, 0, 'pre', 0],
[49, 180, 'pre', -300]]],
587),
('normal control 4', [[[58, 95, 'final', 0], [232, 180, 'final', 1], [166, 95, 'final', 3600]]], 456)],
[('regression: remaining time proration',
[[[-14, 95, 'live', 900], [174, 95, 'ppd', 3600], [40, 180, 'final', -300]]], 49),
('partial repair probe: remaining time proration',
[[[150, 120, 'ppd', 1], [80, 95, 'ppd', 900], [4, 120, 'final', 1], [-20, 120, 'live', 1]]], -16),
('second regression',
[[[156, 120, 'live', -300], [207, 0, 'ppd', 0], [96, 95, 'live', 3600], [1, 180, 'live', 1800]]], 438),
('normal control 1',
[[[131, 180, 'pre', 1], [11, 180, 'ppd', 900], [12, 0, 'ppd', 3600], [73, 0, 'final', 0],
[55, 0, 'live', 3600], [86, 120, 'pre', 0]]],
428),
('normal control 2', [[[13, 120, 'pre', 0], [212, 0, 'pre', 900]]], 120),
('normal control 3', [[[230, 95, 'ppd', 3600], [245, 0, 'live', 0]]], 245),
('normal control 4',
[[[95, 120, 'ppd', 900], [245, 0, 'pre', 1], [37, 0, 'pre', 0], [194, 0, 'final', 0],
[94, 180, 'ppd', 1800]]],
194)],
[('regression: remaining time proration',
[[[52, 120, 'ppd', 900], [184, 95, 'live', 1], [6, 0, 'pre', 0], [198, 180, 'final', 1],
[118, 95, 'live', 0]]],
500),
('partial repair probe: remaining time proration',
[[[170, 95, 'pre', 1800], [64, 180, 'ppd', 900], [212, 120, 'live', 1], [68, 180, 'final', -300],
[61, 0, 'pre', 3600], [102, 120, 'pre', 1]]],
495),
('second regression',
[[[68, 180, 'live', 1], [84, 95, 'final', 3600], [73, 120, 'ppd', 900], [49, 0, 'live', 0],
[48, 0, 'pre', 3600]]],
201),
('normal control 1',
[[[35, 180, 'pre', 1], [168, 0, 'pre', 900], [69, 95, 'pre', 1], [85, 0, 'live', 900],
[43, 0, 'live', 900]]],
403),
('normal control 2',
[[[23, 0, 'pre', -300], [210, 95, 'pre', 3600], [9, 0, 'live', 900], [3, 0, 'live', -300],
[166, 180, 'pre', 3600], [174, 95, 'final', 1800]]],
461),
('normal control 3', [[[80, 180, 'final', 1], [118, 180, 'ppd', 3600], [249, 95, 'pre', -300]]], 175),
('normal control 4', [[[185, 120, 'final', 3600], [223, 0, 'pre', 3600]]], 185)],
[('regression: remaining time proration',
[[[231, 0, 'live', 0], [195, 95, 'live', -300], [191, 120, 'ppd', -300]]], 426),
('partial repair probe: remaining time proration',
[[[188, 180, 'live', 0], [66, 95, 'pre', 900], [105, 95, 'live', 1800], [227, 120, 'ppd', 900],
[124, 0, 'live', 1]]],
559),
('second regression', [[[154, 0, 'live', 0], [250, 180, 'live', -300], [44, 120, 'final', 1800]]], 448),
('normal control 1', [[[170, 120, 'ppd', 1800], [186, 180, 'final', 1]]], 186),
('normal control 2', [[[230, 120, 'ppd', 1], [209, 95, 'pre', 1]]], 95),
('normal control 3',
[[[171, 0, 'pre', 3600], [55, 120, 'pre', 1800], [204, 0, 'final', 1], [35, 95, 'final', 3600],
[211, 120, 'final', 3600]]],
570),
('normal control 4',
[[[38, 0, 'live', 1800], [-1, 0, 'live', 3600], [94, 120, 'pre', 1], [12, 0, 'live', 1800],
[139, 120, 'pre', 0]]],
289)]]
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: remaining time proration | 742 | 562 | Failed |
| partial repair probe: remaining time proration | 994 | 725 | Failed |
| second regression | 683 | 730 | Failed |
| normal control 1 | 110 | 110 | Passed |
| normal control 2 | 893 | 893 | Passed |
| normal control 3 | 212 | 212 | Passed |
| normal control 4 | 429 | 429 | Passed |
SHA-256 / bf682f0e0d28d836d17ef36627335ec1ebc5f943675b76fc450dcac017db2457
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(players):
total = 0
for actual, proj, status, left in players:
if status == 'final':
total += actual
elif status == 'pre':
total += proj
elif status == 'live':
left = max(left, 0)
total += actual + proj - proj * (3600 - left) // 3600
return total
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: remaining time proration',
[[[213, 180, 'final', 3600], [200, 180, 'live', -300], [102, 95, 'live', 1800]]], 562),
('partial repair probe: remaining time proration',
[[[36, 0, 'live', 1800], [17, 180, 'live', 900], [72, 0, 'live', 1800], [137, 180, 'pre', -300],
[221, 180, 'live', 1], [154, 0, 'live', 1800]]],
725),
('second regression', [[[237, 95, 'live', 900], [48, 95, 'live', 3600], [237, 180, 'live', 1800]]], 730),
('normal control 1', [[[110, 0, 'final', 900], [154, 95, 'ppd', 3600]]], 110),
('normal control 2',
[[[130, 0, 'live', 0], [150, 120, 'final', 3600], [231, 0, 'live', 1800], [86, 0, 'ppd', 1],
[148, 0, 'live', -300], [234, 0, 'final', -300]]],
893),
('normal control 3', [[[173, 180, 'pre', 1], [126, 180, 'ppd', 0], [32, 0, 'final', 0]]], 212),
('normal control 4',
[[[101, 120, 'ppd', 900], [78, 180, 'ppd', 0], [57, 180, 'final', 900], [220, 120, 'pre', 1800],
[192, 120, 'live', 1800]]],
429)],
[('regression: remaining time proration',
[[[115, 120, 'live', 1800], [221, 180, 'live', 900], [144, 95, 'ppd', 900], [237, 180, 'live', 3600],
[48, 180, 'ppd', 1], [92, 180, 'pre', -300]]],
1038),
('partial repair probe: remaining time proration', [[[113, 180, 'pre', 3600], [57, 95, 'live', 1]]], 237),
('second regression', [[[172, 120, 'live', 900], [5, 0, 'final', 3600]]], 207),
('normal control 1',
[[[18, 120, 'ppd', 900], [72, 120, 'ppd', 3600], [129, 120, 'pre', 1800], [3, 120, 'pre', 3600],
[224, 180, 'pre', 1800]]],
420),
('normal control 2',
[[[145, 180, 'final', 900], [133, 120, 'pre', 0], [42, 120, 'live', 1800], [39, 120, 'final', -300]]],
406),
('normal control 3',
[[[250, 180, 'ppd', 1], [227, 0, 'live', 0], [205, 180, 'pre', 1800], [89, 0, 'pre', 0],
[49, 180, 'pre', -300]]],
587),
('normal control 4', [[[58, 95, 'final', 0], [232, 180, 'final', 1], [166, 95, 'final', 3600]]], 456)],
[('regression: remaining time proration',
[[[-14, 95, 'live', 900], [174, 95, 'ppd', 3600], [40, 180, 'final', -300]]], 49),
('partial repair probe: remaining time proration',
[[[150, 120, 'ppd', 1], [80, 95, 'ppd', 900], [4, 120, 'final', 1], [-20, 120, 'live', 1]]], -16),
('second regression',
[[[156, 120, 'live', -300], [207, 0, 'ppd', 0], [96, 95, 'live', 3600], [1, 180, 'live', 1800]]], 438),
('normal control 1',
[[[131, 180, 'pre', 1], [11, 180, 'ppd', 900], [12, 0, 'ppd', 3600], [73, 0, 'final', 0],
[55, 0, 'live', 3600], [86, 120, 'pre', 0]]],
428),
('normal control 2', [[[13, 120, 'pre', 0], [212, 0, 'pre', 900]]], 120),
('normal control 3', [[[230, 95, 'ppd', 3600], [245, 0, 'live', 0]]], 245),
('normal control 4',
[[[95, 120, 'ppd', 900], [245, 0, 'pre', 1], [37, 0, 'pre', 0], [194, 0, 'final', 0],
[94, 180, 'ppd', 1800]]],
194)],
[('regression: remaining time proration',
[[[52, 120, 'ppd', 900], [184, 95, 'live', 1], [6, 0, 'pre', 0], [198, 180, 'final', 1],
[118, 95, 'live', 0]]],
500),
('partial repair probe: remaining time proration',
[[[170, 95, 'pre', 1800], [64, 180, 'ppd', 900], [212, 120, 'live', 1], [68, 180, 'final', -300],
[61, 0, 'pre', 3600], [102, 120, 'pre', 1]]],
495),
('second regression',
[[[68, 180, 'live', 1], [84, 95, 'final', 3600], [73, 120, 'ppd', 900], [49, 0, 'live', 0],
[48, 0, 'pre', 3600]]],
201),
('normal control 1',
[[[35, 180, 'pre', 1], [168, 0, 'pre', 900], [69, 95, 'pre', 1], [85, 0, 'live', 900],
[43, 0, 'live', 900]]],
403),
('normal control 2',
[[[23, 0, 'pre', -300], [210, 95, 'pre', 3600], [9, 0, 'live', 900], [3, 0, 'live', -300],
[166, 180, 'pre', 3600], [174, 95, 'final', 1800]]],
461),
('normal control 3', [[[80, 180, 'final', 1], [118, 180, 'ppd', 3600], [249, 95, 'pre', -300]]], 175),
('normal control 4', [[[185, 120, 'final', 3600], [223, 0, 'pre', 3600]]], 185)],
[('regression: remaining time proration',
[[[231, 0, 'live', 0], [195, 95, 'live', -300], [191, 120, 'ppd', -300]]], 426),
('partial repair probe: remaining time proration',
[[[188, 180, 'live', 0], [66, 95, 'pre', 900], [105, 95, 'live', 1800], [227, 120, 'ppd', 900],
[124, 0, 'live', 1]]],
559),
('second regression', [[[154, 0, 'live', 0], [250, 180, 'live', -300], [44, 120, 'final', 1800]]], 448),
('normal control 1', [[[170, 120, 'ppd', 1800], [186, 180, 'final', 1]]], 186),
('normal control 2', [[[230, 120, 'ppd', 1], [209, 95, 'pre', 1]]], 95),
('normal control 3',
[[[171, 0, 'pre', 3600], [55, 120, 'pre', 1800], [204, 0, 'final', 1], [35, 95, 'final', 3600],
[211, 120, 'final', 3600]]],
570),
('normal control 4',
[[[38, 0, 'live', 1800], [-1, 0, 'live', 3600], [94, 120, 'pre', 1], [12, 0, 'live', 1800],
[139, 120, 'pre', 0]]],
289)]]
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: remaining time proration | 563 | 562 | Failed |
| partial repair probe: remaining time proration | 726 | 725 | Failed |
| second regression | 731 | 730 | Failed |
| normal control 1 | 110 | 110 | Passed |
| normal control 2 | 893 | 893 | Passed |
| normal control 3 | 212 | 212 | Passed |
| normal control 4 | 429 | 429 | Passed |
SHA-256 / d1bfb1ce158505a82510740b8319f91e6cfe1c8ea1d7df524fc2c2513e29e922
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(players):
total = 0
for actual, proj, status, left in players:
if status == 'final':
total += actual
elif status == 'pre':
total += proj
elif status == 'live':
left = max(left, 0)
total += actual + proj * left // 3600
return total
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: remaining time proration',
[[[213, 180, 'final', 3600], [200, 180, 'live', -300], [102, 95, 'live', 1800]]], 562),
('partial repair probe: remaining time proration',
[[[36, 0, 'live', 1800], [17, 180, 'live', 900], [72, 0, 'live', 1800], [137, 180, 'pre', -300],
[221, 180, 'live', 1], [154, 0, 'live', 1800]]],
725),
('second regression', [[[237, 95, 'live', 900], [48, 95, 'live', 3600], [237, 180, 'live', 1800]]], 730),
('normal control 1', [[[110, 0, 'final', 900], [154, 95, 'ppd', 3600]]], 110),
('normal control 2',
[[[130, 0, 'live', 0], [150, 120, 'final', 3600], [231, 0, 'live', 1800], [86, 0, 'ppd', 1],
[148, 0, 'live', -300], [234, 0, 'final', -300]]],
893),
('normal control 3', [[[173, 180, 'pre', 1], [126, 180, 'ppd', 0], [32, 0, 'final', 0]]], 212),
('normal control 4',
[[[101, 120, 'ppd', 900], [78, 180, 'ppd', 0], [57, 180, 'final', 900], [220, 120, 'pre', 1800],
[192, 120, 'live', 1800]]],
429)],
[('regression: remaining time proration',
[[[115, 120, 'live', 1800], [221, 180, 'live', 900], [144, 95, 'ppd', 900], [237, 180, 'live', 3600],
[48, 180, 'ppd', 1], [92, 180, 'pre', -300]]],
1038),
('partial repair probe: remaining time proration', [[[113, 180, 'pre', 3600], [57, 95, 'live', 1]]], 237),
('second regression', [[[172, 120, 'live', 900], [5, 0, 'final', 3600]]], 207),
('normal control 1',
[[[18, 120, 'ppd', 900], [72, 120, 'ppd', 3600], [129, 120, 'pre', 1800], [3, 120, 'pre', 3600],
[224, 180, 'pre', 1800]]],
420),
('normal control 2',
[[[145, 180, 'final', 900], [133, 120, 'pre', 0], [42, 120, 'live', 1800], [39, 120, 'final', -300]]],
406),
('normal control 3',
[[[250, 180, 'ppd', 1], [227, 0, 'live', 0], [205, 180, 'pre', 1800], [89, 0, 'pre', 0],
[49, 180, 'pre', -300]]],
587),
('normal control 4', [[[58, 95, 'final', 0], [232, 180, 'final', 1], [166, 95, 'final', 3600]]], 456)],
[('regression: remaining time proration',
[[[-14, 95, 'live', 900], [174, 95, 'ppd', 3600], [40, 180, 'final', -300]]], 49),
('partial repair probe: remaining time proration',
[[[150, 120, 'ppd', 1], [80, 95, 'ppd', 900], [4, 120, 'final', 1], [-20, 120, 'live', 1]]], -16),
('second regression',
[[[156, 120, 'live', -300], [207, 0, 'ppd', 0], [96, 95, 'live', 3600], [1, 180, 'live', 1800]]], 438),
('normal control 1',
[[[131, 180, 'pre', 1], [11, 180, 'ppd', 900], [12, 0, 'ppd', 3600], [73, 0, 'final', 0],
[55, 0, 'live', 3600], [86, 120, 'pre', 0]]],
428),
('normal control 2', [[[13, 120, 'pre', 0], [212, 0, 'pre', 900]]], 120),
('normal control 3', [[[230, 95, 'ppd', 3600], [245, 0, 'live', 0]]], 245),
('normal control 4',
[[[95, 120, 'ppd', 900], [245, 0, 'pre', 1], [37, 0, 'pre', 0], [194, 0, 'final', 0],
[94, 180, 'ppd', 1800]]],
194)],
[('regression: remaining time proration',
[[[52, 120, 'ppd', 900], [184, 95, 'live', 1], [6, 0, 'pre', 0], [198, 180, 'final', 1],
[118, 95, 'live', 0]]],
500),
('partial repair probe: remaining time proration',
[[[170, 95, 'pre', 1800], [64, 180, 'ppd', 900], [212, 120, 'live', 1], [68, 180, 'final', -300],
[61, 0, 'pre', 3600], [102, 120, 'pre', 1]]],
495),
('second regression',
[[[68, 180, 'live', 1], [84, 95, 'final', 3600], [73, 120, 'ppd', 900], [49, 0, 'live', 0],
[48, 0, 'pre', 3600]]],
201),
('normal control 1',
[[[35, 180, 'pre', 1], [168, 0, 'pre', 900], [69, 95, 'pre', 1], [85, 0, 'live', 900],
[43, 0, 'live', 900]]],
403),
('normal control 2',
[[[23, 0, 'pre', -300], [210, 95, 'pre', 3600], [9, 0, 'live', 900], [3, 0, 'live', -300],
[166, 180, 'pre', 3600], [174, 95, 'final', 1800]]],
461),
('normal control 3', [[[80, 180, 'final', 1], [118, 180, 'ppd', 3600], [249, 95, 'pre', -300]]], 175),
('normal control 4', [[[185, 120, 'final', 3600], [223, 0, 'pre', 3600]]], 185)],
[('regression: remaining time proration',
[[[231, 0, 'live', 0], [195, 95, 'live', -300], [191, 120, 'ppd', -300]]], 426),
('partial repair probe: remaining time proration',
[[[188, 180, 'live', 0], [66, 95, 'pre', 900], [105, 95, 'live', 1800], [227, 120, 'ppd', 900],
[124, 0, 'live', 1]]],
559),
('second regression', [[[154, 0, 'live', 0], [250, 180, 'live', -300], [44, 120, 'final', 1800]]], 448),
('normal control 1', [[[170, 120, 'ppd', 1800], [186, 180, 'final', 1]]], 186),
('normal control 2', [[[230, 120, 'ppd', 1], [209, 95, 'pre', 1]]], 95),
('normal control 3',
[[[171, 0, 'pre', 3600], [55, 120, 'pre', 1800], [204, 0, 'final', 1], [35, 95, 'final', 3600],
[211, 120, 'final', 3600]]],
570),
('normal control 4',
[[[38, 0, 'live', 1800], [-1, 0, 'live', 3600], [94, 120, 'pre', 1], [12, 0, 'live', 1800],
[139, 120, 'pre', 0]]],
289)]]
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: remaining time proration | 562 | 562 | Passed |
| partial repair probe: remaining time proration | 725 | 725 | Passed |
| second regression | 730 | 730 | Passed |
| normal control 1 | 110 | 110 | Passed |
| normal control 2 | 893 | 893 | Passed |
| normal control 3 | 212 | 212 | Passed |
| normal control 4 | 429 | 429 | Passed |
SHA-256 / bd2031f4f656c2f50fbc88e9f88f739d1f7b6faf7ca661c74351eb3516187312
Verification & scope
A deterministic toy scoring contract stipulated for this example; it is not the rulebook of any real fantasy platform. 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:39.204850+00:00.
Case digest / 82e56cc4ebd949a46e177119cdf702a28b12d71d5a5693be57dac868a09ef850