diff --git a/FABStarterDeckGen/DeckGenerator.cs b/FABStarterDeckGen/DeckGenerator.cs index 7eaf44f..fe0435e 100644 --- a/FABStarterDeckGen/DeckGenerator.cs +++ b/FABStarterDeckGen/DeckGenerator.cs @@ -1,8 +1,6 @@ using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; -using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; @@ -10,13 +8,18 @@ namespace FabStarterDeckGen { using System; using System.Collections.Generic; - - using System.Globalization; using Newtonsoft.Json; - using Newtonsoft.Json.Converters; - public partial class DeckConfig + public class DeckConfig { + public DeckConfig(string name, string hero, CardSpec[] core, CardSpec[] variables) + { + Name = name; + Hero = hero; + Core = core; + Variables = variables; + } + [JsonProperty("Name")] public string Name { get; set; } @@ -28,10 +31,22 @@ namespace FabStarterDeckGen [JsonProperty("Variables")] public CardSpec[] Variables { get; set; } + + public List LargestBuildableCombination = new List(); } - public partial class CardSpec + public class CardSpec { + public CardSpec(string name, bool isPitchless, string count, string r, string y, string b) + { + Name = name; + IsPitchless = isPitchless; + Count = count; + R = r; + Y = y; + B = b; + } + [JsonProperty("Name")] public string Name { get; set; } @@ -53,29 +68,22 @@ namespace FabStarterDeckGen public class DeckGenerator { - static IEnumerable> GetPermutations(IEnumerable list, int length) - { - if (length == 1) - return list.Select(t => new T[] { t }); - return GetPermutations(list, length - 1).SelectMany(t => list.Where(o => !t.Contains(o)), (t1, t2) => t1.Concat(new T[] { t2 })); - } - - static IEnumerable> GetPermutationsWithRept(IEnumerable list, int length) + private static IEnumerable> GetPermutationsWithRept(IEnumerable list, int length) { if (length == 1) return list.Select(t => new T[] { t }); return GetPermutationsWithRept(list, length - 1).SelectMany(t => list, (t1, t2) => t1.Concat(new T[] { t2 })); } - - static IEnumerable> GetKCombsWithRept(IEnumerable list, int length) where T : IComparable + + private static IEnumerable> GetKCombsWithRept(IEnumerable list, int length) where T : IComparable { if (length == 1) return list.Select(t => new T[] { t }); return GetKCombsWithRept(list, length - 1) .SelectMany(t => list.Where(o => o.CompareTo(t.Last()) >= 0), (t1, t2) => t1.Concat(new T[] { t2 })); } - - static IEnumerable> CartesianProduct (IEnumerable> sequences) + + private static IEnumerable> CartesianProduct (IEnumerable> sequences) { IEnumerable> emptyProduct = new[] { Enumerable.Empty() }; @@ -90,7 +98,9 @@ namespace FabStarterDeckGen private List? DeckConfigs = new List(); public List> DeckLists = new List>(); - private readonly int REASONABLE_MAX = 10; + private Dictionary>> PerHeroLists = new Dictionary>>(); + + private const int REASONABLE_MAX = 6; private bool IsAssortedThree(string pValue) { return pValue == "3*";} private bool IsAssortedTwo(string pValue) { return pValue == "2*";} @@ -120,9 +130,9 @@ namespace FabStarterDeckGen return false; } - public void LoadDeckConfigs(string pfilePath) + public void LoadDeckConfigs(string pFilepath) { - using (StreamReader file = File.OpenText(pfilePath)) + using (StreamReader file = File.OpenText(pFilepath)) { DeckConfigs = JsonConvert.DeserializeObject > (file.ReadToEnd()); } @@ -199,9 +209,12 @@ namespace FabStarterDeckGen } else { - card_list.Add(card.Name + " - R", int.Parse(card.R)); - card_list.Add(card.Name + " - Y", int.Parse(card.Y)); - card_list.Add(card.Name + " - B", int.Parse(card.B)); + if(int.Parse(card.R) != 0) + card_list.Add(card.Name + " - R", int.Parse(card.R)); + if(int.Parse(card.Y) != 0) + card_list.Add(card.Name + " - Y", int.Parse(card.Y)); + if(int.Parse(card.B) != 0) + card_list.Add(card.Name + " - B", int.Parse(card.B)); } } @@ -224,7 +237,11 @@ namespace FabStarterDeckGen Console.WriteLine(card_list.ToString()); Debug.Assert(card_count == 45); } + + if ( !PerHeroLists.ContainsKey(config) ) + PerHeroLists[config] = new List>(); + PerHeroLists[config].Add(card_list); DeckLists.Add(card_list); } } @@ -232,87 +249,76 @@ namespace FabStarterDeckGen public void DetermineMaxBuilds(in Dictionary pCollectionCounts) { - var timer = new Stopwatch(); - timer.Start(); - - // Limit this to per hero once i have more specs written - var range = Enumerable.Range(0, DeckLists.Count); - List largest_buildable_combo = new List(); - for (int i = 1; i <= REASONABLE_MAX; i++) + foreach ( var hero_config in PerHeroLists ) { - bool combo_was_built = false; - var combos = GetKCombsWithRept(range, i).Select(c => c.ToList()); - var ints = pCollectionCounts; + var timer = new Stopwatch(); + timer.Start(); - Parallel.ForEach(combos, (combo, state) => + var num_lists_for_hero = Enumerable.Range(0, hero_config.Value.Count); + for (int i = 1; i <= REASONABLE_MAX; i++) { - var temp_card_counts = new Dictionary(ints); - if (ComboIsBuildable(combo, temp_card_counts)) - { - // Cache it off somehwere as the largest buildable combo - largest_buildable_combo = new List(combo); - // Move on and enlarge the number of decks we are trying to build - combo_was_built = true; - state.Break(); - } - }); + bool combo_was_built = false; + var combos = GetKCombsWithRept(num_lists_for_hero, i).Select(c => c.ToList()); + var ints = pCollectionCounts; - /* - foreach (var combo in combos) - { - // Multithread! - var temp_card_counts = new Dictionary(pCollectionCounts); - if (ComboIsBuildable(combo, temp_card_counts)) + Parallel.ForEach(combos, (combo, state) => { - // Cache it off somehwere as the largest buildable combo - largest_buildable_combo = new List(combo); - // Move on and enlarge the number of decks we are trying to build - combo_was_built = true; + var temp_card_counts = new Dictionary(ints); + if (ComboIsBuildable(hero_config.Value, combo, temp_card_counts)) + { + hero_config.Key.LargestBuildableCombination = new List(combo); + // Move on and enlarge the number of decks we are trying to build + combo_was_built = true; + state.Break(); + } + }); + + if (!combo_was_built) break; - } } - */ - if (!combo_was_built) - break; - } - Console.WriteLine(string.Join(",", largest_buildable_combo)); - Dictionary totals_for_combo_build = new Dictionary(); - foreach (var index in largest_buildable_combo) - { - var deck = DeckLists[index]; - foreach (var entry in deck) + var f = string.Join(",", hero_config.Key.LargestBuildableCombination); + Dictionary totals_for_combo_build = new Dictionary(); + foreach (var index in hero_config.Key.LargestBuildableCombination) { - if (!totals_for_combo_build.ContainsKey(entry.Key)) - totals_for_combo_build[entry.Key] = 0; - totals_for_combo_build[entry.Key] += entry.Value; + var deck = hero_config.Value[index]; + foreach (var entry in deck) + { + if (!totals_for_combo_build.ContainsKey(entry.Key)) + totals_for_combo_build[entry.Key] = 0; + totals_for_combo_build[entry.Key] += entry.Value; + } + f += Newtonsoft.Json.JsonConvert.SerializeObject(deck, Newtonsoft.Json.Formatting.Indented); + Console.WriteLine(f); } - var f = Newtonsoft.Json.JsonConvert.SerializeObject(deck, Newtonsoft.Json.Formatting.Indented); + f += Newtonsoft.Json.JsonConvert.SerializeObject(totals_for_combo_build, Newtonsoft.Json.Formatting.Indented); + File.WriteAllText(@"D:\Dev\FABStarterDeckGenerator\Out\" + hero_config.Key.Hero + ".json", f); Console.WriteLine(f); + timer.Stop(); + TimeSpan timeTaken = timer.Elapsed; + Console.WriteLine("Time taken: " + timeTaken.ToString(@"m\:ss\.fff")); } - var total_counts = Newtonsoft.Json.JsonConvert.SerializeObject(totals_for_combo_build, Newtonsoft.Json.Formatting.Indented); - Console.WriteLine(total_counts); - timer.Stop(); - TimeSpan timeTaken = timer.Elapsed; - Console.WriteLine("Time taken: " + timeTaken.ToString(@"m\:ss\.fff")); } private bool DeckIsBuildable(in Dictionary pDeckCardCounts, in Dictionary pCardCounts) { foreach (var required_count in pDeckCardCounts) { + if (required_count.Value == 0 && !pCardCounts.ContainsKey(required_count.Key)) + continue; + if (pCardCounts[required_count.Key] - required_count.Value < 0) return false; } return true; } - private bool ComboIsBuildable(in List pCombination, Dictionary pCardCounts) + private bool ComboIsBuildable(in List> lists, in List pCombination, Dictionary pCardCounts) { Console.WriteLine("({1})Testing combo: {0}", String.Join(",", pCombination), Thread.CurrentThread.ManagedThreadId); foreach (var index in pCombination) { - var deck = DeckLists[index]; + var deck = lists[index]; if (!DeckIsBuildable(deck, pCardCounts)) return false; diff --git a/FABStarterDeckGen/FABCollectionReader.cs b/FABStarterDeckGen/FABCollectionReader.cs index 1bfec6a..6630205 100644 --- a/FABStarterDeckGen/FABCollectionReader.cs +++ b/FABStarterDeckGen/FABCollectionReader.cs @@ -21,6 +21,8 @@ namespace FabStarterDeckGen public readonly int STARTING_ROW_INDEX = 3; + private const bool REDUCE_COUNTS_FOR_COLLECTION = true; + public Dictionary CollectionCounts = new Dictionary(); public void LoadCollection(string pFilePath, ReferenceCardLoader pReferenceCard) { @@ -49,7 +51,7 @@ namespace FabStarterDeckGen if (card.IsRed) { if (!CollectionCounts.ContainsKey(card.CleanNameRed)) - CollectionCounts.Add(card.CleanNameRed, 0); + CollectionCounts.Add(card.CleanNameRed, REDUCE_COUNTS_FOR_COLLECTION ? -3 : 0); CollectionCounts[card.CleanNameRed] += int.Parse(sheet.Cells[COLUMN_RED + current_row_index.ToString()].Text); } @@ -57,7 +59,7 @@ namespace FabStarterDeckGen if (card.IsYellow) { if (!CollectionCounts.ContainsKey(card.CleanNameYellow)) - CollectionCounts.Add(card.CleanNameYellow, 0); + CollectionCounts.Add(card.CleanNameYellow, REDUCE_COUNTS_FOR_COLLECTION ? -3 : 0); CollectionCounts[card.CleanNameYellow] += int.Parse(sheet.Cells[COLUMN_YELLOW + current_row_index.ToString()].Text); } @@ -65,7 +67,7 @@ namespace FabStarterDeckGen if (card.IsBlue) { if (!CollectionCounts.ContainsKey(card.CleanNameBlue)) - CollectionCounts.Add(card.CleanNameBlue, 0); + CollectionCounts.Add(card.CleanNameBlue, REDUCE_COUNTS_FOR_COLLECTION ? -3 : 0); CollectionCounts[card.CleanNameBlue] += int.Parse(sheet.Cells[COLUMN_BLUE + current_row_index.ToString()].Text); } diff --git a/FABStarterDeckGen/FabStarterDeckGen.csproj b/FABStarterDeckGen/FabStarterDeckGen.csproj index 6cc91a8..9e27937 100644 --- a/FABStarterDeckGen/FabStarterDeckGen.csproj +++ b/FABStarterDeckGen/FabStarterDeckGen.csproj @@ -5,6 +5,7 @@ net5.0 enable enable + latestmajor