feat(watchlist): the auto-contest pattern — DXHunter's contest_prefix
A field in the tab's toolbar (e.g. WWA): while non-empty, any spotted callsign CONTAINING it joins the watchlist as a contest entry by itself — a special-event fleet (HB9WWA, DL0WWA, F4WWA/P…) is collected as it appears instead of typed in one by one, and each is judged per UTC day like any contest entry. Contains, not prefix, because the event string sits anywhere in those calls. Global setting, cached in an atomic so the spot pipeline never touches the settings store per spot. Emptying the field stops the collecting but keeps what was collected — DXHunter deletes non-matching contest entries on a pattern change, and a setting that silently empties an operator's list is the one behaviour of the original this port refuses. The tab also refreshes on backend auto-adds (event) and on a slow tick, so last-seen and the counters stay honest while it sits open.
This commit is contained in:
@@ -11,12 +11,35 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"hamlog/internal/applog"
|
||||
"hamlog/internal/qso"
|
||||
"hamlog/internal/watchlist"
|
||||
|
||||
wruntime "github.com/wailsapp/wails/v2/pkg/runtime"
|
||||
)
|
||||
|
||||
// The auto-contest pattern, DXHunter's contest_prefix: while non-empty, any
|
||||
// spotted callsign CONTAINING it is added to the watchlist as a contest entry
|
||||
// by itself — a special-event fleet (HB9WWA, DL0WWA, F4WWA…) is collected as
|
||||
// it appears instead of typed in one by one. Held in an atomic so the spot
|
||||
// pipeline never touches the settings store per spot.
|
||||
func (a *App) GetWatchlistContestPattern() string {
|
||||
if v := a.watchPattern.Load(); v != nil {
|
||||
return v.(string)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// SetWatchlistContestPattern stores the pattern (global, like the list itself).
|
||||
// Emptying it stops the auto-add; entries already collected stay — deleting an
|
||||
// operator's list because a setting changed is DXHunter behaviour this port
|
||||
// deliberately drops.
|
||||
func (a *App) SetWatchlistContestPattern(p string) {
|
||||
p = strings.ToUpper(strings.TrimSpace(p))
|
||||
a.watchPattern.Store(p)
|
||||
a.setSettingGlobal(keyWatchlistContestPattern, p)
|
||||
}
|
||||
|
||||
// WatchlistEntries returns the list for the tab.
|
||||
func (a *App) WatchlistEntries() []watchlist.Entry {
|
||||
if a.watchlist == nil {
|
||||
@@ -160,6 +183,20 @@ func (a *App) watchSpot(dxCall, band, mode, country, comment string, freqHz int6
|
||||
return
|
||||
}
|
||||
entry, notify, ok := a.watchlist.MarkSeen(dxCall)
|
||||
if !ok {
|
||||
// Not watched yet — the auto-contest pattern may claim it. Contains, not
|
||||
// prefix: the event string sits anywhere in these calls (HB9WWA, F4WWA/P).
|
||||
if p := a.GetWatchlistContestPattern(); p != "" &&
|
||||
strings.Contains(strings.ToUpper(dxCall), p) {
|
||||
if err := a.watchlist.Add(dxCall, true); err == nil {
|
||||
applog.Printf("watchlist: auto-added %s (contest pattern %q)", dxCall, p)
|
||||
entry, notify, ok = a.watchlist.MarkSeen(dxCall)
|
||||
if a.ctx != nil {
|
||||
wruntime.EventsEmit(a.ctx, "watchlist:changed")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if !ok || !notify || a.ctx == nil {
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user