FAILURE MAP
← Case archive

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

Light characteristic abbreviation: Fractional periods are not recognised · case 01

Quick lights with 1.2 s or 2.5 s periods fail to parse.

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

ROOT CAUSE

The period pattern accepts only whole seconds.

VERIFIED REPAIR

Allow an optional decimal part in the period.

Unsuccessful approach: Rounding the parsed period to whole seconds loses the tenths.

Case contract

Input a chart light abbreviation such as "Fl(3)WR.10s15m20M". Return [class, groups, colours, period_s, height_m, range_nm]: class includes an "Al." prefix; groups is a list (composite "2+1" -> [2,1], default [1]); colours default "W"; missing numbers are None. Unparseable strings return None.

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 re
N = 1
observations = []
def solve(x):
    m=re.match(r"^(Al\.|)(LFl|Fl|VQ|Q|Iso|Oc|F)(?:\(([0-9+]+)\))?\.?([WRGY]*)\.?(?:(\d+)s)?(?:(\d+)m)?(?:(\d+)M)?$",x)
    if not m: return None
    cls=m.group(1)+m.group(2)
    grp=[int(p) for p in m.group(3).split('+')] if m.group(3) else [1]
    col=m.group(4) or 'W'
    per=float(m.group(5)) if m.group(5) else None
    return [cls,grp,col,per,int(m.group(6)) if m.group(6) else None,int(m.group(7)) if m.group(7) else None]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('light characteristic abbreviation "Fl.2.5s"', 'Fl.2.5s', ['Fl', [1], 'W', 2.5, None, None]), ('light characteristic abbreviation "Fl(3)WR.10s15m20M"', 'Fl(3)WR.10s15m20M', ['Fl', [3], 'WR', 10.0, 15, 20]), ('light characteristic abbreviation "LFl.10s"', 'LFl.10s', ['LFl', [1], 'W', 10.0, None, None]), ('light characteristic abbreviation "Q"', 'Q', ['Q', [1], 'W', None, None, None]), ('light characteristic abbreviation "VQ(6)10s"', 'VQ(6)10s', ['VQ', [6], 'W', 10.0, None, None]), ('light characteristic abbreviation "Iso.WRG.4s"', 'Iso.WRG.4s', ['Iso', [1], 'WRG', 4.0, None, None]), ('light characteristic abbreviation "Oc(2)R.8s12m9M"', 'Oc(2)R.8s12m9M', ['Oc', [2], 'R', 8.0, 12, 9])], [('light characteristic abbreviation "Q.1.2s"', 'Q.1.2s', ['Q', [1], 'W', 1.2, None, None]), ('light characteristic abbreviation "VQ(6)10s"', 'VQ(6)10s', ['VQ', [6], 'W', 10.0, None, None]), ('light characteristic abbreviation "Iso.WRG.4s"', 'Iso.WRG.4s', ['Iso', [1], 'WRG', 4.0, None, None]), ('light characteristic abbreviation "Oc(2)R.8s12m9M"', 'Oc(2)R.8s12m9M', ['Oc', [2], 'R', 8.0, 12, 9]), ('light characteristic abbreviation "Al.Fl.WR.5s"', 'Al.Fl.WR.5s', ['Al.Fl', [1], 'WR', 5.0, None, None]), ('light characteristic abbreviation "Fl(2+1)G.15s"', 'Fl(2+1)G.15s', ['Fl', [2, 1], 'G', 15.0, None, None]), ('light characteristic abbreviation "Q(9)15s"', 'Q(9)15s', ['Q', [9], 'W', 15.0, None, None])], [('light characteristic abbreviation "Fl.2.5s"', 'Fl.2.5s', ['Fl', [1], 'W', 2.5, None, None]), ('light characteristic abbreviation "Al.Fl.WR.5s"', 'Al.Fl.WR.5s', ['Al.Fl', [1], 'WR', 5.0, None, None]), ('light characteristic abbreviation "Fl(2+1)G.15s"', 'Fl(2+1)G.15s', ['Fl', [2, 1], 'G', 15.0, None, None]), ('light characteristic abbreviation "Q(9)15s"', 'Q(9)15s', ['Q', [9], 'W', 15.0, None, None]), ('light characteristic abbreviation "F.R"', 'F.R', ['F', [1], 'R', None, None, None]), ('light characteristic abbreviation "Fl(4)Y.20s8m5M"', 'Fl(4)Y.20s8m5M', ['Fl', [4], 'Y', 20.0, 8, 5]), ('light characteristic abbreviation "LFl.G.12s24m15M"', 'LFl.G.12s24m15M', ['LFl', [1], 'G', 12.0, 24, 15])], [('light characteristic abbreviation "Q.1.2s"', 'Q.1.2s', ['Q', [1], 'W', 1.2, None, None]), ('light characteristic abbreviation "F.R"', 'F.R', ['F', [1], 'R', None, None, None]), ('light characteristic abbreviation "Fl.2.5s"', 'Fl.2.5s', ['Fl', [1], 'W', 2.5, None, None]), ('light characteristic abbreviation "Fl(4)Y.20s8m5M"', 'Fl(4)Y.20s8m5M', ['Fl', [4], 'Y', 20.0, 8, 5]), ('light characteristic abbreviation "LFl.G.12s24m15M"', 'LFl.G.12s24m15M', ['LFl', [1], 'G', 12.0, 24, 15]), ('light characteristic abbreviation "Fl.10s20M"', 'Fl.10s20M', ['Fl', [1], 'W', 10.0, None, 20]), ('light characteristic abbreviation "Al.Oc.WG.6s"', 'Al.Oc.WG.6s', ['Al.Oc', [1], 'WG', 6.0, None, None])], [('light characteristic abbreviation "Fl.2.5s"', 'Fl.2.5s', ['Fl', [1], 'W', 2.5, None, None]), ('light characteristic abbreviation "LFl.G.12s24m15M"', 'LFl.G.12s24m15M', ['LFl', [1], 'G', 12.0, 24, 15]), ('light characteristic abbreviation "Fl.10s20M"', 'Fl.10s20M', ['Fl', [1], 'W', 10.0, None, 20]), ('light characteristic abbreviation "Al.Oc.WG.6s"', 'Al.Oc.WG.6s', ['Al.Oc', [1], 'WG', 6.0, None, None]), ('light characteristic abbreviation "Q.1.2s"', 'Q.1.2s', ['Q', [1], 'W', 1.2, None, None]), ('light characteristic abbreviation "Mo(A)10s"', 'Mo(A)10s', None), ('light characteristic abbreviation "Fl(3)WR.10s15m20M"', 'Fl(3)WR.10s15m20M', ['Fl', [3], 'WR', 10.0, 15, 20])]]
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
light characteristic abbreviation "Fl.2.5s"None['Fl', [1], 'W', 2.5, None, None]Failed
light characteristic abbreviation "Fl(3)WR.10s15m20M"['Fl', [3], 'WR', 10.0, 15, 20]['Fl', [3], 'WR', 10.0, 15, 20]Passed
light characteristic abbreviation "LFl.10s"['LFl', [1], 'W', 10.0, None, None]['LFl', [1], 'W', 10.0, None, None]Passed
light characteristic abbreviation "Q"['Q', [1], 'W', None, None, None]['Q', [1], 'W', None, None, None]Passed
light characteristic abbreviation "VQ(6)10s"['VQ', [6], 'W', 10.0, None, None]['VQ', [6], 'W', 10.0, None, None]Passed
light characteristic abbreviation "Iso.WRG.4s"['Iso', [1], 'WRG', 4.0, None, None]['Iso', [1], 'WRG', 4.0, None, None]Passed
light characteristic abbreviation "Oc(2)R.8s12m9M"['Oc', [2], 'R', 8.0, 12, 9]['Oc', [2], 'R', 8.0, 12, 9]Passed

SHA-256 / 0a4131112b57bc326bd87ff6d3697dc884a13eee5ca9826da9255dd6b2d8136d

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import re
N = 1
observations = []
def solve(x):
    m=re.match(r"^(Al\.|)(LFl|Fl|VQ|Q|Iso|Oc|F)(?:\(([0-9+]+)\))?\.?([WRGY]*)\.?(?:(\d+(?:\.\d+)?)s)?(?:(\d+)m)?(?:(\d+)M)?$",x)
    if not m: return None
    cls=m.group(1)+m.group(2)
    grp=[int(p) for p in m.group(3).split('+')] if m.group(3) else [1]
    col=m.group(4) or 'W'
    per=float(round(float(m.group(5)))) if m.group(5) else None
    return [cls,grp,col,per,int(m.group(6)) if m.group(6) else None,int(m.group(7)) if m.group(7) else None]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('light characteristic abbreviation "Fl.2.5s"', 'Fl.2.5s', ['Fl', [1], 'W', 2.5, None, None]), ('light characteristic abbreviation "Fl(3)WR.10s15m20M"', 'Fl(3)WR.10s15m20M', ['Fl', [3], 'WR', 10.0, 15, 20]), ('light characteristic abbreviation "LFl.10s"', 'LFl.10s', ['LFl', [1], 'W', 10.0, None, None]), ('light characteristic abbreviation "Q"', 'Q', ['Q', [1], 'W', None, None, None]), ('light characteristic abbreviation "VQ(6)10s"', 'VQ(6)10s', ['VQ', [6], 'W', 10.0, None, None]), ('light characteristic abbreviation "Iso.WRG.4s"', 'Iso.WRG.4s', ['Iso', [1], 'WRG', 4.0, None, None]), ('light characteristic abbreviation "Oc(2)R.8s12m9M"', 'Oc(2)R.8s12m9M', ['Oc', [2], 'R', 8.0, 12, 9])], [('light characteristic abbreviation "Q.1.2s"', 'Q.1.2s', ['Q', [1], 'W', 1.2, None, None]), ('light characteristic abbreviation "VQ(6)10s"', 'VQ(6)10s', ['VQ', [6], 'W', 10.0, None, None]), ('light characteristic abbreviation "Iso.WRG.4s"', 'Iso.WRG.4s', ['Iso', [1], 'WRG', 4.0, None, None]), ('light characteristic abbreviation "Oc(2)R.8s12m9M"', 'Oc(2)R.8s12m9M', ['Oc', [2], 'R', 8.0, 12, 9]), ('light characteristic abbreviation "Al.Fl.WR.5s"', 'Al.Fl.WR.5s', ['Al.Fl', [1], 'WR', 5.0, None, None]), ('light characteristic abbreviation "Fl(2+1)G.15s"', 'Fl(2+1)G.15s', ['Fl', [2, 1], 'G', 15.0, None, None]), ('light characteristic abbreviation "Q(9)15s"', 'Q(9)15s', ['Q', [9], 'W', 15.0, None, None])], [('light characteristic abbreviation "Fl.2.5s"', 'Fl.2.5s', ['Fl', [1], 'W', 2.5, None, None]), ('light characteristic abbreviation "Al.Fl.WR.5s"', 'Al.Fl.WR.5s', ['Al.Fl', [1], 'WR', 5.0, None, None]), ('light characteristic abbreviation "Fl(2+1)G.15s"', 'Fl(2+1)G.15s', ['Fl', [2, 1], 'G', 15.0, None, None]), ('light characteristic abbreviation "Q(9)15s"', 'Q(9)15s', ['Q', [9], 'W', 15.0, None, None]), ('light characteristic abbreviation "F.R"', 'F.R', ['F', [1], 'R', None, None, None]), ('light characteristic abbreviation "Fl(4)Y.20s8m5M"', 'Fl(4)Y.20s8m5M', ['Fl', [4], 'Y', 20.0, 8, 5]), ('light characteristic abbreviation "LFl.G.12s24m15M"', 'LFl.G.12s24m15M', ['LFl', [1], 'G', 12.0, 24, 15])], [('light characteristic abbreviation "Q.1.2s"', 'Q.1.2s', ['Q', [1], 'W', 1.2, None, None]), ('light characteristic abbreviation "F.R"', 'F.R', ['F', [1], 'R', None, None, None]), ('light characteristic abbreviation "Fl.2.5s"', 'Fl.2.5s', ['Fl', [1], 'W', 2.5, None, None]), ('light characteristic abbreviation "Fl(4)Y.20s8m5M"', 'Fl(4)Y.20s8m5M', ['Fl', [4], 'Y', 20.0, 8, 5]), ('light characteristic abbreviation "LFl.G.12s24m15M"', 'LFl.G.12s24m15M', ['LFl', [1], 'G', 12.0, 24, 15]), ('light characteristic abbreviation "Fl.10s20M"', 'Fl.10s20M', ['Fl', [1], 'W', 10.0, None, 20]), ('light characteristic abbreviation "Al.Oc.WG.6s"', 'Al.Oc.WG.6s', ['Al.Oc', [1], 'WG', 6.0, None, None])], [('light characteristic abbreviation "Fl.2.5s"', 'Fl.2.5s', ['Fl', [1], 'W', 2.5, None, None]), ('light characteristic abbreviation "LFl.G.12s24m15M"', 'LFl.G.12s24m15M', ['LFl', [1], 'G', 12.0, 24, 15]), ('light characteristic abbreviation "Fl.10s20M"', 'Fl.10s20M', ['Fl', [1], 'W', 10.0, None, 20]), ('light characteristic abbreviation "Al.Oc.WG.6s"', 'Al.Oc.WG.6s', ['Al.Oc', [1], 'WG', 6.0, None, None]), ('light characteristic abbreviation "Q.1.2s"', 'Q.1.2s', ['Q', [1], 'W', 1.2, None, None]), ('light characteristic abbreviation "Mo(A)10s"', 'Mo(A)10s', None), ('light characteristic abbreviation "Fl(3)WR.10s15m20M"', 'Fl(3)WR.10s15m20M', ['Fl', [3], 'WR', 10.0, 15, 20])]]
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
light characteristic abbreviation "Fl.2.5s"['Fl', [1], 'W', 2.0, None, None]['Fl', [1], 'W', 2.5, None, None]Failed
light characteristic abbreviation "Fl(3)WR.10s15m20M"['Fl', [3], 'WR', 10.0, 15, 20]['Fl', [3], 'WR', 10.0, 15, 20]Passed
light characteristic abbreviation "LFl.10s"['LFl', [1], 'W', 10.0, None, None]['LFl', [1], 'W', 10.0, None, None]Passed
light characteristic abbreviation "Q"['Q', [1], 'W', None, None, None]['Q', [1], 'W', None, None, None]Passed
light characteristic abbreviation "VQ(6)10s"['VQ', [6], 'W', 10.0, None, None]['VQ', [6], 'W', 10.0, None, None]Passed
light characteristic abbreviation "Iso.WRG.4s"['Iso', [1], 'WRG', 4.0, None, None]['Iso', [1], 'WRG', 4.0, None, None]Passed
light characteristic abbreviation "Oc(2)R.8s12m9M"['Oc', [2], 'R', 8.0, 12, 9]['Oc', [2], 'R', 8.0, 12, 9]Passed

SHA-256 / 1396034511b064c653d1ed7c13080bbc79d3f173498fba68434b228d3ae749f8

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json
import re
N = 1
observations = []
def solve(x):
    m=re.match(r"^(Al\.|)(LFl|Fl|VQ|Q|Iso|Oc|F)(?:\(([0-9+]+)\))?\.?([WRGY]*)\.?(?:(\d+(?:\.\d+)?)s)?(?:(\d+)m)?(?:(\d+)M)?$",x)
    if not m: return None
    cls=m.group(1)+m.group(2)
    grp=[int(p) for p in m.group(3).split('+')] if m.group(3) else [1]
    col=m.group(4) or 'W'
    per=float(m.group(5)) if m.group(5) else None
    return [cls,grp,col,per,int(m.group(6)) if m.group(6) else None,int(m.group(7)) if m.group(7) else None]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('light characteristic abbreviation "Fl.2.5s"', 'Fl.2.5s', ['Fl', [1], 'W', 2.5, None, None]), ('light characteristic abbreviation "Fl(3)WR.10s15m20M"', 'Fl(3)WR.10s15m20M', ['Fl', [3], 'WR', 10.0, 15, 20]), ('light characteristic abbreviation "LFl.10s"', 'LFl.10s', ['LFl', [1], 'W', 10.0, None, None]), ('light characteristic abbreviation "Q"', 'Q', ['Q', [1], 'W', None, None, None]), ('light characteristic abbreviation "VQ(6)10s"', 'VQ(6)10s', ['VQ', [6], 'W', 10.0, None, None]), ('light characteristic abbreviation "Iso.WRG.4s"', 'Iso.WRG.4s', ['Iso', [1], 'WRG', 4.0, None, None]), ('light characteristic abbreviation "Oc(2)R.8s12m9M"', 'Oc(2)R.8s12m9M', ['Oc', [2], 'R', 8.0, 12, 9])], [('light characteristic abbreviation "Q.1.2s"', 'Q.1.2s', ['Q', [1], 'W', 1.2, None, None]), ('light characteristic abbreviation "VQ(6)10s"', 'VQ(6)10s', ['VQ', [6], 'W', 10.0, None, None]), ('light characteristic abbreviation "Iso.WRG.4s"', 'Iso.WRG.4s', ['Iso', [1], 'WRG', 4.0, None, None]), ('light characteristic abbreviation "Oc(2)R.8s12m9M"', 'Oc(2)R.8s12m9M', ['Oc', [2], 'R', 8.0, 12, 9]), ('light characteristic abbreviation "Al.Fl.WR.5s"', 'Al.Fl.WR.5s', ['Al.Fl', [1], 'WR', 5.0, None, None]), ('light characteristic abbreviation "Fl(2+1)G.15s"', 'Fl(2+1)G.15s', ['Fl', [2, 1], 'G', 15.0, None, None]), ('light characteristic abbreviation "Q(9)15s"', 'Q(9)15s', ['Q', [9], 'W', 15.0, None, None])], [('light characteristic abbreviation "Fl.2.5s"', 'Fl.2.5s', ['Fl', [1], 'W', 2.5, None, None]), ('light characteristic abbreviation "Al.Fl.WR.5s"', 'Al.Fl.WR.5s', ['Al.Fl', [1], 'WR', 5.0, None, None]), ('light characteristic abbreviation "Fl(2+1)G.15s"', 'Fl(2+1)G.15s', ['Fl', [2, 1], 'G', 15.0, None, None]), ('light characteristic abbreviation "Q(9)15s"', 'Q(9)15s', ['Q', [9], 'W', 15.0, None, None]), ('light characteristic abbreviation "F.R"', 'F.R', ['F', [1], 'R', None, None, None]), ('light characteristic abbreviation "Fl(4)Y.20s8m5M"', 'Fl(4)Y.20s8m5M', ['Fl', [4], 'Y', 20.0, 8, 5]), ('light characteristic abbreviation "LFl.G.12s24m15M"', 'LFl.G.12s24m15M', ['LFl', [1], 'G', 12.0, 24, 15])], [('light characteristic abbreviation "Q.1.2s"', 'Q.1.2s', ['Q', [1], 'W', 1.2, None, None]), ('light characteristic abbreviation "F.R"', 'F.R', ['F', [1], 'R', None, None, None]), ('light characteristic abbreviation "Fl.2.5s"', 'Fl.2.5s', ['Fl', [1], 'W', 2.5, None, None]), ('light characteristic abbreviation "Fl(4)Y.20s8m5M"', 'Fl(4)Y.20s8m5M', ['Fl', [4], 'Y', 20.0, 8, 5]), ('light characteristic abbreviation "LFl.G.12s24m15M"', 'LFl.G.12s24m15M', ['LFl', [1], 'G', 12.0, 24, 15]), ('light characteristic abbreviation "Fl.10s20M"', 'Fl.10s20M', ['Fl', [1], 'W', 10.0, None, 20]), ('light characteristic abbreviation "Al.Oc.WG.6s"', 'Al.Oc.WG.6s', ['Al.Oc', [1], 'WG', 6.0, None, None])], [('light characteristic abbreviation "Fl.2.5s"', 'Fl.2.5s', ['Fl', [1], 'W', 2.5, None, None]), ('light characteristic abbreviation "LFl.G.12s24m15M"', 'LFl.G.12s24m15M', ['LFl', [1], 'G', 12.0, 24, 15]), ('light characteristic abbreviation "Fl.10s20M"', 'Fl.10s20M', ['Fl', [1], 'W', 10.0, None, 20]), ('light characteristic abbreviation "Al.Oc.WG.6s"', 'Al.Oc.WG.6s', ['Al.Oc', [1], 'WG', 6.0, None, None]), ('light characteristic abbreviation "Q.1.2s"', 'Q.1.2s', ['Q', [1], 'W', 1.2, None, None]), ('light characteristic abbreviation "Mo(A)10s"', 'Mo(A)10s', None), ('light characteristic abbreviation "Fl(3)WR.10s15m20M"', 'Fl(3)WR.10s15m20M', ['Fl', [3], 'WR', 10.0, 15, 20])]]
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
light characteristic abbreviation "Fl.2.5s"['Fl', [1], 'W', 2.5, None, None]['Fl', [1], 'W', 2.5, None, None]Passed
light characteristic abbreviation "Fl(3)WR.10s15m20M"['Fl', [3], 'WR', 10.0, 15, 20]['Fl', [3], 'WR', 10.0, 15, 20]Passed
light characteristic abbreviation "LFl.10s"['LFl', [1], 'W', 10.0, None, None]['LFl', [1], 'W', 10.0, None, None]Passed
light characteristic abbreviation "Q"['Q', [1], 'W', None, None, None]['Q', [1], 'W', None, None, None]Passed
light characteristic abbreviation "VQ(6)10s"['VQ', [6], 'W', 10.0, None, None]['VQ', [6], 'W', 10.0, None, None]Passed
light characteristic abbreviation "Iso.WRG.4s"['Iso', [1], 'WRG', 4.0, None, None]['Iso', [1], 'WRG', 4.0, None, None]Passed
light characteristic abbreviation "Oc(2)R.8s12m9M"['Oc', [2], 'R', 8.0, 12, 9]['Oc', [2], 'R', 8.0, 12, 9]Passed

SHA-256 / de78e1ea8732f533b62c87f2bead96ca96c98ec960f45ccdb64505e452d8dab6

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.770473+00:00.

Case digest / cca1f6534ab7b9e47f28a34b4df58733165c5205832bf3443f1badffddd3a0ea