mirror of
https://github.com/AmanTahiliani/box-box.git
synced 2026-08-08 12:07:23 -04:00
Compare commits
1 Commits
c475011c49
...
fix/live-s
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
255b296ecc |
@@ -472,6 +472,62 @@ func TestProcessTopicTimingAppData(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The feed sends stints as sparse deltas keyed by stint index. Replacing the
|
||||||
|
// slice on each delta collapsed pit history to one entry and pinned tyre age
|
||||||
|
// near zero — observed live at lap 49 of a 70-lap race, where every driver
|
||||||
|
// reported a single stint of age 0 despite having pitted.
|
||||||
|
func TestProcessTopicTimingAppDataMergesSparseStintDeltas(t *testing.T) {
|
||||||
|
state := live.NewState()
|
||||||
|
state.ProcessTopic("TimingAppData", json.RawMessage(`{
|
||||||
|
"Lines": {"4": {"Stints": {"0": {"Compound": "MEDIUM", "New": "true", "TotalLaps": 0}}}}
|
||||||
|
}`))
|
||||||
|
// Stint 0 runs to 18 laps, then the driver pits onto a new hard.
|
||||||
|
state.ProcessTopic("TimingAppData", json.RawMessage(`{
|
||||||
|
"Lines": {"4": {"Stints": {"0": {"TotalLaps": 18}}}}
|
||||||
|
}`))
|
||||||
|
state.ProcessTopic("TimingAppData", json.RawMessage(`{
|
||||||
|
"Lines": {"4": {"Stints": {"1": {"Compound": "HARD", "New": "true", "TotalLaps": 0}}}}
|
||||||
|
}`))
|
||||||
|
state.ProcessTopic("TimingAppData", json.RawMessage(`{
|
||||||
|
"Lines": {"4": {"Stints": {"1": {"TotalLaps": 12}}}}
|
||||||
|
}`))
|
||||||
|
|
||||||
|
snap := state.Snapshot()
|
||||||
|
stints := snap.Stints["4"]
|
||||||
|
if len(stints) != 2 {
|
||||||
|
t.Fatalf("expected 2 stints after a pit stop, got %d: %+v", len(stints), stints)
|
||||||
|
}
|
||||||
|
if stints[0].Compound != "MEDIUM" || stints[0].Laps != 18 {
|
||||||
|
t.Errorf("first stint lost across deltas: %+v", stints[0])
|
||||||
|
}
|
||||||
|
if stints[1].Compound != "HARD" || stints[1].Laps != 12 {
|
||||||
|
t.Errorf("second stint = %+v", stints[1])
|
||||||
|
}
|
||||||
|
if tyre := snap.Tyres["4"]; tyre.Compound != "HARD" || tyre.Age != 12 {
|
||||||
|
t.Errorf("current tyre should track the latest stint, got %+v", tyre)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProcessTopicTimingAppDataIgnoresNonNumericStintKeys(t *testing.T) {
|
||||||
|
state := live.NewState()
|
||||||
|
state.ProcessTopic("TimingAppData", json.RawMessage(`{
|
||||||
|
"Lines": {"4": {"Stints": {"0": {"Compound": "SOFT", "New": "true", "TotalLaps": 9}}}}
|
||||||
|
}`))
|
||||||
|
// "_kf" is a feed key-frame marker, not a stint index. Parsing it as 0
|
||||||
|
// would overwrite the real first stint.
|
||||||
|
state.ProcessTopic("TimingAppData", json.RawMessage(`{
|
||||||
|
"Lines": {"4": {"Stints": {"_kf": {"Compound": "HARD", "TotalLaps": 99}}}}
|
||||||
|
}`))
|
||||||
|
|
||||||
|
stints := state.Snapshot().Stints["4"]
|
||||||
|
if len(stints) != 1 {
|
||||||
|
t.Fatalf("expected 1 stint, got %d: %+v", len(stints), stints)
|
||||||
|
}
|
||||||
|
if stints[0].Compound != "SOFT" || stints[0].Laps != 9 {
|
||||||
|
t.Errorf("key-frame marker corrupted stint 0: %+v", stints[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestProcessTopicTimingStats(t *testing.T) {
|
func TestProcessTopicTimingStats(t *testing.T) {
|
||||||
state := live.NewState()
|
state := live.NewState()
|
||||||
state.Drivers["55"] = live.LiveDriverData{RacingNumber: "55"}
|
state.Drivers["55"] = live.LiveDriverData{RacingNumber: "55"}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -404,22 +405,42 @@ func (s *State) ProcessTopic(topic string, data json.RawMessage) bool {
|
|||||||
Stints json.RawMessage `json:"Stints"`
|
Stints json.RawMessage `json:"Stints"`
|
||||||
}
|
}
|
||||||
if json.Unmarshal(lineRaw, &line) == nil && line.Stints != nil {
|
if json.Unmarshal(lineRaw, &line) == nil && line.Stints != nil {
|
||||||
var driverStints []LiveStintData
|
// The feed sends stints as sparse deltas keyed by stint index:
|
||||||
|
// a mid-stint update is just {"1": {"TotalLaps": 14}}. Merge
|
||||||
|
// each entry into the stint it addresses. Replacing the slice
|
||||||
|
// wholesale discarded every earlier stint, so pit history
|
||||||
|
// collapsed to one entry and tyre age stuck near zero for the
|
||||||
|
// whole race.
|
||||||
|
driverStints := append([]LiveStintData(nil), s.Stints[num]...)
|
||||||
|
changed := false
|
||||||
for _, sRaw := range indexedRawValues(line.Stints) {
|
for _, sRaw := range indexedRawValues(line.Stints) {
|
||||||
var st struct {
|
var st struct {
|
||||||
Compound string `json:"Compound"`
|
Compound *string `json:"Compound"`
|
||||||
New string `json:"New"`
|
New *string `json:"New"`
|
||||||
TotalLaps int `json:"TotalLaps"`
|
TotalLaps *int `json:"TotalLaps"`
|
||||||
}
|
}
|
||||||
if json.Unmarshal(sRaw.Raw, &st) == nil && st.Compound != "" {
|
if json.Unmarshal(sRaw.Raw, &st) != nil {
|
||||||
driverStints = append(driverStints, LiveStintData{
|
continue
|
||||||
Compound: st.Compound,
|
|
||||||
New: st.New == "true" || st.New == "True",
|
|
||||||
Laps: st.TotalLaps,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
if st.Compound == nil && st.New == nil && st.TotalLaps == nil {
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
if len(driverStints) > 0 {
|
for len(driverStints) <= sRaw.Index {
|
||||||
|
driverStints = append(driverStints, LiveStintData{})
|
||||||
|
}
|
||||||
|
entry := &driverStints[sRaw.Index]
|
||||||
|
if st.Compound != nil && *st.Compound != "" {
|
||||||
|
entry.Compound = *st.Compound
|
||||||
|
}
|
||||||
|
if st.New != nil {
|
||||||
|
entry.New = *st.New == "true" || *st.New == "True"
|
||||||
|
}
|
||||||
|
if st.TotalLaps != nil {
|
||||||
|
entry.Laps = *st.TotalLaps
|
||||||
|
}
|
||||||
|
changed = true
|
||||||
|
}
|
||||||
|
if changed {
|
||||||
s.Stints[num] = driverStints
|
s.Stints[num] = driverStints
|
||||||
lastStint := driverStints[len(driverStints)-1]
|
lastStint := driverStints[len(driverStints)-1]
|
||||||
t := s.Tyres[num]
|
t := s.Tyres[num]
|
||||||
@@ -874,8 +895,13 @@ func indexedRawValues(raw json.RawMessage) []indexedRaw {
|
|||||||
if err := json.Unmarshal(raw, &obj); err == nil {
|
if err := json.Unmarshal(raw, &obj); err == nil {
|
||||||
values := make([]indexedRaw, 0, len(obj))
|
values := make([]indexedRaw, 0, len(obj))
|
||||||
for k, v := range obj {
|
for k, v := range obj {
|
||||||
i := 0
|
// Keys are array indices in the feed's delta form. Non-numeric keys
|
||||||
fmt.Sscanf(k, "%d", &i)
|
// are feed metadata — "_kf" (key frame) is the common one — and must
|
||||||
|
// not be folded in as index 0, which would clobber the first entry.
|
||||||
|
i, err := strconv.Atoi(k)
|
||||||
|
if err != nil || i < 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
values = append(values, indexedRaw{Index: i, Raw: v})
|
values = append(values, indexedRaw{Index: i, Raw: v})
|
||||||
}
|
}
|
||||||
sort.Slice(values, func(i, j int) bool {
|
sort.Slice(values, func(i, j int) bool {
|
||||||
|
|||||||
Reference in New Issue
Block a user