package award import ( "testing" "hamlog/internal/qso" ) // ddfmLike is a small stand-in for the French departments award: predefined // references whose codes carry a letter the operator does not type. func ddfmLike() []Def { return []Def{{ Code: "DDFM", Name: "Departments", Type: TypeQSOFields, Field: "state", MatchBy: "code", Prefix: "D", }} } func ddfmRefs() map[string][]RefMeta { return map[string][]RefMeta{"DDFM": { {Code: "D29", Name: "Finistère", Valid: true}, {Code: "D49", Name: "Maine-et-Loire", Valid: true}, {Code: "D74", Name: "Haute-Savoie", Valid: true}, }} } func refsOf(t *testing.T, defs []Def, q qso.QSO) []string { t.Helper() res := Compute(defs, []qso.QSO{q}, ddfmRefs(), nil) if len(res) != 1 { t.Fatalf("want 1 result, got %d", len(res)) } var out []string for _, r := range res[0].Refs { if r.Worked { out = append(out, r.Ref) } } return out } // The reported case: the operator writes just "74" in STATE, the award's codes // are "D74", match-by is "code" and a Prefix of "D" is set. That found nothing — // the prefix was applied only AFTER the list lookup, i.e. after the step that // had already failed — so the only workaround was a regex, in a mode where the // operator had explicitly chosen "code" rather than "pattern". func TestPrefixCompletesABareReference(t *testing.T) { got := refsOf(t, ddfmLike(), qso.QSO{Callsign: "F5AYE", State: "74"}) if len(got) != 1 || got[0] != "D74" { t.Errorf("bare state 74 with prefix D → %v, want [D74]", got) } } // And a field that ALREADY holds the whole code must not be prefixed twice. // The blanket pass turned "D74" into "DD74" whenever a prefix was configured. func TestPrefixDoesNotDoubleUpOnACompleteCode(t *testing.T) { got := refsOf(t, ddfmLike(), qso.QSO{Callsign: "F5AYE", State: "D74"}) if len(got) != 1 || got[0] != "D74" { t.Errorf("state D74 with prefix D → %v, want [D74]", got) } } // A token that is neither a code nor a prefixable one stays unmatched: the // prefix must not invent references. func TestPrefixDoesNotInventReferences(t *testing.T) { if got := refsOf(t, ddfmLike(), qso.QSO{Callsign: "F5AYE", State: "99"}); len(got) != 0 { t.Errorf("unknown department 99 → %v, want none", got) } } // Without a prefix nothing changes: a bare number matches nothing, a full code // matches itself. func TestNoPrefixKeepsExactCodeMatching(t *testing.T) { defs := ddfmLike() defs[0].Prefix = "" if got := refsOf(t, defs, qso.QSO{Callsign: "F5AYE", State: "74"}); len(got) != 0 { t.Errorf("no prefix, state 74 → %v, want none", got) } if got := refsOf(t, defs, qso.QSO{Callsign: "F5AYE", State: "D74"}); len(got) != 1 || got[0] != "D74" { t.Errorf("no prefix, state D74 → %v, want [D74]", got) } }