diff --git a/PKHeX.Core/Game/GameStrings/GameInfo.cs b/PKHeX.Core/Game/GameStrings/GameInfo.cs index 7e4b084a9..d23835ed2 100644 --- a/PKHeX.Core/Game/GameStrings/GameInfo.cs +++ b/PKHeX.Core/Game/GameStrings/GameInfo.cs @@ -210,7 +210,7 @@ namespace PKHeX.Core gen = format; locval %= size; - if (bankID >= 3) + if (bankID >= 3) // 30000 and onwards don't use 0th index, shift down 1 locval--; } diff --git a/PKHeX.Core/Game/GameStrings/GameStrings.cs b/PKHeX.Core/Game/GameStrings/GameStrings.cs index 26ff2daa1..bab5c760f 100644 --- a/PKHeX.Core/Game/GameStrings/GameStrings.cs +++ b/PKHeX.Core/Game/GameStrings/GameStrings.cs @@ -36,8 +36,8 @@ namespace PKHeX.Core private string[] Get(string ident) => GameInfo.GetStrings(ident, lang); private const string NPC = "NPC"; private static readonly string[] abilIdentifier = { " (1)", " (2)", " (H)" }; - public static readonly IReadOnlyList Regions = Util.GetUnsortedCBList("regions3ds"); - private static readonly IReadOnlyList LanguageList = Util.GetUnsortedCBList("languages"); + public static readonly IReadOnlyList Regions = Util.GetCSVUnsortedCBList("regions3ds"); + private static readonly IReadOnlyList LanguageList = Util.GetCSVUnsortedCBList("languages"); private static readonly string[] LanguageNames = LanguageList.GetArray(); public GameStrings(string l) @@ -367,23 +367,23 @@ namespace PKHeX.Core // Gen 2 { var met_list = Util.GetCBList(metGSC_00000, Enumerable.Range(0, 0x5F).ToArray()); - Util.AddCBWithOffset(met_list, metGSC_00000, 00000, new[] { 0x7E, 0x7F }); + Util.AddCBWithOffset(met_list, metGSC_00000, 00000, 0x7E, 0x7F); MetGen2 = met_list; } // Gen 3 { var met_list = Util.GetCBList(metRSEFRLG_00000, Enumerable.Range(0, 213).ToArray()); - Util.AddCBWithOffset(met_list, metRSEFRLG_00000, 00000, new[] { 253, 254, 255 }); + Util.AddCBWithOffset(met_list, metRSEFRLG_00000, 00000, 253, 254, 255); MetGen3 = met_list; MetGen3CXD = Util.GetCBList(metCXD_00000, Enumerable.Range(0, metCXD_00000.Length).ToArray()).Where(c => c.Text.Length > 0).ToList(); } // Gen 4 { - var met_list = Util.GetCBList(metHGSS_00000, new[] { 0 }); - Util.AddCBWithOffset(met_list, metHGSS_02000, 2000, new[] { 2000 }); - Util.AddCBWithOffset(met_list, metHGSS_02000, 2000, new[] { 2002 }); - Util.AddCBWithOffset(met_list, metHGSS_03000, 3000, new[] { 3001 }); + var met_list = Util.GetCBList(metHGSS_00000, 0); + Util.AddCBWithOffset(met_list, metHGSS_02000, 2000, 2000); + Util.AddCBWithOffset(met_list, metHGSS_02000, 2000, 2002); + Util.AddCBWithOffset(met_list, metHGSS_03000, 3000, 3001); Util.AddCBWithOffset(met_list, metHGSS_00000, 0000, Legal.Met_HGSS_0); Util.AddCBWithOffset(met_list, metHGSS_02000, 2000, Legal.Met_HGSS_2); Util.AddCBWithOffset(met_list, metHGSS_03000, 3000, Legal.Met_HGSS_3); @@ -391,9 +391,9 @@ namespace PKHeX.Core } // Gen 5 { - var met_list = Util.GetCBList(metBW2_00000, new[] { 0 }); - Util.AddCBWithOffset(met_list, metBW2_60000, 60001, new[] { 60002 }); - Util.AddCBWithOffset(met_list, metBW2_30000, 30001, new[] { 30003 }); + var met_list = Util.GetCBList(metBW2_00000, 0); + Util.AddCBWithOffset(met_list, metBW2_60000, 60002, 60002); + Util.AddCBWithOffset(met_list, metBW2_30000, 30002, 30003); Util.AddCBWithOffset(met_list, metBW2_00000, 00000, Legal.Met_BW2_0); Util.AddCBWithOffset(met_list, metBW2_30000, 30001, Legal.Met_BW2_3); Util.AddCBWithOffset(met_list, metBW2_40000, 40001, Legal.Met_BW2_4); @@ -402,9 +402,9 @@ namespace PKHeX.Core } // Gen 6 { - var met_list = Util.GetCBList(metXY_00000, new[] { 0 }); - Util.AddCBWithOffset(met_list, metXY_60000, 60001, new[] { 60002 }); - Util.AddCBWithOffset(met_list, metXY_30000, 30001, new[] { 30002 }); + var met_list = Util.GetCBList(metXY_00000, 0); + Util.AddCBWithOffset(met_list, metXY_60000, 60001, 60002); + Util.AddCBWithOffset(met_list, metXY_30000, 30001, 30002); Util.AddCBWithOffset(met_list, metXY_00000, 00000, Legal.Met_XY_0); Util.AddCBWithOffset(met_list, metXY_30000, 30001, Legal.Met_XY_3); Util.AddCBWithOffset(met_list, metXY_40000, 40001, Legal.Met_XY_4); @@ -413,9 +413,9 @@ namespace PKHeX.Core } // Gen 7 { - var met_list = Util.GetCBList(metSM_00000, new[] { 0 }); - Util.AddCBWithOffset(met_list, metSM_60000, 60001, new[] { 60002 }); - Util.AddCBWithOffset(met_list, metSM_30000, 30001, new[] { 30002 }); + var met_list = Util.GetCBList(metSM_00000, 0); + Util.AddCBWithOffset(met_list, metSM_60000, 60001, 60002); + Util.AddCBWithOffset(met_list, metSM_30000, 30001, 30002); Util.AddCBWithOffset(met_list, metSM_00000, 00000, Legal.Met_SM_0); Util.AddCBWithOffset(met_list, metSM_30000, 30001, Legal.Met_SM_3); Util.AddCBWithOffset(met_list, metSM_40000, 40001, Legal.Met_SM_4); @@ -424,9 +424,9 @@ namespace PKHeX.Core } // Gen 7 GG { - var met_list = Util.GetCBList(metGG_00000, new[] { 0 }); - Util.AddCBWithOffset(met_list, metGG_60000, 60001, new[] { 60002 }); - Util.AddCBWithOffset(met_list, metGG_30000, 30001, new[] { 30002 }); + var met_list = Util.GetCBList(metGG_00000, 0); + Util.AddCBWithOffset(met_list, metGG_60000, 60001, 60002); + Util.AddCBWithOffset(met_list, metGG_30000, 30001, 30002); Util.AddCBWithOffset(met_list, metGG_00000, 00000, Legal.Met_GG_0); Util.AddCBWithOffset(met_list, metGG_30000, 30001, Legal.Met_GG_3); Util.AddCBWithOffset(met_list, metGG_40000, 40001, Legal.Met_GG_4); diff --git a/PKHeX.Core/Util/DataUtil.cs b/PKHeX.Core/Util/DataUtil.cs index 3fd6970a6..a20251ac7 100644 --- a/PKHeX.Core/Util/DataUtil.cs +++ b/PKHeX.Core/Util/DataUtil.cs @@ -223,36 +223,80 @@ namespace PKHeX.Core #endregion #region DataSource Providing + + private static readonly string[] CountryRegionLanguages = {"ja", "en", "fr", "de", "it", "es", "ko", "zh"}; + public static List GetCountryRegionList(string textfile, string lang) { - // Set up string[] inputCSV = GetStringList(textfile); - - // Get Language we're fetching for - int index = Array.IndexOf(new[] { "ja", "en", "fr", "de", "it", "es", "ko", "zh", }, lang); - - // Gather our data from the input file - return inputCSV.Skip(1) - .Select(entry => entry.Split(',')) - .Select(data => new ComboItem { Text = data[1 + index], Value = Convert.ToInt32(data[0]) }) - .OrderBy(z => z.Text) - .ToList(); + int index = Array.IndexOf(CountryRegionLanguages, lang); + return GetCBListCSVSorted(inputCSV, index); } - public static List GetUnsortedCBList(string textfile) + private static List GetCBListCSVSorted(string[] inputCSV, int index = 0) + { + var list = GetCBListFromCSV(inputCSV, index); + list.Sort(Comparer); + return list; + } + + public static List GetCSVUnsortedCBList(string textfile) { string[] inputCSV = GetStringList(textfile); - return inputCSV.Skip(1) - .Select(entry => entry.Split(',')) - .Select(data => new ComboItem { Text = data[1], Value = Convert.ToInt32(data[0]) }) - .ToList(); + return GetCBListFromCSV(inputCSV, 0); + } + + private static List GetCBListFromCSV(IReadOnlyList inputCSV, int index) + { + var arr = new List(inputCSV.Count - 1); // skip header + index++; + for (int i = 1; i < inputCSV.Count; i++) + { + var line = inputCSV[i]; + var zeroth = line.IndexOf(','); + + var val = line.Substring(0, zeroth); + var text = GetNthEntry(line, index, zeroth); + var item = new ComboItem {Text = text, Value = Convert.ToInt32(val)}; + arr.Add(item); + } + return arr; + } + + private static string GetNthEntry(string line, int nth, int start) + { + if (nth != 1) + start = line.IndexOfNth(',', nth - 1, start + 1); + var end = line.IndexOfNth(',', 1, start + 1); + return end < 0 ? line.Substring(start + 1) : line.Substring(start + 1, end - start - 1); + } + + private static int IndexOfNth(this string s, char t, int n, int start) + { + int count = 0; + for (int i = start; i < s.Length; i++) + { + if (s[i] != t) + continue; + if (++count == n) + return i; + } + return -1; } public static List GetCBList(IReadOnlyList inStrings) { var list = new List(inStrings.Count); - var items = inStrings.Select((t, i) => new ComboItem {Text = t, Value = i}).OrderBy(z => z.Text); - list.AddRange(items); + for (int i = 0; i < inStrings.Count; i++) + list.Add(new ComboItem {Text = inStrings[i], Value = i}); + list.Sort(Comparer); + return list; + } + + public static List GetCBList(IReadOnlyList inStrings, int index, int offset = 0) + { + var list = new List(); + AddCBWithOffset(list, inStrings, offset, index); return list; } @@ -261,39 +305,71 @@ namespace PKHeX.Core var count = allowed.Sum(z => z.Length); var list = new List(count); foreach (var arr in allowed) - { - var subset = arr - .Select(z => new ComboItem {Text = inStrings[z], Value = z}) - .OrderBy(z => z.Text); - list.AddRange(subset); - } + AddCB(list, inStrings, arr); return list; } - public static void AddCBWithOffset(List cbList, IReadOnlyList inStrings, int offset, int[] allowed) + public static void AddCBWithOffset(List list, IReadOnlyList inStrings, int offset, int index) { - var list = allowed - .Select(z => new ComboItem {Text = inStrings[z - offset], Value = z}) - .OrderBy(z => z.Text); + var item = new ComboItem {Text = inStrings[index - offset], Value = index}; + list.Add(item); + } - cbList.AddRange(list); + public static void AddCBWithOffset(List cbList, IReadOnlyList inStrings, int offset, params int[] allowed) + { + int beginCount = cbList.Count; + for (int i = 0; i < allowed.Length; i++) + { + int index = allowed[i]; + var item = new ComboItem {Text = inStrings[index - offset], Value = index}; + cbList.Add(item); + } + cbList.Sort(beginCount, allowed.Length, Comparer); + } + + public static void AddCB(List cbList, IReadOnlyList inStrings, int[] allowed) + { + int beginCount = cbList.Count; + for (int i = 0; i < allowed.Length; i++) + { + int index = allowed[i]; + var item = new ComboItem {Text = inStrings[index], Value = index}; + cbList.Add(item); + } + cbList.Sort(beginCount, allowed.Length, Comparer); } public static List GetVariedCBListBall(string[] inStrings, int[] stringNum, int[] stringVal) { - // First 3 Balls are always first - var newlist = new List(3 + stringNum.Length) + const int forcedTop = 3; // 3 Balls are preferentially first + var list = new List(forcedTop + stringNum.Length) { new ComboItem {Text = inStrings[4], Value = (int)Ball.Poke}, new ComboItem {Text = inStrings[3], Value = (int)Ball.Great}, new ComboItem {Text = inStrings[2], Value = (int)Ball.Ultra}, }; - var ordered = stringNum - .Select((z, i) => new ComboItem {Text = inStrings[z], Value = stringVal[i]}) - .OrderBy(z => z.Text); - newlist.AddRange(ordered); - return newlist; + for (int i = 0; i < stringNum.Length; i++) + { + int index = stringNum[i]; + var val = stringVal[i]; + var txt = inStrings[index]; + list.Add(new ComboItem {Text = txt, Value = val}); + } + + list.Sort(forcedTop, stringNum.Length, Comparer); + return list +; + } + + private static readonly FunctorComparer Comparer = + new FunctorComparer((a, b) => string.Compare(a.Text, b.Text, StringComparison.Ordinal)); + + private sealed class FunctorComparer : IComparer + { + private readonly Comparison Comparison; + public FunctorComparer(Comparison comparison) => Comparison = comparison; + public int Compare(T x, T y) => Comparison(x, y); } #endregion }