Reported by VK4DX with the case that names itself: YB confirmed on 20m digital, painted blue, because one unconfirmed YB station had also been worked on that slot. The ladder ran call_c > call_w > dxcc_c > dxcc_w, so a callsign worked and not confirmed beat an entity CONFIRMED on the same band and mode. The grid answers 'what do I still need here', and a confirmed entity needs nothing whoever was worked afterwards — so the order is now call_c > dxcc_c > call_w > dxcc_w. Two things made it easy to get wrong, and both are fixed rather than merely corrected. The code was a run of assignments where the later test silently overwrote the earlier, so 'call worked' erased 'entity confirmed'; it now takes the maximum. And the rule lived inside a scan loop where nothing could reach it, so it is lifted into bandStatusCode with a table test — including this exact case, and one that fails if anybody reorders the constants.
59 lines
2.3 KiB
Go
59 lines
2.3 KiB
Go
package qso
|
|
|
|
import "testing"
|
|
|
|
// The colour of a matrix cell is a claim about what the operator still needs,
|
|
// and it was wrong for several releases: a callsign worked and not confirmed
|
|
// outranked an entity CONFIRMED on the same band and mode, so a slot that was
|
|
// finished showed as unfinished.
|
|
//
|
|
// Reported by VK4DX with the case that names itself: YB confirmed on 20m
|
|
// digital, shown blue, because one unconfirmed YB station had also been worked
|
|
// there.
|
|
func TestBandStatusConfirmedOutranksWorked(t *testing.T) {
|
|
cases := []struct {
|
|
name string
|
|
callWorked, callConfirmed, entityConfirm bool
|
|
want string
|
|
}{
|
|
{"entity worked only", false, false, false, "dxcc_w"},
|
|
{"this call worked, nothing confirmed", true, false, false, "call_w"},
|
|
// The regression, in one line.
|
|
{"entity confirmed, this call worked but not confirmed", true, false, true, "dxcc_c"},
|
|
{"entity confirmed, this call not worked here", false, false, true, "dxcc_c"},
|
|
{"this call confirmed", true, true, true, "call_c"},
|
|
// A confirmed contact with this call implies it was worked, but the flags
|
|
// arrive from separate SQL aggregates and nothing guarantees the pair.
|
|
{"call confirmed without the worked flag", false, true, true, "call_c"},
|
|
}
|
|
for _, c := range cases {
|
|
t.Run(c.name, func(t *testing.T) {
|
|
got := bandStatusNames[bandStatusCode(c.callWorked, c.callConfirmed, c.entityConfirm)]
|
|
if got != c.want {
|
|
t.Errorf("bandStatusCode(worked=%v, callConf=%v, entityConf=%v) = %s, want %s",
|
|
c.callWorked, c.callConfirmed, c.entityConfirm, got, c.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// The ladder itself, stated once: every confirmed code must beat every worked
|
|
// code. A future edit that reorders the constants fails here rather than in a
|
|
// screenshot from an operator.
|
|
func TestBandStatusLadderPutsConfirmedAbove(t *testing.T) {
|
|
for _, worked := range []int{stDxccW, stCallW} {
|
|
for _, confirmed := range []int{stDxccC, stCallC} {
|
|
if confirmed <= worked {
|
|
t.Errorf("%s (%d) does not outrank %s (%d)",
|
|
bandStatusNames[confirmed], confirmed, bandStatusNames[worked], worked)
|
|
}
|
|
}
|
|
}
|
|
if stCallC <= stDxccC {
|
|
t.Error("call_c must outrank dxcc_c: the callsign is the more specific claim")
|
|
}
|
|
if stCallW <= stDxccW {
|
|
t.Error("call_w must outrank dxcc_w for the same reason")
|
|
}
|
|
}
|