Every station on an already-worked band was flagged NEW MODE. A WSJT-X Decode does not carry the mode's name. It carries the one-character marker from the decode line - "~" for FT8, "+" for FT4 - and that character was passed straight through as though it were a mode. The status resolver then compared "~" against the modes worked for the entity, matched nothing, and concluded the mode had never been worked. Same cause put "~ -07" in the comment of every decode spot pushed to the FlexRadio panadapter, which nobody had traced back. Resolved through a marker table, with the mode from the sender's last Status as the fallback - Status is the message that carries the real name. So an unlisted or future marker degrades to correct rather than to nonsense, and a sender that puts the name in the field directly is believed as-is. With neither available the mode is left empty, which makes the resolver answer "worked": the safe side, since a wrong mode invents a new-mode flag exactly as the marker did.
60 lines
2.1 KiB
Go
60 lines
2.1 KiB
Go
package udp
|
|
|
|
import "testing"
|
|
|
|
// A Decode does not carry the mode's NAME. It carries the one-character marker
|
|
// from the decode line — "~" for FT8, "+" for FT4 — and that character used to
|
|
// be passed on as if it were a mode. Everything downstream compared it against
|
|
// the modes in the log, matched nothing, and reported every station on an
|
|
// already-worked band as a NEW MODE.
|
|
func TestDecodeModeNameResolvesTheMarker(t *testing.T) {
|
|
for raw, want := range map[string]string{
|
|
"~": "FT8",
|
|
"+": "FT4",
|
|
"#": "JT65",
|
|
"@": "JT9",
|
|
} {
|
|
if got := DecodeModeName(raw, "FT8"); got != want {
|
|
t.Errorf("DecodeModeName(%q) = %q, want %q", raw, got, want)
|
|
}
|
|
}
|
|
}
|
|
|
|
// A sender that puts the real name in the field is believed as-is — several do,
|
|
// and the marker table must not get in their way.
|
|
func TestDecodeModeNameKeepsARealName(t *testing.T) {
|
|
for _, raw := range []string{"FT8", "ft4", "JS8", "Q65"} {
|
|
if got := DecodeModeName(raw, ""); got == "" || got != upper(raw) {
|
|
t.Errorf("DecodeModeName(%q) = %q, want the name itself", raw, got)
|
|
}
|
|
}
|
|
}
|
|
|
|
// The safety net: an unknown marker falls back to the mode from the sender's
|
|
// last Status, which always carries the real name. This is what keeps a future
|
|
// or unlisted marker degrading to correct rather than to nonsense.
|
|
func TestDecodeModeNameFallsBackToStatus(t *testing.T) {
|
|
if got := DecodeModeName("%", "FT4"); got != "FT4" {
|
|
t.Errorf("unknown marker resolved to %q, want the Status mode FT4", got)
|
|
}
|
|
if got := DecodeModeName("", "FT8"); got != "FT8" {
|
|
t.Errorf("empty mode resolved to %q, want the Status mode FT8", got)
|
|
}
|
|
// Nothing known at all is empty rather than a guess: an empty mode makes the
|
|
// status resolver answer "worked", which is the safe side — a wrong mode
|
|
// would invent a new-mode flag exactly as the marker did.
|
|
if got := DecodeModeName("%", ""); got != "" {
|
|
t.Errorf("with no Status mode the result was %q, want empty", got)
|
|
}
|
|
}
|
|
|
|
func upper(s string) string {
|
|
out := []rune(s)
|
|
for i, r := range out {
|
|
if r >= 'a' && r <= 'z' {
|
|
out[i] = r - 32
|
|
}
|
|
}
|
|
return string(out)
|
|
}
|