fix(dxcc): /MM and /AM belong to no entity

RI1FJL/MM resolved to Franz Josef Land while the expedition was still sailing
there, telling the operator they had worked an entity they had not.

The old behaviour was deliberate — the comment read "strict DXCC says no
entity, but the log should still show the operator's country" — and that is
wrong for exactly this reason. A home country on a maritime mobile is not extra
information; it is a false claim about where the contact happened, and it is
the kind of false claim that gets a QSO submitted for an award it cannot win.

Trailing only. A LEADING "MM" is the Scotland prefix and "AM" is Spain, so
MM0ABC and AM5X keep their entities — getting that wrong would be a far larger
error than the one being fixed. /P, /M and /B are unaffected: a portable
station is still ashore.

In the cluster the column says "Maritime mobile — no DXCC" rather than going
blank, because blank is what an UNRESOLVED spot looks like and the two mean
opposite things — one is "we don't know yet", this is "there is nothing to
know". Display only: the QSO's own Country stays empty, since that field holds
a DXCC entity name and there is none.
This commit is contained in:
2026-08-13 12:25:33 +02:00
parent dc0b00b474
commit 4ba5569ca8
6 changed files with 443 additions and 361 deletions
+21 -21
View File
@@ -178,9 +178,9 @@ Sicily: 15: 28: EU: 37.50: -14.00: -1.0: *IT9:
t.Fatalf("load: %v", err)
}
cases := map[string]string{
"IW9EZO": "Italy", // Sicily (*IT9) → Italy
"IW9EZO": "Italy", // Sicily (*IT9) → Italy
"IT9CLY": "Italy",
"IG9A": "Italy", // African Italy (*IG9) → Italy
"IG9A": "Italy", // African Italy (*IG9) → Italy
"IK0ABC": "Italy",
"IS0XYZ": "Sardinia", // real DXCC entity — must stay Sardinia
"IM0ABC": "Sardinia",
@@ -210,25 +210,25 @@ Sicily: 15: 28: EU: 37.50: -14.00: -1.0: *IT9:
func TestNormalize(t *testing.T) {
cases := map[string]string{
"F4BPO": "F4BPO",
"f4bpo": "F4BPO",
" F4BPO ": "F4BPO",
"F4BPO/P": "F4BPO",
"F4BPO/MM": "F4BPO", // maritime mobile → strip, keep home entity for the log
"F4BPO/AM": "F4BPO", // aeronautical mobile → strip, keep home entity for the log
"F4BPO/M": "F4BPO", // plain mobile keeps the home entity
"F4BPO/5": "F5BPO", // "/5" re-homes to call area 5
"HD5MW/8": "HD8MW", // "/8" → Galápagos call area (HD8)
"7X2ARA/4": "7X4ARA", // "/4" changes the AREA digit (2→4), NOT the 7 of the 7X prefix (was wrongly 4X2ARA = Israel)
"3A2ABC/6": "3A6ABC", // digit-first prefix 3A: area digit is the 2, not the 3
"4X1AB/2": "4X2AB", // 4X (Israel) area 1→2, keep the leading 4
"DL/F4BPO": "DL",
"MM/KA9P": "MM", // leading MM = Scotland operating prefix
"MM/LY3X/P": "MM",
"F4BPO/W6": "W6",
"VK9/F4BPO": "VK9",
"4U1UN/B": "4U1UN", // trailing /B = beacon → strip, keep the base call
"B/F4BPO": "B", // leading B = China operating prefix, NOT a beacon
"F4BPO": "F4BPO",
"f4bpo": "F4BPO",
" F4BPO ": "F4BPO",
"F4BPO/P": "F4BPO",
"F4BPO/MM": "F4BPO", // maritime mobile → strip, keep home entity for the log
"F4BPO/AM": "F4BPO", // aeronautical mobile → strip, keep home entity for the log
"F4BPO/M": "F4BPO", // plain mobile keeps the home entity
"F4BPO/5": "F5BPO", // "/5" re-homes to call area 5
"HD5MW/8": "HD8MW", // "/8" → Galápagos call area (HD8)
"7X2ARA/4": "7X4ARA", // "/4" changes the AREA digit (2→4), NOT the 7 of the 7X prefix (was wrongly 4X2ARA = Israel)
"3A2ABC/6": "3A6ABC", // digit-first prefix 3A: area digit is the 2, not the 3
"4X1AB/2": "4X2AB", // 4X (Israel) area 1→2, keep the leading 4
"DL/F4BPO": "DL",
"MM/KA9P": "MM", // leading MM = Scotland operating prefix
"MM/LY3X/P": "MM",
"F4BPO/W6": "W6",
"VK9/F4BPO": "VK9",
"4U1UN/B": "4U1UN", // trailing /B = beacon → strip, keep the base call
"B/F4BPO": "B", // leading B = China operating prefix, NOT a beacon
}
for in, want := range cases {
if got := normalizeCallsign(in); got != want {