FAILURE MAP
← Case archive

FA-69296 / Tide and marine navigation tables / Open access

Deviation card interpolation: Headings past the last card entry have no deviation · case 01

Headings between the last card heading and 360 return nothing.

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

ROOT CAUSE

The wrap-around point first+360 is never appended to the card.

VERIFIED REPAIR

Append the first card point shifted by 360 degrees.

Unsuccessful approach: Appending a flat point at 360 with the last deviation ignores the first card value.

Case contract

Input [heading, card]: card lists [compass heading, deviation] pairs (east positive) in any order. Headings wrap modulo 360; deviation is linearly interpolated between neighbouring card headings, including across the 360/0 seam. Return deviation rounded to 2 decimals.

Why this case matters

Tide tables and passage plans turn published predictions into go/no-go decisions about depth, clearance and timing.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    hdg,card=x
    pts=sorted(card)
    first=pts[0][0]
    t=hdg%360
    if t<first: t+=360
    pass
    for k in range(len(pts)-1):
        h0,d0=pts[k]; h1,d1=pts[k+1]
        if h0<=t<h1:
            return round(d0+(d1-d0)*(t-h0)/(h1-h0),2)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('deviation card interpolation [330, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [330, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 1.67), ('deviation card interpolation [0, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [0, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 2.0), ('deviation card interpolation [20, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [20, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 2.67), ('deviation card interpolation [90, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [90, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 1.0), ('deviation card interpolation [100, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [100, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 0.44), ('deviation card interpolation [200, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [200, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], -2.56), ('deviation card interpolation [359, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [359, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 1.99)], [('deviation card interpolation [359, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [359, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 1.99), ('deviation card interpolation [100, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [100, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 0.44), ('deviation card interpolation [200, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [200, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], -2.56), ('deviation card interpolation [330, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [330, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 1.67), ('deviation card interpolation [360, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [360, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 2.0), ('deviation card interpolation [-30, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [-30, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 1.67), ('deviation card interpolation [725, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [725, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 2.17)], [('deviation card interpolation [-30, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [-30, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 1.67), ('deviation card interpolation [359, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [359, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 1.99), ('deviation card interpolation [360, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [360, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 2.0), ('deviation card interpolation [725, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [725, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 2.17), ('deviation card interpolation [5, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [5, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], 0.83), ('deviation card interpolation [15, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [15, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], 1.0), ('deviation card interpolation [50, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [50, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], 1.88)], [('deviation card interpolation [5, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [5, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], 0.83), ('deviation card interpolation [725, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [725, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 2.17), ('deviation card interpolation [15, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [15, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], 1.0), ('deviation card interpolation [50, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [50, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], 1.88), ('deviation card interpolation [150, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [150, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], -0.94), ('deviation card interpolation [300, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [300, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], -0.25), ('deviation card interpolation [350, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [350, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], 0.58)], [('deviation card interpolation [300, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [300, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], -0.25), ('deviation card interpolation [50, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [50, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], 1.88), ('deviation card interpolation [150, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [150, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], -0.94), ('deviation card interpolation [350, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [350, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], 0.58), ('deviation card interpolation [60, [[315, 1.5], [270, 0.5], [225, -2.0], [180, -3.0], [135, -1.5], [90, 1.0], [45, 3.5], [0, 2.0]]]', [60, [[315, 1.5], [270, 0.5], [225, -2.0], [180, -3.0], [135, -1.5], [90, 1.0], [45, 3.5], [0, 2.0]]], 2.67), ('deviation card interpolation [250, [[315, 1.5], [270, 0.5], [225, -2.0], [180, -3.0], [135, -1.5], [90, 1.0], [45, 3.5], [0, 2.0]]]', [250, [[315, 1.5], [270, 0.5], [225, -2.0], [180, -3.0], [135, -1.5], [90, 1.0], [45, 3.5], [0, 2.0]]], -0.61), ('deviation card interpolation [30, [[90, 1.0], [0, 0.0], [270, -1.0], [180, 2.0]]]', [30, [[90, 1.0], [0, 0.0], [270, -1.0], [180, 2.0]]], 0.33)]]
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
deviation card interpolation [330, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]None1.67Failed
deviation card interpolation [0, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]2.02.0Passed
deviation card interpolation [20, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]2.672.67Passed
deviation card interpolation [90, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]1.01.0Passed
deviation card interpolation [100, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]0.440.44Passed
deviation card interpolation [200, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]-2.56-2.56Passed
deviation card interpolation [359, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]None1.99Failed

SHA-256 / bea743742568b953db5b4a6b6d236aad0c1849d338e4869cd34462d9a833a92d

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    hdg,card=x
    pts=sorted(card)
    first=pts[0][0]
    t=hdg%360
    if t<first: t+=360
    pts.append([360,pts[-1][1]])
    for k in range(len(pts)-1):
        h0,d0=pts[k]; h1,d1=pts[k+1]
        if h0<=t<h1:
            return round(d0+(d1-d0)*(t-h0)/(h1-h0),2)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('deviation card interpolation [330, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [330, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 1.67), ('deviation card interpolation [0, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [0, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 2.0), ('deviation card interpolation [20, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [20, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 2.67), ('deviation card interpolation [90, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [90, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 1.0), ('deviation card interpolation [100, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [100, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 0.44), ('deviation card interpolation [200, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [200, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], -2.56), ('deviation card interpolation [359, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [359, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 1.99)], [('deviation card interpolation [359, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [359, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 1.99), ('deviation card interpolation [100, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [100, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 0.44), ('deviation card interpolation [200, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [200, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], -2.56), ('deviation card interpolation [330, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [330, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 1.67), ('deviation card interpolation [360, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [360, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 2.0), ('deviation card interpolation [-30, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [-30, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 1.67), ('deviation card interpolation [725, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [725, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 2.17)], [('deviation card interpolation [-30, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [-30, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 1.67), ('deviation card interpolation [359, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [359, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 1.99), ('deviation card interpolation [360, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [360, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 2.0), ('deviation card interpolation [725, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [725, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 2.17), ('deviation card interpolation [5, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [5, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], 0.83), ('deviation card interpolation [15, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [15, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], 1.0), ('deviation card interpolation [50, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [50, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], 1.88)], [('deviation card interpolation [5, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [5, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], 0.83), ('deviation card interpolation [725, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [725, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 2.17), ('deviation card interpolation [15, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [15, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], 1.0), ('deviation card interpolation [50, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [50, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], 1.88), ('deviation card interpolation [150, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [150, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], -0.94), ('deviation card interpolation [300, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [300, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], -0.25), ('deviation card interpolation [350, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [350, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], 0.58)], [('deviation card interpolation [300, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [300, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], -0.25), ('deviation card interpolation [50, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [50, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], 1.88), ('deviation card interpolation [150, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [150, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], -0.94), ('deviation card interpolation [350, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [350, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], 0.58), ('deviation card interpolation [60, [[315, 1.5], [270, 0.5], [225, -2.0], [180, -3.0], [135, -1.5], [90, 1.0], [45, 3.5], [0, 2.0]]]', [60, [[315, 1.5], [270, 0.5], [225, -2.0], [180, -3.0], [135, -1.5], [90, 1.0], [45, 3.5], [0, 2.0]]], 2.67), ('deviation card interpolation [250, [[315, 1.5], [270, 0.5], [225, -2.0], [180, -3.0], [135, -1.5], [90, 1.0], [45, 3.5], [0, 2.0]]]', [250, [[315, 1.5], [270, 0.5], [225, -2.0], [180, -3.0], [135, -1.5], [90, 1.0], [45, 3.5], [0, 2.0]]], -0.61), ('deviation card interpolation [30, [[90, 1.0], [0, 0.0], [270, -1.0], [180, 2.0]]]', [30, [[90, 1.0], [0, 0.0], [270, -1.0], [180, 2.0]]], 0.33)]]
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
deviation card interpolation [330, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]1.51.67Failed
deviation card interpolation [0, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]2.02.0Passed
deviation card interpolation [20, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]2.672.67Passed
deviation card interpolation [90, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]1.01.0Passed
deviation card interpolation [100, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]0.440.44Passed
deviation card interpolation [200, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]-2.56-2.56Passed
deviation card interpolation [359, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]1.51.99Failed

SHA-256 / ed63b23c9aa4d4da66840cbcbdd53cf6e82a43233d0e4c2b82d7a4e7df6817b9

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    hdg,card=x
    pts=sorted(card)
    first=pts[0][0]
    t=hdg%360
    if t<first: t+=360
    pts.append([first+360,pts[0][1]])
    for k in range(len(pts)-1):
        h0,d0=pts[k]; h1,d1=pts[k+1]
        if h0<=t<h1:
            return round(d0+(d1-d0)*(t-h0)/(h1-h0),2)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('deviation card interpolation [330, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [330, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 1.67), ('deviation card interpolation [0, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [0, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 2.0), ('deviation card interpolation [20, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [20, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 2.67), ('deviation card interpolation [90, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [90, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 1.0), ('deviation card interpolation [100, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [100, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 0.44), ('deviation card interpolation [200, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [200, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], -2.56), ('deviation card interpolation [359, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [359, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 1.99)], [('deviation card interpolation [359, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [359, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 1.99), ('deviation card interpolation [100, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [100, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 0.44), ('deviation card interpolation [200, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [200, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], -2.56), ('deviation card interpolation [330, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [330, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 1.67), ('deviation card interpolation [360, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [360, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 2.0), ('deviation card interpolation [-30, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [-30, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 1.67), ('deviation card interpolation [725, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [725, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 2.17)], [('deviation card interpolation [-30, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [-30, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 1.67), ('deviation card interpolation [359, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [359, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 1.99), ('deviation card interpolation [360, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [360, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 2.0), ('deviation card interpolation [725, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [725, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 2.17), ('deviation card interpolation [5, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [5, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], 0.83), ('deviation card interpolation [15, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [15, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], 1.0), ('deviation card interpolation [50, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [50, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], 1.88)], [('deviation card interpolation [5, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [5, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], 0.83), ('deviation card interpolation [725, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [725, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 2.17), ('deviation card interpolation [15, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [15, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], 1.0), ('deviation card interpolation [50, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [50, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], 1.88), ('deviation card interpolation [150, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [150, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], -0.94), ('deviation card interpolation [300, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [300, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], -0.25), ('deviation card interpolation [350, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [350, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], 0.58)], [('deviation card interpolation [300, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [300, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], -0.25), ('deviation card interpolation [50, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [50, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], 1.88), ('deviation card interpolation [150, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [150, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], -0.94), ('deviation card interpolation [350, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [350, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], 0.58), ('deviation card interpolation [60, [[315, 1.5], [270, 0.5], [225, -2.0], [180, -3.0], [135, -1.5], [90, 1.0], [45, 3.5], [0, 2.0]]]', [60, [[315, 1.5], [270, 0.5], [225, -2.0], [180, -3.0], [135, -1.5], [90, 1.0], [45, 3.5], [0, 2.0]]], 2.67), ('deviation card interpolation [250, [[315, 1.5], [270, 0.5], [225, -2.0], [180, -3.0], [135, -1.5], [90, 1.0], [45, 3.5], [0, 2.0]]]', [250, [[315, 1.5], [270, 0.5], [225, -2.0], [180, -3.0], [135, -1.5], [90, 1.0], [45, 3.5], [0, 2.0]]], -0.61), ('deviation card interpolation [30, [[90, 1.0], [0, 0.0], [270, -1.0], [180, 2.0]]]', [30, [[90, 1.0], [0, 0.0], [270, -1.0], [180, 2.0]]], 0.33)]]
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
deviation card interpolation [330, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]1.671.67Passed
deviation card interpolation [0, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]2.02.0Passed
deviation card interpolation [20, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]2.672.67Passed
deviation card interpolation [90, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]1.01.0Passed
deviation card interpolation [100, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]0.440.44Passed
deviation card interpolation [200, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]-2.56-2.56Passed
deviation card interpolation [359, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]1.991.99Passed

SHA-256 / ad5f5d29fa82b3a549228b02dc3da2436fca14703114c652ee498da133d21d65

Verification & scope

A deterministic toy model with stipulated rules and constants; not certified hydrographic software or a substitute for official tide tables. 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:48:10.054969+00:00.

Case digest / 98d1b5ace637e5152d878e420536bab9eec6798fe245fd3d69d01574cd748136