This commit is contained in:
2026-05-28 21:32:46 +02:00
parent e8cac569e3
commit e82e30dd02
29 changed files with 2485 additions and 97 deletions
+20 -19
View File
@@ -141,10 +141,18 @@ func (m *Manager) Lookup(ctx context.Context, callsign string) (Result, error) {
}
// fillFromDXCC fills (or overrides) country/continent/zones/lat/lon from
// the cty.dat resolver. Default behaviour is "fill empty fields only";
// for slashed callsigns (IT9/DK6XZ, DL/F4NIE…) we OVERRIDE because the
// provider returned the home-call's entity, which is wrong for portable
// operations. The provider keeps Name/QTH/Address (still useful for QSL).
// the cty.dat resolver. cty.dat is the authoritative source for DXCC
// mapping, so Country/Continent/CQZ/ITUZ are ALWAYS overridden when it
// has an answer — QRZ tends to return the political country (Greece for
// SV5*, Russia for UA9*) instead of the DXCC entity (Dodecanese,
// Asiatic Russia). Lat/Lon are filled only when empty so a more precise
// home QTH from QRZ wins over the cty.dat entity centroid.
//
// For slashed callsigns (IT9/DK6XZ, DL/F4NIE…) the provider returned the
// home-call's entity which is wrong for portable operations; we keep the
// Name/QTH/Address from the provider (still useful for QSL) but reset
// the DXCC number since QRZ's value is wrong and we don't have an entity
// → DXCC# table yet.
// Returns true if any field was filled.
func fillFromDXCC(r *Result, dxcc DXCCResolver) bool {
if dxcc == nil {
@@ -154,22 +162,15 @@ func fillFromDXCC(r *Result, dxcc DXCCResolver) bool {
if !ok {
return false
}
slashed := strings.ContainsRune(r.Callsign, '/')
shouldStr := func(existing string) bool { return existing == "" || slashed }
shouldInt := func(existing int) bool { return existing == 0 || slashed }
shouldF := func(existing float64) bool { return existing == 0 || slashed }
filled := false
if country != "" && shouldStr(r.Country) { r.Country = country; filled = true }
if cont != "" && shouldStr(r.Continent) { r.Continent = cont; filled = true }
if cqz != 0 && shouldInt(r.CQZ) { r.CQZ = cqz; filled = true }
if ituz != 0 && shouldInt(r.ITUZ) { r.ITUZ = ituz; filled = true }
if lat != 0 && shouldF(r.Lat) { r.Lat = lat; filled = true }
if lon != 0 && shouldF(r.Lon) { r.Lon = lon; filled = true }
// QRZ's DXCC number is the home call's — wrong for portable ops.
// cty.dat has no DXCC# (only Clublog does), so clear it: the UI
// will fall back to callsign-level worked-before until we ship a
// proper entity-name → DXCC# mapping.
if slashed && r.DXCC != 0 {
if country != "" { r.Country = country; filled = true }
if cont != "" { r.Continent = cont; filled = true }
if cqz != 0 { r.CQZ = cqz; filled = true }
if ituz != 0 { r.ITUZ = ituz; filled = true }
if lat != 0 && r.Lat == 0 { r.Lat = lat; filled = true }
if lon != 0 && r.Lon == 0 { r.Lon = lon; filled = true }
// Slashed call → drop QRZ's DXCC# (it's the home call's).
if strings.ContainsRune(r.Callsign, '/') && r.DXCC != 0 {
r.DXCC = 0
filled = true
}