From 0c90e5d4ac03936292a8b8c2e8d321820eeca0a6 Mon Sep 17 00:00:00 2001 From: Eduardo Silva Date: Mon, 1 Jun 2026 17:38:30 +0100 Subject: [PATCH] Satisfactory fuel calculator done (still have plenty to do on it) --- layouts/layout.yaml | 602 +++++++++++++++++++---------------- providers/iracing/iracing.go | 2 +- telemetry/data.go | 12 +- telemetry/fuel_calculator.go | 247 +++++++++----- 4 files changed, 502 insertions(+), 361 deletions(-) diff --git a/layouts/layout.yaml b/layouts/layout.yaml index 46ff413..fd02211 100755 --- a/layouts/layout.yaml +++ b/layouts/layout.yaml @@ -1,29 +1,5 @@ Windows: 1: - uiwindow: - Dims: - X0: 359 - Y0: 355 - Width: 120 - Height: 49 - Decor: - BGColour: 4161 - FGColour: 65535 - TitleColour: 65535 - BorderColour: 63488 - TitleSize: 2 - TextSize: 3 - HasBorder: 1 - Padding: 0 - Opts: - ShowID: 0 - WinType: 2 - PreviewValue: YELLOW - Title: RPMColour - uidata: - WID: 1 - TelemetryField: RPM State Colour - 2: uiwindow: Dims: X0: 74 @@ -45,177 +21,9 @@ Windows: PreviewValue: "12" Title: TC uidata: - WID: 2 + WID: 1 TelemetryField: TC Control - 3: - uiwindow: - Dims: - X0: 60 - Y0: 91 - Width: 85 - Height: 57 - Decor: - BGColour: 4161 - FGColour: 65535 - TitleColour: 65535 - BorderColour: 63488 - TitleSize: 2 - TextSize: 4 - HasBorder: 1 - Padding: 0 - Opts: - ShowID: 0 - WinType: 2 - PreviewValue: "123" - Title: Lap - uidata: - WID: 3 - TelemetryField: Lap Number - 4: - uiwindow: - Dims: - X0: 9 - Y0: 413 - Width: 57 - Height: 57 - Decor: - BGColour: 4161 - FGColour: 65535 - TitleColour: 65535 - BorderColour: 63488 - TitleSize: 2 - TextSize: 4 - HasBorder: 1 - Padding: 0 - Opts: - ShowID: 0 - WinType: 2 - PreviewValue: "12" - Title: ABS - uidata: - WID: 4 - TelemetryField: ABS Control - 5: - uiwindow: - Dims: - X0: 694 - Y0: 367 - Width: 100 - Height: 50 - Decor: - BGColour: 4161 - FGColour: 65535 - TitleColour: 65535 - BorderColour: 63488 - TitleSize: 2 - TextSize: 3 - HasBorder: 1 - Padding: 0 - Opts: - ShowID: 0 - WinType: 2 - PreviewValue: "101.4" - Title: Oil T - uidata: - WID: 5 - TelemetryField: Oil Temperature - 6: - uiwindow: - Dims: - X0: 60 - Y0: 155 - Width: 226 - Height: 57 - Decor: - BGColour: 4161 - FGColour: 65535 - TitleColour: 65535 - BorderColour: 63488 - TitleSize: 2 - TextSize: 4 - HasBorder: 1 - Padding: 0 - Opts: - ShowID: 0 - WinType: 2 - PreviewValue: "06:45.123" - Title: Last Lap - uidata: - WID: 6 - TelemetryField: Last Lap Time - 7: - uiwindow: - Dims: - X0: 590 - Y0: 367 - Width: 100 - Height: 50 - Decor: - BGColour: 4161 - FGColour: 65535 - TitleColour: 65535 - BorderColour: 63488 - TitleSize: 2 - TextSize: 3 - HasBorder: 1 - Padding: 0 - Opts: - ShowID: 0 - WinType: 2 - PreviewValue: "101.5" - Title: Water T - uidata: - WID: 7 - TelemetryField: Water Temperature - 8: - uiwindow: - Dims: - X0: 642 - Y0: 188 - Width: 150 - Height: 50 - Decor: - BGColour: 4161 - FGColour: 65535 - TitleColour: 65535 - BorderColour: 63488 - TitleSize: 2 - TextSize: 3 - HasBorder: 1 - Padding: 0 - Opts: - ShowID: 0 - WinType: 2 - PreviewValue: "2.7" - Title: Fuel Cur Lap - uidata: - WID: 8 - TelemetryField: Fuel Current Lap - 9: - uiwindow: - Dims: - X0: 470 - Y0: 188 - Width: 168 - Height: 50 - Decor: - BGColour: 4161 - FGColour: 65535 - TitleColour: 65535 - BorderColour: 63488 - TitleSize: 2 - TextSize: 3 - HasBorder: 1 - Padding: 0 - Opts: - ShowID: 0 - WinType: 2 - PreviewValue: 12.3 L - Title: Fuel Last Lap - uidata: - WID: 9 - TelemetryField: Fuel Last Lap - 10: + 2: uiwindow: Dims: X0: 354 @@ -237,33 +45,9 @@ Windows: PreviewValue: R Title: Box uidata: - WID: 10 + WID: 2 TelemetryField: Gear - 11: - uiwindow: - Dims: - X0: 142 - Y0: 19 - Width: 500 - Height: 20 - Decor: - BGColour: 4161 - FGColour: 65535 - TitleColour: 65535 - BorderColour: 63488 - TitleSize: 1 - TextSize: 2 - HasBorder: 1 - Padding: 0 - Opts: - ShowID: 0 - WinType: 1 - PreviewValue: "5678" - Title: TACHO - uidata: - WID: 11 - TelemetryField: RPM - 12: + 3: uiwindow: Dims: X0: 140 @@ -285,9 +69,105 @@ Windows: PreviewValue: "6" Title: Thr uidata: - WID: 12 + WID: 3 TelemetryField: Throttle Control - 13: + 4: + uiwindow: + Dims: + X0: 359 + Y0: 355 + Width: 120 + Height: 49 + Decor: + BGColour: 4161 + FGColour: 65535 + TitleColour: 65535 + BorderColour: 63488 + TitleSize: 2 + TextSize: 3 + HasBorder: 1 + Padding: 0 + Opts: + ShowID: 0 + WinType: 2 + PreviewValue: YELLOW + Title: RPMColour + uidata: + WID: 4 + TelemetryField: RPM State Colour + 5: + uiwindow: + Dims: + X0: 60 + Y0: 155 + Width: 226 + Height: 57 + Decor: + BGColour: 4161 + FGColour: 65535 + TitleColour: 65535 + BorderColour: 63488 + TitleSize: 2 + TextSize: 4 + HasBorder: 1 + Padding: 0 + Opts: + ShowID: 0 + WinType: 2 + PreviewValue: "06:45.123" + Title: Last Lap + uidata: + WID: 5 + TelemetryField: Last Lap Time + 6: + uiwindow: + Dims: + X0: 470 + Y0: 188 + Width: 168 + Height: 50 + Decor: + BGColour: 4161 + FGColour: 65535 + TitleColour: 65535 + BorderColour: 63488 + TitleSize: 2 + TextSize: 3 + HasBorder: 1 + Padding: 0 + Opts: + ShowID: 0 + WinType: 2 + PreviewValue: 12.3 L + Title: Fuel Last Lap + uidata: + WID: 6 + TelemetryField: Fuel Last Lap + 7: + uiwindow: + Dims: + X0: 142 + Y0: 19 + Width: 500 + Height: 20 + Decor: + BGColour: 4161 + FGColour: 65535 + TitleColour: 65535 + BorderColour: 63488 + TitleSize: 1 + TextSize: 2 + HasBorder: 1 + Padding: 0 + Opts: + ShowID: 0 + WinType: 1 + PreviewValue: "5678" + Title: TACHO + uidata: + WID: 7 + TelemetryField: RPM + 8: uiwindow: Dims: X0: 694 @@ -309,57 +189,9 @@ Windows: PreviewValue: "4.56" Title: Oil P uidata: - WID: 13 + WID: 8 TelemetryField: Oil Pressure - 14: - uiwindow: - Dims: - X0: 436 - Y0: 71 - Width: 206 - Height: 57 - Decor: - BGColour: 4161 - FGColour: 65535 - TitleColour: 65535 - BorderColour: 63488 - TitleSize: 2 - TextSize: 4 - HasBorder: 1 - Padding: 0 - Opts: - ShowID: 0 - WinType: 2 - PreviewValue: "9999" - Title: Dig Tacho - uidata: - WID: 14 - TelemetryField: RPM - 15: - uiwindow: - Dims: - X0: 710 - Y0: 8 - Width: 84 - Height: 57 - Decor: - BGColour: 4161 - FGColour: 65535 - TitleColour: 65535 - BorderColour: 63488 - TitleSize: 2 - TextSize: 4 - HasBorder: 1 - Padding: 0 - Opts: - ShowID: 0 - WinType: 2 - PreviewValue: PIT - Title: Pit Sp - uidata: - WID: 15 - TelemetryField: Pit Speed Limiter - 16: + 9: uiwindow: Dims: X0: 331 @@ -381,9 +213,129 @@ Windows: PreviewValue: "234" Title: SPEEDO uidata: - WID: 16 + WID: 9 TelemetryField: Speed - 17: + 10: + uiwindow: + Dims: + X0: 694 + Y0: 367 + Width: 100 + Height: 50 + Decor: + BGColour: 4161 + FGColour: 65535 + TitleColour: 65535 + BorderColour: 63488 + TitleSize: 2 + TextSize: 3 + HasBorder: 1 + Padding: 0 + Opts: + ShowID: 0 + WinType: 2 + PreviewValue: "101.4" + Title: Oil T + uidata: + WID: 10 + TelemetryField: Oil Temperature + 11: + uiwindow: + Dims: + X0: 590 + Y0: 367 + Width: 100 + Height: 50 + Decor: + BGColour: 4161 + FGColour: 65535 + TitleColour: 65535 + BorderColour: 63488 + TitleSize: 2 + TextSize: 3 + HasBorder: 1 + Padding: 0 + Opts: + ShowID: 0 + WinType: 2 + PreviewValue: "101.5" + Title: Water T + uidata: + WID: 11 + TelemetryField: Water Temperature + 12: + uiwindow: + Dims: + X0: 642 + Y0: 188 + Width: 150 + Height: 50 + Decor: + BGColour: 4161 + FGColour: 65535 + TitleColour: 65535 + BorderColour: 63488 + TitleSize: 2 + TextSize: 3 + HasBorder: 1 + Padding: 0 + Opts: + ShowID: 0 + WinType: 2 + PreviewValue: "2.7" + Title: Fuel Cur Lap + uidata: + WID: 12 + TelemetryField: Fuel Current Lap + 13: + uiwindow: + Dims: + X0: 436 + Y0: 71 + Width: 206 + Height: 57 + Decor: + BGColour: 4161 + FGColour: 65535 + TitleColour: 65535 + BorderColour: 63488 + TitleSize: 2 + TextSize: 4 + HasBorder: 1 + Padding: 0 + Opts: + ShowID: 0 + WinType: 2 + PreviewValue: "9999" + Title: Dig Tacho + uidata: + WID: 13 + TelemetryField: RPM + 14: + uiwindow: + Dims: + X0: 710 + Y0: 8 + Width: 84 + Height: 57 + Decor: + BGColour: 4161 + FGColour: 65535 + TitleColour: 65535 + BorderColour: 63488 + TitleSize: 2 + TextSize: 4 + HasBorder: 1 + Padding: 0 + Opts: + ShowID: 0 + WinType: 2 + PreviewValue: PIT + Title: Pit Sp + uidata: + WID: 14 + TelemetryField: Pit Speed Limiter + 15: uiwindow: Dims: X0: 207 @@ -405,9 +357,9 @@ Windows: PreviewValue: "61.4" Title: BBias uidata: - WID: 17 + WID: 15 TelemetryField: BrakeBias - 18: + 16: uiwindow: Dims: X0: 470 @@ -429,5 +381,101 @@ Windows: PreviewValue: "123.4" Title: Fuel Level uidata: - WID: 18 + WID: 16 TelemetryField: Fuel Level + 17: + uiwindow: + Dims: + X0: 60 + Y0: 91 + Width: 85 + Height: 57 + Decor: + BGColour: 4161 + FGColour: 65535 + TitleColour: 65535 + BorderColour: 63488 + TitleSize: 2 + TextSize: 4 + HasBorder: 1 + Padding: 0 + Opts: + ShowID: 0 + WinType: 2 + PreviewValue: "123" + Title: Lap + uidata: + WID: 17 + TelemetryField: Lap Number + 18: + uiwindow: + Dims: + X0: 9 + Y0: 413 + Width: 57 + Height: 57 + Decor: + BGColour: 4161 + FGColour: 65535 + TitleColour: 65535 + BorderColour: 63488 + TitleSize: 2 + TextSize: 4 + HasBorder: 1 + Padding: 0 + Opts: + ShowID: 0 + WinType: 2 + PreviewValue: "12" + Title: ABS + uidata: + WID: 18 + TelemetryField: ABS Control + 19: + uiwindow: + Dims: + X0: 643 + Y0: 132 + Width: 149 + Height: 50 + Decor: + BGColour: 4161 + FGColour: 65535 + TitleColour: 65535 + BorderColour: 63488 + TitleSize: 2 + TextSize: 3 + HasBorder: 1 + Padding: 0 + Opts: + ShowID: 0 + WinType: 2 + PreviewValue: "10.54" + Title: Fuel Av. + uidata: + WID: 19 + TelemetryField: Fuel Average Usage + 20: + uiwindow: + Dims: + X0: 470 + Y0: 242 + Width: 322 + Height: 50 + Decor: + BGColour: 4161 + FGColour: 65535 + TitleColour: 65535 + BorderColour: 63488 + TitleSize: 2 + TextSize: 3 + HasBorder: 1 + Padding: 0 + Opts: + ShowID: 0 + WinType: 2 + PreviewValue: "41.2" + Title: Fuel Rem. + uidata: + WID: 20 + TelemetryField: Fuel Expected Laps diff --git a/providers/iracing/iracing.go b/providers/iracing/iracing.go index fdfc608..b4a4a98 100644 --- a/providers/iracing/iracing.go +++ b/providers/iracing/iracing.go @@ -171,7 +171,7 @@ func (i *IRacing) Subscribe(requestFields map[int16]telem.FieldID) { switch id { case telem.RPMStateColour: i.data.VirtualBinds = append(i.data.VirtualBinds, telem.NewRPMLights()) - case telem.FuelCurrentLap: + case telem.FCCurrentLap: i.data.VirtualBinds = append(i.data.VirtualBinds, telem.NewFuelCalculator(i.logger.WithGroup("FUEL CALC"))) default: diff --git a/telemetry/data.go b/telemetry/data.go index 4e855bf..16648c7 100644 --- a/telemetry/data.go +++ b/telemetry/data.go @@ -172,8 +172,10 @@ const ( // RPM Dash Lights RPMStateColour // Fuel Calculator - FuelCurrentLap - FuelLastLap + FCCurrentLap + FCLastLap + FCAverage + FCExpectedLaps MaxFields ) const FirstField = Speed @@ -217,8 +219,10 @@ var FieldNames = [MaxFields]string{ // RPM Dash Lights RPMStateColour: "RPM State Colour", // Fuel Calculator - FuelCurrentLap: "Fuel Current Lap", - FuelLastLap: "Fuel Last Lap", + FCCurrentLap: "Fuel Current Lap", + FCLastLap: "Fuel Last Lap", + FCAverage: "Fuel Average Usage", + FCExpectedLaps: "Fuel Expected Laps", Empty: "Emtpy", } diff --git a/telemetry/fuel_calculator.go b/telemetry/fuel_calculator.go index deb0a02..548bbc8 100644 --- a/telemetry/fuel_calculator.go +++ b/telemetry/fuel_calculator.go @@ -10,18 +10,47 @@ import ( // NOTE: for managing fuel consumption and predictions we need to filter out // abnormal laps like going into the pits and refueling and whatnot +// NOTE: create a log file specifically for this, I reckon it would be better + type fuelCalcState int +const ( + MaxLaps = 256 +) + const ( // leaves pits or whenever this starts - outlap fuelCalcState = iota + OutlapState fuelCalcState = iota // we cross the line for the first time, we can count real time usage here // but don't have history yet - firstLap + FirstLapState // We already have history and can therefore do averages - normal + NormalState ) +type lapFuelData struct { + Lap int // Number of the lap of this data + StartFuelLevel float64 // Fuel level at the start/finish line + FuelUsage float64 // Fuel used during the lap + Valid bool // If we should consider this data for calculations +} + +func (lfd *lapFuelData) SetLap(lap int) { + lfd.Lap = lap +} + +func (lfd *lapFuelData) SetStartFuelLevel(fuelLevel float64) { + lfd.StartFuelLevel = fuelLevel +} + +func (lfd *lapFuelData) InvalidateLap() { + lfd.Valid = false +} + +func (lfd *lapFuelData) CalculateFuelUsage(fuelLevel float64) { + lfd.FuelUsage = lfd.StartFuelLevel - fuelLevel +} + // FuelCalculator acts as a Virtual Field middleware type FuelCalculator struct { Logger *slog.Logger @@ -47,121 +76,181 @@ type FuelCalculator struct { maxUsage float64 state fuelCalcState + + Laps [MaxLaps]lapFuelData + CurrentLap int + + averageFuelUsage float64 + expectedLaps float64 } func NewFuelCalculator(logger *slog.Logger) *FuelCalculator { return &FuelCalculator{ - Logger: logger, - setup: &sync.Once{}, - lapHistory: make([]float64, 0, 5), // Pre-allocate space for 5 laps - maxHistoryLaps: 3, // We want a 3-lap rolling average - lastLapNumber: 0, - state: outlap, + Logger: logger, + setup: &sync.Once{}, + lapHistory: make([]float64, 0, 5), // Pre-allocate space for 5 laps + maxHistoryLaps: 3, // We want a 3-lap rolling average + lastLapNumber: 0, + state: OutlapState, + CurrentLap: 0, + averageFuelUsage: 0.0, } } -func (fc *FuelCalculator) transitionState(state fuelCalcState) { - fc.state = state +func (fc *FuelCalculator) initializeFCTelemetryFields(td *TelemetryData) { + td.Values[FCLastLap].Type = DataTypeSTRING + td.Values[FCLastLap].Str = "No Data" + + td.Values[FCCurrentLap].Type = DataTypeSTRING + td.Values[FCCurrentLap].Str = "No Data" + + td.Values[FCExpectedLaps].Type = DataTypeSTRING + td.Values[FCExpectedLaps].Str = "No Data" + + td.Values[FCAverage].Type = DataTypeSTRING + td.Values[FCAverage].Str = "No Data" } -func (fc *FuelCalculator) crossedStartFinishLine(lap int) bool { - return lap > fc.lastLapNumber +func (fc *FuelCalculator) newLapData(lap int, fuelLevel float64) { + fc.Laps[fc.CurrentLap].SetStartFuelLevel(fuelLevel) + fc.Laps[fc.CurrentLap].SetLap(lap) + fc.Laps[fc.CurrentLap].Valid = true } -func (fc *FuelCalculator) refueled(currentFuelLevel float64) bool { - return currentFuelLevel > fc.fuelAtLapStart +func (fc *FuelCalculator) MaxLapsReached(td *TelemetryData) { + td.Values[FCLastLap].Str = "MAX!!!" + td.Values[FCCurrentLap].Str = "MAX!!!" } -func (fc *FuelCalculator) storeStartFinishLineFuelLevels(curFuel float64, lap int) { - fc.fuelAtLapStart = curFuel - fc.lastLapNumber = lap +func (fc *FuelCalculator) updateLapFuelUsage(td *TelemetryData, fuel float64) { + fc.Logger.Debug(fmt.Sprintf("= %-2d =============================================", fc.CurrentLap)) + fc.Logger.Debug(fmt.Sprintf("-> Updating Lap Fuel Usage")) + fc.Logger.Debug(fmt.Sprintf(" %+v", fc.Laps[fc.CurrentLap])) + fc.Logger.Debug(fmt.Sprintf(" %f - %f = %f", + fc.Laps[fc.CurrentLap].StartFuelLevel, fuel, fc.Laps[fc.CurrentLap].StartFuelLevel-fuel)) + + fc.Laps[fc.CurrentLap].CalculateFuelUsage(fuel) + td.Values[FCLastLap].Str = fmt.Sprintf("%.1f", fc.Laps[fc.CurrentLap].FuelUsage) } -func (fc *FuelCalculator) calculateCurLapFuelUsage(td *TelemetryData, fuel float64) { - td.Values[FuelCurrentLap].Type = DataTypeSTRING - td.Values[FuelCurrentLap].Str = fmt.Sprintf("%.2f", fc.fuelAtLapStart-fuel) +func (fc *FuelCalculator) updateAverageFuelUsage(td *TelemetryData) { + // NOTE: this is a dumb approach on how to calculte fuel usage + // sum := 0.0 + // lapCount := 0 + // for k := 0; k < fc.CurrentLap; k++ { + // if !fc.Laps[k].Valid { + // continue + // } + // + // sum += fc.Laps[k].FuelUsage + // lapCount += 1 + // } + // + // if lapCount == 0 { + // return + // } + // + // fc.averageFuelUsage = sum / float64(lapCount) + fc.averageFuelUsage = fc.Laps[fc.CurrentLap].FuelUsage + + td.Values[FCAverage].Str = fmt.Sprintf("%.2f", fc.averageFuelUsage) } -func (fc *FuelCalculator) processOutlap(td *TelemetryData, lap int) { - currentFuelLevel, err := strconv.ParseFloat(td.Values[FuelLevel].Str, 64) - if err != nil { - fc.Logger.Debug(fmt.Sprintf("error parsing fuel level: %+v", err)) +func (fc *FuelCalculator) updateExpectedLaps(td *TelemetryData, fuel float64) { + fc.expectedLaps = fuel / fc.averageFuelUsage + + td.Values[FCExpectedLaps].Str = fmt.Sprintf("%.1f", fc.expectedLaps) +} + +func (fc *FuelCalculator) startFinishLineCrossed(td *TelemetryData, lap int, fuel float64) { + if fc.state == OutlapState { + fc.state = FirstLapState + } + + if fc.state == FirstLapState { + fc.state = NormalState + } + + // if fc.state == NormalState { + // // In the normal state we have normal calculations to compute + // fc.updateLapFuelUsage(td, fuel) + // } + + if fc.CurrentLap == MaxLaps { + fc.MaxLapsReached(td) return } - if fc.crossedStartFinishLine(lap) { - fc.storeStartFinishLineFuelLevels(currentFuelLevel, lap) - fc.transitionState(firstLap) - } + // 1. Update last lap (we are still on the curret index) lap's fuel usage + fc.updateLapFuelUsage(td, fuel) + // 2. Update the average usage + fc.updateAverageFuelUsage(td) + // 3. Update the expected laps + fc.updateExpectedLaps(td, fuel) - if fc.refueled(currentFuelLevel) { - fc.transitionState(outlap) - } + // Go into the next lap + fc.CurrentLap += 1 + fc.newLapData(lap, fuel) } -func (fc *FuelCalculator) processFirstlap(td *TelemetryData, lap int) { - currentFuelLevel, err := strconv.ParseFloat(td.Values[FuelLevel].Str, 64) - if err != nil { - fc.Logger.Debug(fmt.Sprintf("error parsing fuel level: %+v", err)) - return - } +func (fc *FuelCalculator) updateCurrentLapFuelUsage(td *TelemetryData, fuel float64) { + // NOTE: find a more performant way of float64 -> string + fuelDelta := fc.Laps[fc.CurrentLap].StartFuelLevel - fuel - if fc.crossedStartFinishLine(lap) { - fc.storeStartFinishLineFuelLevels(currentFuelLevel, lap) - fc.transitionState(normal) - } - - if fc.refueled(currentFuelLevel) { - fc.transitionState(outlap) - } - - fc.calculateCurLapFuelUsage(td, currentFuelLevel) + td.Values[FCCurrentLap].Str = fmt.Sprintf("%.1f", fuelDelta) } -func (fc *FuelCalculator) processNormal(td *TelemetryData, lap int) { - currentFuelLevel, err := strconv.ParseFloat(td.Values[FuelLevel].Str, 64) - if err != nil { - fc.Logger.Debug(fmt.Sprintf("error parsing fuel level: %+v", err)) - return - } +func (fc *FuelCalculator) updateRealTimeVariables(td *TelemetryData, lap int, fuel float64) { + // if fc.state == OutlapState { + // Nothing to calculate here currently + // return + // } - if fc.crossedStartFinishLine(lap) { - fc.storeStartFinishLineFuelLevels(currentFuelLevel, lap) - fc.transitionState(normal) - } + // Real time updates + fc.updateCurrentLapFuelUsage(td, fuel) +} - if fc.refueled(currentFuelLevel) { - fc.transitionState(outlap) - } - - fc.calculateCurLapFuelUsage(td, currentFuelLevel) - - // And here we add how to calculate last lap usage or whatever yo +// NOTE: I need to add better logic for this. We need to detect pit stops +// instead of just checking if the fuel is greater than before +func (fc *FuelCalculator) refueled(fuel float64) bool { + return fuel > fc.Laps[fc.CurrentLap].StartFuelLevel } func (fc *FuelCalculator) Process(td *TelemetryData) { // This setup function will set the default values for the fields we work // with on this fuel calculator fc.setup.Do(func() { - td.Values[FuelLastLap].Type = DataTypeSTRING - td.Values[FuelLastLap].Str = "No Data" - - td.Values[FuelCurrentLap].Type = DataTypeSTRING - td.Values[FuelCurrentLap].Str = "No Data" + fc.initializeFCTelemetryFields(td) }) - currentLap := int(td.Values[LapNumber].Raw) + scannedLap := int(td.Values[LapNumber].Raw) // NOTE: this is stupid as, fix it. I mean don't store fuel level as a string - // currentFuelLevel, err := strconv.ParseFloat(td.Values[FuelLevel].Str, 64) + scannedFuelLevel, err := strconv.ParseFloat(td.Values[FuelLevel].Str, 64) + if err != nil { + fc.Logger.Debug(fmt.Sprintf("error parsing fuel level: %+v", err)) - switch fc.state { - case outlap: - fc.processOutlap(td, currentLap) - case firstLap: - fc.processFirstlap(td, currentLap) - case normal: - fc.processNormal(td, currentLap) + td.Values[FCLastLap].Str = "ERROR" + td.Values[FCCurrentLap].Str = "ERROR" + + return } + + // Start the 0th lap + if fc.CurrentLap == 0 && fc.Laps[0].StartFuelLevel == 0 { + fc.newLapData(scannedLap, scannedFuelLevel) + } + + if fc.refueled(scannedFuelLevel) { + fc.Laps[fc.CurrentLap].StartFuelLevel = scannedFuelLevel + fc.Laps[fc.CurrentLap].InvalidateLap() + } + + if scannedLap > fc.CurrentLap { + // Crossed the start finish line to the next lap + fc.startFinishLineCrossed(td, scannedLap, scannedFuelLevel) + } + + fc.updateRealTimeVariables(td, scannedLap, scannedFuelLevel) } // Simple helper to wipe state on session changes