Esempio n. 1
0
        // Reset on when a new game starts
        internal async void GameStart()
        {
            // Only continue if in valid game mode and game format
            if (IsValidGameMode && IsValidGameFormat)
            {
                _advisorOverlay.UpdatePosition();
                _advisorOverlay.LblArchetype.Text = "";
                _advisorOverlay.LblStats.Text     = "";

                await Task.Delay(5000);

                _advisorOverlay.Update(new List <Card>(), true);
                _currentArchetypeDeckGuid = Guid.Empty;

                UpdateCardList();
                _advisorOverlay.Show();
            }
            else
            {
                _advisorOverlay.Hide();
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Determine similarity between all archetype decks and all cards played by the opponent yet.
        /// Then update the cardlist displayed in the overlay with the highest matching archetype deck after removing all opponent cards.
        /// </summary>
        internal async void UpdateCardList()
        {
            // Only continue if in valid game mode or game format
            if (!IsValidGameMode || !IsValidGameFormat)
            {
                return;
            }

            // Small delay to guarantee opponents cards list is up to date (should be 300+ ms in debug mode or with attached debugger, otherwise restarting HDT could lead to an incomplete opponent decklist!)
#if DEBUG
            await Task.Delay(1000);
#else
            await Task.Delay(100);
#endif

            // Get opponent's cards list (all yet revealed cards)
            //var opponentCardlist = Core.Game.Opponent.RevealedCards;
            IList <Card> opponentCardlist = Core.Game.Opponent.OpponentCardList.Where(x => !x.IsCreated).ToList();

            // If no opponent's cards were revealed yet or we have no imported archetype decks in the database, return empty card list
            if (!opponentCardlist.Any() || !ArchetypeDecks.Any())
            {
                currentArchetypeDeckGuid = Guid.Empty;
                _advisorOverlay.Update(new List <Card>(), true);
            }
            else
            {
                // Create archetype dictionary
                IDictionary <Deck, float> dict = new Dictionary <Deck, float>();

                // Calculate similarities between all opponent's class archetype decks and all yet known opponent cards. Exclude wild decks in standard format using NAND expression.
                foreach (var archetypeDeck in ArchetypeDecks.Where(d => d.Class == CoreAPI.Game.Opponent.Class && !(d.IsWildDeck && CoreAPI.Game.CurrentFormat == Format.Standard)))
                {
                    // Insert deck with calculated value into dictionary and prevent exception by inserting duplicate decks
                    if (!dict.ContainsKey(archetypeDeck))
                    {
                        dict.Add(archetypeDeck, archetypeDeck.Similarity(opponentCardlist));
                    }
                }

                // Get highest similarity value
                var maxSim = dict.Values.Max(); // TODO: Some unreproducable bug threw an exception here. System.InvalidOperationException: Sequence contains no elements @ IEnumerable.Max()

                // If any archetype deck matches more than MinimumSimilarity show the deck with the highest similarity
                if (maxSim >= Settings.Default.MinimumSimilarity)
                {
                    // Select top decks with highest similarity value
                    var topSimDecks = (from d in dict where Math.Abs(d.Value - maxSim) < 0.001 select d).ToList();
                    // Select top decks with most played games
                    var maxGames      = topSimDecks.Max(x => x.Key.GetPlayedGames());
                    var topGamesDecks = (from t in topSimDecks where t.Key.GetPlayedGames() == maxGames select t).ToList();
                    // Select best matched deck with both highest similarity value and most played games
                    var matchedDeck = topGamesDecks.First();

                    // Show matched deck name and similarity value or number of matching cards and number of all played cards
                    if (Settings.Default.ShowAbsoluteSimilarity)
                    {
                        // Count how many cards from opponent deck are in matched deck
                        int matchingCards = matchedDeck.Key.CountMatchingCards(opponentCardlist);
                        _advisorOverlay.LblArchetype.Text = String.Format("{0} ({1}/{2})", matchedDeck.Key.Name, matchingCards, matchedDeck.Key.CountUnion(opponentCardlist));
                    }
                    else
                    {
                        _advisorOverlay.LblArchetype.Text = String.Format("{0} ({1}%)", matchedDeck.Key.Name, Math.Round(matchedDeck.Value * 100, 2));
                    }

                    _advisorOverlay.LblStats.Text = String.Format("{0}", matchedDeck.Key.Note);
                    Deck deck = DeckList.Instance.Decks.Where(d => d.TagList.ToLowerInvariant().Contains("archetype")).First(d => d.Name == matchedDeck.Key.Name);
                    if (deck != null)
                    {
                        var predictedCards = ((Deck)deck.Clone()).Cards.ToList();

                        foreach (var card in opponentCardlist)
                        {
                            // Remove already played opponent cards from predicted archetype deck. But don't remove revealed jousted cards, because they were only seen and not played yet.
                            if (predictedCards.Contains(card))
                            {
                                var item = predictedCards.Find(x => x.Id == card.Id);

                                if (!card.Jousted)
                                {
                                    item.Count -= card.Count;
                                }

                                // highlight jousted cards in green
                                // also highlight when deck has 2 of a card and we have matched one
                                if (item.Count > 0)
                                {
                                    item.HighlightInHand = true;
                                    item.InHandCount    += card.Count;
                                }
                                else
                                {
                                    item.HighlightInHand = false;
                                    item.InHandCount     = 0;
                                }
                            }
                            if (Settings.Default.ShowNonMatchingCards)
                            {
                                // Show known cards that don't match the archetype deck, in red
                                if (!predictedCards.Contains(card))
                                {
                                    var item = (Card)card.Clone();
                                    item.HighlightInHand = false;
                                    item.WasDiscarded    = true;
                                    if (!item.Jousted)
                                    {
                                        item.Count = 0;
                                    }
                                    predictedCards.Add(item);
                                }
                            }
                        }
                        //var sortedPredictedCards = predictedCards.OrderBy(x => x.Cost).ThenBy(y => y.Name).ToList();
                        bool isNewArchetypeDeck = currentArchetypeDeckGuid != matchedDeck.Key.DeckId;
                        // Update overlay cards
                        _advisorOverlay.Update(predictedCards.ToSortedCardList(), isNewArchetypeDeck);
                        // Remember current archetype deck guid with highest similarity to opponent's played cards
                        currentArchetypeDeckGuid = matchedDeck.Key.DeckId;
                    }
                }
                else
                {
                    _advisorOverlay.LblArchetype.Text = String.Format("Best match: {0}%", Math.Round(maxSim * 100, 2));
                    _advisorOverlay.LblStats.Text     = "";
                    _advisorOverlay.Update(Settings.Default.ShowNonMatchingCards ? opponentCardlist.ToList() : new List <Card>(), currentArchetypeDeckGuid != Guid.Empty);
                    currentArchetypeDeckGuid = Guid.Empty;
                }
            }
        }