public List <NascarRaceLap> GetStartingLineup(NascarEvent raceEvent) { NascarRaceRun stage1 = raceEvent .Runs .OfType <NascarRaceRun>() .FirstOrDefault(r => r.RunType == NascarRunType.RaceStage1); return(StartingLineup(raceEvent, stage1)); }
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); }
public async virtual Task <NascarEvent> SimulateRaceAsync(NascarEvent raceEvent) { _lapTimeService = new LapTimeService(raceEvent.Track); _vehicleLapService = new VehicleLapService2(_lapTimeService); StateService.Initialize(); int cautionLapsRemaining = 0; int greenWhiteCheckeredLapCount = 2; int endOfStageCautionLapCount = 5; int pitsClosedBeforeStageEndLaps = 2; int nextStageEndLap = 0; int currentStageIndex = 0; int lapsRunUnderThisCaution = 0; bool pitsAreOpen = true; bool leadLapPitOnly = false; bool isFirstCautionLap = true; List <int> stageEndLaps = GetStageEndLaps(raceEvent); nextStageEndLap = stageEndLaps[currentStageIndex]; var firstStage = raceEvent.Runs.OfType <NascarRaceRun>().Where(r => r.RunType == NascarRunType.RaceStage1).SingleOrDefault(); var secondStage = raceEvent.Runs.OfType <NascarRaceRun>().Where(r => r.RunType == NascarRunType.RaceStage2).SingleOrDefault(); var finalStage = raceEvent.Runs.OfType <NascarRaceRun>().Where(r => r.RunType == NascarRunType.FinalRaceStage).SingleOrDefault(); NascarRaceRun run = firstStage; int advertisedRaceEndLap = finalStage.EndLap; int actualRaceEndLap = advertisedRaceEndLap; List <NascarRaceLap> raceLaps = _vehicleLapService.GetStartingLineup(raceEvent); List <NascarRaceLap> laps = new List <NascarRaceLap>(); StateService.GreenFlagOn(); for (int lapNumber = 1; lapNumber <= actualRaceEndLap; lapNumber++) { //***** random caution generator *****// if (!StateService.IsCaution) { var randomCautionResult = _cautionService.GetRandomCautionResult(); var isCaution = randomCautionResult.IsCaution; if (isCaution) { var caution = new NascarCautionSegment() { StartLap = lapNumber }; raceEvent.Cautions.Add(caution); isFirstCautionLap = true; StateService.CautionOn(); if (StateService.IsWhiteFlag) { cautionLapsRemaining = 1; } else { cautionLapsRemaining = randomCautionResult.CautionLaps; pitsAreOpen = false; } } } else { isFirstCautionLap = false; if (!pitsAreOpen && lapsRunUnderThisCaution > 0 && (lapNumber + pitsClosedBeforeStageEndLaps <= nextStageEndLap)) { pitsAreOpen = true; leadLapPitOnly = true; } else if (pitsAreOpen) { leadLapPitOnly = false; } } //***** end of race *****// if (lapNumber == actualRaceEndLap - 1) { StateService.WhiteFlagOn(); } else if (lapNumber == actualRaceEndLap) { StateService.CheckeredFlagOn(); } //***** end of stage *****// if (run.RunType != NascarRunType.FinalRaceStage) { if (lapNumber + pitsClosedBeforeStageEndLaps == nextStageEndLap) { // end of stage pitsAreOpen = false; } else if (lapNumber == nextStageEndLap) { // end of stage StateService.EndOfStageOn(); cautionLapsRemaining = endOfStageCautionLapCount; var caution = new NascarCautionSegment() { StartLap = lapNumber }; raceEvent.Cautions.Add(caution); isFirstCautionLap = true; currentStageIndex++; if (currentStageIndex == 1) { if (currentStageIndex < stageEndLaps.Count) { nextStageEndLap = stageEndLaps[currentStageIndex]; run = secondStage; } else { currentStageIndex++; } } leadLapPitOnly = (pitsAreOpen && lapsRunUnderThisCaution <= 2); pitsAreOpen = (lapsRunUnderThisCaution > 0); if (currentStageIndex == 2) { run = finalStage; nextStageEndLap = finalStage.EndLap; } } } //***** overdrive *****// if (StateService.IsCaution && !StateService.IsWhiteFlag && lapNumber + cautionLapsRemaining >= actualRaceEndLap) { // end of race extended by caution StateService.OverdriveOn(); actualRaceEndLap = (lapNumber + cautionLapsRemaining + greenWhiteCheckeredLapCount); } //***** end of caution *****// if (StateService.IsCaution && cautionLapsRemaining == 0) { // end of caution, back to green StateService.GreenFlagOn(); lapsRunUnderThisCaution = 0; raceEvent.Cautions.LastOrDefault().EndLap = lapNumber; var luckyDog = raceLaps.FirstOrDefault(l => l.IsLuckyDog); if (luckyDog != null) { luckyDog.IsLuckyDog = false; } } // vehicle pit stops if (pitsAreOpen) { raceLaps = SetPitStops(raceLaps, raceEvent.Track.PitWindow, StateService.IsCaution, leadLapPitOnly); } // vehicle lap times if (StateService.IsGreenFlag) { laps = _vehicleLapService.UpdateRaceLaps(raceLaps, LapState.GreenFlag); } else if (StateService.IsCaution) { if (isFirstCautionLap) { laps = _vehicleLapService.UpdateRaceLaps(raceLaps, LapState.CautionFlag); } else if (cautionLapsRemaining == 1) { laps = _vehicleLapService.UpdateRaceLaps(raceLaps, LapState.OneToGreenFlag); } else { laps = _vehicleLapService.UpdateRaceLaps(raceLaps, LapState.CautionFlag); } } ((List <NascarRaceLap>)run.Laps).AddRange(laps.ToList()); raceLaps.Clear(); raceLaps.AddRange(laps); laps.Clear(); if (StateService.IsCaution) { cautionLapsRemaining--; lapsRunUnderThisCaution++; } Console.WriteLine($"Lap {lapNumber} [{StateService.State.ToString()}] "); } return(await Task.FromResult(raceEvent)); }