Skip to content

Commit

Permalink
Validate and infer continent from DXCC/country
Browse files Browse the repository at this point in the history
  • Loading branch information
flwyd committed Jan 26, 2025
1 parent b165cfb commit 57609cc
Show file tree
Hide file tree
Showing 6 changed files with 608 additions and 0 deletions.
461 changes: 461 additions & 0 deletions adif/spec/continents.go

Large diffs are not rendered by default.

51 changes: 51 additions & 0 deletions adif/spec/continents_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package spec

import "testing"

func TestAllCountriesContinent(t *testing.T) {
var active, inactive []CountryEnum
for _, e := range CountryEnumeration.Values {
c := e.(CountryEnum)
if c == CountryNone {
continue
}
if c.Deleted == "true" {
inactive = append(inactive, c)
} else {
active = append(active, c)
}
}
tests := []struct {
name string
countries []CountryEnum
}{
{name: "Active", countries: active},
{name: "Inactive", countries: inactive},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
for _, c := range tc.countries {
if ContinentFor(c.EntityName) == (ContinentEnum{}) {
t.Errorf("ContinentFor(%q) is missing", c.EntityName)
}
if ContinentFor(c.EntityCode) == (ContinentEnum{}) {
t.Errorf("ContinentFor(%q) is missing", c.EntityCode)
}
}
})
}
}
12 changes: 12 additions & 0 deletions adif/spec/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,18 @@ func ValidateEnumeration(val string, f Field, ctx ValidationContext) Validation
}
return fn("%s unknown value %q for enumeration %s", f.Name, val, e.Name)
}
if f.Name == ContField.Name {
if d := ctx.FieldValue(DxccField.Name); d != "" {
if c := ContinentFor(d); !strings.EqualFold(val, c.Abbreviation) {
return warningf("continent %s does not match DXCC %s continent %s", val, d, c.Abbreviation)
}
}
if d := ctx.FieldValue(CountryField.Name); d != "" {
if c := ContinentFor(d); !strings.EqualFold(val, c.Abbreviation) {
return warningf("continent %s does not match country %s continent %s", val, d, c.Abbreviation)
}
}
}
return valid()
}

Expand Down
27 changes: 27 additions & 0 deletions adif/spec/validate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -903,3 +903,30 @@ func TestValidateCQZone(t *testing.T) {
testValidator(t, tc.validateTest, ctx, "TestValidateCQZone")
}
}

func TestValidateContinent(t *testing.T) {
tests := []struct {
validateTest
dxcc, country string
}{
{validateTest: validateTest{field: ContField, value: "SA", want: Valid}, dxcc: CountryTrinidadTobago.EntityCode, country: ""},
{validateTest: validateTest{field: ContField, value: "OC", want: Valid}, dxcc: "", country: CountryEastMalaysia.EntityName},
{validateTest: validateTest{field: ContField, value: "AS", want: Valid}, dxcc: "", country: CountryWestMalaysia.EntityName},
{validateTest: validateTest{field: ContField, value: "EU", want: InvalidWarning}, dxcc: CountryCanaryIslands.EntityCode, country: ""},
{validateTest: validateTest{field: ContField, value: "EU", want: Valid}, dxcc: "", country: "Iceland"},
{validateTest: validateTest{field: ContField, value: "AS", want: InvalidWarning}, dxcc: CountryBolivia.EntityCode, country: ""},
}
for _, tc := range tests {
ctx := ValidationContext{FieldValue: func(name string) string {
switch name {
case DxccField.Name:
return tc.dxcc
case CountryField.Name:
return tc.country
default:
return ""
}
}}
testValidator(t, tc.validateTest, ctx, "TestValidateCountry")
}
}
26 changes: 26 additions & 0 deletions cmd/infer.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ var inferrers = map[string]inferrer{
spec.MyDxccField.Name: inferDXCC,
spec.CqzField.Name: inferCQZone,
spec.MyCqZoneField.Name: inferCQZone,
spec.ContField.Name: inferContinent,
spec.GridsquareField.Name: inferGridsquare,
spec.GridsquareExtField.Name: inferGridsquare,
spec.MyGridsquareField.Name: inferGridsquare,
Expand Down Expand Up @@ -84,8 +85,12 @@ func helpInfer() string {
fmt.Fprintf(res, fromfmt, spec.MyCountryField.Name, spec.MyDxccField.Name)
fmt.Fprintf(res, fromfmt, spec.DxccField.Name, spec.CountryField.Name)
fmt.Fprintf(res, fromfmt, spec.MyDxccField.Name, spec.MyCountryField.Name)
fmt.Fprintf(res, fromfmt, spec.CqzField.Name, spec.CountryField.Name)
fmt.Fprintf(res, fromfmt, spec.CqzField.Name, spec.DxccField.Name)
fmt.Fprintf(res, fromfmt, spec.MyCqZoneField.Name, spec.MyCountryField.Name)
fmt.Fprintf(res, fromfmt, spec.MyCqZoneField.Name, spec.MyDxccField.Name)
fmt.Fprintf(res, fromfmt, spec.ContField.Name, spec.MyCountryField.Name)
fmt.Fprintf(res, fromfmt, spec.ContField.Name, spec.MyDxccField.Name)
fmt.Fprintf(res, fromfmt, spec.CntyField.Name, spec.UsacaCountiesField.Name)
fmt.Fprintf(res, fromfmt, spec.MyCntyField.Name, spec.MyUsacaCountiesField.Name)
fmt.Fprintf(res, fromfmt, spec.UsacaCountiesField.Name, spec.CntyField.Name)
Expand Down Expand Up @@ -433,6 +438,27 @@ func inferCQZone(r *adif.Record, name string) bool {
return false
}

func inferContinent(r *adif.Record, name string) bool {
if f, ok := r.Get(name); ok && f.Value != "" {
return false
}
my := myPrefix(name)
var c string
if dx, ok := r.Get(my(spec.DxccField.Name)); ok && dx.Value != "" {
c = dx.Value
} else if cc, ok := r.Get(my(spec.CountryField.Name)); ok && cc.Value != "" {
c = cc.Value
} else {
return false
}
cont := spec.ContinentFor(c)
if cont == (spec.ContinentEnum{}) {
return false
}
r.Set(adif.Field{Name: name, Value: cont.Abbreviation})
return false
}

func inferLatLon(r *adif.Record, name string) bool {
my := myPrefix(name)
f, ok := r.Get(my(spec.GridsquareField.Name))
Expand Down
31 changes: 31 additions & 0 deletions cmd/infer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,37 @@ func TestInfer(t *testing.T) {
want: []adif.Field{{Name: "DXCC", Value: spec.CountryCanada.EntityCode}, {Name: "STATE", Value: "NL"}, {Name: "MY_DXCC", Value: "230"}, {Name: "STATE", Value: "BY"}},
},

{
name: "continent Panama",
infer: FieldList{"CONT"},
start: []adif.Field{{Name: "DXCC", Value: spec.CountryPanama.EntityCode}},
want: []adif.Field{{Name: "DXCC", Value: spec.CountryPanama.EntityCode}, {Name: "CONT", Value: "NA"}},
},
{
name: "continent South Sandwich",
infer: FieldList{"CONT"},
start: []adif.Field{{Name: "COUNTRY", Value: spec.CountrySouthSandwichIslands.EntityName}},
want: []adif.Field{{Name: "COUNTRY", Value: spec.CountrySouthSandwichIslands.EntityName}, {Name: "CONT", Value: "AN"}},
},
{
name: "continent Turkey",
infer: FieldList{"CONT"},
start: []adif.Field{{Name: "COUNTRY", Value: "Turkey"}},
want: []adif.Field{{Name: "COUNTRY", Value: "Turkey"}, {Name: "CONT", Value: "AS"}},
},
{
name: "continent unknown country",
infer: FieldList{"CONT"},
start: []adif.Field{{Name: "COUNTRY", Value: "Freedonia"}},
want: []adif.Field{{Name: "COUNTRY", Value: "Freedonia"}},
},
{
name: "continent unknown DXCC",
infer: FieldList{"CONT"},
start: []adif.Field{{Name: "DXCC", Value: "999"}},
want: []adif.Field{{Name: "DXCC", Value: "999"}},
},

{
name: "mode MFSK",
infer: FieldList{"MODE"},
Expand Down

0 comments on commit 57609cc

Please sign in to comment.