コード例 #1
0
        private bool IsDone(IRaceDefinition raceDefinition, IStrategieResult strategie)
        {
            var done = false;

            switch (raceDefinition.RaceMode)
            {
            case RaceMode.Race:
                if (strategie.NumberOfLaps == raceDefinition.NumberOfLaps)
                {
                    done = true;
                }

                break;

            case RaceMode.Endurance:
                if (strategie.RaceTime >= raceDefinition.RaceDuration)
                {
                    done = true;
                }

                break;
            }

            return(done);
        }
コード例 #2
0
        private TimeSpan GetFuelFillingTime(IRaceDefinition raceDefinition, double currentFuelRate, int refuel)
        {
            // [s/%]
            var fillingSpeed = raceDefinition.FuelFillingDuration.TotalSeconds / raceDefinition.FuelToFillInPercent;

            return(TimeSpan.FromSeconds((refuel - currentFuelRate) * fillingSpeed));
        }
コード例 #3
0
        private void RunLaps(IRaceDefinition raceDefinition, ItemsProvider <TiresType> tiresProvider, double fuelConsumptionPerLap, PitStrategie pitStrategie, IStrategieResult strategie, ItemsProvider <int> fuelProvider)
        {
            var tireDefinition = raceDefinition.TiresDefinitions.First(t => t.TiresType == strategie.StartTiresType);

            var currentFuelRate       = 100.0;
            var currentTiresRate      = 100.0;
            var tireConsumptionPerLap = 100.0 / tireDefinition.OptimalNumberOfLaps;
            var needRefuel            = false;
            var needChangeTires       = false;

            var nextRefuel = fuelProvider.GetNext();

            do
            {
                strategie.NumberOfLaps++;
                currentFuelRate  -= fuelConsumptionPerLap;
                currentTiresRate -= tireConsumptionPerLap;

                if (currentFuelRate <= raceDefinition.FuelReservePercent)
                {
                    needRefuel = true;
                }

                if (currentTiresRate <= 10)
                {
                    needChangeTires = true;
                }

                if (needChangeTires || needRefuel)
                {
                    switch (pitStrategie)
                    {
                    case PitStrategie.OnlyNeeded:
                        break;

                    case PitStrategie.FuelEachTime:
                        needRefuel = currentFuelRate < nextRefuel;
                        break;

                    case PitStrategie.TiresEachTime:
                        needChangeTires = true;
                        break;

                    case PitStrategie.FuelAndTiresEachTime:
                        needRefuel      = currentFuelRate < nextRefuel;
                        needChangeTires = true;
                        break;
                    }

                    var pitStop = new PitStop
                    {
                        Refuel      = needRefuel ? nextRefuel : 0,
                        ChangeTires = needChangeTires,
                        LapNumber   = strategie.NumberOfLaps,
                        TiresType   = tireDefinition.TiresType,
                        FuelState   = currentFuelRate,
                        TiresState  = currentTiresRate
                    };
                    strategie.PitStops.Add(pitStop);

                    if (needChangeTires)
                    {
                        strategie.RaceTime = strategie.RaceTime.Add(raceDefinition.TiresChangeDuration);
                        needChangeTires    = false;
                        currentTiresRate   = 100.0;
                        var nextTires = tiresProvider.GetNext();
                        tireDefinition        = raceDefinition.TiresDefinitions.First(t => t.TiresType == nextTires);
                        tireConsumptionPerLap = 100.0 / tireDefinition.OptimalNumberOfLaps;
                        pitStop.TiresType     = tireDefinition.TiresType;
                    }

                    if (needRefuel)
                    {
                        strategie.RaceTime = strategie.RaceTime.Add(GetFuelFillingTime(raceDefinition, currentFuelRate, nextRefuel));
                        needRefuel         = false;
                        currentFuelRate    = nextRefuel;
                        nextRefuel         = fuelProvider.GetNext();
                    }

                    strategie.RaceTime = strategie.RaceTime.Add(raceDefinition.TimeLostForPitStop);
                }

                strategie.RaceTime      = strategie.RaceTime.Add(tireDefinition.AverageLapTime);
                strategie.TiresEndState = currentTiresRate;
                strategie.FuelEndState  = currentFuelRate;
            } while (!IsDone(raceDefinition, strategie));
        }
コード例 #4
0
        public IStrategieResult Resolve(IRaceDefinition raceDefinition)
        {
            var tireTypes         = raceDefinition.TiresDefinitions.Select(t => t.TiresType).ToList();
            var numberOfTiresType = tireTypes.Distinct().Count();

            if (numberOfTiresType != raceDefinition.TiresDefinitions.Count)
            {
                throw new InvalidOperationException("TiresDefinions is invalid, TiresType must be distinct");
            }


            var strategieResults      = new List <StrategieResult>();
            var fuelConsumptionPerLap = 100 / raceDefinition.NumberOfLapsWithFullFuel;
            var tiresProviders        = GetProviders(5, raceDefinition.TiresDefinitions.Select(t => t.TiresType).OrderBy(t => t).ToList());
            var fuelProviders         = GetProviders(4, new[]
            {
                50,
                60,
                70,
                80,
                90,
                100
            });

            foreach (PitStrategie pitStrategie in Enum.GetValues(typeof(PitStrategie)))
            {
                foreach (var tiresProvider in tiresProviders)
                {
                    foreach (var refuelProvider in fuelProviders)
                    {
                        var startTiresType = tiresProvider.GetNext();

                        var strategie = new StrategieResult
                        {
                            StartTiresType = startTiresType,
                            PitStops       = new List <IPitStop>(),
                            RaceTime       = TimeSpan.Zero
                        };
                        strategieResults.Add(strategie);

                        RunLaps(raceDefinition, tiresProvider, fuelConsumptionPerLap, pitStrategie, strategie, refuelProvider);
                    }
                }
            }

            StrategieResult result = null;

            switch (raceDefinition.RaceMode)
            {
            case RaceMode.Race:
                result = strategieResults.OrderBy(s => s.RaceTime).First();
                break;

            case RaceMode.Endurance:
                result = strategieResults
                         .OrderByDescending(s => s.NumberOfLaps)
                         .ThenBy(s => s.FuelEndState)
                         .First();
                break;
            }

            return(result);
        }