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 = new(); /// /// 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(int version, LanguageID? language = null) => GetTrainer((GameVersion)version, language); /// /// 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 ver, LanguageID? language = null) { if (ver <= 0) return null; if (!ver.IsValidSavedVersion()) return GetTrainerFromGroup(ver, language); if (Database.TryGetValue(ver, 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 ver, LanguageID? lang = null) { var possible = Database.Where(z => ver.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(int 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 ver = (GameVersion)trainer.Game; if (ver <= 0 && trainer is SaveFile s) ver = s.Version; if (!Database.TryGetValue(ver, out var list)) { Database.Add(ver, new List { 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 pkm) => Register(GetTrainerReference(pkm)); /// /// 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 ITrainerInfo GetTrainerReference(PKM pkm) { var result = new SimpleTrainerInfo((GameVersion)pkm.Version) { TID = pkm.TID, SID = pkm.SID, OT = pkm.OT_Name, Gender = pkm.OT_Gender, Language = pkm.Language, Generation = pkm.Generation, }; if (pkm is IRegionOrigin r) r.CopyRegionOrigin(result); else result.SetDefaultRegionOrigins(); return result; } /// /// Clears all trainer details from the . /// public void Clear() => Database.Clear(); }