up
This commit is contained in:
+54
-11
@@ -139,7 +139,15 @@ func (db *DB) Lookup(callsign string) (Match, bool) {
|
||||
if e, ok := db.exact[call]; ok {
|
||||
return materialize(e), true
|
||||
}
|
||||
// KG4 special case: Guantanamo Bay (DXCC 105) is "KG4" followed by EXACTLY
|
||||
// two characters (KG4XX). "KG4", "KG4X", "KG4XYZ"… are continental USA.
|
||||
// cty.dat carries a bare "KG4" prefix for Guantanamo, so for the other
|
||||
// suffix lengths we must skip it and fall through to the USA prefixes.
|
||||
skipKG4 := strings.HasPrefix(call, "KG4") && len(call) != len("KG4")+2
|
||||
for _, p := range db.byPrefix {
|
||||
if skipKG4 && p.prefix == "KG4" {
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(call, p.prefix) {
|
||||
return materialize(p), true
|
||||
}
|
||||
@@ -262,22 +270,33 @@ func stripAnnotation(s string, open, close rune, cb func(string)) string {
|
||||
}
|
||||
|
||||
// suffixModifiers are non-DXCC-relevant callsign suffixes we strip before
|
||||
// matching. /P /M /MM /AM /QRP /A and single-digit area changes (/5 …) all
|
||||
// keep the operator's home DXCC.
|
||||
// matching. /P /M /QRP /A and single-digit area changes (/5 …) all keep the
|
||||
// operator's home DXCC. NOTE: "MM" and "AM" are NOT here — a TRAILING /MM or
|
||||
// /AM (maritime/aeronautical mobile) means "no DXCC entity", while a LEADING
|
||||
// "MM" is the Scotland operating prefix; both are handled in normalizeCallsign.
|
||||
var suffixModifiers = map[string]bool{
|
||||
"P": true, "M": true, "MM": true, "AM": true, "QRP": true, "A": true,
|
||||
"P": true, "M": true, "QRP": true, "A": true,
|
||||
"PM": true, "LH": true,
|
||||
}
|
||||
|
||||
// normalizeCallsign uppercases, trims, and resolves the "active" call when
|
||||
// the operator uses slashes (DL/F4NIE → DL; F4NIE/P → F4NIE).
|
||||
// the operator uses slashes (DL/F4NIE → DL; F4NIE/P → F4NIE). Returns "" for
|
||||
// maritime/aeronautical mobile (.../MM, .../AM), which count for no DXCC.
|
||||
func normalizeCallsign(s string) string {
|
||||
s = strings.ToUpper(strings.TrimSpace(s))
|
||||
if !strings.ContainsRune(s, '/') {
|
||||
return s
|
||||
}
|
||||
parts := strings.Split(s, "/")
|
||||
// A trailing /MM or /AM is maritime/aeronautical mobile → no DXCC entity.
|
||||
// (A leading "MM" is the Scotland prefix and must NOT trigger this.)
|
||||
for i, p := range parts {
|
||||
if i > 0 && (p == "MM" || p == "AM") {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
keep := parts[:0]
|
||||
var areaDigit byte // a single-digit "/N" re-homes the call to call area N
|
||||
for _, p := range parts {
|
||||
if p == "" {
|
||||
continue
|
||||
@@ -285,21 +304,45 @@ func normalizeCallsign(s string) string {
|
||||
if suffixModifiers[p] {
|
||||
continue
|
||||
}
|
||||
if len(p) == 1 && p >= "0" && p <= "9" {
|
||||
if len(p) == 1 && p[0] >= '0' && p[0] <= '9' {
|
||||
areaDigit = p[0]
|
||||
continue
|
||||
}
|
||||
keep = append(keep, p)
|
||||
}
|
||||
var main string
|
||||
switch len(keep) {
|
||||
case 0:
|
||||
return s
|
||||
case 1:
|
||||
return keep[0]
|
||||
main = keep[0]
|
||||
default:
|
||||
// Two non-modifier parts → operating-from prefix wins (shorter one).
|
||||
// DL/F4NIE: DL is shorter → use DL (Germany). F4NIE/W6: W6 → W6.
|
||||
if len(keep[0]) <= len(keep[1]) {
|
||||
main = keep[0]
|
||||
} else {
|
||||
main = keep[1]
|
||||
}
|
||||
}
|
||||
// Two non-modifier parts → operating-from prefix wins (shorter one).
|
||||
// DL/F4NIE: DL is shorter → use DL (Germany). F4NIE/W6: W6 shorter → W6.
|
||||
if len(keep[0]) <= len(keep[1]) {
|
||||
return keep[0]
|
||||
// Apply the call-area digit: "/N" replaces the area digit of the base call,
|
||||
// which can change the DXCC entity (HD5MW/8 → HD8MW → Galápagos, not
|
||||
// Ecuador). This is the same class of rule as KG4 and /MM.
|
||||
if areaDigit != 0 {
|
||||
main = replaceFirstDigit(main, areaDigit)
|
||||
}
|
||||
return keep[1]
|
||||
return main
|
||||
}
|
||||
|
||||
// replaceFirstDigit substitutes the first 0-9 digit of a call with d (used to
|
||||
// apply a "/N" call-area change). Returns the call unchanged if it has no digit.
|
||||
func replaceFirstDigit(call string, d byte) string {
|
||||
b := []byte(call)
|
||||
for i := range b {
|
||||
if b[i] >= '0' && b[i] <= '9' {
|
||||
b[i] = d
|
||||
return string(b)
|
||||
}
|
||||
}
|
||||
return call
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user