fix(adif): a logged QSO carries its receive side
The importer has always read an absent BAND_RX/FREQ_RX as 'not split, so RX = TX'. The logging paths never did, so what a contact carried depended on which door it came in through — and it shows outside OpsLog: the record forwarded over UDP is written from the QSO as logged, so a receiver that reads BAND_RX (Log4OM does) found nothing there. Filled at AddQSO, the one funnel every path goes through, so the database, the export and the forwarded copy agree. A genuine split contact keeps what it was given — table-tested both ways.
This commit is contained in:
@@ -2948,6 +2948,28 @@ func (a *App) reloadLookupProviders() {
|
||||
|
||||
// --- QSO bindings ---
|
||||
|
||||
// fillRXDefaults stamps the receive side when the contact was not split.
|
||||
//
|
||||
// The ADIF importer has always done this — an absent BAND_RX/FREQ_RX means RX
|
||||
// equals TX — but the LOGGING paths did not, so what a QSO carried depended on
|
||||
// which door it came through. It shows up outside OpsLog: the record forwarded
|
||||
// to another logger over UDP is written from the QSO as logged, and a receiver
|
||||
// reading BAND_RX (Log4OM does) found nothing there for contacts logged by a
|
||||
// path that left it blank.
|
||||
//
|
||||
// Applied at AddQSO, the one funnel every path goes through — manual entry, the
|
||||
// WSJT-X/UDP log, CW, contest, net control, the ADIF monitor — so the database,
|
||||
// the export and the forwarded copy all say the same thing.
|
||||
func fillRXDefaults(q *qso.QSO) {
|
||||
if strings.TrimSpace(q.BandRX) == "" {
|
||||
q.BandRX = q.Band
|
||||
}
|
||||
if q.FreqRXHz == nil && q.FreqHz != nil {
|
||||
v := *q.FreqHz
|
||||
q.FreqRXHz = &v
|
||||
}
|
||||
}
|
||||
|
||||
func (a *App) AddQSO(q qso.QSO) (id int64, err error) {
|
||||
if a.qso == nil {
|
||||
return 0, fmt.Errorf("db not initialized")
|
||||
@@ -2963,6 +2985,7 @@ func (a *App) AddQSO(q qso.QSO) (id int64, err error) {
|
||||
}
|
||||
}()
|
||||
a.applyStationDefaults(&q, true)
|
||||
fillRXDefaults(&q)
|
||||
fillDistance(&q)
|
||||
a.applyDXCCNumber(&q)
|
||||
a.applyULSCounty(&q) // fill blank US county/grid from the offline ULS store
|
||||
|
||||
+4
-2
@@ -4,11 +4,13 @@
|
||||
"date": "",
|
||||
"en": [
|
||||
"DX Cluster: a disconnected server keeps its pill, so it can be reconnected — disconnecting one used to make it vanish along with the only way back.",
|
||||
"HamQTH: an “Upload the whole log” button in the QSL Manager — one file instead of one request per QSO, so a first sync takes seconds rather than the better part of an hour. It REPLACES the log held on HamQTH (the site has no partial upload), so it asks first, is scoped to the callsign this profile uploads as, and compresses a large log to stay under the 20 MB limit."
|
||||
"HamQTH: an “Upload the whole log” button in the QSL Manager — one file instead of one request per QSO, so a first sync takes seconds rather than the better part of an hour. It REPLACES the log held on HamQTH (the site has no partial upload), so it asks first, is scoped to the callsign this profile uploads as, and compresses a large log to stay under the 20 MB limit.",
|
||||
"Outbound ADIF (forwarding a logged QSO to another logger such as Log4OM): the receive side is filled in when the contact was not split, so BAND_RX and FREQ_RX are present. The importer already did this; the logging paths did not, so what a QSO carried depended on which door it came in through."
|
||||
],
|
||||
"fr": [
|
||||
"DX Cluster : un serveur déconnecté garde sa pastille et peut donc être reconnecté — le déconnecter le faisait disparaître avec le seul moyen d’y revenir.",
|
||||
"HamQTH : un bouton « Envoyer tout le log » dans le QSL Manager — un seul fichier au lieu d’une requête par QSO, une première synchro passe de près d’une heure à quelques secondes. Il REMPLACE le log stocké sur HamQTH (le site n’a pas d’envoi partiel) : il demande donc confirmation, se limite à l’indicatif du profil et compresse un gros log pour rester sous la limite de 20 Mo."
|
||||
"HamQTH : un bouton « Envoyer tout le log » dans le QSL Manager — un seul fichier au lieu d’une requête par QSO, une première synchro passe de près d’une heure à quelques secondes. Il REMPLACE le log stocké sur HamQTH (le site n’a pas d’envoi partiel) : il demande donc confirmation, se limite à l’indicatif du profil et compresse un gros log pour rester sous la limite de 20 Mo.",
|
||||
"ADIF sortant (transfert d’un QSO vers un autre log, Log4OM par exemple) : le côté réception est renseigné quand le contact n’était pas en split, donc BAND_RX et FREQ_RX sont présents. L’import le faisait déjà, pas les chemins de log — ce qu’un QSO transportait dépendait donc de la porte par laquelle il était entré."
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"hamlog/internal/adif"
|
||||
"hamlog/internal/qso"
|
||||
)
|
||||
|
||||
// A contact that was not split still has a receive side, and the record
|
||||
// forwarded to another logger has to carry it: Log4OM reads BAND_RX.
|
||||
func TestFillRXDefaults(t *testing.T) {
|
||||
hz := int64(14074000)
|
||||
q := qso.QSO{Callsign: "F4BPO", Band: "20m", FreqHz: &hz}
|
||||
fillRXDefaults(&q)
|
||||
if q.BandRX != "20m" {
|
||||
t.Errorf("BandRX = %q, want 20m", q.BandRX)
|
||||
}
|
||||
if q.FreqRXHz == nil || *q.FreqRXHz != hz {
|
||||
t.Errorf("FreqRXHz = %v, want %d", q.FreqRXHz, hz)
|
||||
}
|
||||
rec := adif.SingleRecordADIF(q)
|
||||
if !strings.Contains(strings.ToUpper(rec), "<BAND_RX:3>20M") {
|
||||
t.Errorf("BAND_RX missing from the forwarded record:\n%s", rec)
|
||||
}
|
||||
}
|
||||
|
||||
// A genuine split contact keeps what it was given.
|
||||
func TestFillRXDefaultsKeepsSplit(t *testing.T) {
|
||||
tx, rx := int64(14195000), int64(14205000)
|
||||
q := qso.QSO{Callsign: "F4BPO", Band: "20m", BandRX: "17m", FreqHz: &tx, FreqRXHz: &rx}
|
||||
fillRXDefaults(&q)
|
||||
if q.BandRX != "17m" || q.FreqRXHz == nil || *q.FreqRXHz != rx {
|
||||
t.Errorf("split QSO was overwritten: band_rx=%q freq_rx=%v", q.BandRX, q.FreqRXHz)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user