Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e20f32c918 | ||
|
|
71adbfd8ff |
@@ -789,6 +789,11 @@ type App struct {
|
|||||||
acLastJudge time.Time
|
acLastJudge time.Time
|
||||||
// acTXPeriod is the last transmit period already counted — see autoCallNoteTX.
|
// acTXPeriod is the last transmit period already counted — see autoCallNoteTX.
|
||||||
acTXPeriod string
|
acTXPeriod string
|
||||||
|
// acJudged is the last period key each receiver has been judged on, and
|
||||||
|
// acDirty says decodes have arrived for it since. Together they let a period
|
||||||
|
// be judged AGAIN when a straggler turns up, with the whole period in hand.
|
||||||
|
acJudged map[string]string
|
||||||
|
acDirty map[string]bool
|
||||||
// What the decodes panel is SHOWING, and whether it is publishing at all.
|
// What the decodes panel is SHOWING, and whether it is publishing at all.
|
||||||
// The panel owns the filters; this is its answer, not a second copy of them.
|
// The panel owns the filters; this is its answer, not a second copy of them.
|
||||||
acVisible map[string]bool
|
acVisible map[string]bool
|
||||||
|
|||||||
+33
-5
@@ -160,6 +160,7 @@ func (a *App) applyAutoCall() {
|
|||||||
e.Reset()
|
e.Reset()
|
||||||
a.acMu.Lock()
|
a.acMu.Lock()
|
||||||
a.acPeriod, a.acBuf = nil, nil
|
a.acPeriod, a.acBuf = nil, nil
|
||||||
|
a.acJudged, a.acDirty = nil, nil
|
||||||
a.acMu.Unlock()
|
a.acMu.Unlock()
|
||||||
}
|
}
|
||||||
a.emitAutoCall()
|
a.emitAutoCall()
|
||||||
@@ -279,17 +280,37 @@ func (a *App) autoCallFeed(d autocall.Decode) {
|
|||||||
if a.acPeriod == nil {
|
if a.acPeriod == nil {
|
||||||
a.acPeriod, a.acAt, a.acTR, a.acBuf = map[string]string{}, map[string]time.Time{}, map[string]int{}, map[string][]acDecode{}
|
a.acPeriod, a.acAt, a.acTR, a.acBuf = map[string]string{}, map[string]time.Time{}, map[string]int{}, map[string][]acDecode{}
|
||||||
a.acFed = map[string]time.Time{}
|
a.acFed = map[string]time.Time{}
|
||||||
|
a.acJudged, a.acDirty = map[string]string{}, map[string]bool{}
|
||||||
}
|
}
|
||||||
if prev := a.acPeriod[inst]; prev != "" && prev != key {
|
if prev := a.acPeriod[inst]; prev != "" && prev != key {
|
||||||
prevAt, prevTR, buf := a.acAt[inst], a.acTR[inst], a.acBuf[inst]
|
prevAt, prevTR, buf := a.acAt[inst], a.acTR[inst], a.acBuf[inst]
|
||||||
|
// Only if something in it has NOT been judged. The buffer now outlives
|
||||||
|
// the judgement (see below), so without this the arrival of the next
|
||||||
|
// period would judge the previous one a second time on the very same
|
||||||
|
// decodes — and act on them, a slot late.
|
||||||
|
pending := a.acDirty[inst] || a.acJudged[inst] != prev
|
||||||
a.acPeriod[inst], a.acAt[inst], a.acTR[inst] = key, d.At, d.TRPeriod
|
a.acPeriod[inst], a.acAt[inst], a.acTR[inst] = key, d.At, d.TRPeriod
|
||||||
a.acBuf[inst] = []acDecode{{d: d}}
|
a.acBuf[inst] = []acDecode{{d: d}}
|
||||||
|
a.acFed[inst], a.acDirty[inst] = time.Now(), true
|
||||||
a.acMu.Unlock()
|
a.acMu.Unlock()
|
||||||
a.autoCallJudge(inst, prev, prevAt, prevTR, buf)
|
// The previous period ends here whatever the sweeper was going to do: a
|
||||||
|
// decode stamped with the next slot is proof the old one is over.
|
||||||
|
if pending {
|
||||||
|
a.autoCallJudge(inst, prev, prevAt, prevTR, buf)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// APPENDED, never restarted. The buffer survives the period being judged,
|
||||||
|
// so a decode that arrives after the others belongs to the same period and
|
||||||
|
// is weighed against all of them.
|
||||||
|
//
|
||||||
|
// It used to be dropped and then judged on its own: the sweeper cleared the
|
||||||
|
// buffer, a straggler opened a "new" one under the same key, and the ladder
|
||||||
|
// was applied to whatever handful had come late — with the other thirty
|
||||||
|
// stations of that period nowhere in sight. A deep decode arriving a second
|
||||||
|
// after the burst is exactly the station worth calling.
|
||||||
a.acPeriod[inst], a.acAt[inst], a.acTR[inst] = key, d.At, d.TRPeriod
|
a.acPeriod[inst], a.acAt[inst], a.acTR[inst] = key, d.At, d.TRPeriod
|
||||||
a.acFed[inst] = time.Now()
|
a.acFed[inst], a.acDirty[inst] = time.Now(), true
|
||||||
a.acBuf[inst] = append(a.acBuf[inst], acDecode{d: d})
|
a.acBuf[inst] = append(a.acBuf[inst], acDecode{d: d})
|
||||||
a.acMu.Unlock()
|
a.acMu.Unlock()
|
||||||
}
|
}
|
||||||
@@ -344,9 +365,14 @@ func (a *App) autoCallSweep() {
|
|||||||
if time.Since(a.acFed[inst]) < acQuiet {
|
if time.Since(a.acFed[inst]) < acQuiet {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
// Judged once per period, and again only when something new has come in
|
||||||
|
// for it. The period itself is kept open until a decode from the NEXT one
|
||||||
|
// arrives, so a straggler is judged with the whole period behind it.
|
||||||
|
if a.acJudged[inst] == key && !a.acDirty[inst] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
ready = append(ready, due{inst, key, a.acAt[inst], tr, a.acBuf[inst]})
|
ready = append(ready, due{inst, key, a.acAt[inst], tr, a.acBuf[inst]})
|
||||||
delete(a.acPeriod, inst)
|
a.acJudged[inst], a.acDirty[inst] = key, false
|
||||||
delete(a.acBuf, inst)
|
|
||||||
}
|
}
|
||||||
a.acMu.Unlock()
|
a.acMu.Unlock()
|
||||||
for _, d := range ready {
|
for _, d := range ready {
|
||||||
@@ -369,7 +395,9 @@ func (a *App) autoCallSilence() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
a.acMu.Lock()
|
a.acMu.Lock()
|
||||||
quiet := a.acPeriod[inst] == "" && time.Since(a.acLastJudge) > 20*time.Second
|
// Nothing pending for this receiver, and nothing judged for a while: the
|
||||||
|
// band has gone quiet under it.
|
||||||
|
quiet := !a.acDirty[inst] && time.Since(a.acLastJudge) > 20*time.Second
|
||||||
tr := a.acTR[inst]
|
tr := a.acTR[inst]
|
||||||
a.acMu.Unlock()
|
a.acMu.Unlock()
|
||||||
if !quiet {
|
if !quiet {
|
||||||
|
|||||||
@@ -1,4 +1,14 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"version": "0.27.14",
|
||||||
|
"date": "",
|
||||||
|
"en": [
|
||||||
|
"Auto-call sees a decode that arrives after the others. A decoder sends a period in a burst and stragglers follow — a deep decode a second behind the rest — and the straggler was judged on its own, with the thirty stations of its own period nowhere in sight. The period now stays open until the next one starts, and a late arrival is weighed against all of it."
|
||||||
|
],
|
||||||
|
"fr": [
|
||||||
|
"L’auto-call voit un décodage qui arrive après les autres. Un décodeur envoie une période en rafale, puis les retardataires — un décodage « deep » une seconde plus tard — et le retardataire était jugé tout seul, sans les trente stations de sa propre période. La période reste maintenant ouverte jusqu’au début de la suivante, et un arrivant tardif est pesé face à l’ensemble."
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "0.27.13",
|
"version": "0.27.13",
|
||||||
"date": "",
|
"date": "",
|
||||||
|
|||||||
Reference in New Issue
Block a user