FA-69276 / Tide and marine navigation tables / Open access
Compass variation and deviation: Compass to magnetic also applies variation · case 01
Magnetic courses include variation that belongs only to true.
ROOT CAUSE
The correction slice for an upward conversion is one step too long.
VERIFIED REPAIR
Sum only the corrections between the two levels.
Unsuccessful approach: Applying both corrections for every conversion is wrong for single-step conversions.
Case contract
Input [value, frm, to, var, dev] with frm/to in C (compass), M (magnetic), T (true); var and dev like "3.5W"/"2E" (east positive). M=C+dev, T=M+var; converting downward subtracts. Return [value mod 360 rounded 1, total compass error dev+var as "x.xE"/"x.xW" or "0"].
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):
val,frm,to,var,dev=x
def sg(s):
v=float(s[:-1])
return v if s[-1]=='E' else -v
lvl={'C':0,'M':1,'T':2}
corr=[sg(dev),sg(var)]
a,b=lvl[frm],lvl[to]
if b>a: val+=sum(corr[a:b+1])
else: val-=sum(corr[b:a])
e=sum(corr)
err='0' if e==0 else '%.1f%s'%(abs(e),'E' if e>0 else 'W')
return [round(val%360,1),err]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('compass variation and deviation [355, "C", "M", "3W", "6E"]', [355, 'C', 'M', '3W', '6E'], [1.0, '3.0E']), ('compass variation and deviation [100, "C", "T", "4W", "2E"]', [100, 'C', 'T', '4W', '2E'], [98.0, '2.0W']), ('compass variation and deviation [100, "T", "C", "4W", "2E"]', [100, 'T', 'C', '4W', '2E'], [102.0, '2.0W']), ('compass variation and deviation [5, "T", "M", "7W", "1W"]', [5, 'T', 'M', '7W', '1W'], [12.0, '8.0W']), ('compass variation and deviation [5, "M", "T", "7W", "1W"]', [5, 'M', 'T', '7W', '1W'], [358.0, '8.0W']), ('compass variation and deviation [200, "M", "C", "0.5E", "1.5W"]', [200, 'M', 'C', '0.5E', '1.5W'], [201.5, '1.0W']), ('compass variation and deviation [200, "C", "M", "0.5E", "1.5W"]', [200, 'C', 'M', '0.5E', '1.5W'], [198.5, '1.0W'])], [('compass variation and deviation [200, "C", "M", "0.5E", "1.5W"]', [200, 'C', 'M', '0.5E', '1.5W'], [198.5, '1.0W']), ('compass variation and deviation [5, "M", "T", "7W", "1W"]', [5, 'M', 'T', '7W', '1W'], [358.0, '8.0W']), ('compass variation and deviation [5, "T", "M", "7W", "1W"]', [5, 'T', 'M', '7W', '1W'], [12.0, '8.0W']), ('compass variation and deviation [200, "M", "C", "0.5E", "1.5W"]', [200, 'M', 'C', '0.5E', '1.5W'], [201.5, '1.0W']), ('compass variation and deviation [90, "T", "T", "3E", "3W"]', [90, 'T', 'T', '3E', '3W'], [90, '0']), ('compass variation and deviation [270.5, "C", "T", "12.5E", "3.5E"]', [270.5, 'C', 'T', '12.5E', '3.5E'], [286.5, '16.0E']), ('compass variation and deviation [1, "T", "C", "2E", "3E"]', [1, 'T', 'C', '2E', '3E'], [356.0, '5.0E'])], [('compass variation and deviation [355, "C", "M", "3W", "6E"]', [355, 'C', 'M', '3W', '6E'], [1.0, '3.0E']), ('compass variation and deviation [200, "C", "M", "0.5E", "1.5W"]', [200, 'C', 'M', '0.5E', '1.5W'], [198.5, '1.0W']), ('compass variation and deviation [90, "T", "T", "3E", "3W"]', [90, 'T', 'T', '3E', '3W'], [90, '0']), ('compass variation and deviation [270.5, "C", "T", "12.5E", "3.5E"]', [270.5, 'C', 'T', '12.5E', '3.5E'], [286.5, '16.0E']), ('compass variation and deviation [1, "T", "C", "2E", "3E"]', [1, 'T', 'C', '2E', '3E'], [356.0, '5.0E']), ('compass variation and deviation [45, "C", "T", "3E", "3W"]', [45, 'C', 'T', '3E', '3W'], [45.0, '0']), ('compass variation and deviation [180, "M", "T", "0E", "2W"]', [180, 'M', 'T', '0E', '2W'], [180.0, '2.0W'])], [('compass variation and deviation [200, "C", "M", "0.5E", "1.5W"]', [200, 'C', 'M', '0.5E', '1.5W'], [198.5, '1.0W']), ('compass variation and deviation [180, "M", "T", "0E", "2W"]', [180, 'M', 'T', '0E', '2W'], [180.0, '2.0W']), ('compass variation and deviation [1, "T", "C", "2E", "3E"]', [1, 'T', 'C', '2E', '3E'], [356.0, '5.0E']), ('compass variation and deviation [45, "C", "T", "3E", "3W"]', [45, 'C', 'T', '3E', '3W'], [45.0, '0']), ('compass variation and deviation [100, "C", "T", "4W", "2E"]', [100, 'C', 'T', '4W', '2E'], [98.0, '2.0W']), ('compass variation and deviation [100, "T", "C", "4W", "2E"]', [100, 'T', 'C', '4W', '2E'], [102.0, '2.0W']), ('compass variation and deviation [355, "C", "M", "3W", "6E"]', [355, 'C', 'M', '3W', '6E'], [1.0, '3.0E'])], [('compass variation and deviation [355, "C", "M", "3W", "6E"]', [355, 'C', 'M', '3W', '6E'], [1.0, '3.0E']), ('compass variation and deviation [100, "C", "T", "4W", "2E"]', [100, 'C', 'T', '4W', '2E'], [98.0, '2.0W']), ('compass variation and deviation [100, "T", "C", "4W", "2E"]', [100, 'T', 'C', '4W', '2E'], [102.0, '2.0W']), ('compass variation and deviation [5, "T", "M", "7W", "1W"]', [5, 'T', 'M', '7W', '1W'], [12.0, '8.0W']), ('compass variation and deviation [5, "M", "T", "7W", "1W"]', [5, 'M', 'T', '7W', '1W'], [358.0, '8.0W']), ('compass variation and deviation [200, "M", "C", "0.5E", "1.5W"]', [200, 'M', 'C', '0.5E', '1.5W'], [201.5, '1.0W']), ('compass variation and deviation [200, "C", "M", "0.5E", "1.5W"]', [200, 'C', 'M', '0.5E', '1.5W'], [198.5, '1.0W'])]]
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 |
|---|---|---|---|
| compass variation and deviation [355, "C", "M", "3W", "6E"] | [358.0, '3.0E'] | [1.0, '3.0E'] | Failed |
| compass variation and deviation [100, "C", "T", "4W", "2E"] | [98.0, '2.0W'] | [98.0, '2.0W'] | Passed |
| compass variation and deviation [100, "T", "C", "4W", "2E"] | [102.0, '2.0W'] | [102.0, '2.0W'] | Passed |
| compass variation and deviation [5, "T", "M", "7W", "1W"] | [12.0, '8.0W'] | [12.0, '8.0W'] | Passed |
| compass variation and deviation [5, "M", "T", "7W", "1W"] | [358.0, '8.0W'] | [358.0, '8.0W'] | Passed |
| compass variation and deviation [200, "M", "C", "0.5E", "1.5W"] | [201.5, '1.0W'] | [201.5, '1.0W'] | Passed |
| compass variation and deviation [200, "C", "M", "0.5E", "1.5W"] | [199.0, '1.0W'] | [198.5, '1.0W'] | Failed |
SHA-256 / f109e16a6273e8840a122b7006be78b08a7c16b609c6ba2327770e1e36b8342d
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
val,frm,to,var,dev=x
def sg(s):
v=float(s[:-1])
return v if s[-1]=='E' else -v
lvl={'C':0,'M':1,'T':2}
corr=[sg(dev),sg(var)]
a,b=lvl[frm],lvl[to]
if b>a: val+=sum(corr)
else: val-=sum(corr[b:a])
e=sum(corr)
err='0' if e==0 else '%.1f%s'%(abs(e),'E' if e>0 else 'W')
return [round(val%360,1),err]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('compass variation and deviation [355, "C", "M", "3W", "6E"]', [355, 'C', 'M', '3W', '6E'], [1.0, '3.0E']), ('compass variation and deviation [100, "C", "T", "4W", "2E"]', [100, 'C', 'T', '4W', '2E'], [98.0, '2.0W']), ('compass variation and deviation [100, "T", "C", "4W", "2E"]', [100, 'T', 'C', '4W', '2E'], [102.0, '2.0W']), ('compass variation and deviation [5, "T", "M", "7W", "1W"]', [5, 'T', 'M', '7W', '1W'], [12.0, '8.0W']), ('compass variation and deviation [5, "M", "T", "7W", "1W"]', [5, 'M', 'T', '7W', '1W'], [358.0, '8.0W']), ('compass variation and deviation [200, "M", "C", "0.5E", "1.5W"]', [200, 'M', 'C', '0.5E', '1.5W'], [201.5, '1.0W']), ('compass variation and deviation [200, "C", "M", "0.5E", "1.5W"]', [200, 'C', 'M', '0.5E', '1.5W'], [198.5, '1.0W'])], [('compass variation and deviation [200, "C", "M", "0.5E", "1.5W"]', [200, 'C', 'M', '0.5E', '1.5W'], [198.5, '1.0W']), ('compass variation and deviation [5, "M", "T", "7W", "1W"]', [5, 'M', 'T', '7W', '1W'], [358.0, '8.0W']), ('compass variation and deviation [5, "T", "M", "7W", "1W"]', [5, 'T', 'M', '7W', '1W'], [12.0, '8.0W']), ('compass variation and deviation [200, "M", "C", "0.5E", "1.5W"]', [200, 'M', 'C', '0.5E', '1.5W'], [201.5, '1.0W']), ('compass variation and deviation [90, "T", "T", "3E", "3W"]', [90, 'T', 'T', '3E', '3W'], [90, '0']), ('compass variation and deviation [270.5, "C", "T", "12.5E", "3.5E"]', [270.5, 'C', 'T', '12.5E', '3.5E'], [286.5, '16.0E']), ('compass variation and deviation [1, "T", "C", "2E", "3E"]', [1, 'T', 'C', '2E', '3E'], [356.0, '5.0E'])], [('compass variation and deviation [355, "C", "M", "3W", "6E"]', [355, 'C', 'M', '3W', '6E'], [1.0, '3.0E']), ('compass variation and deviation [200, "C", "M", "0.5E", "1.5W"]', [200, 'C', 'M', '0.5E', '1.5W'], [198.5, '1.0W']), ('compass variation and deviation [90, "T", "T", "3E", "3W"]', [90, 'T', 'T', '3E', '3W'], [90, '0']), ('compass variation and deviation [270.5, "C", "T", "12.5E", "3.5E"]', [270.5, 'C', 'T', '12.5E', '3.5E'], [286.5, '16.0E']), ('compass variation and deviation [1, "T", "C", "2E", "3E"]', [1, 'T', 'C', '2E', '3E'], [356.0, '5.0E']), ('compass variation and deviation [45, "C", "T", "3E", "3W"]', [45, 'C', 'T', '3E', '3W'], [45.0, '0']), ('compass variation and deviation [180, "M", "T", "0E", "2W"]', [180, 'M', 'T', '0E', '2W'], [180.0, '2.0W'])], [('compass variation and deviation [200, "C", "M", "0.5E", "1.5W"]', [200, 'C', 'M', '0.5E', '1.5W'], [198.5, '1.0W']), ('compass variation and deviation [180, "M", "T", "0E", "2W"]', [180, 'M', 'T', '0E', '2W'], [180.0, '2.0W']), ('compass variation and deviation [1, "T", "C", "2E", "3E"]', [1, 'T', 'C', '2E', '3E'], [356.0, '5.0E']), ('compass variation and deviation [45, "C", "T", "3E", "3W"]', [45, 'C', 'T', '3E', '3W'], [45.0, '0']), ('compass variation and deviation [100, "C", "T", "4W", "2E"]', [100, 'C', 'T', '4W', '2E'], [98.0, '2.0W']), ('compass variation and deviation [100, "T", "C", "4W", "2E"]', [100, 'T', 'C', '4W', '2E'], [102.0, '2.0W']), ('compass variation and deviation [355, "C", "M", "3W", "6E"]', [355, 'C', 'M', '3W', '6E'], [1.0, '3.0E'])], [('compass variation and deviation [355, "C", "M", "3W", "6E"]', [355, 'C', 'M', '3W', '6E'], [1.0, '3.0E']), ('compass variation and deviation [100, "C", "T", "4W", "2E"]', [100, 'C', 'T', '4W', '2E'], [98.0, '2.0W']), ('compass variation and deviation [100, "T", "C", "4W", "2E"]', [100, 'T', 'C', '4W', '2E'], [102.0, '2.0W']), ('compass variation and deviation [5, "T", "M", "7W", "1W"]', [5, 'T', 'M', '7W', '1W'], [12.0, '8.0W']), ('compass variation and deviation [5, "M", "T", "7W", "1W"]', [5, 'M', 'T', '7W', '1W'], [358.0, '8.0W']), ('compass variation and deviation [200, "M", "C", "0.5E", "1.5W"]', [200, 'M', 'C', '0.5E', '1.5W'], [201.5, '1.0W']), ('compass variation and deviation [200, "C", "M", "0.5E", "1.5W"]', [200, 'C', 'M', '0.5E', '1.5W'], [198.5, '1.0W'])]]
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 |
|---|---|---|---|
| compass variation and deviation [355, "C", "M", "3W", "6E"] | [358.0, '3.0E'] | [1.0, '3.0E'] | Failed |
| compass variation and deviation [100, "C", "T", "4W", "2E"] | [98.0, '2.0W'] | [98.0, '2.0W'] | Passed |
| compass variation and deviation [100, "T", "C", "4W", "2E"] | [102.0, '2.0W'] | [102.0, '2.0W'] | Passed |
| compass variation and deviation [5, "T", "M", "7W", "1W"] | [12.0, '8.0W'] | [12.0, '8.0W'] | Passed |
| compass variation and deviation [5, "M", "T", "7W", "1W"] | [357.0, '8.0W'] | [358.0, '8.0W'] | Failed |
| compass variation and deviation [200, "M", "C", "0.5E", "1.5W"] | [201.5, '1.0W'] | [201.5, '1.0W'] | Passed |
| compass variation and deviation [200, "C", "M", "0.5E", "1.5W"] | [199.0, '1.0W'] | [198.5, '1.0W'] | Failed |
SHA-256 / 8c39b8afcea1d3eba827a3940e8087d62d972f6cce11c629abcd9e284bb10f3f
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
val,frm,to,var,dev=x
def sg(s):
v=float(s[:-1])
return v if s[-1]=='E' else -v
lvl={'C':0,'M':1,'T':2}
corr=[sg(dev),sg(var)]
a,b=lvl[frm],lvl[to]
if b>a: val+=sum(corr[a:b])
else: val-=sum(corr[b:a])
e=sum(corr)
err='0' if e==0 else '%.1f%s'%(abs(e),'E' if e>0 else 'W')
return [round(val%360,1),err]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('compass variation and deviation [355, "C", "M", "3W", "6E"]', [355, 'C', 'M', '3W', '6E'], [1.0, '3.0E']), ('compass variation and deviation [100, "C", "T", "4W", "2E"]', [100, 'C', 'T', '4W', '2E'], [98.0, '2.0W']), ('compass variation and deviation [100, "T", "C", "4W", "2E"]', [100, 'T', 'C', '4W', '2E'], [102.0, '2.0W']), ('compass variation and deviation [5, "T", "M", "7W", "1W"]', [5, 'T', 'M', '7W', '1W'], [12.0, '8.0W']), ('compass variation and deviation [5, "M", "T", "7W", "1W"]', [5, 'M', 'T', '7W', '1W'], [358.0, '8.0W']), ('compass variation and deviation [200, "M", "C", "0.5E", "1.5W"]', [200, 'M', 'C', '0.5E', '1.5W'], [201.5, '1.0W']), ('compass variation and deviation [200, "C", "M", "0.5E", "1.5W"]', [200, 'C', 'M', '0.5E', '1.5W'], [198.5, '1.0W'])], [('compass variation and deviation [200, "C", "M", "0.5E", "1.5W"]', [200, 'C', 'M', '0.5E', '1.5W'], [198.5, '1.0W']), ('compass variation and deviation [5, "M", "T", "7W", "1W"]', [5, 'M', 'T', '7W', '1W'], [358.0, '8.0W']), ('compass variation and deviation [5, "T", "M", "7W", "1W"]', [5, 'T', 'M', '7W', '1W'], [12.0, '8.0W']), ('compass variation and deviation [200, "M", "C", "0.5E", "1.5W"]', [200, 'M', 'C', '0.5E', '1.5W'], [201.5, '1.0W']), ('compass variation and deviation [90, "T", "T", "3E", "3W"]', [90, 'T', 'T', '3E', '3W'], [90, '0']), ('compass variation and deviation [270.5, "C", "T", "12.5E", "3.5E"]', [270.5, 'C', 'T', '12.5E', '3.5E'], [286.5, '16.0E']), ('compass variation and deviation [1, "T", "C", "2E", "3E"]', [1, 'T', 'C', '2E', '3E'], [356.0, '5.0E'])], [('compass variation and deviation [355, "C", "M", "3W", "6E"]', [355, 'C', 'M', '3W', '6E'], [1.0, '3.0E']), ('compass variation and deviation [200, "C", "M", "0.5E", "1.5W"]', [200, 'C', 'M', '0.5E', '1.5W'], [198.5, '1.0W']), ('compass variation and deviation [90, "T", "T", "3E", "3W"]', [90, 'T', 'T', '3E', '3W'], [90, '0']), ('compass variation and deviation [270.5, "C", "T", "12.5E", "3.5E"]', [270.5, 'C', 'T', '12.5E', '3.5E'], [286.5, '16.0E']), ('compass variation and deviation [1, "T", "C", "2E", "3E"]', [1, 'T', 'C', '2E', '3E'], [356.0, '5.0E']), ('compass variation and deviation [45, "C", "T", "3E", "3W"]', [45, 'C', 'T', '3E', '3W'], [45.0, '0']), ('compass variation and deviation [180, "M", "T", "0E", "2W"]', [180, 'M', 'T', '0E', '2W'], [180.0, '2.0W'])], [('compass variation and deviation [200, "C", "M", "0.5E", "1.5W"]', [200, 'C', 'M', '0.5E', '1.5W'], [198.5, '1.0W']), ('compass variation and deviation [180, "M", "T", "0E", "2W"]', [180, 'M', 'T', '0E', '2W'], [180.0, '2.0W']), ('compass variation and deviation [1, "T", "C", "2E", "3E"]', [1, 'T', 'C', '2E', '3E'], [356.0, '5.0E']), ('compass variation and deviation [45, "C", "T", "3E", "3W"]', [45, 'C', 'T', '3E', '3W'], [45.0, '0']), ('compass variation and deviation [100, "C", "T", "4W", "2E"]', [100, 'C', 'T', '4W', '2E'], [98.0, '2.0W']), ('compass variation and deviation [100, "T", "C", "4W", "2E"]', [100, 'T', 'C', '4W', '2E'], [102.0, '2.0W']), ('compass variation and deviation [355, "C", "M", "3W", "6E"]', [355, 'C', 'M', '3W', '6E'], [1.0, '3.0E'])], [('compass variation and deviation [355, "C", "M", "3W", "6E"]', [355, 'C', 'M', '3W', '6E'], [1.0, '3.0E']), ('compass variation and deviation [100, "C", "T", "4W", "2E"]', [100, 'C', 'T', '4W', '2E'], [98.0, '2.0W']), ('compass variation and deviation [100, "T", "C", "4W", "2E"]', [100, 'T', 'C', '4W', '2E'], [102.0, '2.0W']), ('compass variation and deviation [5, "T", "M", "7W", "1W"]', [5, 'T', 'M', '7W', '1W'], [12.0, '8.0W']), ('compass variation and deviation [5, "M", "T", "7W", "1W"]', [5, 'M', 'T', '7W', '1W'], [358.0, '8.0W']), ('compass variation and deviation [200, "M", "C", "0.5E", "1.5W"]', [200, 'M', 'C', '0.5E', '1.5W'], [201.5, '1.0W']), ('compass variation and deviation [200, "C", "M", "0.5E", "1.5W"]', [200, 'C', 'M', '0.5E', '1.5W'], [198.5, '1.0W'])]]
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 |
|---|---|---|---|
| compass variation and deviation [355, "C", "M", "3W", "6E"] | [1.0, '3.0E'] | [1.0, '3.0E'] | Passed |
| compass variation and deviation [100, "C", "T", "4W", "2E"] | [98.0, '2.0W'] | [98.0, '2.0W'] | Passed |
| compass variation and deviation [100, "T", "C", "4W", "2E"] | [102.0, '2.0W'] | [102.0, '2.0W'] | Passed |
| compass variation and deviation [5, "T", "M", "7W", "1W"] | [12.0, '8.0W'] | [12.0, '8.0W'] | Passed |
| compass variation and deviation [5, "M", "T", "7W", "1W"] | [358.0, '8.0W'] | [358.0, '8.0W'] | Passed |
| compass variation and deviation [200, "M", "C", "0.5E", "1.5W"] | [201.5, '1.0W'] | [201.5, '1.0W'] | Passed |
| compass variation and deviation [200, "C", "M", "0.5E", "1.5W"] | [198.5, '1.0W'] | [198.5, '1.0W'] | Passed |
SHA-256 / 5ab39c1011bf6d83074f68dff41efbfc26899a37a9e52ecdaf416b0285098317
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:09.984188+00:00.
Case digest / f16e65f9b5c4cfa4e6729401a8898b059f9d1c641a3b4562de9012ddad76d93b