protected virtual void ProcessLap(NascarRaceLap vehicle, RaceState state) { switch (state) { case RaceState.PreRace: { throw new ArgumentException($"Invalid state in LapService.ProcessLap: {state.ToString()}"); } case RaceState.GreenFlag: case RaceState.WhiteFlag: case RaceState.Checkered: case RaceState.Overdrive: { ProcessGreenFlagLap(vehicle); break; } case RaceState.EndOfStage: case RaceState.Caution: case RaceState.OneToGo: { ProcessCautionFlagLap(vehicle); break; } default: { throw new ArgumentException($"Unknown race state in LapService.ProcessLap: {state.ToString()}", nameof(state)); } } }
public void RegisterVehicle(NascarRaceLap vehicle) { if (Vehicles.Keys.Contains(vehicle.VehicleId)) { throw new ArgumentException($"Already registered vehicle {vehicle.VehicleId}"); } Vehicles.Add(vehicle.VehicleId, new VehicleStatus() { VehicleState = VehicleState.OnTrack, LapNumber = 0, LapsDown = 0, DeltaLeader = vehicle.DeltaLeader, DeltaNext = vehicle.Delta }); }
protected virtual List <NascarRaceLap> StartingLineup(NascarEvent raceEvent, NascarRaceRun stage1) { List <NascarRaceLap> raceLaps = new List <NascarRaceLap>(); int position = 1; double leaderTotalTime = 0; foreach (QualifyingResult vehicle in raceEvent.QualifyingResults.OrderBy(q => q.Position)) { vehicle.Position = position; double deltaRow = 0.5; double deltaNext = vehicle.Position == 1 ? 0 : (vehicle.Position % 2) == 0 ? 0.0 : 0.5; double deltaLeader = vehicle.Position <= 2 ? 0 : Math.Round((double)((vehicle.Position - 1) / 2), 0) * deltaRow; var newLap = new NascarRaceLap() { Position = vehicle.Position, VehicleId = vehicle.VehicleId, DriverId = vehicle.DriverId, LapNumber = 0, LeaderLap = 0, Delta = Math.Round(deltaNext, 3), DeltaLeader = Math.Round(deltaLeader, 3), DeltaTravelledLeader = Math.Round(deltaLeader, 3), LapSpeed = 0, LapTime = 0, TotalTime = 0 }; raceLaps.Add(newLap); if (leaderTotalTime == 0) { leaderTotalTime = newLap.TotalTime; } position++; } Console.WriteLine("Starting Lineup"); PrintStandings(raceLaps, LapState.OneToGreenFlag); return(raceLaps); }
protected virtual List <NascarRaceLap> SetPitStops(List <NascarRaceLap> thisLaps, int pitWindow, bool underCaution, bool leadLapOnly) { if (underCaution) { if (!thisLaps.Any(l => l.IsLuckyDog)) { int maxLapsDown = thisLaps.Max(l => l.LapsBehind); for (int i = 1; i <= maxLapsDown; i++) { var luckyDog = thisLaps.Where(l => l.LapsBehind == i).OrderBy(l => l.Position).FirstOrDefault(); if (luckyDog != null) { luckyDog.IsLuckyDog = true; break; } } } var leadLapCount = thisLaps.Count(l => l.IsLeadLap); for (int i = 0; i < thisLaps.Count; i++) { NascarRaceLap thisLap = thisLaps[i]; if (leadLapOnly && thisLap.IsLeadLap) { if (thisLap.LapsSincePit > (pitWindow * .25)) { thisLap.PitInLap = true; } else if (i > (leadLapCount / 2)) { // end of lead lap thisLap.PitInLap = true; } } else if (!leadLapOnly && !thisLap.IsLeadLap) { if (thisLap.LapsSincePit > (pitWindow * .6)) { thisLap.PitInLap = true; } } //else if (i == leadLapCount - 1 && !thisLaps.Any(l => l.IsLuckyDog)) //{ // // lucky dog // // TODO: FIX LUCKY DOG // // TODO: FIX WAVE-AROUNDS // thisLap.IsLuckyDog = true; // thisLap.PitInLap = true; //} } } else { var pitWindowRange = (int)(pitWindow * .25); foreach (NascarRaceLap thisLap in thisLaps.Where(l => l.LapsSincePit > (pitWindow - pitWindowRange))) { if (thisLap.LapsSincePit > pitWindow) { thisLap.PitInLap = true; } else { var margin = 1 - (thisLap.LapsSincePit / (double)pitWindow); var threshold = margin * pitWindowRange; var rawValue = _pitRandom.Next(pitWindowRange); var value = ((double)rawValue / pitWindowRange) * 10; if (value > threshold) { thisLap.PitInLap = true; } } } } return(thisLaps); }
protected virtual void ProcessCautionFlagLap(NascarRaceLap vehicle) { var vehicleStatus = _state.Vehicles[vehicle.VehicleId]; // Update the status for this lap switch (vehicleStatus.VehicleState) { case VehicleState.OnTrack: { if (vehicle.PitInLap) { vehicleStatus.VehicleState = VehicleState.PitInLap; } vehicleStatus.LapNumber += 1; break; } case VehicleState.PitInLap: { vehicleStatus.VehicleState = VehicleState.PitOutLap; vehicleStatus.LastPitStop = _lapNumber; vehicleStatus.LapNumber += 1; break; } case VehicleState.PitOutLap: { vehicleStatus.VehicleState = VehicleState.OnTrack; vehicleStatus.LapNumber += 1; break; } case VehicleState.InPit: case VehicleState.InGarage: case VehicleState.Retired: default: break; } if (vehicleStatus.VehicleState != VehicleState.InPit && vehicleStatus.VehicleState != VehicleState.InGarage && vehicleStatus.VehicleState != VehicleState.Retired) { var lapTimeResult = LapTimeService.GetLapTime(vehicle.LapsSincePit, RaceState.Caution, vehicleStatus.VehicleState); var newVehicleEvent = new VehicleEvent() { VehicleId = vehicle.VehicleId, Elapsed = vehicleStatus.Elapsed.Add(lapTimeResult.Elapsed), LapNumber = vehicleStatus.LapNumber, VehicleEventType = vehicleStatus.VehicleState == VehicleState.PitInLap ? VehicleEventType.EnterPit : vehicleStatus.VehicleState == VehicleState.PitOutLap ? VehicleEventType.ExitPit : VehicleEventType.CompleteLap }; _vehicleEvents.Add(newVehicleEvent); } }