feat(flex): send SmartSDR's spot priority; fix(chase): the same station on the same slot has nothing left to give

The panadapter has finite room: spots close in frequency are stacked
behind a '+' and only one is drawn, chosen by PRIORITY — a parameter
'spot add' accepts and OpsLog never sent. So a new entity sat invisible
behind three stations already in the log. DXHunter has sent it for
years; the tiers here are the same idea in the operator's own words:
the entity never worked (with my own callsign, for a multi-op), then
band/mode/slot, then the reference hunts, then everything else.

And a callsign already worked on this exact band and mode stops
advertising a need. Working it again cannot turn a missing QSL into a
confirmation — the QSO is already there — so shouting NEW DXCC over a
station worked an hour ago only teaches an operator to distrust the
colour. The need is real and stays on every OTHER station of the entity,
which is where it can be answered. Applied on both paths out of the
verdict, including the early one that leaves the loop first.
This commit is contained in:
2026-09-01 23:33:56 +02:00
parent 4d8cb58550
commit 4c4b3b6c2d
6 changed files with 111 additions and 3 deletions
+45 -1
View File
@@ -57,7 +57,9 @@ func TestClusterStatusFlagsUnconfirmedBand(t *testing.T) {
add("ZS6GAV", "15m", "FT8", "N") // 15m worked, never confirmed
add("ZS4AW", "15m", "FT8", "N")
got := a.ClusterSpotStatuses([]SpotQuery{{Call: "ZS4AW", Band: "15m", Mode: "FT8"}})
// A station of the entity that is NOT the one already worked on this slot:
// that case has a rule of its own, tested below.
got := a.ClusterSpotStatuses([]SpotQuery{{Call: "ZS9XX", Band: "15m", Mode: "FT8"}})
if len(got) != 1 {
t.Fatalf("got %d results", len(got))
}
@@ -68,3 +70,45 @@ func TestClusterStatusFlagsUnconfirmedBand(t *testing.T) {
t.Error("UnconfStatus is false — the badge draws solid, as if 15m had never been worked")
}
}
// The same station, already worked on the same band and mode, has nothing left
// to give: working it again cannot turn a missing QSL into a confirmation. The
// need belongs to the entity, not to that callsign, so the badge goes quiet on
// it — and stays on every other station of the entity.
func TestWorkedSameSlotDropsTheUnconfirmedBadge(t *testing.T) {
dir := t.TempDir()
conn, err := db.Open(filepath.Join(dir, "log.db"))
if err != nil {
t.Fatalf("open: %v", err)
}
t.Cleanup(func() { conn.Close() })
a := &App{ctx: context.Background(), qso: qso.NewRepo(conn), settings: settings.NewStore(conn)}
a.settingsScoped.Store(true)
_ = a.settings.Set(a.ctx, keyChaseMode, "new_unconfirmed")
_ = a.settings.Set(a.ctx, keyChaseConfirm, "lotw,card")
a.dxcc = dxcc.NewManager(filepath.Join("build", "bin", "data"))
if err := a.dxcc.LoadFromDisk(); err != nil {
t.Skipf("cty.dat not available here: %v", err)
}
hz := int64(10136000)
if _, err := a.qso.Add(a.ctx, qso.QSO{
Callsign: "TN8GD", Band: "30m", Mode: "FT8", FreqHz: &hz,
QSODate: time.Now().UTC().Add(-24 * time.Hour),
}); err != nil {
t.Fatalf("add: %v", err)
}
got := a.ClusterSpotStatuses([]SpotQuery{
{Call: "TN8GD", Band: "30m", Mode: "FT8"}, // the very station worked
{Call: "TN4XY", Band: "30m", Mode: "FT8"}, // another in the same entity
})
if got[0].Status == "new" || got[0].UnconfStatus {
t.Errorf("the worked station still advertises a need: status=%q unconf=%v",
got[0].Status, got[0].UnconfStatus)
}
if got[1].Status != "new" {
t.Errorf("another station in the entity lost its badge: status=%q", got[1].Status)
}
}