private void ComputePace() { if (LastCompletedLap == null) { Pace = TimeSpan.Zero; return; } int totalPaceLaps = 0; TimeSpan pace = TimeSpan.Zero; for (int i = _lapsInfo.Count - 1; i >= 0 && totalPaceLaps < PaceLaps; i--) { LapInfo lap = _lapsInfo[i]; if (!lap.Completed || (!lap.Valid && !Session.RetrieveAlsoInvalidLaps)) { continue; } pace = pace.Add(lap.LapTime); totalPaceLaps++; } Pace = totalPaceLaps == 0 ? TimeSpan.Zero : new TimeSpan(pace.Ticks / totalPaceLaps); }
private void FinishLap(LapInfo lapToFinish, SimulatorDataSet dataSet) { lapToFinish.FinishLap(dataSet, DriverInfo); lapToFinish.SectorCompletedEvent -= LapSectorCompletedEvent; lapToFinish.LapCompletedEvent -= LapCompletedHandler; lapToFinish.LapInvalidatedEvent -= LapInvalidatedHandler; if (lapToFinish.LapTime == TimeSpan.Zero) { lapToFinish.Valid = false; RevertSectorChanges(lapToFinish); } if (ShouldLapBeDiscarded(lapToFinish, dataSet)) { _lapsInfo.Remove(lapToFinish); return; } if (lapToFinish.Valid && lapToFinish.LapTime != TimeSpan.Zero && (BestLap == null || lapToFinish.LapTime < BestLap.LapTime)) { BestLap = lapToFinish; } OnLapCompleted(new LapEventArgs(lapToFinish)); ComputePace(); }
public LapPortionTimesComparatorViewModel(LapInfo referenceLap, LapInfo comparedLap) { ReferenceLap = referenceLap; ComparedLap = comparedLap; TimeDifference = TimeSpan.Zero; SubscribeToComparedLap(); }
public LapTelemetryInfo(DriverInfo driverInfo, SimulatorDataSet dataSet, LapInfo lapInfo, TimeSpan snapshotInterval, SimulatorSourceInfo simulatorSourceInfo) { LapStarSnapshot = new TelemetrySnapshot(driverInfo, dataSet.SessionInfo.WeatherInfo, dataSet.InputInfo, simulatorSourceInfo); LapInfo = lapInfo; PortionTimes = new LapPortionTimes(10, dataSet.SessionInfo.TrackInfo.LayoutLength.InMeters, lapInfo); TimedTelemetrySnapshots = new TimedTelemetrySnapshots(snapshotInterval); }
public LapPortionTimes(int baseTrackPortionLength, double trackLength, LapInfo lap) { _lastTrackedPortion = -1; _baseTrackPortionLength = baseTrackPortionLength; Lap = lap; _trackPortions = new TimeSpan[(int)trackLength / baseTrackPortionLength + 1]; }
private void FinishLap(LapInfo lapToFinish, SimulatorDataSet dataSet) { if (lapToFinish.Completed) { return; } lapToFinish.FinishLap(dataSet, DriverInfo); lapToFinish.SectorCompletedEvent -= LapSectorCompletedEvent; lapToFinish.LapInvalidatedEvent -= LapInvalidatedHandler; if (lapToFinish.LapTime == TimeSpan.Zero) { lapToFinish.InvalidateLap(LapInvalidationReasonKind.NoValidLapTime); RevertSectorChanges(lapToFinish); } if (ShouldLapBeDiscarded(lapToFinish, dataSet)) { _lapsInfo.Remove(lapToFinish); return; } if (lapToFinish.Valid && lapToFinish.LapTime != TimeSpan.Zero && (BestLap == null || lapToFinish.LapTime < BestLap.LapTime)) { BestLap = lapToFinish; } OnLapCompleted(new LapEventArgs(lapToFinish)); Logger.Info($"Driver {DriverInfo.DriverName}, Lap {lapToFinish.LapNumber} finnished. REASON: {lapToFinish.LapCompletionMethod}"); ComputePace(); PurgeLapsTelemetry(); }
public PitStopInfo(SimulatorDataSet set, DriverTiming driver, LapInfo entryLap) { Driver = driver; EntryLap = entryLap; Phase = PitPhase.Entry; PitEntry = set.SessionInfo.SessionTime; PitStopDuration = TimeSpan.Zero; PitExit = PitEntry; PitStopStart = PitEntry; PitStopEnd = PitEntry; }
private bool ShouldFinishLap(SimulatorDataSet dataSet, LapInfo currentLap) { SessionInfo sessionInfo = dataSet.SessionInfo; // Use completed laps indication to end lap, when we use the sim provided lap times. This gives us the biggest assurance that lap time is already properly set. But wait for lap to be at least 5 seconds in if (dataSet.SimulatorSourceInfo.HasLapTimeInformation && (currentLap.LapNumber < DriverInfo.CompletedLaps + 1)) { currentLap.LapCompletionMethod = LapCompletionMethod.ByLapNumber; return(true); } // Crossed line at out lap if (dataSet.SessionInfo.SessionType != SessionType.Race && currentLap.PitLap && (DriverInfo.LapDistance - _previousTickLapDistance < sessionInfo.TrackInfo.LayoutLength.InMeters * -0.90)) { currentLap.LapCompletionMethod = LapCompletionMethod.ByCrossingTheLine; return(true); } if ((!dataSet.SimulatorSourceInfo.HasLapTimeInformation || dataSet.SimulatorSourceInfo.SimNotReportingEndOfOutLapCorrectly) && (DriverInfo.LapDistance - _previousTickLapDistance < sessionInfo.TrackInfo.LayoutLength.InMeters * -0.90)) { currentLap.LapCompletionMethod = LapCompletionMethod.ByCrossingTheLine; return(true); } if (!dataSet.SimulatorSourceInfo.OutLapIsValid && !currentLap.Valid && DriverInfo.CurrentLapValid && DriverInfo.IsPlayer && (currentLap.FirstLap && !InvalidateFirstLap)) { currentLap.LapCompletionMethod = LapCompletionMethod.ByChangingValidity; return(true); } if (!dataSet.SimulatorSourceInfo.OutLapIsValid && !currentLap.Valid && DriverInfo.CurrentLapValid && DriverInfo.IsPlayer && currentLap.PitLap && _previousTickLapDistance < DriverInfo.LapDistance && SessionType.Race != sessionInfo.SessionType && !DriverInfo.InPits) { currentLap.LapCompletionMethod = LapCompletionMethod.ByChangingValidity2; return(true); } if (!currentLap.Valid && DriverInfo.CurrentLapValid && SessionType.Race == sessionInfo.SessionType && !DriverInfo.IsPlayer && (currentLap.FirstLap && !InvalidateFirstLap)) { currentLap.LapCompletionMethod = LapCompletionMethod.ByChangingValidity3; return(true); } // Driver is DNF/DQ -> finish timed lap, and set it to invalid if (DriverInfo.FinishStatus != DriverFinishStatus.Na && DriverInfo.FinishStatus != DriverFinishStatus.None) { CurrentLap.InvalidateLap(LapInvalidationReasonKind.DriverDnf); return(true); } return(false); }
public LapInfo(SimulatorDataSet dataSet, int lapNumber, DriverTiming driver, bool firstLap, LapInfo previousLapInfo) { Driver = driver; LapStart = dataSet.SessionInfo.SessionTime; LapProgressTimeBySim = TimeSpan.Zero; LapProgressTimeByTiming = TimeSpan.Zero; LapNumber = lapNumber; Valid = true; FirstLap = firstLap; PitLap = false; PreviousLap = previousLapInfo; CompletedDistance = double.NaN; LapTelemetryInfo = new LapTelemetryInfo(driver.DriverInfo, dataSet, this, TimeSpan.FromMilliseconds(Driver.Session.TimingDataViewModel.DisplaySettingsViewModel.TelemetrySettingsViewModel.LoggingInterval), dataSet.SimulatorSourceInfo); }
public LapInfo(SimulatorDataSet dataSet, int lapNumber, DriverTiming driver, bool firstLap, LapInfo previousLapInfo) { Driver = driver; LapStart = dataSet.SessionInfo.SessionTime; LapProgressTimeBySim = TimeSpan.Zero; LapProgressTimeByTiming = TimeSpan.Zero; LapNumber = lapNumber; Valid = true; FirstLap = firstLap; PitLap = false; PreviousLap = previousLapInfo; CompletedDistance = double.NaN; LapTelemetryInfo = new LapTelemetryInfo(driver.DriverInfo, dataSet, this); }
private void CreateNewLap(SimulatorDataSet dataSet, ILapInfo lapToCreateFrom) { if ((DriverInfo.FinishStatus == DriverFinishStatus.Na || DriverInfo.FinishStatus == DriverFinishStatus.None) && dataSet.SessionInfo.SessionPhase != SessionPhase.Checkered) { var newLap = new LapInfo( dataSet, DriverInfo.CompletedLaps + 1, this, lapToCreateFrom); newLap.SectorCompletedEvent += LapSectorCompletedEvent; newLap.LapInvalidatedEvent += LapInvalidatedHandler; _lapsInfo.Add(newLap); OnNewLapStarted(new LapEventArgs(newLap)); } }
private void RevertSectorChanges(LapInfo lap) { if (BestSector1 != null && BestSector1 == lap.Sector1) { BestSector1 = FindBestSector(LapInfo.Sector1SelFunc); } if (BestSector2 != null && BestSector2 == lap.Sector2) { BestSector2 = FindBestSector(LapInfo.Sector2SelFunc); } if (BestSector3 != null && BestSector3 == lap.Sector3) { BestSector3 = FindBestSector(LapInfo.Sector3SelFunc); } }
public LapEventArgs(LapInfo lapInfo) { Lap = lapInfo; }
public LapInfo(SimulatorDataSet dataSet, int lapNumber, DriverTiming driver, LapInfo previousLapInfo) : this(dataSet, lapNumber, driver, false, previousLapInfo) { }
public SectorTiming(int sectorNumber, SimulatorDataSet simulatorData, LapInfo lap) { SectorNumber = sectorNumber; _startTime = simulatorData.SessionInfo.SessionTime; Lap = lap; }
public CombinedLapPortionComparatorsVM(LapInfo playerLap) { _playerLap = playerLap; RecreatePlayerLapToPrevious(); RecreatePlayerLapToPlayerBest(); }
public bool UpdateLaps(SimulatorDataSet set) { SessionInfo sessionInfo = set.SessionInfo; if (!sessionInfo.IsActive) { return(false); } if (sessionInfo.SessionPhase == SessionPhase.Countdown) { return(false); } if (DriverInfo.FinishStatus != DriverFinishStatus.Na && DriverInfo.FinishStatus != DriverFinishStatus.None && CurrentLap != null && CurrentLap.Completed) { return(false); } if (TopSpeed < DriverInfo.Speed && DriverInfo.Speed < _maximumVelocity) { TopSpeed = DriverInfo.Speed; } UpdateInPitsProperty(set); if (_lapsInfo.Count == 0) { LapInfo firstLap = new LapInfo(set, DriverInfo.CompletedLaps + 1, this, true, null); if (InvalidateFirstLap) { firstLap.InvalidateLap(LapInvalidationReasonKind.InvalidatedFirstLap); } firstLap.SectorCompletedEvent += LapSectorCompletedEvent; firstLap.LapInvalidatedEvent += LapInvalidatedHandler; _lapsInfo.Add(firstLap); OnNewLapStarted(new LapEventArgs(firstLap)); } if (LastLap != null && LastLap.IsPending && !LastLap.UpdatePendingState(set, DriverInfo)) { FinishLap(LastLap, set); } ILapInfo currentLap = CurrentLap; if (!currentLap.Completed) { UpdateCurrentLap(set); } if (_refreshBestSectorIndicationWatch.ElapsedMilliseconds > 2000) { UpdateBestSectorProperties(); _refreshBestSectorIndicationWatch.Restart(); } if (ShouldFinishLap(set, currentLap)) { if (!currentLap.SwitchToPendingIfNecessary(set, DriverInfo)) { FinishLap(currentLap, set); } CreateNewLap(set, currentLap); _previousTickLapDistance = DriverInfo.LapDistance; return(currentLap.Valid); } if (set.SimulatorSourceInfo.OverrideBestLap) { CheckAndOverrideBestLap(sessionInfo.TrackInfo.LayoutLength.InMeters); } _previousTickLapDistance = DriverInfo.LapDistance; return(false); }
private bool ShouldLapBeDiscarded(LapInfo lap, SimulatorDataSet dataSet) { return(!lap.IsLapDataSane(dataSet)); }
public bool UpdateLaps(SimulatorDataSet set) { SessionInfo sessionInfo = set.SessionInfo; if (!sessionInfo.IsActive) { return(false); } if (sessionInfo.SessionPhase == SessionPhase.Countdown) { return(false); } if (DriverInfo.FinishStatus != DriverInfo.DriverFinishStatus.Na && DriverInfo.FinishStatus != DriverInfo.DriverFinishStatus.None && CurrentLap != null && CurrentLap.Completed) { return(false); } if (TopSpeed < DriverInfo.Speed && DriverInfo.Speed < _maximumVelocity) { TopSpeed = DriverInfo.Speed; } UpdateInPitsProperty(set); if (_lapsInfo.Count == 0) { LapInfo firstLap = new LapInfo(set, DriverInfo.CompletedLaps + 1, this, true, null) { Valid = !InvalidateFirstLap }; firstLap.SectorCompletedEvent += LapSectorCompletedEvent; firstLap.LapInvalidatedEvent += LapInvalidatedHandler; firstLap.LapCompletedEvent += LapCompletedHandler; _lapsInfo.Add(firstLap); OnNewLapStarted(new LapEventArgs(firstLap)); } if (LastLap != null && LastLap.IsPending && !LastLap.UpdatePendingState(set, DriverInfo)) { FinishLap(LastLap, set); } LapInfo currentLap = CurrentLap; if (!currentLap.Completed) { UpdateCurrentLap(set); } if (ShouldFinishLap(set, currentLap)) { if (!currentLap.SwitchToPendingIfNecessary(set, DriverInfo)) { FinishLap(currentLap, set); } CreateNewLap(set, currentLap); _previousTickLapDistance = DriverInfo.LapDistance; return(currentLap.Valid); } _previousTickLapDistance = DriverInfo.LapDistance; return(false); }
public LapTelemetryInfo(DriverInfo driverInfo, SimulatorDataSet dataSet, LapInfo lapInfo) { LapStarSnapshot = new TelemetrySnapshot(driverInfo, dataSet.SessionInfo.WeatherInfo); LapInfo = lapInfo; PortionTimes = new LapPortionTimes(10, dataSet.SessionInfo.TrackInfo.LayoutLength, lapInfo); }