public static ArchetypeResult Detect(Card[] mainboardCards, Card[] sideboardCards, ArchetypeFormat format, double minSimiliarity = 0.1) { Archetype[] archetypeData = format.Archetypes; Dictionary <string, ArchetypeColor> landColors = format.Lands; Dictionary <string, ArchetypeColor> cardColors = format.NonLands; ArchetypeSpecific[] specificArchetypes = archetypeData.Where(a => a is ArchetypeSpecific && !(a is ArchetypeVariant)).Select(a => a as ArchetypeSpecific).ToArray(); ArchetypeGeneric[] genericArchetypes = archetypeData.Where(a => a is ArchetypeGeneric).Select(a => a as ArchetypeGeneric).ToArray(); ArchetypeCompanion?companion = GetCompanion(mainboardCards, sideboardCards); ArchetypeColor color = GetColors(mainboardCards, sideboardCards, landColors, cardColors); List <ArchetypeMatch> results = new List <ArchetypeMatch>(); foreach (ArchetypeSpecific archetype in specificArchetypes) { if (Test(mainboardCards, sideboardCards, color, archetype)) { bool isVariant = false; if (archetype.Variants != null) { foreach (ArchetypeSpecific variant in archetype.Variants) { if (Test(mainboardCards, sideboardCards, color, variant)) { isVariant = true; results.Add(new ArchetypeMatch() { Archetype = archetype, Variant = variant, Similarity = 1 }); } } } if (!isVariant) { results.Add(new ArchetypeMatch() { Archetype = archetype, Variant = null, Similarity = 1 }); } } } if (results.Count == 0) { ArchetypeMatch genericArchetype = GetBestGenericArchetype(mainboardCards, sideboardCards, color, genericArchetypes); if (genericArchetype != null && genericArchetype.Similarity > minSimiliarity) { results.Add(genericArchetype); } } return(new ArchetypeResult() { Matches = results.ToArray(), Color = color, Companion = companion }); }
private static string GetArchetype(ArchetypeMatch match, ArchetypeColor color) { string result = match.Archetype.GetName(color); if (match.Variant != null) { result = match.Variant.GetName(color); } return(result); }
public string GetName(ArchetypeColor color) { string name = this.Name.Replace("Generic", ""); if (IncludeColorInName) { string colorName = GetColorName(color); name = colorName + name; } // Source: https://stackoverflow.com/questions/3216085/split-a-pascalcase-string-into-separate-words name = new Regex(@"(?<=[A-Z])(?=[A-Z][a-z])|(?<=[^A-Z])(?=[A-Z])|(?<=[A-Za-z])(?=[^A-Za-z])").Replace(name, " "); return(name); }
private static ArchetypeMatch GetBestGenericArchetype(Card[] mainboardCards, Card[] sideboardCards, ArchetypeColor color, ArchetypeGeneric[] genericArchetypes) { Dictionary <ArchetypeGeneric, int> weights = new Dictionary <ArchetypeGeneric, int>(); foreach (ArchetypeGeneric genericArchetype in genericArchetypes) { weights.Add(genericArchetype, 0); foreach (var card in mainboardCards.Concat(sideboardCards).Distinct()) { if (genericArchetype.CommonCards.Contains(card.Name)) { weights[genericArchetype] += card.Count; } } } if (weights.All(k => k.Value == 0)) { return(null); } else { int max = weights.Max(k => k.Value); KeyValuePair <ArchetypeGeneric, int> bestMatch = weights.Where(k => k.Value == max).ToArray().OrderBy(k => k.Key.CommonCards.Length).First(); return(new ArchetypeMatch() { Archetype = bestMatch.Key, Variant = null, Similarity = ((double)max) / ((double)(mainboardCards.Length + sideboardCards.Length)) }); } }
private static bool Test(Card[] mainboardCards, Card[] sideboardCards, ArchetypeColor color, ArchetypeSpecific archetypeData) { foreach (var condition in archetypeData.Conditions) { switch (condition.Type) { case ArchetypeConditionType.InMainboard: if (!mainboardCards.Any(c => c.Name == condition.Cards[0])) { return(false); } break; case ArchetypeConditionType.InSideboard: if (!sideboardCards.Any(c => c.Name == condition.Cards[0])) { return(false); } break; case ArchetypeConditionType.InMainOrSideboard: if (!mainboardCards.Any(c => c.Name == condition.Cards[0]) && !sideboardCards.Any(c => c.Name == condition.Cards[0])) { return(false); } break; case ArchetypeConditionType.OneOrMoreInMainboard: if (!mainboardCards.Any(c => condition.Cards.Contains(c.Name))) { return(false); } break; case ArchetypeConditionType.OneOrMoreInSideboard: if (!sideboardCards.Any(c => condition.Cards.Contains(c.Name))) { return(false); } break; case ArchetypeConditionType.OneOrMoreInMainOrSideboard: if (!mainboardCards.Any(c => condition.Cards.Contains(c.Name)) && !sideboardCards.Any(c => condition.Cards.Contains(c.Name))) { return(false); } break; case ArchetypeConditionType.TwoOrMoreInMainboard: if (mainboardCards.Where(c => condition.Cards.Contains(c.Name)).Count() < 2) { return(false); } break; case ArchetypeConditionType.TwoOrMoreInSideboard: if (sideboardCards.Where(c => condition.Cards.Contains(c.Name)).Count() < 2) { return(false); } break; case ArchetypeConditionType.TwoOrMoreInMainOrSideboard: if ((mainboardCards.Where(c => condition.Cards.Contains(c.Name)).Count() + sideboardCards.Where(c => condition.Cards.Contains(c.Name)).Count()) < 2) { return(false); } break; case ArchetypeConditionType.DoesNotContain: if (mainboardCards.Any(c => c.Name == condition.Cards[0]) || sideboardCards.Any(c => c.Name == condition.Cards[0])) { return(false); } break; case ArchetypeConditionType.DoesNotContainMainboard: if (mainboardCards.Any(c => c.Name == condition.Cards[0])) { return(false); } break; case ArchetypeConditionType.DoesNotContainSideboard: if (sideboardCards.Any(c => c.Name == condition.Cards[0])) { return(false); } break; default: throw new NotImplementedException(); } } return(true); }
private void DetectionFailure(ArchetypeConditionType condition, string[] archetypeCards, ArchetypeColor archetypeColor, string[] testMainboard, string[] testSideboard) { var archetype = new ArchetypeSpecific() { Conditions = new ArchetypeCondition[] { new ArchetypeCondition() { Type = condition, Cards = archetypeCards } } }; var result = ArchetypeAnalyzer.Detect( testMainboard.Select(c => new Card() { Count = 4, Name = c }).ToArray(), testSideboard.Select(c => new Card() { Count = 4, Name = c }).ToArray(), new ArchetypeFormat { Archetypes = new Archetype[] { archetype }, Lands = _modern.Lands, NonLands = _modern.NonLands }); result.Matches.Should().HaveCount(0); }
private void DetectionFailure(ArchetypeConditionType condition, ArchetypeColor archetypeColor, string[] testMainboard, string[] testSideboard) { DetectionFailure(condition, new string[0], archetypeColor, testMainboard, testSideboard); }
private string GetColorName(ArchetypeColor color) { switch (color) { case ArchetypeColor.W: return($"MonoWhite"); case ArchetypeColor.U: return($"MonoBlue"); case ArchetypeColor.B: return($"MonoBlack"); case ArchetypeColor.R: return($"MonoRed"); case ArchetypeColor.G: return($"MonoGreen"); case ArchetypeColor.WU: // Azorius return($"Azorius"); case ArchetypeColor.WB: // Orzhov return($"Orzhov"); case ArchetypeColor.WR: // Boros return($"Boros"); case ArchetypeColor.WG: // Selesnya return($"Selesnya"); case ArchetypeColor.UB: // Dimir return($"Dimir"); case ArchetypeColor.UR: // Izzet return($"Izzet"); case ArchetypeColor.UG: // Simic return($"Simic"); case ArchetypeColor.BR: // Rakdos return($"Rakdos"); case ArchetypeColor.BG: // Golgari return($"Golgari"); case ArchetypeColor.RG: // Gruul return($"Gruul"); case ArchetypeColor.WUB: // Esper return($"Esper"); case ArchetypeColor.WUR: // Jeskai return($"Jeskai"); case ArchetypeColor.WUG: // Bant return($"Bant"); case ArchetypeColor.WBR: // Mardu return($"Mardu"); case ArchetypeColor.WBG: // Abzan return($"Abzan"); case ArchetypeColor.WRG: // Naya return($"Naya"); case ArchetypeColor.UBR: // Grixis return($"Grixis"); case ArchetypeColor.UBG: // Sultai return($"Sultai"); case ArchetypeColor.URG: // Temur return($"Temur"); case ArchetypeColor.BRG: // Jund return($"Jund"); case ArchetypeColor.WUBR: // Not-G return($"WUBR"); case ArchetypeColor.WBRG: // Not-U return($"WBRG"); case ArchetypeColor.WUBG: // Not-R return($"WUBG"); case ArchetypeColor.WURG: // Not-B return($"WURG"); case ArchetypeColor.UBRG: // Not-W return($"UBRG"); case ArchetypeColor.WUBRG: return($"5Color"); default: return(""); } }