Files
OpsLog/internal/award/override_test.go
T
rouggy 06e34372ed fix: a hand-assigned award reference no longer loses to the matcher
Reported on the DARC DOK award, with DL2FDM: a German address matches two or
three DOKs, the operator deletes the wrong ones and assigns the right one, and
the next recompute puts the wrong ones straight back.

The manual reference was APPENDED to what the matcher found. Storage already
kept exactly one manual entry per award — setOverrideRef drops the previous one
— so it was an override everywhere except at the one place it mattered. The
operator was arguing with the matcher and could not win.

It now replaces. The trace records what was superseded, so a corrected QSO can
still be explained rather than being merely different. A QSO with no correction
keeps every automatic reference, which the test also pins: an override must not
quietly disable matching for everyone else.

This does not address the over-matching itself — an address containing "Berlin
Mitte, 10115 Berlin" genuinely matches two DOK descriptions. That is the next
question, and a separate one.
2026-08-01 00:57:34 +02:00

57 lines
1.8 KiB
Go

package award
import (
"strings"
"testing"
"hamlog/internal/qso"
)
// An operator's correction must survive a recompute.
//
// Reported on the DARC DOK award: a German address matches two or three DOKs,
// the operator deletes the wrong ones and assigns the right one, and the next
// recompute puts the wrong ones straight back. The manual reference was being
// ADDED to what the matcher found instead of replacing it, so the correction
// could never win.
func TestManualReferenceReplacesTheMatch(t *testing.T) {
// An award that reads the address and matches a reference's description —
// the shape the DOK award uses, and the shape that over-matches.
def := Def{
Code: "DLD", Name: "DARC DOK", Field: "address",
MatchBy: "description", Type: "QSOFIELDS", Valid: true,
}
metas := []RefMeta{
{Code: "A01", Name: "Berlin", Valid: true},
{Code: "B05", Name: "Berlin Mitte", Valid: true},
}
// An address that legitimately matches both.
q := &qso.QSO{
Callsign: "DL2FDM",
Address: "Berlin Mitte, 10115 Berlin",
}
auto := Explain(def, metas, q)
if len(auto.Result) < 2 {
t.Fatalf("the test needs an over-matching case; got %v", auto.Result)
}
// The operator picks the right one.
q.Extras = map[string]string{ManualRefsKey: "DLD@B05"}
fixed := Explain(def, metas, q)
if got := strings.Join(fixed.Result, ","); got != "B05" {
t.Errorf("after the correction the QSO counts for %q — want B05 alone", got)
}
if len(fixed.Superseded) == 0 {
t.Error("the trace does not say what the correction replaced")
}
// A QSO with no correction still gets everything the matcher found: the
// override must not disable matching for everyone else.
q2 := &qso.QSO{Callsign: "DL3XYZ", Address: "Berlin Mitte, 10115 Berlin"}
if len(Explain(def, metas, q2).Result) < 2 {
t.Error("an untouched QSO lost its automatic references")
}
}