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);
        }
Beispiel #4
0
        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);
            }
        }