feat(awards): offer the ambiguous references at log time

The refusal to guess was only visible in the award editor's test tab and
in the awards table — both of them places an operator goes long after the
contact is over. It has to appear while the station is still in front of
you, so ComputeQSOAwardRefs now reports the candidates it declined to
assign and the F3 panel lists them as buttons: click one and it is
written to award_refs, replacing any sibling picked for that award.

They are never auto-added — adding one would be exactly the guess the
setting exists to refuse.

Also: the dark-theme fix for the native calendar glyph named only
input[type=date], so date-time fields kept an invisible icon. All the
temporal input types now share the rule.
This commit is contained in:
2026-08-01 01:10:59 +02:00
parent a4623e9ea3
commit ae21ddb9d7
6 changed files with 75 additions and 14 deletions
+28
View File
@@ -4236,6 +4236,11 @@ type QSOAwardRef struct {
Ref string `json:"ref"`
Name string `json:"name,omitempty"`
Pickable bool `json:"pickable"`
// Ambiguous marks a reference the matcher found but did NOT assign, because
// the award allows one reference per QSO and several matched. Offered as a
// choice in the entry panel instead of being added silently — see
// award.Def.OneRefPerQSO.
Ambiguous bool `json:"ambiguous,omitempty"`
}
// enrichQSOForAwards fills in CQ/ITU zone, continent and DXCC entity from
@@ -4367,6 +4372,29 @@ func (a *App) ComputeQSOAwardRefs(q qso.QSO) ([]QSOAwardRef, error) {
out = append(out, QSOAwardRef{Code: r.Code, Ref: rf.Ref, Name: rf.Name, Pickable: pickable})
}
}
// A one-reference award that matched several candidates assigned none. Say so
// HERE, while the QSO is still on screen: an operator who only learns about it
// from the awards table months later has to go and find the contact again.
for _, d := range defs {
if !d.OneRefPerQSO {
continue
}
metas := a.awardRefMetas([]award.Def{d})[strings.ToUpper(d.Code)]
ex := award.Explain(d, metas, &q)
if len(ex.Ambiguous) == 0 {
continue
}
names := map[string]string{}
for _, m := range metas {
names[strings.ToUpper(m.Code)] = m.Name
}
for _, ref := range ex.Ambiguous {
out = append(out, QSOAwardRef{
Code: d.Code, Ref: ref, Name: names[strings.ToUpper(ref)],
Pickable: true, Ambiguous: true,
})
}
}
return out, nil
}