feat: upload to external services clublog qrz
This commit is contained in:
@@ -146,7 +146,11 @@ var dxccByName = map[string]int{
|
||||
"liechtenstein": 251,
|
||||
"austria": 206,
|
||||
"italy": 248,
|
||||
"sicily": 225,
|
||||
// Sicily (IT9) and African Italy (IG9/IH9) are cty.dat WAE splits, not
|
||||
// DXCC entities — they count as Italy (248). Sardinia (IS0) IS its own
|
||||
// DXCC entity (225) and keeps its number.
|
||||
"sicily": 248,
|
||||
"african italy": 248,
|
||||
"sardinia": 225,
|
||||
"spain": 281,
|
||||
"portugal": 272,
|
||||
@@ -318,3 +322,23 @@ func EntityDXCC(name string) int {
|
||||
}
|
||||
return dxccByName[strings.ToLower(strings.TrimSpace(name))]
|
||||
}
|
||||
|
||||
// ctyEntityAliases maps cty.dat's non-DXCC pseudo-entities — the CQ-zone /
|
||||
// WAE splits AD1C lists separately — onto the ARRL DXCC entity they belong
|
||||
// to. cty.dat reports e.g. "Sicily" or "Sardinia" so contesters get the
|
||||
// right zones, but for DXCC (and the COUNTRY field) they are Italy. Add an
|
||||
// entry here for any other split that should report its parent entity.
|
||||
var ctyEntityAliases = map[string]string{
|
||||
"sicily": "Italy",
|
||||
"african italy": "Italy",
|
||||
// NB: Sardinia is intentionally absent — it's a real DXCC entity.
|
||||
}
|
||||
|
||||
// CanonicalEntityName normalises a cty.dat entity name to its ARRL DXCC
|
||||
// entity. Names that already are DXCC entities pass through unchanged.
|
||||
func CanonicalEntityName(name string) string {
|
||||
if c, ok := ctyEntityAliases[strings.ToLower(strings.TrimSpace(name))]; ok {
|
||||
return c
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
+14
-2
@@ -181,10 +181,22 @@ func parseEntityHeader(line string) *Entity {
|
||||
if len(parts) < 8 {
|
||||
return nil
|
||||
}
|
||||
name := strings.TrimSpace(parts[0])
|
||||
primary := strings.TrimSpace(parts[7])
|
||||
// cty.dat marks non-DXCC entities (WAE / contest-only zone splits such
|
||||
// as Sicily *IT9 and African Italy *IG9) with a leading '*' on the
|
||||
// primary prefix. Those report under their parent DXCC entity. True
|
||||
// DXCC entities — including Sardinia (IS0) and Corsica (TK) — have no
|
||||
// '*' and keep their own name. Per-prefix zones/lat-lon are preserved,
|
||||
// so e.g. IG9 still resolves to CQ 33 / continent AF under "Italy".
|
||||
if strings.HasPrefix(primary, "*") {
|
||||
primary = strings.TrimPrefix(primary, "*")
|
||||
name = CanonicalEntityName(name)
|
||||
}
|
||||
e := &Entity{
|
||||
Name: strings.TrimSpace(parts[0]),
|
||||
Name: name,
|
||||
Continent: strings.TrimSpace(parts[3]),
|
||||
Primary: strings.TrimSpace(parts[7]),
|
||||
Primary: primary,
|
||||
}
|
||||
e.CQZone, _ = strconv.Atoi(strings.TrimSpace(parts[1]))
|
||||
e.ITUZone, _ = strconv.Atoi(strings.TrimSpace(parts[2]))
|
||||
|
||||
@@ -54,6 +54,54 @@ func TestLookup(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// cty.dat marks non-DXCC entities (Sicily *IT9, African Italy *IG9) with a
|
||||
// leading '*'; the parser must fold those into their parent DXCC entity
|
||||
// "Italy" while leaving real DXCC entities — Sardinia (IS0), no '*' — alone.
|
||||
func TestCanonicalEntityNames(t *testing.T) {
|
||||
const cty = `Italy: 15: 28: EU: 42.82: -12.58: -1.0: I:
|
||||
I,IK,IZ;
|
||||
African Italy: 33: 37: AF: 35.67: -12.67: -1.0: *IG9:
|
||||
IG9,IH9;
|
||||
Sardinia: 15: 28: EU: 40.15: -9.27: -1.0: IS0:
|
||||
IM0,IS,IW0U,IW0V;
|
||||
Sicily: 15: 28: EU: 37.50: -14.00: -1.0: *IT9:
|
||||
IT9,IW9;
|
||||
`
|
||||
db, err := Load(strings.NewReader(cty))
|
||||
if err != nil {
|
||||
t.Fatalf("load: %v", err)
|
||||
}
|
||||
cases := map[string]string{
|
||||
"IW9EZO": "Italy", // Sicily (*IT9) → Italy
|
||||
"IT9CLY": "Italy",
|
||||
"IG9A": "Italy", // African Italy (*IG9) → Italy
|
||||
"IK0ABC": "Italy",
|
||||
"IS0XYZ": "Sardinia", // real DXCC entity — must stay Sardinia
|
||||
"IM0ABC": "Sardinia",
|
||||
}
|
||||
for call, want := range cases {
|
||||
m, ok := db.Lookup(call)
|
||||
if !ok {
|
||||
t.Errorf("%s: no match", call)
|
||||
continue
|
||||
}
|
||||
if m.Entity.Name != want {
|
||||
t.Errorf("%s: country = %q, want %q", call, m.Entity.Name, want)
|
||||
}
|
||||
}
|
||||
// African Italy keeps its own zones/continent even though it reports
|
||||
// Italy as the entity.
|
||||
if m, _ := db.Lookup("IG9A"); m.CQZone != 33 || m.Continent != "AF" {
|
||||
t.Errorf("IG9A: got CQ=%d cont=%s, want 33/AF", m.CQZone, m.Continent)
|
||||
}
|
||||
if EntityDXCC("Sicily") != 248 {
|
||||
t.Errorf("EntityDXCC(Sicily) = %d, want 248 (Italy)", EntityDXCC("Sicily"))
|
||||
}
|
||||
if EntityDXCC("Sardinia") != 225 {
|
||||
t.Errorf("EntityDXCC(Sardinia) = %d, want 225", EntityDXCC("Sardinia"))
|
||||
}
|
||||
}
|
||||
|
||||
func TestNormalize(t *testing.T) {
|
||||
cases := map[string]string{
|
||||
"F4BPO": "F4BPO",
|
||||
|
||||
Reference in New Issue
Block a user