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 + (int)((opponentsNumber < 2 ? 1f : 1f - (float)i / (opponentsNumber - 1)) * (AiLevel - AiLevelMin));
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(OpponentsNumberLimited);
} else {
var skip = _playerCar;
final = LinqExtension.RangeFrom().Select(x => list.RandomElement()).Where(x => {
if (x.Car == skip) {
skip = null;
return false;
}
return true;
}).Take(OpponentsNumberLimited);
}
} else {
final = NonfilteredList.Where(x => !x.SpecialEntry);
}
if (_playerCar != null) {
skins.GetValueOrDefault(_playerCar.Id)?.IgnoreOnce(_playerCar.SelectedSkin);
}
var takenNames = new List<string>(OpponentsNumberLimited);
return final.Take(OpponentsNumberLimited).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 &&
!takenNames.Contains(skin?.DriverName)) {
name = skin?.DriverName;
takenNames.Add(name);
}
if (string.IsNullOrWhiteSpace(name)) {
name = nameNationalities?[i].Name ?? @"AI #" + i;
}
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();
}
#endregion