Skip to content

Commit da2f008

Browse files
committed
add a QTCList type to manage the logic around QTCs
1 parent b6991f9 commit da2f008

File tree

3 files changed

+164
-0
lines changed

3 files changed

+164
-0
lines changed

core/app/app.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ type Controller struct {
7575
VFO *vfo.VFO
7676
Logbook *logbook.Logbook
7777
QSOList *logbook.QSOList
78+
QTCList *logbook.QTCList
7879
Entry *entry.Controller
7980
Workmode *workmode.Controller
8081
Radio *radio.Controller
@@ -167,6 +168,7 @@ func (c *Controller) Startup() {
167168

168169
c.Score = score.NewCounter(c.Settings, c.dxccFinder)
169170
c.QSOList = logbook.NewQSOList(c.Settings, c.Score)
171+
c.QTCList = logbook.NewQTCList()
170172
c.Bandmap = bandmap.NewBandmap(c.clock, c.Settings, c.QSOList, c.asyncRunner, bandmap.DefaultUpdatePeriod, c.configuration.SpotLifetime())
171173
c.Clusters = cluster.NewClusters(c.configuration.SpotSources(), c.Bandmap, c.bandplan, c.dxccFinder, c.clock)
172174
c.Entry = entry.NewController(
@@ -342,6 +344,7 @@ func (c *Controller) changeLogbook(filename string, store *store.FileStore, newL
342344
c.Logbook = newLogbook
343345
c.Logbook.SetWriter(c.store)
344346
c.Logbook.Notify(logbook.QSOAddedListenerFunc(c.QSOList.Put))
347+
c.Logbook.Notify(c.QTCList)
345348
c.Logbook.Notify(c.Workmode)
346349

347350
c.VFO.SetLogbook(c.Logbook)
@@ -629,6 +632,7 @@ func (c *Controller) ExportSummary() {
629632
}
630633

631634
func (c *Controller) ExportCabrillo() {
635+
// TODO: export QTCs
632636
result, ok := c.ExportCabrilloController.Run(c.Settings, c.Score.Result(), c.QSOList.All())
633637
if !ok {
634638
return
@@ -757,7 +761,9 @@ func (c *Controller) ShowSpots() {
757761

758762
func (c *Controller) Refresh() {
759763
c.QSOList.Clear()
764+
c.QTCList.Clear()
760765
c.QSOList.Fill(c.Logbook.AllQSOs())
766+
c.QTCList.Fill(c.Logbook.AllQTCs())
761767
c.Entry.Clear()
762768
}
763769

core/logbook/qtclist.go

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
package logbook
2+
3+
import (
4+
"slices"
5+
"sync"
6+
7+
"github.com/ftl/hellocontest/core"
8+
)
9+
10+
type QTCsClearedListener interface {
11+
QTCsCleared()
12+
}
13+
14+
type QTCList struct {
15+
dataLock *sync.RWMutex
16+
data map[core.QSONumber]core.QTC
17+
18+
listeners []any
19+
}
20+
21+
func NewQTCList() *QTCList {
22+
return &QTCList{
23+
dataLock: new(sync.RWMutex),
24+
data: make(map[core.QSONumber]core.QTC),
25+
}
26+
}
27+
28+
func (l *QTCList) Notify(listener any) {
29+
l.listeners = append(l.listeners, listener)
30+
}
31+
32+
func (l *QTCList) emitQTCsCleared() {
33+
for _, lis := range l.listeners {
34+
if listener, ok := lis.(QTCsClearedListener); ok {
35+
listener.QTCsCleared()
36+
}
37+
}
38+
}
39+
40+
func (l *QTCList) emitQTCAdded(qtc core.QTC) {
41+
for _, lis := range l.listeners {
42+
if listener, ok := lis.(QTCAddedListener); ok {
43+
listener.QTCAdded(qtc)
44+
}
45+
}
46+
}
47+
48+
func (l *QTCList) Clear() {
49+
l.dataLock.Lock()
50+
l.clear()
51+
l.dataLock.Unlock()
52+
53+
l.emitQTCsCleared()
54+
}
55+
56+
func (l *QTCList) clear() {
57+
l.data = make(map[core.QSONumber]core.QTC)
58+
}
59+
60+
func (l *QTCList) Fill(qtcs []core.QTC) {
61+
l.dataLock.Lock()
62+
if len(l.data) > 0 {
63+
l.clear()
64+
}
65+
for _, qtc := range qtcs {
66+
l.put(qtc)
67+
}
68+
allQTCs := l.all()
69+
l.dataLock.Unlock()
70+
71+
l.emitQTCsCleared()
72+
for _, qtc := range allQTCs {
73+
l.emitQTCAdded(qtc)
74+
}
75+
}
76+
77+
func (l *QTCList) QTCAdded(qtc core.QTC) {
78+
l.dataLock.Lock()
79+
l.put(qtc)
80+
l.dataLock.Unlock()
81+
l.emitQTCAdded(qtc)
82+
}
83+
84+
func (l *QTCList) put(qtc core.QTC) {
85+
l.data[qtc.QSONumber] = qtc
86+
}
87+
88+
func (l *QTCList) All() []core.QTC {
89+
l.dataLock.RLock()
90+
defer l.dataLock.RUnlock()
91+
92+
return l.all()
93+
}
94+
95+
func (l *QTCList) all() []core.QTC {
96+
result := make([]core.QTC, 0, len(l.data))
97+
for _, qtc := range l.data {
98+
result = append(result, qtc)
99+
}
100+
101+
slices.SortStableFunc(result, core.QTCByTimestamp)
102+
return result
103+
}
104+
105+
func (l *QTCList) QSOAdded(qso core.QSO) {
106+
// TODO: add an available QTC for the new QSO if appropriate
107+
}

core/logbook/qtclist_test.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package logbook
2+
3+
import (
4+
"testing"
5+
"time"
6+
7+
"github.com/ftl/hellocontest/core"
8+
"github.com/stretchr/testify/assert"
9+
)
10+
11+
func TestQTCList_basicSetup(t *testing.T) {
12+
l := NewQTCList()
13+
now := time.Now()
14+
listener := new(qtcListListener)
15+
l.Notify(listener)
16+
17+
initialQTCs := []core.QTC{
18+
{Timestamp: now.Add(-4 * time.Minute), QSONumber: 1},
19+
{Timestamp: now.Add(-2 * time.Minute), QSONumber: 2},
20+
{Timestamp: now.Add(-1 * time.Minute), QSONumber: 3},
21+
}
22+
l.Fill(initialQTCs)
23+
assert.Equal(t, initialQTCs, l.All())
24+
assert.Equal(t, 1, listener.clearEvents)
25+
assert.Equal(t, 3, listener.addedEvents)
26+
27+
newQTC := core.QTC{Timestamp: now, QSONumber: 4}
28+
l.QTCAdded(newQTC)
29+
assert.Equal(t, 4, len(l.All()))
30+
assert.Equal(t, newQTC, l.All()[3])
31+
assert.Equal(t, 1, listener.clearEvents)
32+
assert.Equal(t, 4, listener.addedEvents)
33+
34+
l.Clear()
35+
assert.Equal(t, 0, len(l.All()))
36+
assert.Equal(t, 2, listener.clearEvents)
37+
assert.Equal(t, 4, listener.addedEvents)
38+
}
39+
40+
type qtcListListener struct {
41+
clearEvents int
42+
addedEvents int
43+
}
44+
45+
func (l *qtcListListener) QTCsCleared() {
46+
l.clearEvents++
47+
}
48+
49+
func (l *qtcListListener) QTCAdded(core.QTC) {
50+
l.addedEvents++
51+
}

0 commit comments

Comments
 (0)