using System.Collections.Generic; using System.Linq; namespace PKHeX.Core; /// /// Contains many instances to match against a . /// public sealed class TrainerDatabase { private readonly Dictionary> Database = []; /// /// Fetches an appropriate trainer based on the requested . /// /// Version the trainer should originate from /// Language to request for /// Null if no trainer found for this version. public ITrainerInfo? GetTrainer(GameVersion version, LanguageID? language = null) { if (version <= 0) return null; if (!version.IsValidSavedVersion()) return GetTrainerFromGroup(version, language); if (Database.TryGetValue(version, out var list)) return GetRandomChoice(list); return null; } private static T GetRandomChoice(IReadOnlyList list) { if (list.Count == 1) return list[0]; return list[Util.Rand.Next(list.Count)]; } /// /// Fetches an appropriate trainer based on the requested group. /// /// Version the trainer should originate from /// Language to request for /// Null if no trainer found for this version. private ITrainerInfo? GetTrainerFromGroup(GameVersion version, LanguageID? lang = null) { var possible = Database.Where(z => version.Contains(z.Key)).ToList(); if (lang != null) { possible = possible.Select(z => { var filtered = z.Value.Where(x => x.Language == (int)lang).ToList(); return new KeyValuePair>(z.Key, filtered); }).Where(z => z.Value.Count != 0).ToList(); } return GetRandomTrainer(possible); } /// /// Fetches an appropriate trainer based on the requested . /// /// Generation the trainer should inhabit /// Language to request for /// Null if no trainer found for this version. public ITrainerInfo? GetTrainerFromGen(byte generation, LanguageID? lang = null) { var possible = Database.Where(z => z.Key.GetGeneration() == generation).ToList(); if (lang != null) { possible = possible.Select(z => { var filtered = z.Value.Where(x => x.Language == (int)lang).ToList(); return new KeyValuePair>(z.Key, filtered); }).Where(z => z.Value.Count != 0).ToList(); } return GetRandomTrainer(possible); } private static ITrainerInfo? GetRandomTrainer(IReadOnlyList>> possible) { if (possible.Count == 0) return null; var group = GetRandomChoice(possible); return GetRandomChoice(group.Value); } /// /// Adds the to the . /// /// Trainer details to add. public void Register(ITrainerInfo trainer) { var version = trainer.Version; if (!Database.TryGetValue(version, out var list)) { Database.Add(version, [trainer]); return; } if (list.Contains(trainer)) return; list.Add(trainer); } /// /// Adds the trainer details of the to the . /// /// Pokémon with Trainer details to add. /// A copy of the object will be made to prevent modifications, just in case. public void RegisterCopy(PKM pk) => Register(GetTrainerReference(pk)); /// /// Adds the trainer details of the to the . /// /// Pokémon with Trainer details to add. /// A copy of the object will be made to prevent modifications, just in case. public void RegisterCopy(ITrainerInfo info) => Register(new SimpleTrainerInfo(info)); private static SimpleTrainerInfo GetTrainerReference(PKM pk) { var result = new SimpleTrainerInfo(pk.Version) { TID16 = pk.TID16, SID16 = pk.SID16, OT = pk.OriginalTrainerName, Gender = pk.OriginalTrainerGender, Language = pk.Language, Generation = pk.Generation, }; if (pk is IRegionOrigin r) r.CopyRegionOrigin(result); else result.SetDefaultRegionOrigins(result.Language); return result; } /// /// Clears all trainer details from the . /// public void Clear() => Database.Clear(); }