using System; using System.Collections.Generic; using System.Linq; namespace PKHeX.Core.Searching { /// /// searching utility /// public static class SearchUtil { public static IEnumerable FilterByFormat(IEnumerable res, int format, SearchComparison formatOperand) { switch (formatOperand) { case SearchComparison.GreaterThanEquals: res = res.Where(pk => pk.Format >= format); break; case SearchComparison.Equals: res = res.Where(pk => pk.Format == format); break; case SearchComparison.LessThanEquals: res = res.Where(pk => pk.Format <= format); break; default: return res; /* Do nothing */ } // Might need to clamp down further for generations that cannot exist in the current format. return format switch { <= 2 => res.Where(pk => pk.Format <= 2), // 1-2 <= 6 => res.Where(pk => pk.Format >= 3), // 3-6 _ => res }; } public static IEnumerable FilterByGeneration(IEnumerable res, int generation) => generation switch { 1 => res.Where(pk => pk.VC || pk.Format < 3), 2 => res.Where(pk => pk.VC || pk.Format < 3), _ => res.Where(pk => pk.Generation == generation) }; public static IEnumerable FilterByLevel(IEnumerable res, SearchComparison option, int level) { if (level > 100) return res; return option switch { SearchComparison.LessThanEquals => res.Where(pk => pk.Stat_Level <= level), SearchComparison.Equals => res.Where(pk => pk.Stat_Level == level), SearchComparison.GreaterThanEquals => res.Where(pk => pk.Stat_Level >= level), _ => res }; } public static IEnumerable FilterByEVs(IEnumerable res, int option) => option switch { 1 => res.Where(pk => pk.EVTotal == 0), // None (0) 2 => res.Where(pk => pk.EVTotal < 128), // Some (127-0) 3 => res.Where(pk => pk.EVTotal is >= 128 and < 508), // Half (128-507) 4 => res.Where(pk => pk.EVTotal >= 508), // Full (508+) _ => res }; public static IEnumerable FilterByIVs(IEnumerable res, int option) => option switch { 1 => res.Where(pk => pk.IVTotal <= 90), // <= 90 2 => res.Where(pk => pk.IVTotal is > 90 and <= 120), // 91-120 3 => res.Where(pk => pk.IVTotal is > 120 and <= 150), // 121-150 4 => res.Where(pk => pk.IVTotal is > 150 and < 180), // 151-179 5 => res.Where(pk => pk.IVTotal >= 180), // 180+ 6 => res.Where(pk => pk.IVTotal == 186), // == 186 _ => res }; public static IEnumerable FilterByMoves(IEnumerable res, IEnumerable requiredMoves) { var moves = new HashSet(requiredMoves); int count = moves.Count; return res.Where(pk => pk.Moves.Where(z => z > 0) .Count(moves.Contains) == count ); } public static IEnumerable FilterByBatchInstruction(IEnumerable res, IList inputInstructions) { if (inputInstructions.All(string.IsNullOrWhiteSpace)) return res; // none specified; var lines = inputInstructions.Where(z => !string.IsNullOrWhiteSpace(z)); var filters = StringInstruction.GetFilters(lines).ToArray(); BatchEditing.ScreenStrings(filters); return res.Where(pkm => BatchEditing.IsFilterMatch(filters, pkm)); // Compare across all filters } public static Func GetCloneDetectMethod(CloneDetectionMethod method) => method switch { CloneDetectionMethod.HashPID => HashByPID, _ => HashByDetails, }; public static string HashByDetails(PKM pk) => pk.Format switch { 1 => $"{pk.Species:000}{((PK1) pk).DV16:X4}", 2 => $"{pk.Species:000}{((PK2) pk).DV16:X4}", _ => $"{pk.Species:000}{pk.PID:X8}{string.Join(" ", pk.IVs)}{pk.Form:00}" }; public static string HashByPID(PKM pk) => pk.Format switch { 1 => $"{((PK1) pk).DV16:X4}", 2 => $"{((PK2) pk).DV16:X4}", _ => $"{pk.PID:X8}" }; public static IEnumerable GetClones(IEnumerable res, CloneDetectionMethod type = CloneDetectionMethod.HashDetails) { var method = GetCloneDetectMethod(type); return GetClones(res, method); } public static IEnumerable GetClones(IEnumerable res, Func method) { return res .GroupBy(method) .Where(grp => grp.Count() > 1) .SelectMany(z => z); } public static IEnumerable GetExtraClones(IEnumerable db) { return GetExtraClones(db, HashByDetails); } public static IEnumerable GetExtraClones(IEnumerable db, Func method) { return db.GroupBy(method).Where(grp => grp.Count() > 1).SelectMany(z => z.Skip(1)); } } }