Skip to content

Commit

Permalink
Support in/out laptime
Browse files Browse the repository at this point in the history
Fixes #66
  • Loading branch information
mpapenbr committed Aug 18, 2024
1 parent 9f80570 commit f7e7cc6
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 26 deletions.
10 changes: 5 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ require (
)

require (
buf.build/gen/go/mpapenbr/iracelog/grpc/go v1.5.1-20240623151922-fb549bddc8ee.1
buf.build/gen/go/mpapenbr/iracelog/protocolbuffers/go v1.34.2-20240623151922-fb549bddc8ee.2
buf.build/gen/go/mpapenbr/iracelog/grpc/go v1.5.1-20240818164234-8da4d13e1b88.1
buf.build/gen/go/mpapenbr/iracelog/protocolbuffers/go v1.34.2-20240818164234-8da4d13e1b88.2
github.com/google/uuid v1.6.0
github.com/mpapenbr/goirsdk v0.6.1
github.com/mpapenbr/goirsdk v0.7.0
github.com/samber/lo v1.46.0
github.com/stretchr/testify v1.9.0
golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611
Expand All @@ -34,8 +34,8 @@ require (
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
golang.org/x/net v0.25.0 // indirect
golang.org/x/sys v0.21.0 // indirect
golang.org/x/text v0.16.0 // indirect
golang.org/x/sys v0.24.0 // indirect
golang.org/x/text v0.17.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 // indirect
)

Expand Down
20 changes: 10 additions & 10 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
buf.build/gen/go/mpapenbr/iracelog/grpc/go v1.5.1-20240623151922-fb549bddc8ee.1 h1:lPlhiINx98V6y5AtBdLvqpJuinC8phWAF2dmi8Z9QKs=
buf.build/gen/go/mpapenbr/iracelog/grpc/go v1.5.1-20240623151922-fb549bddc8ee.1/go.mod h1:PHNMs6PIYA0TiUfjMeqK1nkfNrUIcA5vCn5VnFYGWEE=
buf.build/gen/go/mpapenbr/iracelog/protocolbuffers/go v1.34.2-20240623151922-fb549bddc8ee.2 h1:eeJL3v/jqCHRmXwnT3bxrYQegpsAw6cv6RgiTUs44DM=
buf.build/gen/go/mpapenbr/iracelog/protocolbuffers/go v1.34.2-20240623151922-fb549bddc8ee.2/go.mod h1:Nz+56AmPchS6dX/7Rc7t15BbsL+9eEHWvD0DpdMO7OA=
buf.build/gen/go/mpapenbr/iracelog/grpc/go v1.5.1-20240818164234-8da4d13e1b88.1 h1:x0o4fkCloKkDnGd0CHcMNMjygkzRIAta4gvwsLndCbc=
buf.build/gen/go/mpapenbr/iracelog/grpc/go v1.5.1-20240818164234-8da4d13e1b88.1/go.mod h1:2z7WgkT7hbeML1+5oyD2cif0VsujRrkyfzVHI35nYgQ=
buf.build/gen/go/mpapenbr/iracelog/protocolbuffers/go v1.34.2-20240818164234-8da4d13e1b88.2 h1:7mJORHD56rYpxIkVwoZTFbgz6lEeVWvaZy1F1EkWezo=
buf.build/gen/go/mpapenbr/iracelog/protocolbuffers/go v1.34.2-20240818164234-8da4d13e1b88.2/go.mod h1:Nz+56AmPchS6dX/7Rc7t15BbsL+9eEHWvD0DpdMO7OA=
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
Expand All @@ -27,8 +27,8 @@ github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0V
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mpapenbr/goirsdk v0.6.1 h1:yn7M3HW9enpDr/k+Nx8T4fFbgIHe4GnpjUUi3PYS+Bs=
github.com/mpapenbr/goirsdk v0.6.1/go.mod h1:mxcnGuogAfsI9gLCxLkFQqcgNGgWvuktMFoZczfpddQ=
github.com/mpapenbr/goirsdk v0.7.0 h1:Zi+CBogQPqo0jXDE32m5tu3FLwNFOfvrTg9PU45h96s=
github.com/mpapenbr/goirsdk v0.7.0/go.mod h1:ZEW55Aq5nT04GmhvyGibTwdtMiiwvDaMExV/0FTsZzM=
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
Expand Down Expand Up @@ -78,10 +78,10 @@ golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0=
golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 h1:Zy9XzmMEflZ/MAaA7vNcoebnRAld7FsPW1EeBB7V0m8=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0=
google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc=
Expand Down
79 changes: 77 additions & 2 deletions internal/processor/cardata.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ package processor
import (
"fmt"

commonv1 "buf.build/gen/go/mpapenbr/iracelog/protocolbuffers/go/iracelog/common/v1"
racestatev1 "buf.build/gen/go/mpapenbr/iracelog/protocolbuffers/go/iracelog/racestate/v1"
trackv1 "buf.build/gen/go/mpapenbr/iracelog/protocolbuffers/go/iracelog/track/v1"
"github.com/mpapenbr/goirsdk/irsdk"

"github.com/mpapenbr/go-racelogger/log"
Expand Down Expand Up @@ -58,6 +60,7 @@ type carRun struct{}

func (cr *carRun) Enter(cd *CarData) { log.Info("Entering state: carRun") }
func (cr *carRun) Exit(cd *CarData) { log.Info("Leaving state: carRun") }

func (cr *carRun) UpdatePre(cd *CarData, cw *carWorkData) {
if cw.trackPos == -1 {
cd.state = CarStateOut
Expand All @@ -70,6 +73,7 @@ func (cr *carRun) UpdatePre(cd *CarData, cw *carWorkData) {
cd.copyWorkData(cw)
if cw.pit {
cd.state = CarStatePit
handleInlap(cd, cw)
cd.pitstops += 1
cd.setState(&carPit{})
return
Expand All @@ -83,10 +87,25 @@ func (cr *carRun) UpdatePost(cd *CarData) {
}
}

func handleInlap(cd *CarData, cw *carWorkData) {
// rare case: car just left pit and immediately entered pit again
if cd.startOutLap > 0 {
cd.inlapTime = cw.sessionTime - cd.startOutLap
cd.lapMode = commonv1.LapMode_LAP_MODE_INOUTLAP
cd.startOutLap = 0
return
}

cd.inlaptiming.lap.markStop(cw.sessionTime)
cd.inlapTime = cd.inlaptiming.lap.duration.time
cd.lapMode = commonv1.LapMode_LAP_MODE_INLAP
}

type carSlow struct{}

func (cs *carSlow) Enter(cd *CarData) { log.Info("Entering state: carSlow") }
func (cs *carSlow) Exit(cd *CarData) { log.Info("Leaving state: carSlow") }

func (cs *carSlow) UpdatePre(cd *CarData, cw *carWorkData) {
if cw.trackPos == -1 {
cd.state = CarStateOut
Expand All @@ -99,6 +118,7 @@ func (cs *carSlow) UpdatePre(cd *CarData, cw *carWorkData) {
cd.copyWorkData(cw)
if cw.pit {
cd.state = CarStatePit
handleInlap(cd, cw)
cd.pitstops += 1
cd.setState(&carPit{})
return
Expand Down Expand Up @@ -135,6 +155,7 @@ func (cp *carPit) UpdatePre(cd *CarData, cw *carWorkData) {
if !cw.pit {
cd.state = CarStateRun
cd.stintLap = 1
cd.startOutLap = cw.sessionTime
cd.setState(&carRun{})
return
}
Expand Down Expand Up @@ -175,12 +196,14 @@ func (co *carOut) UpdatePost(cd *CarData) {}
type carWorkData struct {
carIdx int32
trackPos float64
trackLoc int32
pos int32
pic int32
lap int32
lc int32
pit bool
tireCompound int32
sessionTime float64
}

// CarData is a struct that contains the logic to process data for a single car data.
Expand All @@ -190,6 +213,7 @@ type CarData struct {
msgData map[string]interface{}
state string
trackPos float64
trackLoc int32
bestLap TimeWithMarker
lastLap TimeWithMarker
currentSector int
Expand All @@ -206,9 +230,14 @@ type CarData struct {
tireCompound int
currentState carState
laptiming *CarLaptiming
inlaptiming *CarLaptiming
carDriverProc *CarDriverProc
pitBoundaryProc *PitBoundaryProc
gpd *GlobalProcessingData
lapMode commonv1.LapMode
startOutLap float64 // session time when car exited pit road
inlapTime float64 // gets computed on pit entry
outlapTime float64 // gets computed after pit exit on s/f
}

//nolint:whitespace // can't get different linters happy
Expand All @@ -220,13 +249,15 @@ func NewCarData(
reportLapStatus ReportTimingStatus,
) *CarData {
laptiming := NewCarLaptiming(len(gpd.TrackInfo.Sectors), reportLapStatus)
inlaptiming := NewCarLaptiming(len(gpd.TrackInfo.Sectors), nil)
ret := CarData{
carIdx: carIdx,
currentState: &carInit{},
msgData: make(map[string]interface{}),
carDriverProc: carDriverProc,
pitBoundaryProc: pitBoundaryProc,
laptiming: laptiming,
inlaptiming: inlaptiming,
gpd: gpd,
currentSector: -1,
lastLap: TimeWithMarker{time: -1, marker: ""},
Expand Down Expand Up @@ -256,6 +287,7 @@ func (cd *CarData) setState(s carState) {
cd.currentState.Enter(cd)
}

//nolint:funlen,cyclop // ok here
func (cd *CarData) prepareGrpcData() *racestatev1.Car {
convertSectors := func(sectors []*SectionTiming) []*racestatev1.TimeWithMarker {
ret := make([]*racestatev1.TimeWithMarker, len(sectors))
Expand All @@ -279,7 +311,12 @@ func (cd *CarData) prepareGrpcData() *racestatev1.Car {
}
return racestatev1.CarState_CAR_STATE_UNSPECIFIED
}

isPitEntryAfterSf := func(t *trackv1.Track) bool {
if t.PitInfo != nil && t.PitInfo.LaneLength > 0 {
return t.PitInfo.Entry < t.PitInfo.Exit
}
return false
}
ret := &racestatev1.Car{
CarIdx: cd.carIdx,
Pos: int32(cd.pos),
Expand All @@ -299,7 +336,27 @@ func (cd *CarData) prepareGrpcData() *racestatev1.Car {
Sectors: convertSectors(cd.laptiming.sectors),
State: convertState(cd.state),
}
if cd.inlapTime > 0 {
ret.TimeInfo = &racestatev1.TimeInfo{
Time: float32(cd.inlapTime),
LapMode: cd.lapMode,
LapNo: int32(cd.lap),
}
if isPitEntryAfterSf(cd.gpd.TrackInfo) {
ret.TimeInfo.LapNo = int32(cd.lc)
}
}

if cd.outlapTime > 0 {
ret.TimeInfo = &racestatev1.TimeInfo{
Time: float32(cd.outlapTime),
LapMode: commonv1.LapMode_LAP_MODE_OUTLAP,
LapNo: int32(cd.lc),
}
}
// reset special values
cd.inlapTime = 0
cd.outlapTime = 0
return ret
}

Expand Down Expand Up @@ -357,9 +414,22 @@ func (cd *CarData) markSectorsAsOld() {

func (cd *CarData) startLap(t float64) {
cd.laptiming.lap.markStart(t)
// start the inlap timing only when car is on track
// otherwise we can't calculate the inlap time correctly
// for tracks where the pit is behind the s/f line
// for example: Interlagos, Mount Panorama
if cd.trackLoc == int32(irsdk.TrackLocationOnTrack) {
cd.inlaptiming.lap.markStart(t) // we may need this when car enters pit road
}
}

func (cd *CarData) stopLap(t float64) float64 {
if cd.startOutLap > 0 {
if cd.state != CarStatePit {
cd.outlapTime = t - cd.startOutLap
}
cd.startOutLap = 0
}
return cd.laptiming.lap.markStop(t)
}

Expand All @@ -375,17 +445,20 @@ func (cd *CarData) setStandingsLaptime(t float64) {
cd.laptiming.lap.duration.time = t
}

//nolint:lll // wrapping is not helpful here
//nolint:lll,errcheck // by design
func (cd *CarData) extractIrsdkData(api *irsdk.Irsdk) *carWorkData {
cw := carWorkData{}
cw.carIdx = cd.carIdx
cw.sessionTime = justValue(api.GetDoubleValue("SessionTime")).(float64)
cw.trackPos = float64(justValue(api.GetValue("CarIdxLapDistPct")).([]float32)[cd.carIdx])
cw.trackLoc = justValue(api.GetValue("CarIdxTrackSurface")).([]int32)[cd.carIdx]
cw.pos = justValue(api.GetValue("CarIdxPosition")).([]int32)[cd.carIdx]
cw.pic = justValue(api.GetValue("CarIdxClassPosition")).([]int32)[cd.carIdx]
cw.lap = justValue(api.GetValue("CarIdxLap")).([]int32)[cd.carIdx]
cw.lc = justValue(api.GetValue("CarIdxLapCompleted")).([]int32)[cd.carIdx]
cw.pit = justValue(api.GetValue("CarIdxOnPitRoad")).([]bool)[cd.carIdx]
cw.tireCompound = justValue(api.GetValue("CarIdxTireCompound")).([]int32)[cd.carIdx]

// maybe put this into the CarStint?
// value not unique
// when wet race: 0=DRY, 1=WET (EventID 314)
Expand All @@ -396,10 +469,12 @@ func (cd *CarData) extractIrsdkData(api *irsdk.Irsdk) *carWorkData {

func (cd *CarData) copyWorkData(cw *carWorkData) {
cd.trackPos = gate(cw.trackPos)
cd.trackLoc = cw.trackLoc
cd.pos = int(cw.pos)
cd.pic = int(cw.pic)
cd.lap = int(cw.lap)
cd.lc = int(cw.lc)

cd.tireCompound = int(cw.tireCompound)
cd.dist = 0
cd.interval = 0
Expand Down
10 changes: 5 additions & 5 deletions internal/racelogger.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,15 +189,15 @@ func (r *Racelogger) RegisterProvider(eventName, eventDescription string) error

r.eventKey = r.config.eventKeyFunc(irYaml)
event.Key = r.eventKey
r.globalData = processor.GlobalProcessingData{
TrackInfo: track,
EventDataInfo: event,
}

err = r.dataprovider.RegisterProvider(event, track, r.config.recordingMode)
resp, err := r.dataprovider.RegisterProvider(event, track, r.config.recordingMode)
if err != nil {
return err
}
r.globalData = processor.GlobalProcessingData{
TrackInfo: resp.Track,
EventDataInfo: event,
}

r.setupMainLoop()
return nil
Expand Down
3 changes: 2 additions & 1 deletion pkg/cmd/logimport/import.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,8 @@ func (p *importProc) sendMesage(msg protoreflect.Message) error {
}
}
}
return p.dpc.RegisterProvider(req.Event, req.Track, p.recordingMode)
_, err := p.dpc.RegisterProvider(req.Event, req.Track, p.recordingMode)
return err
case *providerv1.UnregisterEventRequest:
req, _ := msg.Interface().(*providerv1.UnregisterEventRequest)
eventKey := req.EventSelector.GetKey()
Expand Down
6 changes: 3 additions & 3 deletions pkg/grpc/dataprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,15 +71,15 @@ func (dpc *DataProviderClient) RegisterProvider(
event *eventv1.Event,
track *trackv1.Track,
recordingMode providerv1.RecordingMode,
) error {
) (*providerv1.RegisterEventResponse, error) {
req := providerv1.RegisterEventRequest{
Event: event, Track: track, Key: event.Key, RecordingMode: recordingMode,
}
//nolint:errcheck // by design
dpc.msgLogger.Log(req.ProtoReflect())
_, err := dpc.providerClient.RegisterEvent(
resp, err := dpc.providerClient.RegisterEvent(
dpc.prepareContext(context.Background()), &req)
return err
return resp, err
}

func (dpc *DataProviderClient) prepareContext(ctx context.Context) context.Context {
Expand Down

0 comments on commit f7e7cc6

Please sign in to comment.