Skip to content

Commit

Permalink
infer: (my_)usaca_counties from (my_)cnty and vice versa
Browse files Browse the repository at this point in the history
Only applies to USA contacts.
  • Loading branch information
flwyd committed Aug 12, 2024
1 parent de5f2b5 commit 11b997c
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 1 deletion.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,10 @@ Inferable fields:
* `MY_COUNTRY` from `MY_DXCC`
* `DXCC` from `COUNTRY`
* `MY_DXCC` from `MY_COUNTRY`
* `CNTY` from `USACA_COUNTIES` (unless multiple county-line counties)
* `MY_CNTY` from `MY_USACA_COUNTIES` (unless multiple county-line counties)
* `USACA_COUNTIES` from `CNTY` (if a USA DXCC entity)
* `MY_USACA_COUNTIES` from `MY_CNTY` (if a USA DXCC entity)
* `GRIDSQUARE` and `GRIDSQUARE_EXT` from `LAT`/`LON`
* `MY_GRIDSQUARE` and `MY_GRIDSQUARE_EXT` from `MY_LAT`/`MY_LON`
* `OPERATOR` from `GUEST_OP`
Expand Down
14 changes: 13 additions & 1 deletion adif/spec/country_codes.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@

package spec

import "strconv"
import (
"strconv"
"strings"
)

// ISO3166CountryCode associates ISO 3166-1 alpha-2, alpha-3, and numeric codes
// with DXCC entities. Most country codes are associated with a single DXCC
Expand All @@ -41,6 +44,15 @@ type ISO3166CountryCode struct {
Subdivisions map[string]CountryEnum // Subdivision codes associated with specific sub-national DXCC entities
}

func (c ISO3166CountryCode) IncludesDXCC(dxcc string) bool {
for _, d := range c.DXCC {
if d.EntityCode == dxcc || strings.EqualFold(d.EntityName, dxcc) {
return true
}
}
return false
}

var (
// ISO3166Alpha maps ISO 3166-1 alpha-2 and alpha-3 codes to countries.
ISO3166Alpha = make(map[string]ISO3166CountryCode)
Expand Down
41 changes: 41 additions & 0 deletions cmd/infer.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"errors"
"fmt"
"math"
"regexp"
"strconv"
"strings"

Expand Down Expand Up @@ -54,6 +55,10 @@ var inferrers = map[string]inferrer{
spec.OperatorField.Name: inferStation,
spec.StationCallsignField.Name: inferStation,
spec.OwnerCallsignField.Name: inferStation,
spec.UsacaCountiesField.Name: inferUSCounty,
spec.MyUsacaCountiesField.Name: inferUSCounty,
spec.CntyField.Name: inferUSCounty, // US is the only secondary subdivision
spec.MyCntyField.Name: inferUSCounty, // with a special field
spec.SigInfoField.Name: inferSigInfo,
spec.MySigInfoField.Name: inferSigInfo,
spec.IotaField.Name: inferProgramRef("IOTA"),
Expand All @@ -77,6 +82,10 @@ 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.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)
fmt.Fprintf(res, fromfmt, spec.MyUsacaCountiesField.Name, spec.MyCntyField.Name)

gsfmt := " %s and %s from %s/%s\n"
fmt.Fprintf(res, gsfmt, spec.GridsquareField.Name, spec.GridsquareExtField.Name, spec.LatField.Name, spec.LonField.Name)
Expand Down Expand Up @@ -347,6 +356,38 @@ func inferStation(r *adif.Record, name string) bool {
return false
}

var usCountyPattern = regexp.MustCompile(`^[A-Z]{2},[A-Za-z '.-]+$`) // doesn't match county-line lists

func inferUSCounty(r *adif.Record, name string) bool {
if f, ok := r.Get(name); ok && f.Value != "" {
return false
}
my := func(s string) string { return s }
if strings.HasPrefix(name, "MY_") {
my = func(s string) string { return "MY_" + s }
}
if dx, ok := r.Get(my(spec.DxccField.Name)); ok && dx.Value != "" {
if !spec.CountryCodeUSA.IncludesDXCC(dx.Value) {
return false // not a US contact
}
}
var src string
switch strings.ToUpper(name) {
case spec.UsacaCountiesField.Name, spec.MyUsacaCountiesField.Name:
src = my(spec.CntyField.Name)
case spec.CntyField.Name, spec.MyCntyField.Name:
src = my(spec.UsacaCountiesField.Name)
default:
return false
}
sub, ok := r.Get(src)
if !ok || sub.Value == "" || !usCountyPattern.MatchString(sub.Value) {
return false
}
r.Set(adif.Field{Name: name, Value: sub.Value})
return true
}

func inferLatLon(r *adif.Record, name string) bool {
my := func(s string) string { return s }
if strings.HasPrefix(name, "MY_") {
Expand Down
64 changes: 64 additions & 0 deletions cmd/infer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"testing"

"github.com/flwyd/adif-multitool/adif"
"github.com/flwyd/adif-multitool/adif/spec"
)

func TestInfer(t *testing.T) {
Expand Down Expand Up @@ -197,6 +198,69 @@ func TestInfer(t *testing.T) {
want: []adif.Field{{Name: "OPERATOR", Value: "W1AW"}, {Name: "OWNER_CALLSIGN", Value: "W1AW"}, {Name: "STATION_CALLSIGN", Value: "W1AW"}},
},

{
name: "usaca_counties from US cnty",
infer: FieldList{"USACA_COUNTIES", "MY_USACA_COUNTIES"},
start: []adif.Field{
{Name: "CNTY", Value: "MD,St. Mary's"}, {Name: "DXCC", Value: spec.CountryUnitedStatesOfAmerica.EntityCode},
{Name: "MY_CNTY", Value: "HI,Maui"}, {Name: "MY_DXCC", Value: spec.CountryHawaii.EntityCode}},
want: []adif.Field{
{Name: "USACA_COUNTIES", Value: "MD,St. Mary's"}, {Name: "CNTY", Value: "MD,St. Mary's"}, {Name: "DXCC", Value: spec.CountryUnitedStatesOfAmerica.EntityCode},
{Name: "MY_USACA_COUNTIES", Value: "HI,Maui"}, {Name: "MY_CNTY", Value: "HI,Maui"}, {Name: "MY_DXCC", Value: spec.CountryHawaii.EntityCode}},
},
{
name: "cnty from usaca_counties",
infer: FieldList{"CNTY", "MY_CNTY"},
start: []adif.Field{
{Name: "USACA_COUNTIES", Value: "AK,Prince of Wales-Outer Ketchikan"}, {Name: "DXCC", Value: spec.CountryAlaska.EntityCode},
{Name: "MY_USACA_COUNTIES", Value: "FL,Miami-Dade"}, {Name: "MY_DXCC", Value: spec.CountryUnitedStatesOfAmerica.EntityCode}},
want: []adif.Field{
{Name: "CNTY", Value: "AK,Prince of Wales-Outer Ketchikan"}, {Name: "USACA_COUNTIES", Value: "AK,Prince of Wales-Outer Ketchikan"}, {Name: "DXCC", Value: spec.CountryAlaska.EntityCode},
{Name: "MY_CNTY", Value: "FL,Miami-Dade"}, {Name: "MY_USACA_COUNTIES", Value: "FL,Miami-Dade"}, {Name: "MY_DXCC", Value: spec.CountryUnitedStatesOfAmerica.EntityCode}},
},
{
name: "multiple usaca_counties not copied to cnty",
infer: FieldList{"CNTY", "MY_CNTY"},
start: []adif.Field{
{Name: "USACA_COUNTIES", Value: "MA,Franklin:MA,Hampshire"}, {Name: "DXCC", Value: spec.CountryUnitedStatesOfAmerica.EntityCode},
{Name: "MY_USACA_COUNTIES", Value: "AK,Northwest Arctic:AK,Nome"}, {Name: "MY_DXCC", Value: spec.CountryAlaska.EntityCode}},
want: []adif.Field{
{Name: "USACA_COUNTIES", Value: "MA,Franklin:MA,Hampshire"}, {Name: "DXCC", Value: spec.CountryUnitedStatesOfAmerica.EntityCode},
{Name: "MY_USACA_COUNTIES", Value: "AK,Northwest Arctic:AK,Nome"}, {Name: "MY_DXCC", Value: spec.CountryAlaska.EntityCode}},
},
{
name: "JA subdivisions not copied to usaca_counties",
infer: FieldList{"USACA_COUNTIES", "MY_USACA_COUNTIES"},
start: []adif.Field{
{Name: "CNTY", Value: "01001"}, {Name: "DXCC", Value: spec.CountryJapan.EntityCode},
{Name: "MY_CNTY", Value: "100100"}, {Name: "MY_DXCC", Value: spec.CountryJapan.EntityCode}},
want: []adif.Field{
{Name: "CNTY", Value: "01001"}, {Name: "DXCC", Value: spec.CountryJapan.EntityCode},
{Name: "MY_CNTY", Value: "100100"}, {Name: "MY_DXCC", Value: spec.CountryJapan.EntityCode}},
},
{
name: "non-US subdivisions matching format not copied to usaca_counties",
infer: FieldList{"USACA_COUNTIES", "MY_USACA_COUNTIES"},
start: []adif.Field{
{Name: "CNTY", Value: "NL,Monterrey"}, {Name: "DXCC", Value: spec.CountryMexico.EntityCode},
{Name: "MY_CNTY", Value: "GD,Guangzhou"}, {Name: "MY_DXCC", Value: spec.CountryChina.EntityCode}},
want: []adif.Field{
{Name: "CNTY", Value: "NL,Monterrey"}, {Name: "DXCC", Value: spec.CountryMexico.EntityCode},
{Name: "MY_CNTY", Value: "GD,Guangzhou"}, {Name: "MY_DXCC", Value: spec.CountryChina.EntityCode}},
},
{
name: "usaca_counties does not overwrite",
infer: FieldList{"CNTY", "MY_CNTY", "USACA_COUNTIES", "MY_USACA_COUNTIES"},
start: []adif.Field{
{Name: "CNTY", Value: "AL,Autauga"}, {Name: "USACA_COUNTIES", Value: "AL,Winston"}, {Name: "DXCC", Value: spec.CountryUnitedStatesOfAmerica.EntityCode},
{Name: "MY_CNTY", Value: "WY,Albany"}, {Name: "MY_USACA_COUNTIES", Value: "WY,Weston"}, {Name: "MY_DXCC", Value: spec.CountryUnitedStatesOfAmerica.EntityCode},
},
want: []adif.Field{
{Name: "CNTY", Value: "AL,Autauga"}, {Name: "USACA_COUNTIES", Value: "AL,Winston"}, {Name: "DXCC", Value: spec.CountryUnitedStatesOfAmerica.EntityCode},
{Name: "MY_CNTY", Value: "WY,Albany"}, {Name: "MY_USACA_COUNTIES", Value: "WY,Weston"}, {Name: "MY_DXCC", Value: spec.CountryUnitedStatesOfAmerica.EntityCode},
},
},

{
name: "sig_info nothing when ambiguous",
infer: FieldList{"SIG_INFO", "MY_SIG_INFO"},
Expand Down

0 comments on commit 11b997c

Please sign in to comment.