Browse Source

- Cleaned up some warnings

- Added per deck lists so we can try a hero by hero build
master
Quildra 4 years ago
parent
commit
5456dd83a5
  1. 162
      FABStarterDeckGen/DeckGenerator.cs
  2. 8
      FABStarterDeckGen/FABCollectionReader.cs
  3. 1
      FABStarterDeckGen/FabStarterDeckGen.csproj

162
FABStarterDeckGen/DeckGenerator.cs

@ -1,8 +1,6 @@
using System.Diagnostics; using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -10,13 +8,18 @@ namespace FabStarterDeckGen
{ {
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization;
using Newtonsoft.Json; 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")] [JsonProperty("Name")]
public string Name { get; set; } public string Name { get; set; }
@ -28,10 +31,22 @@ namespace FabStarterDeckGen
[JsonProperty("Variables")] [JsonProperty("Variables")]
public CardSpec[] Variables { get; set; } public CardSpec[] Variables { get; set; }
public List<int> LargestBuildableCombination = new List<int>();
} }
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")] [JsonProperty("Name")]
public string Name { get; set; } public string Name { get; set; }
@ -53,29 +68,22 @@ namespace FabStarterDeckGen
public class DeckGenerator public class DeckGenerator
{ {
static IEnumerable<IEnumerable<T>> GetPermutations<T>(IEnumerable<T> list, int length) private static IEnumerable<IEnumerable<T>> GetPermutationsWithRept<T>(IEnumerable<T> 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<IEnumerable<T>> GetPermutationsWithRept<T>(IEnumerable<T> list, int length)
{ {
if (length == 1) if (length == 1)
return list.Select(t => new T[] { t }); return list.Select(t => new T[] { t });
return GetPermutationsWithRept(list, length - 1).SelectMany(t => list, (t1, t2) => t1.Concat(new T[] { t2 })); return GetPermutationsWithRept(list, length - 1).SelectMany(t => list, (t1, t2) => t1.Concat(new T[] { t2 }));
} }
static IEnumerable<IEnumerable<T>> GetKCombsWithRept<T>(IEnumerable<T> list, int length) where T : IComparable private static IEnumerable<IEnumerable<T>> GetKCombsWithRept<T>(IEnumerable<T> list, int length) where T : IComparable
{ {
if (length == 1) return list.Select(t => new T[] { t }); if (length == 1) return list.Select(t => new T[] { t });
return GetKCombsWithRept(list, length - 1) return GetKCombsWithRept(list, length - 1)
.SelectMany(t => list.Where(o => o.CompareTo(t.Last()) >= 0), .SelectMany(t => list.Where(o => o.CompareTo(t.Last()) >= 0),
(t1, t2) => t1.Concat(new T[] { t2 })); (t1, t2) => t1.Concat(new T[] { t2 }));
} }
static IEnumerable<IEnumerable<T>> CartesianProduct<T> (IEnumerable<IEnumerable<T>> sequences) private static IEnumerable<IEnumerable<T>> CartesianProduct<T> (IEnumerable<IEnumerable<T>> sequences)
{ {
IEnumerable<IEnumerable<T>> emptyProduct = IEnumerable<IEnumerable<T>> emptyProduct =
new[] { Enumerable.Empty<T>() }; new[] { Enumerable.Empty<T>() };
@ -90,7 +98,9 @@ namespace FabStarterDeckGen
private List<DeckConfig>? DeckConfigs = new List<DeckConfig>(); private List<DeckConfig>? DeckConfigs = new List<DeckConfig>();
public List<Dictionary<string, int>> DeckLists = new List<Dictionary<string, int>>(); public List<Dictionary<string, int>> DeckLists = new List<Dictionary<string, int>>();
private readonly int REASONABLE_MAX = 10; private Dictionary<DeckConfig, List<Dictionary<string, int>>> PerHeroLists = new Dictionary<DeckConfig, List<Dictionary<string, int>>>();
private const int REASONABLE_MAX = 6;
private bool IsAssortedThree(string pValue) { return pValue == "3*";} private bool IsAssortedThree(string pValue) { return pValue == "3*";}
private bool IsAssortedTwo(string pValue) { return pValue == "2*";} private bool IsAssortedTwo(string pValue) { return pValue == "2*";}
@ -120,9 +130,9 @@ namespace FabStarterDeckGen
return false; 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 <List<DeckConfig>> (file.ReadToEnd()); DeckConfigs = JsonConvert.DeserializeObject <List<DeckConfig>> (file.ReadToEnd());
} }
@ -199,9 +209,12 @@ namespace FabStarterDeckGen
} }
else else
{ {
card_list.Add(card.Name + " - R", int.Parse(card.R)); if(int.Parse(card.R) != 0)
card_list.Add(card.Name + " - Y", int.Parse(card.Y)); card_list.Add(card.Name + " - R", int.Parse(card.R));
card_list.Add(card.Name + " - B", int.Parse(card.B)); 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()); Console.WriteLine(card_list.ToString());
Debug.Assert(card_count == 45); Debug.Assert(card_count == 45);
} }
if ( !PerHeroLists.ContainsKey(config) )
PerHeroLists[config] = new List<Dictionary<string, int>>();
PerHeroLists[config].Add(card_list);
DeckLists.Add(card_list); DeckLists.Add(card_list);
} }
} }
@ -232,87 +249,76 @@ namespace FabStarterDeckGen
public void DetermineMaxBuilds(in Dictionary<string, int> pCollectionCounts) public void DetermineMaxBuilds(in Dictionary<string, int> pCollectionCounts)
{ {
var timer = new Stopwatch(); foreach ( var hero_config in PerHeroLists )
timer.Start();
// Limit this to per hero once i have more specs written
var range = Enumerable.Range(0, DeckLists.Count);
List<int> largest_buildable_combo = new List<int>();
for (int i = 1; i <= REASONABLE_MAX; i++)
{ {
bool combo_was_built = false; var timer = new Stopwatch();
var combos = GetKCombsWithRept(range, i).Select(c => c.ToList()); timer.Start();
var ints = pCollectionCounts;
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<string, int>(ints); bool combo_was_built = false;
if (ComboIsBuildable(combo, temp_card_counts)) var combos = GetKCombsWithRept(num_lists_for_hero, i).Select(c => c.ToList());
{ var ints = pCollectionCounts;
// Cache it off somehwere as the largest buildable combo
largest_buildable_combo = new List<int>(combo);
// Move on and enlarge the number of decks we are trying to build
combo_was_built = true;
state.Break();
}
});
/* Parallel.ForEach(combos, (combo, state) =>
foreach (var combo in combos)
{
// Multithread!
var temp_card_counts = new Dictionary<string, int>(pCollectionCounts);
if (ComboIsBuildable(combo, temp_card_counts))
{ {
// Cache it off somehwere as the largest buildable combo var temp_card_counts = new Dictionary<string, int>(ints);
largest_buildable_combo = new List<int>(combo); if (ComboIsBuildable(hero_config.Value, combo, temp_card_counts))
// Move on and enlarge the number of decks we are trying to build {
combo_was_built = true; hero_config.Key.LargestBuildableCombination = new List<int>(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; break;
}
} }
*/
if (!combo_was_built) var f = string.Join(",", hero_config.Key.LargestBuildableCombination);
break; Dictionary<string, int> totals_for_combo_build = new Dictionary<string, int>();
} foreach (var index in hero_config.Key.LargestBuildableCombination)
Console.WriteLine(string.Join(",", largest_buildable_combo));
Dictionary<string, int> totals_for_combo_build = new Dictionary<string, int>();
foreach (var index in largest_buildable_combo)
{
var deck = DeckLists[index];
foreach (var entry in deck)
{ {
if (!totals_for_combo_build.ContainsKey(entry.Key)) var deck = hero_config.Value[index];
totals_for_combo_build[entry.Key] = 0; foreach (var entry in deck)
totals_for_combo_build[entry.Key] += entry.Value; {
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); 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<string, int> pDeckCardCounts, in Dictionary<string, int> pCardCounts) private bool DeckIsBuildable(in Dictionary<string, int> pDeckCardCounts, in Dictionary<string, int> pCardCounts)
{ {
foreach (var required_count in pDeckCardCounts) 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) if (pCardCounts[required_count.Key] - required_count.Value < 0)
return false; return false;
} }
return true; return true;
} }
private bool ComboIsBuildable(in List<int> pCombination, Dictionary<string, int> pCardCounts) private bool ComboIsBuildable(in List<Dictionary<string, int>> lists, in List<int> pCombination, Dictionary<string, int> pCardCounts)
{ {
Console.WriteLine("({1})Testing combo: {0}", String.Join(",", pCombination), Thread.CurrentThread.ManagedThreadId); Console.WriteLine("({1})Testing combo: {0}", String.Join(",", pCombination), Thread.CurrentThread.ManagedThreadId);
foreach (var index in pCombination) foreach (var index in pCombination)
{ {
var deck = DeckLists[index]; var deck = lists[index];
if (!DeckIsBuildable(deck, pCardCounts)) if (!DeckIsBuildable(deck, pCardCounts))
return false; return false;

8
FABStarterDeckGen/FABCollectionReader.cs

@ -21,6 +21,8 @@ namespace FabStarterDeckGen
public readonly int STARTING_ROW_INDEX = 3; public readonly int STARTING_ROW_INDEX = 3;
private const bool REDUCE_COUNTS_FOR_COLLECTION = true;
public Dictionary<string, int> CollectionCounts = new Dictionary<string, int>(); public Dictionary<string, int> CollectionCounts = new Dictionary<string, int>();
public void LoadCollection(string pFilePath, ReferenceCardLoader pReferenceCard) public void LoadCollection(string pFilePath, ReferenceCardLoader pReferenceCard)
{ {
@ -49,7 +51,7 @@ namespace FabStarterDeckGen
if (card.IsRed) if (card.IsRed)
{ {
if (!CollectionCounts.ContainsKey(card.CleanNameRed)) 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); CollectionCounts[card.CleanNameRed] += int.Parse(sheet.Cells[COLUMN_RED + current_row_index.ToString()].Text);
} }
@ -57,7 +59,7 @@ namespace FabStarterDeckGen
if (card.IsYellow) if (card.IsYellow)
{ {
if (!CollectionCounts.ContainsKey(card.CleanNameYellow)) 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); CollectionCounts[card.CleanNameYellow] += int.Parse(sheet.Cells[COLUMN_YELLOW + current_row_index.ToString()].Text);
} }
@ -65,7 +67,7 @@ namespace FabStarterDeckGen
if (card.IsBlue) if (card.IsBlue)
{ {
if (!CollectionCounts.ContainsKey(card.CleanNameBlue)) 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); CollectionCounts[card.CleanNameBlue] += int.Parse(sheet.Cells[COLUMN_BLUE + current_row_index.ToString()].Text);
} }

1
FABStarterDeckGen/FabStarterDeckGen.csproj

@ -5,6 +5,7 @@
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net5.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<LangVersion>latestmajor</LangVersion>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">

Loading…
Cancel
Save