Example #1
0
        public RaceBuilder AddDrivers(IEnumerable <SeasonDriver> drivers)
        {
            // Check if given parameters aren't null
            if (drivers is null)
            {
                throw new NullReferenceException();
            }

            foreach (var driver in drivers)
            {
                // Ensures that dropped drivers won't be added to a race by not creating a result object for them
                if (driver.Dropped)
                {
                    continue;
                }

                DriverResult driverResult = new DriverResult {
                    SeasonDriver = driver
                };
                foreach (var stint in _race.Stints)
                {
                    StintResult driverStint = new StintResult
                    {
                        StintStatus = StintStatus.Concept,
                        Number      = stint.Number
                    };
                    driverResult.StintResults.Add(driverStint);
                }
                _race.DriverResults.Add(driverResult);
            }
            return(this);
        }
        /// <summary>
        /// Gets the points result of a single <see cref="StintResult"/>, with any enabled <see cref="StintResult"/> modifiers applied.
        /// </summary>
        /// <param name="stint">The <see cref="Stint"/> supplying the modifiers to use.</param>
        /// <param name="driverResult">The partial <see cref="DriverResult"/> from which to derive certain modifiers.</param>
        public void UpdateStintResult(StintResult stintResult,
                                      Stint stint,
                                      DriverResult driverResult,
                                      SeasonTeam team,
                                      Weather weather,
                                      Specification trackSpec,
                                      int driverCount,
                                      int qualyBonus,
                                      int pitMin,
                                      int pitMax,
                                      AppConfig appConfig)
        {
            if (stintResult is null || driverResult is null || stint is null || team is null || appConfig is null)
            {
                throw new NullReferenceException();
            }

            // Applies the increased or decreased odds for the specific track.
            double engineWeatherMultiplier = 1;
            int    weatherRNG = 0;
            int    weatherDNF = 0;

            var driver = driverResult.SeasonDriver;

            stintResult.StintStatus = StintStatus.Running;
            switch (weather)
            {
            case Weather.Sunny:
                engineWeatherMultiplier = appConfig.SunnyEngineMultiplier;
                break;

            case Weather.Overcast:
                engineWeatherMultiplier = appConfig.OvercastEngineMultiplier;
                break;

            case Weather.Rain:
                weatherRNG += appConfig.RainAdditionalRNG;
                weatherDNF += appConfig.RainDriverReliabilityModifier;
                engineWeatherMultiplier = appConfig.WetEngineMultiplier;
                break;

            case Weather.Storm:
                weatherRNG += appConfig.StormAdditionalRNG;
                weatherDNF += appConfig.StormDriverReliabilityModifier;
                engineWeatherMultiplier = appConfig.WetEngineMultiplier;
                break;
            }

            if (stint.ApplyReliability)
            {
                // Check for the reliability of the chassis.
                if (GetReliabilityResult(team.Reliability + driverResult.ChassisRelMod) == -1)
                {
                    stintResult.StintStatus = StintStatus.ChassisDNF;
                }
                // Check for the reliability of the driver.
                else if (GetReliabilityResult(driver.Reliability + weatherDNF + driverResult.DriverRelMod) == -1)
                {
                    stintResult.StintStatus = StintStatus.DriverDNF;
                    if (driver.SeasonDriverId == 1894)
                    {
                        stintResult.StintStatus = StintStatus.DriverDNF;
                    }
                }
            }

            if (stintResult.StintStatus == StintStatus.Running || stintResult.StintStatus == StintStatus.Mistake)
            {
                // Add one because Random.Next() has an exclusive upper bound.
                int result = _rng.Next(stint.RNGMinimum + driverResult.MinRNG, stint.RNGMaximum + weatherRNG + driverResult.MaxRNG + 1);
                // Iterate through GetReliabilityResult twice to check if a driver made a mistake or not, requires two consequential true's to return a mistake
                bool mistake = false;
                for (int i = 0; i < appConfig.MistakeAmountRolls; i++)
                {
                    mistake = GetReliabilityResult(driver.Reliability + weatherDNF + driverResult.DriverRelMod) == -1;
                    if (!mistake)
                    {
                        break;
                    }
                }
                // If the bool mistake is true then we have to subtract from the result
                if (mistake)
                {
                    result += _rng.Next(appConfig.MistakeLowerValue, appConfig.MistakeUpperValue);
                    stintResult.StintStatus = StintStatus.Mistake;
                }
                // In here we loop through the strategy of the driver to see if it is time for a pitstop
                foreach (var tyreStrat in driverResult.Strategy.Tyres.OrderBy(t => t.StintNumberApplied))
                {
                    // The value for the tyre in iteration matches the current stint number, so it is time for a pitstop
                    if (tyreStrat.StintNumberApplied == stint.Number && stint.Number != 1)
                    {
                        driverResult.TyreLife = tyreStrat.Tyre.Pace;
                        driverResult.CurrTyre = tyreStrat.Tyre;
                        stintResult.Pitstop   = true;
                    }
                }
                // Current status tells us there is a pitstop so calculate pitstop RNG over the result
                if (stintResult.Pitstop)
                {
                    result += _rng.Next(pitMin, pitMax + 1);
                }
                // Deals with the tyre wear for this driver and changes tyres if it is needed
                result += driverResult.TyreLife;
                // Current status tells us the driver is still running so we apply some of the wear to the tyre
                driverResult.TyreLife += _rng.Next(driverResult.CurrTyre.MaxWear + driverResult.MaxTyreWear, driverResult.CurrTyre.MinWear + driverResult.MinTyreWear);

                // Applies the qualifying bonus based on the amount of drivers for the current stint
                if (stint.ApplyQualifyingBonus)
                {
                    result += Helpers.GetQualifyingBonus(driverResult.Grid, driverCount, qualyBonus);
                }
                // Applies the quality of the driver to the current stint if it is relevant
                if (stint.ApplyDriverLevel)
                {
                    result += driver.Skill + driverResult.DriverRacePace;
                }
                // Applies the power of the chassis to the result when it applies
                if (stint.ApplyChassisLevel)
                {
                    int bonus       = Helpers.GetChassisBonus(Helpers.CreateTeamSpecDictionary(team), trackSpec.ToString());
                    int statusBonus = 0;
                    if (driver.DriverStatus == DriverStatus.First)
                    {
                        statusBonus = appConfig.ChassisModifierDriverStatus;
                    }
                    else if (driver.DriverStatus == DriverStatus.Second)
                    {
                        statusBonus = (appConfig.ChassisModifierDriverStatus * -1);
                    }

                    result += team.Chassis + driverResult.ChassisRacePace + bonus + statusBonus;
                }
                // Applies the power of the engine plus external factors when it is relevant for the current stint
                if (stint.ApplyEngineLevel)
                {
                    result += (int)Math.Round((team.Engine.Power + driverResult.EngineRacePace) * engineWeatherMultiplier);
                }
                // Finally adds the result of the stint to the stintresult
                stintResult.Result = result;
            }
        }