feat(chase-new): drop the frequency column, the beacons and the bands you don't have
Three cuts, all of them removing things nobody could act on. The frequency column is gone. Clicking the row tunes the rig to it, so the number was there to be read and never used. It is still carried on the spot — the click is what needs it — and it is in the row's tooltip. The country takes the space. Modes are limited to FT8, FT4, FT2, PSK31 and RTTY. WSPR is the one worth spelling out: it is a beacon, nobody answers a WSPR transmission, so a "new entity on WSPR" is a path report and not a station to work — and on a quiet band it would have been most of the list. Bands are limited to the operator's own list. PSK Reporter carries every band its receivers listen on, and a 13 cm decode is not an opportunity for a station with no 13 cm. Both tests run before the status lookup and both read a cached map: they throw away most of the feed, so nothing downstream pays for it. The band list is re-read when the lists are saved, so ticking a band in Settings applies to the next decode rather than the next restart — which would have looked like the filter not working.
This commit is contained in:
+61
@@ -129,14 +129,69 @@ func (s *chaseNewStore) clear() {
|
||||
s.seen = make(map[string]time.Time, 512)
|
||||
}
|
||||
|
||||
// chaseModes is what the panel will show. PSK Reporter reports everything its
|
||||
// receivers decode, and most of it is not a contact waiting to happen:
|
||||
//
|
||||
// - WSPR is a beacon. Nobody answers a WSPR transmission, so a "new entity on
|
||||
// WSPR" is a path report, not a station to work — and on a quiet band it
|
||||
// would be most of the list.
|
||||
// - JT65, JT9, FST4W, Q65 and the rest are real but rare enough that they
|
||||
// would only dilute what an operator scans.
|
||||
//
|
||||
// The list is the modes an operator actually calls on. Deliberately not a
|
||||
// setting: a widget with its own mode list is a second place to get the answer
|
||||
// wrong, and this one is short enough to read.
|
||||
var chaseModes = map[string]bool{
|
||||
"FT8": true, "FT4": true, "FT2": true, "PSK31": true, "RTTY": true,
|
||||
}
|
||||
|
||||
// chaseNewEnabled reads the option. Called per message, so it reads the cached
|
||||
// atomic rather than the settings store.
|
||||
func (a *App) chaseNewEnabled() bool { return a.chaseNewOn.Load() }
|
||||
|
||||
// chaseBandAllowed reports whether a band is one the operator uses.
|
||||
//
|
||||
// PSK Reporter carries every band its receivers listen on, including microwave
|
||||
// segments nobody in the region is equipped for. A 13 cm decode is not an
|
||||
// opportunity for a station with no 13 cm — it is a row in the way.
|
||||
//
|
||||
// The answer is the operator's own band list (Settings → Modes & bands), read
|
||||
// once and cached: this is consulted per message, and re-reading a JSON setting
|
||||
// at that rate on the MQTT goroutine is exactly what must not happen.
|
||||
func (a *App) chaseBandAllowed(band string) bool {
|
||||
a.chaseBandsMu.RLock()
|
||||
m := a.chaseBands
|
||||
a.chaseBandsMu.RUnlock()
|
||||
if m == nil {
|
||||
return true // list not loaded yet — better to show than to swallow
|
||||
}
|
||||
return m[strings.ToLower(strings.TrimSpace(band))]
|
||||
}
|
||||
|
||||
// refreshChaseBands re-reads the operator's band list into the cache. Called
|
||||
// when the widget is switched on and whenever the lists are saved.
|
||||
func (a *App) refreshChaseBands() {
|
||||
s, _ := a.GetListsSettings()
|
||||
m := make(map[string]bool, len(s.Bands))
|
||||
for _, b := range s.Bands {
|
||||
if b = strings.ToLower(strings.TrimSpace(b)); b != "" {
|
||||
m[b] = true
|
||||
}
|
||||
}
|
||||
a.chaseBandsMu.Lock()
|
||||
a.chaseBands = m
|
||||
a.chaseBandsMu.Unlock()
|
||||
}
|
||||
|
||||
// refreshChaseNew re-reads the option into the atomic the feed consults.
|
||||
func (a *App) refreshChaseNew() {
|
||||
on := a.settingOr(keyChaseNew, "") == "1"
|
||||
a.chaseNewOn.Store(on)
|
||||
if on {
|
||||
// Read the band list here rather than per message. Saving the lists calls
|
||||
// back into this, so a band ticked in Settings applies to the next decode.
|
||||
a.refreshChaseBands()
|
||||
}
|
||||
if !on && a.chaseNew != nil {
|
||||
// Drop the list rather than leave it on screen: it would go stale with no
|
||||
// feed behind it, and a frozen list of "new" stations is worse than none.
|
||||
@@ -159,6 +214,12 @@ func (a *App) feedChaseNew(sp pskr.Spot) {
|
||||
}
|
||||
band := strings.ToLower(strings.TrimSpace(sp.Band))
|
||||
mode := strings.ToUpper(strings.TrimSpace(sp.Mode))
|
||||
// Both tests before the status lookup: they are map reads on short keys and
|
||||
// they throw away most of the feed, so nothing further down pays for a band
|
||||
// this station cannot work or a mode nobody answers.
|
||||
if !chaseModes[mode] || !a.chaseBandAllowed(band) {
|
||||
return
|
||||
}
|
||||
|
||||
// The same verdict the cluster grid computes, from the same cached index:
|
||||
// map lookups per spot, no query.
|
||||
|
||||
Reference in New Issue
Block a user