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; } }