public void LimitedShuffleTest() { var array = Enumerable.Range(1, 10).ToArray(); Debug.WriteLine(string.Join(", ", LimitedShuffle.Get(array, 0.1).Take(array.Length))); Debug.WriteLine(string.Join(", ", LimitedShuffle.Get(array, 0.2).Take(array.Length))); Debug.WriteLine(string.Join(", ", LimitedShuffle.Get(array, 0.3).Take(array.Length))); foreach (var i in Enumerable.Range(1, 4)) { var v = Enumerable.Range(4 - i, 1 + 2 * i).Select(x => CountAverage(() => LimitedShuffle.Get(array, 0.1 * i).IndexOf(5), y => y == x)).ToList(); var t = 1d / (1 + 2 * i); Debug.WriteLine($"{v.Select(x => $"{x * 100:F1}%").JoinToString(", ")} (target: {t * 100:F1}%)"); foreach (var d in v) { Assert.AreEqual(t, d, 0.06, "something wrong at " + i); } } }
public void BigLimitedShuffleTest() { var array = Enumerable.Range(1, 100).ToArray(); { var v0 = CountAverage(() => LimitedShuffle.Get(array, 0.01).IndexOf(4), x => x < 2 || x > 4); var v1 = CountAverage(() => LimitedShuffle.Get(array, 0.01).IndexOf(4), x => x == 2); var v2 = CountAverage(() => LimitedShuffle.Get(array, 0.01).IndexOf(4), x => x == 3); var v3 = CountAverage(() => LimitedShuffle.Get(array, 0.01).IndexOf(4), x => x == 4); Assert.AreEqual(0, v0, "0.01: out of bounds"); Assert.AreEqual(0.33, v1, 0.03, "0.01: something wrong"); Assert.AreEqual(0.33, v2, 0.03, "0.01: something wrong"); Assert.AreEqual(0.33, v3, 0.03, "0.01: something wrong"); } { var v0 = CountAverage(() => LimitedShuffle.Get(array, 0.02).IndexOf(4), x => x < 1 || x > 5); var v1 = CountAverage(() => LimitedShuffle.Get(array, 0.02).IndexOf(4), x => x == 1); Assert.AreEqual(0, v0, "0.02: out of bounds"); Assert.AreEqual(0.2, v1, 0.03, "0.02: something wrong"); } }
public async Task <IList <Game.AiCar> > GenerateGameEntries(CancellationToken cancellation = default(CancellationToken)) { if (IsBusy) { await RebuildGridAsync(); if (cancellation.IsCancellationRequested) { return(null); } } var opponentsNumber = OpponentsNumberLimited; if (FilteredView.Count == 0 || opponentsNumber == 0) { return(new Game.AiCar[0]); } var skins = new Dictionary <string, GoodShuffle <CarSkinObject> >(); foreach (var car in FilteredView.OfType <RaceGridEntry>().Where(x => x.CarSkin == null).Select(x => x.Car).Distinct()) { await car.SkinsManager.EnsureLoadedAsync(); if (cancellation.IsCancellationRequested) { return(null); } skins[car.Id] = GoodShuffle.Get(car.EnabledOnlySkins); } NameNationality[] nameNationalities; if (opponentsNumber == 7 && OptionNfsPorscheNames) { nameNationalities = new[] { new NameNationality { Name = "Dylan", Nationality = "Wales" }, new NameNationality { Name = "Parise", Nationality = "Italy" }, new NameNationality { Name = "Steele", Nationality = "United States" }, new NameNationality { Name = "Wingnut", Nationality = "England" }, new NameNationality { Name = "Leadfoot", Nationality = "Australia" }, new NameNationality { Name = "Amazon", Nationality = "United States" }, new NameNationality { Name = "Backlash", Nationality = "United States" } }; } else if (DataProvider.Instance.NationalitiesAndNames.Any()) { nameNationalities = GoodShuffle.Get(DataProvider.Instance.NationalitiesAndNamesList).Take(opponentsNumber).ToArray(); } else { nameNationalities = null; } List <int> aiLevels; if (AiLevelFixed) { aiLevels = null; } else { var aiLevelsInner = from i in Enumerable.Range(0, opponentsNumber) select AiLevelMin + ((opponentsNumber < 2 ? 1d : 1d - i / (opponentsNumber - 1d)) * (AiLevel - AiLevelMin)).RoundToInt(); if (AiLevelArrangeReverse) { aiLevelsInner = aiLevelsInner.Reverse(); } if (Equals(AiLevelArrangeRandom, 1d)) { aiLevelsInner = GoodShuffle.Get(aiLevelsInner); } else if (AiLevelArrangeRandom > 0d) { aiLevelsInner = LimitedShuffle.Get(aiLevelsInner, AiLevelArrangeRandom); } aiLevels = aiLevelsInner.Take(opponentsNumber).ToList(); Logging.Debug("AI levels: " + aiLevels.Select(x => $@"{x}%").JoinToString(@", ")); } IEnumerable <RaceGridEntry> final; if (Mode.CandidatesMode) { var list = FilteredView.OfType <RaceGridEntry>().SelectMany(x => new[] { x }.Repeat(x.CandidatePriority)).ToList(); if (ShuffleCandidates) { var shuffled = GoodShuffle.Get(list); if (_playerCar != null) { var same = list.FirstOrDefault(x => x.Car == _playerCar); if (same != null) { shuffled.IgnoreOnce(same); } } final = shuffled.Take(opponentsNumber); } else { var skip = _playerCar; final = LinqExtension.RangeFrom().Select(x => list.RandomElement()).Where(x => { if (x.Car == skip) { skip = null; return(false); } return(true); }).Take(opponentsNumber); } } else { final = NonfilteredList.Where(x => !x.SpecialEntry); } if (_playerCar != null) { skins.GetValueOrDefault(_playerCar.Id)?.IgnoreOnce(_playerCar.SelectedSkin); } var takenNames = new List <string>(opponentsNumber); return(final.Take(opponentsNumber).Select((entry, i) => { var level = entry.AiLevel ?? aiLevels?[i] ?? 100; var skin = entry.CarSkin; if (skin == null) { skin = skins.GetValueOrDefault(entry.Car.Id)?.Next; } var name = entry.Name; if (string.IsNullOrWhiteSpace(name) && SettingsHolder.Drive.QuickDriveUseSkinNames) { var skinDriverNames = skin?.DriverName?.Split(',').Select(x => x.Trim()).Where(x => x.Length > 0).ToList(); if (skinDriverNames?.Count > 0) { name = GoodShuffle.Get(skinDriverNames).Take(skinDriverNames.Count).FirstOrDefault(x => !takenNames.Contains(x)) ?? name; takenNames.Add(name); } } if (string.IsNullOrWhiteSpace(name)) { name = nameNationalities?[i].Name ?? @"AI #" + i; takenNames.Add(name); } var nationality = entry.Nationality ?? nameNationalities?[i].Nationality ?? @"Italy"; var skinId = skin?.Id; return new Game.AiCar { AiLevel = level, CarId = entry.Car.Id, DriverName = AiLevelInDriverName ? $@"{name} ({level}%)" : name, Nationality = nationality, Setup = "", SkinId = skinId }; }).ToList()); }