revert(dxped): no chase badge on the news pane

Tried it, looked at it, took it out. A headline names no band, so the
only honest verdict is entity-level — and a pane where every row reads
NEW DXCC or worked says nothing an operator can act on. Two words
repeated forty times is noise wearing the clothes of information.

The announcements pane keeps its badge, where the announced bands and
modes make the verdict specific enough to be worth a colour. The news
pane keeps what it is good at: what is happening, and a Watch button.
Changelog entry withdrawn with it — it never shipped.
This commit is contained in:
2026-08-31 19:00:44 +02:00
parent 2b6f1ba9d7
commit 2f1d592497
5 changed files with 45 additions and 111 deletions
+10 -62
View File
@@ -119,22 +119,16 @@ func (a *App) judgeDXpeditions(list []DXpedition) {
}
}
// DXNews is one DX-World post plus what its callsigns are worth here.
type DXNews struct {
dxped.News
// Status is ENTITY-LEVEL only, and deliberately so: a headline announces no
// bands or modes, and asking the slot question without them would answer
// "new band" for every entity ever worked — the one mistake that costs a
// QSO. So it says "new" (entity never worked) or "worked", nothing finer;
// the announcements pane, which HAS the bands and modes, is where the
// sharper verdicts belong.
Status string `json:"status_chase"`
Unconfirmed bool `json:"unconfirmed"`
}
// GetDXWorldNews returns the DX-World headlines, with the callsigns mined out
// of each one and judged against the log.
func (a *App) GetDXWorldNews() ([]DXNews, error) {
// of each one so the reader can watch them.
//
// Deliberately NOT judged against the log. A headline names no band, so the
// only verdict available is entity-level, and a pane of "NEW DXCC" and
// "worked" badges turned out to say nothing an operator could act on — the
// same two words on every row is noise wearing the clothes of information.
// The announcements pane, which knows the bands and modes, is where a chase
// verdict is worth drawing.
func (a *App) GetDXWorldNews() ([]dxped.News, error) {
if a.dxped == nil {
a.dxped = dxped.New()
}
@@ -145,53 +139,7 @@ func (a *App) GetDXWorldNews() ([]DXNews, error) {
return nil, err
}
}
out := make([]DXNews, 0, len(news))
for _, n := range news {
out = append(out, DXNews{News: n})
}
a.judgeNews(out)
return out, nil
}
// judgeNews fills the entity-level verdict for each headline.
//
// One query per callsign with NO band and NO mode: the only verdict that
// means anything in that state is "this entity has never been worked". Every
// finer answer the spot judge can give without a band is an artefact of the
// missing band, so it is flattened to "worked" rather than repeated.
func (a *App) judgeNews(list []DXNews) {
if a.qso == nil || len(list) == 0 {
return
}
var queries []SpotQuery
var owners []int
for i, n := range list {
for _, call := range n.Calls {
queries = append(queries, SpotQuery{Call: call})
owners = append(owners, i)
}
}
if len(queries) == 0 {
return
}
res := a.ClusterSpotStatuses(queries)
for i, r := range res {
if i >= len(owners) {
break
}
row := owners[i]
st := ""
switch {
case r.Status == "new":
st = "new"
case r.Status != "":
st = "worked"
}
if chaseRank[st] > chaseRank[list[row].Status] {
list[row].Status = st
list[row].Unconfirmed = r.UnconfStatus
}
}
return news, nil
}
// RefreshDXpeditions drops both caches so the next read goes to the network.