Example #1
0
        private async void DeleteDeck(Deck deck)
        {
            if (deck == null)
            {
                return;
            }

            var deckStats = DeckStatsList.Instance.DeckStats.FirstOrDefault(ds => ds.BelongsToDeck(deck));

            if (deckStats != null)
            {
                if (deckStats.Games.Any())
                {
                    if (Config.Instance.KeepStatsWhenDeletingDeck)
                    {
                        DefaultDeckStats.Instance.GetDeckStats(deck.Class).Games.AddRange(deckStats.Games);
                        DefaultDeckStats.Save();
                        Logger.WriteLine(string.Format("Moved deckstats for deck {0} to default stats", deck.Name), "Edit");
                    }
                    else
                    {
                        try
                        {
                            foreach (var game in deckStats.Games)
                            {
                                game.DeleteGameFile();
                            }
                            Logger.WriteLine("Deleted games from deck: " + deck.Name, "Edit");
                        }
                        catch (Exception)
                        {
                            Logger.WriteLine("Error deleting games", "Edit");
                        }
                    }
                }
                DeckStatsList.Instance.DeckStats.Remove(deckStats);
                DeckStatsList.Save();
                Logger.WriteLine("Removed deckstats from deck: " + deck.Name, "Edit");
            }

            if (HearthStatsAPI.IsLoggedIn && deck.HasHearthStatsId && await CheckHearthStatsDeckDeletion())
            {
                HearthStatsManager.DeleteDeckAsync(deck, false, true);
            }

            DeckList.Instance.Decks.Remove(deck);
            DeckList.Save();
            ;
            //DeckPickerList.RemoveDeck(deck);
            DeckPickerList.UpdateDecks();
            ListViewDeck.ItemsSource = null;
            Logger.WriteLine("Deleted deck: " + deck.Name, "Edit");
        }
        private static async Task <Deck> ImportHearthPwn(string url)
        {
            try
            {
                var doc = await GetHtmlDoc(url);

                var deck = new Deck();

                var deckName = HttpUtility.HtmlDecode(doc.DocumentNode.SelectSingleNode("//header/h2[contains(@class,'t-deck-title')]").InnerText);
                deck.Name = deckName;

                var cardNameNodes =
                    doc.DocumentNode.SelectNodes("//td[contains(@class,'col-name')]//a[contains(@href,'/cards/') and contains(@class,'rarity')]");
                var cardCountNodes = doc.DocumentNode.SelectNodes("//td[contains(@class,'col-name')]");
                //<span class="t-deck-type-label">Midrange</span>
                var decktype = doc.DocumentNode.SelectSingleNode("//span[contains(@class,'t-deck-type-label')]").InnerText;
                if (decktype != "None" && Config.Instance.TagDecksOnImport)
                {
                    if (!DeckList.Instance.AllTags.Contains(decktype))
                    {
                        DeckList.Instance.AllTags.Add(decktype);
                        DeckList.Save();
                        Helper.MainWindow.SortFilterDecksFlyout.LoadTags(DeckList.Instance.AllTags);
                        Helper.MainWindow.TagControlEdit.LoadTags(DeckList.Instance.AllTags.Where(t => t != "All").ToList());
                    }
                    deck.Tags.Add(decktype);
                }


                var cardNames = cardNameNodes.Select(cardNameNode => HttpUtility.HtmlDecode(cardNameNode.InnerText));
                var cardCosts = cardCountNodes.Select(countNode => int.Parse(Regex.Match(countNode.LastChild.InnerText, @"\d+").Value));

                var cardInfo = cardNames.Zip(cardCosts, (n, c) => new { Name = n, Count = c });
                foreach (var info in cardInfo)
                {
                    var card = Game.GetCardFromName(info.Name);
                    card.Count = info.Count;
                    deck.Cards.Add(card);
                    if (string.IsNullOrEmpty(deck.Class) && card.PlayerClass != "Neutral")
                    {
                        deck.Class = card.PlayerClass;
                    }
                }

                return(deck);
            }
            catch (Exception e)
            {
                Logger.WriteLine(e.ToString(), "DeckImporter");
                return(null);
            }
        }
Example #3
0
        internal void BtnUnarchiveDeck_Click(object sender, RoutedEventArgs e)
        {
            foreach (var deck in DeckPickerList.SelectedDecks)
            {
                ArchiveDeck(deck, false, false);
            }

            DeckList.Save();
            DeckPickerList.UpdateDecks();
            DeckPickerList.SelectDeckAndAppropriateView(DeckPickerList.SelectedDecks.FirstOrDefault());
            UpdateMenuItemVisibility();
            DeckPickerList.UpdateArchivedClassVisibility();
        }
Example #4
0
 public static void SaveDeck(Deck deck, bool invokeApi = true)
 {
     deck.Edited();
     DeckList.Instance.Decks.Add(deck);
     DeckList.Save();
     Core.MainWindow.DeckPickerList.SelectDeckAndAppropriateView(deck);
     Core.MainWindow.DeckPickerList.UpdateDecks(forceUpdate: new[] { deck });
     Core.MainWindow.SelectDeck(deck, true);
     if (invokeApi)
     {
         DeckManagerEvents.OnDeckCreated.Execute(deck);
     }
 }
Example #5
0
        public void ArchiveDeck(Deck deck, bool archive, bool saveAndUpdate = true)
        {
            if (deck == null)
            {
                return;
            }

            var oldArchived = deck.Archived;

            if (oldArchived == archive)
            {
                return;
            }

            deck.Archived = archive;
            deck.Edited();

            try
            {
                if (saveAndUpdate)
                {
                    DeckList.Save();
                    DeckPickerList.UpdateDecks();

                    if (archive)
                    {
                        SelectDeck(null, true);
                    }
                    else
                    {
                        DeckPickerList.SelectDeckAndAppropriateView(deck);
                        UpdateMenuItemVisibility();
                    }

                    DeckPickerList.UpdateArchivedClassVisibility();
                }

                var archivedLog = archive ? "archived" : "unarchived";
                Logger.WriteLine(String.Format("Successfully {0} deck: {1}", archivedLog, deck.Name), "ArchiveDeck");

                if (Config.Instance.HearthStatsAutoUploadNewDecks && HearthStatsAPI.IsLoggedIn)
                {
                    Logger.WriteLine(String.Format("auto uploading {0} deck", archivedLog), "ArchiveDeck");
                    HearthStatsManager.UpdateDeckAsync(deck, background: true);
                }
            }
            catch (Exception)
            {
                Logger.WriteLine(String.Format("Error {0} deck", archive ? "archiving" : "unarchiving", deck.Name), "ArchiveDeck");
            }
        }
Example #6
0
        internal async void BtnCloneDeck_Click(object sender, RoutedEventArgs e)
        {
            var cloneStats =
                (await
                 this.ShowMessageAsync("Clone game history?", "(Cloned games do not count towards class or overall stats.)",
                                       MessageDialogStyle.AffirmativeAndNegative,
                                       new MetroDialogSettings
            {
                AffirmativeButtonText = "clone history",
                NegativeButtonText = "do not clone history"
            })) == MessageDialogResult.Affirmative;
            var deck = DeckPickerList.SelectedDecks.FirstOrDefault();

            var clone         = (Deck)deck.CloneWithNewId(false);
            var originalStats = deck.DeckStats;

            clone.ResetHearthstatsIds();
            clone.Versions.ForEach(v => v.ResetHearthstatsIds());
            clone.Archived = false;

            DeckList.Instance.Decks.Add(clone);
            DeckList.Save();

            var newStatsEntry = DeckStatsList.Instance.DeckStats.FirstOrDefault(ds => ds.BelongsToDeck(clone));

            if (newStatsEntry == null)
            {
                newStatsEntry = new DeckStats(clone);
                DeckStatsList.Instance.DeckStats.Add(newStatsEntry);
            }

            if (cloneStats)
            {
                foreach (var game in originalStats.Games)
                {
                    newStatsEntry.AddGameResult(game.CloneWithNewId());
                }
                Logger.WriteLine("cloned gamestats", "Edit");
            }

            DeckStatsList.Save();
            DeckPickerList.SelectDeckAndAppropriateView(clone);

            if (Config.Instance.HearthStatsAutoUploadNewDecks && HearthStatsAPI.IsLoggedIn)
            {
                HearthStatsManager.UploadDeckAsync(clone);
            }
        }
        private void DeleteTag(string tag)
        {
            if (DeckList.Instance.AllTags.Contains(tag))
            {
                DeckList.Instance.AllTags.Remove(tag);

                foreach (var deck in DeckList.Instance.Decks.Where(deck => deck.Tags.Contains(tag)))
                {
                    deck.Tags.Remove(tag);
                }

                DeckList.Save();
                Core.MainWindow.ReloadTags();
                Core.MainWindow.DeckPickerList.UpdateDecks();
            }
        }
Example #8
0
        private static Deck CreateDungeonDeck(string playerClass)
        {
            Log.Info($"Creating new {playerClass} dungeon run deck");
            var deck = DungeonRun.GetDefaultDeck(playerClass);

            if (deck == null)
            {
                Log.Info($"Could not find default deck for {playerClass}");
                return(null);
            }
            DeckList.Instance.Decks.Add(deck);
            DeckList.Save();
            Core.MainWindow.DeckPickerList.UpdateDecks();
            Core.MainWindow.SelectDeck(deck, true);
            return(deck);
        }
Example #9
0
 public void SaveDeck()
 {
     if (!_noteChanged || _currentDeck == null)
     {
         return;
     }
     DeckList.Save();
     if (Config.Instance.HearthStatsAutoUploadNewDecks && HearthStatsAPI.IsLoggedIn)
     {
         Log.Info($"auto updating {_currentDeck} deck");
         HearthStatsManager.UpdateDeckAsync(_currentDeck, background: true).Forget();
     }
     _noteChanged      = false;
     BtnSave.IsEnabled = false;
     Core.MainWindow.DeckPickerList.UpdateDecks();
 }
 public void SaveDeck()
 {
     if (!_noteChanged || _currentDeck == null)
     {
         return;
     }
     DeckList.Save();
     if (Config.Instance.HearthStatsAutoUploadNewDecks && HearthStatsAPI.IsLoggedIn)
     {
         Logger.WriteLine(string.Format("auto updating {0} deck", _currentDeck), "NoteDialog");
         HearthStatsManager.UpdateDeckAsync(_currentDeck, background: true);
     }
     _noteChanged      = false;
     BtnSave.IsEnabled = false;
     Helper.MainWindow.DeckPickerList.UpdateDecks();
 }
Example #11
0
        public static void ImportDecks(IEnumerable <ImportedDeck> decks, bool brawl, bool importNew = true, bool updateExisting = true, bool select = true)
        {
            var imported = ImportDecksTo(DeckList.Instance.Decks, decks, brawl, importNew, updateExisting);

            if (!imported.Any())
            {
                return;
            }
            DeckList.Save();
            Core.MainWindow.DeckPickerList.UpdateDecks();
            Core.MainWindow.UpdateIntroLabelVisibility();
            if (select)
            {
                Core.MainWindow.SelectDeck(imported.First(), true);
            }
            Core.UpdatePlayerCards(true);
        }
Example #12
0
        private static Deck CreateDungeonDeck(string playerClass, CardSet set)
        {
            var shrine = Core.Game.Player.Board.FirstOrDefault(x => x.HasTag(GameTag.SHRINE))?.CardId;

            Log.Info($"Creating new {playerClass} dungeon run deck (CardSet={set}, Shrine={shrine})");
            var deck = DungeonRun.GetDefaultDeck(playerClass, set, shrine);

            if (deck == null)
            {
                Log.Info($"Could not find default deck for {playerClass} in card set {set} with Shrine={shrine}");
                return(null);
            }
            DeckList.Instance.Decks.Add(deck);
            DeckList.Save();
            Core.MainWindow.DeckPickerList.UpdateDecks();
            Core.MainWindow.SelectDeck(deck, true);
            return(deck);
        }
        private void FixTagOrder()
        {
            var changed = false;

            if (DeckList.Instance.AllTags.IndexOf("All") != 0)
            {
                MoveTag("All", DeckList.Instance.AllTags.IndexOf("All"), 0);
                changed = true;
            }
            if (DeckList.Instance.AllTags.IndexOf("None") != 1)
            {
                MoveTag("None", DeckList.Instance.AllTags.IndexOf("None"), 1);
                changed = true;
            }
            if (changed)
            {
                DeckList.Save();
            }
        }
        private void TagControlOnDeleteTag(SortFilterDecks sender, string tag)
        {
            if (DeckList.Instance.AllTags.Contains(tag))
            {
                DeckList.Instance.AllTags.Remove(tag);

                foreach (var deck in DeckList.Instance.Decks.Where(deck => deck.Tags.Contains(tag)))
                {
                    deck.Tags.Remove(tag);
                }

                //if(Helper.MainWindow.NewDeck.Tags.Contains(tag))
                //	Helper.MainWindow.NewDeck.Tags.Remove(tag);

                DeckList.Save();
                Helper.MainWindow.SortFilterDecksFlyout.LoadTags(DeckList.Instance.AllTags);
                Helper.MainWindow.TagControlEdit.LoadTags(DeckList.Instance.AllTags.Where(t => t != "All" && t != "None").ToList());
                //Helper.MainWindow.DeckPickerList.UpdateList();
                Helper.MainWindow.DeckPickerList.UpdateDecks();
            }
        }
 private void SortFilterDecksFlyoutOnSelectedTagsChanged()
 {
     //only set tags if tags were changed in "My Decks"
     if (Name == "SortFilterDecksFlyout")
     {
         var tags = Tags.Where(tag => tag.Selected).Select(tag => tag.Name).ToList();
         //Helper.MainWindow.DeckPickerList.SetSelectedTags(tags);
         Config.Instance.SelectedTags = tags;
         Config.Save();
         Helper.MainWindow.DeckPickerList.UpdateDecks();
         Helper.MainWindow.StatsWindow.StatsControl.LoadOverallStats();
         Helper.MainWindow.DeckStatsFlyout.LoadOverallStats();
     }
     else if (Name == "TagControlEdit")
     {
         var tags = Tags.Where(tag => tag.Selected).Select(tag => tag.Name).ToList();
         DeckList.Instance.ActiveDeck.Tags = new List <string>(tags);
         Helper.MainWindow.DeckPickerList.UpdateDecks();
         DeckList.Save();
         ;
         Helper.MainWindow.UpdateQuickFilterItemSource();
     }
 }
Example #16
0
 private void SortFilterDecksFlyoutOnSelectedTagsChanged()
 {
     //only set tags if tags were changed in "My Decks"
     if (Name == nameof(Core.MainWindow.SortFilterDecksFlyout))
     {
         var tags = Tags.Where(tag => tag.Selected == true).Select(tag => tag.Name).ToList();
         Config.Instance.SelectedTags = tags;
         Config.Save();
         Core.MainWindow.DeckPickerList.UpdateDecks();
     }
     else if (Name == nameof(Core.MainWindow.TagControlEdit))
     {
         var tags   = Tags.Where(tag => tag.Selected == true).Select(tag => tag.Name).ToList();
         var ignore = Tags.Where(tag => tag.Selected == null).Select(tag => tag.Name).ToList();
         foreach (var deck in Core.MainWindow.DeckPickerList.SelectedDecks)
         {
             var keep = deck.Tags.Intersect(ignore);
             deck.Tags = new List <string>(tags.Concat(keep));
             deck.Edited();
         }
         Core.MainWindow.DeckPickerList.UpdateDecks(false);
         DeckList.Save();
     }
 }
        internal async void BtnName_Click(object sender, RoutedEventArgs e)
        {
            var deck = DeckList.Instance.ActiveDeck;

            if (deck == null)
            {
                return;
            }
            var settings = new MetroDialogSettings {
                AffirmativeButtonText = "set", NegativeButtonText = "cancel", DefaultText = deck.Name
            };
            var newName = await this.ShowInputAsync("Set deck name", "", settings);

            if (!string.IsNullOrEmpty(newName) && deck.Name != newName)
            {
                deck.Name = newName;
                DeckList.Save();
                DeckPickerList.UpdateDecks();
                if (Config.Instance.HearthStatsAutoUploadNewDecks && HearthStatsAPI.IsLoggedIn)
                {
                    HearthStatsManager.UpdateDeckAsync(deck, true, true);
                }
            }
        }
        private static Deck CreateDungeonDeck(string playerClass, CardSet set, bool isPVPDR, List <int> selectedDeck = null, Card loadout = null)
        {
            var shrine = Core.Game.Player.Board.FirstOrDefault(x => x.HasTag(GameTag.SHRINE))?.CardId;

            Log.Info($"Creating new {playerClass} dungeon run deck (CardSet={set}, Shrine={shrine}, SelectedDeck={selectedDeck != null})");
            var deck = selectedDeck == null
                                ? DungeonRun.GetDefaultDeck(playerClass, set, shrine)
                                : DungeonRun.GetDeckFromDbfIds(playerClass, set, isPVPDR, selectedDeck);

            if (deck == null)
            {
                Log.Info($"Could not find default deck for {playerClass} in card set {set} with Shrine={shrine}");
                return(null);
            }
            if (loadout != null && selectedDeck != null && !selectedDeck.Contains(loadout.DbfIf))
            {
                deck.Cards.Add(loadout);
            }
            DeckList.Instance.Decks.Add(deck);
            DeckList.Save();
            Core.MainWindow.DeckPickerList.UpdateDecks();
            Core.MainWindow.SelectDeck(deck, true);
            return(deck);
        }
Example #19
0
        private void MoveGameToOtherDeck(List <GameStats> selectedGames)
        {
            if (selectedGames == null)
            {
                return;
            }

            var heroes = new Dictionary <string, int>();

            foreach (var game in selectedGames)
            {
                if (!heroes.ContainsKey(game.PlayerHero))
                {
                    heroes.Add(game.PlayerHero, 0);
                }
                heroes[game.PlayerHero]++;
            }

            var heroPlayed      = heroes.Any() ? heroes.OrderByDescending(x => x.Value).First().Key : "Any";
            var possibleTargets = DeckList.Instance.Decks.Where(d => d.Class == heroPlayed || heroPlayed == "Any");

            var dialog = new MoveGameDialog(possibleTargets);

            if (Config.Instance.StatsInWindow)
            {
                dialog.Owner = Core.Windows.StatsWindow;
            }
            else
            {
                dialog.Owner = Helper.MainWindow;
            }

            dialog.ShowDialog();
            var selectedDeck = dialog.SelectedDeck;

            if (selectedDeck == null)
            {
                return;
            }
            foreach (var game in selectedGames)
            {
                var defaultDeck = DefaultDeckStats.Instance.DeckStats.FirstOrDefault(ds => ds.Games.Contains(game));
                if (defaultDeck != null)
                {
                    defaultDeck.Games.Remove(game);
                    DefaultDeckStats.Save();
                }
                else
                {
                    var deck = DeckList.Instance.Decks.FirstOrDefault(d => game.DeckId == d.DeckId);
                    if (deck != null)
                    {
                        deck.DeckStats.Games.Remove(game);
                    }
                }
                game.PlayerDeckVersion        = dialog.SelectedVersion;
                game.HearthStatsDeckVersionId = selectedDeck.GetVersion(dialog.SelectedVersion).HearthStatsDeckVersionId;
                game.DeckId   = selectedDeck.DeckId;
                game.DeckName = selectedDeck.Name;
                selectedDeck.DeckStats.Games.Add(game);
                if (HearthStatsAPI.IsLoggedIn && Config.Instance.HearthStatsAutoUploadNewGames)
                {
                    HearthStatsManager.MoveMatchAsync(game, selectedDeck, background: true);
                }
            }
            DeckStatsList.Save();
            DeckList.Save();
            Refresh();
            Core.MainWindow.DeckPickerList.UpdateDecks();
        }
Example #20
0
        internal async void BtnCloneSelectedVersion_Click(object sender, RoutedEventArgs e)
        {
            var deck = DeckPickerList.SelectedDecks.FirstOrDefault();

            if (deck == null)
            {
                return;
            }
            var cloneStats =
                (await
                 this.ShowMessageAsync("Clone game history?", "(Cloned games do not count towards class or overall stats.)",
                                       MessageDialogStyle.AffirmativeAndNegative,
                                       new MetroDialogSettings
            {
                AffirmativeButtonText = "clone history",
                NegativeButtonText = "do not clone history"
            })) == MessageDialogResult.Affirmative;
            var clone = (Deck)deck.CloneWithNewId(false);

            // bug #1316 - ResetVersions needs the current version as an argument
            clone.ResetVersions();
            clone.ResetHearthstatsIds();
            clone.Archived = false;

            var originalStatsEntry = clone.DeckStats;

            /*while(DeckList.DecksList.Any(d => d.Name == clone.Name))
             * {
             *      var settings = new MetroDialogSettings {AffirmativeButtonText = "Set", DefaultText = clone.Name};
             *      var name =
             *              await
             *              this.ShowInputAsync("Name already exists", "You already have a deck with that name, please select a different one.", settings);
             *
             *      if(string.IsNullOrEmpty(name))
             *              return;
             *
             *      clone.Name = name;
             * }*/

            DeckList.Instance.Decks.Add(clone);
            DeckPickerList.UpdateDecks();
            DeckList.Save();


            var newStatsEntry = DeckStatsList.Instance.DeckStats.FirstOrDefault(ds => ds.BelongsToDeck(clone));

            if (newStatsEntry == null)
            {
                newStatsEntry = new DeckStats(clone);
                DeckStatsList.Instance.DeckStats.Add(newStatsEntry);
            }

            //clone game stats
            if (cloneStats)
            {
                foreach (var game in originalStatsEntry.Games)
                {
                    newStatsEntry.AddGameResult(game.CloneWithNewId());
                }
                Logger.WriteLine("cloned gamestats (version)", "Edit");
            }

            DeckStatsList.Save();
            //DeckPickerList.UpdateList();
            DeckPickerList.SelectDeckAndAppropriateView(clone);

            if (Config.Instance.HearthStatsAutoUploadNewDecks && HearthStatsAPI.IsLoggedIn)
            {
                HearthStatsManager.UploadDeckAsync(clone);
            }
        }
Example #21
0
        private void MoveGameToOtherDeck(GameStats selectedGame)
        {
            if (selectedGame == null)
            {
                return;
            }

            var heroes = new Dictionary <string, int>();

            foreach (var turn in selectedGame.TurnStats)
            {
                foreach (var play in turn.Plays)
                {
                    if (!play.Type.ToString().Contains("Player"))
                    {
                        continue;
                    }
                    var hero = Game.GetCardFromId(play.CardId).PlayerClass;
                    if (hero == null)
                    {
                        continue;
                    }
                    if (!heroes.ContainsKey(hero))
                    {
                        heroes.Add(hero, 0);
                    }
                    heroes[hero]++;
                }
            }


            var heroPlayed = heroes.Any() ? heroes.OrderByDescending(x => x.Value).First().Key : "Any";

            var possibleTargets = DeckList.Instance.Decks.Where(d => d.Class == heroPlayed || heroPlayed == "Any");

            var dialog = new MoveGameDialog(possibleTargets);

            if (Config.Instance.StatsInWindow)
            {
                dialog.Owner = Helper.MainWindow.StatsWindow;
            }
            else
            {
                dialog.Owner = Helper.MainWindow;
            }

            dialog.ShowDialog();
            var selectedDeck = dialog.SelectedDeck;

            if (selectedDeck == null)
            {
                return;
            }
            var defaultDeck = DefaultDeckStats.Instance.DeckStats.FirstOrDefault(ds => ds.Games.Contains(selectedGame));

            if (defaultDeck != null)
            {
                defaultDeck.Games.Remove(selectedGame);
                DefaultDeckStats.Save();
            }
            else
            {
                _deck.DeckStats.Games.Remove(selectedGame);
            }
            selectedGame.PlayerDeckVersion        = selectedDeck.Version;      //move to latest version
            selectedGame.HearthStatsDeckVersionId = selectedDeck.HearthStatsDeckVersionId;
            selectedDeck.DeckStats.Games.Add(selectedGame);
            DeckStatsList.Save();
            DeckList.Save();
            ;
            Refresh();
            Helper.MainWindow.DeckPickerList.UpdateDecks();
            if (HearthStatsAPI.IsLoggedIn && Config.Instance.HearthStatsAutoUploadNewGames)
            {
                HearthStatsManager.MoveMatchAsync(selectedGame, selectedDeck, background: true);
            }
        }
Example #22
0
        public static void UpdateDungeonRunDeck(DungeonInfo info)
        {
            if (!Config.Instance.DungeonAutoImport)
            {
                return;
            }
            Log.Info($"Found dungeon run deck Set={((CardSet)info.CardSet).ToString()}");
            var baseDeck = info.SelectedDeck ?? new List <int>();
            var allCards = info.DbfIds?.ToList() ?? new List <int>();

            if (baseDeck.All(x => allCards.Contains(x)))
            {
                if (info.PlayerChosenLoot > 0)
                {
                    var loot   = new[] { info.LootA, info.LootB, info.LootC };
                    var chosen = loot[info.PlayerChosenLoot - 1];
                    for (var i = 1; i < chosen.Count; i++)
                    {
                        allCards.Add(chosen[i]);
                    }
                }
                if (info.PlayerChosenTreasure > 0)
                {
                    allCards.Add(info.Treasure[info.PlayerChosenTreasure - 1]);
                }
            }
            else
            {
                allCards = baseDeck;
            }
            var cards = allCards.GroupBy(x => x).Select(x =>
            {
                var card = Database.GetCardFromDbfId(x.Key, false);
                if (card == null)
                {
                    return(null);
                }
                card.Count = x.Count();
                return(card);
            }).Where(x => x != null).ToList();

            var loadoutCardId = info.LoadoutCardId;
            var loadout       = loadoutCardId != null?Database.GetCardFromId(loadoutCardId) : null;

            if (loadout != null && !allCards.Contains(loadout.DbfIf))
            {
                cards.Add(loadout);
            }

            if (!Config.Instance.DungeonRunIncludePassiveCards)
            {
                cards.RemoveAll(c => !c.Collectible && c.HideStats);
            }

            var cardSet = (CardSet)info.CardSet;

            string playerClass = null;

            if (cardSet == CardSet.ULDUM && loadout != null)
            {
                playerClass = DungeonRun.GetUldumHeroPlayerClass(loadout.PlayerClass);
            }
            else
            {
                if (allCards.Count == 10)
                {
                    playerClass = allCards.Select(x => Database.GetCardFromDbfId(x).PlayerClass).FirstOrDefault(x => x != null)?.ToUpperInvariant();
                }
                if (playerClass == null)
                {
                    playerClass = ((CardClass)info.HeroCardClass).ToString().ToUpperInvariant();
                }
            }

            var deck = DeckList.Instance.Decks.FirstOrDefault(x => x.IsDungeonDeck && x.Class.ToUpperInvariant() == playerClass.ToUpperInvariant() &&
                                                              !(x.IsDungeonRunCompleted ?? false) &&
                                                              x.Cards.All(e => cards.Any(c => c.Id == e.Id && c.Count >= e.Count)));

            if (deck == null && (deck = CreateDungeonDeck(playerClass, cardSet, info.SelectedDeck, loadout)) == null)
            {
                Log.Info($"No existing deck - can't find default deck for {playerClass}");
                return;
            }
            if (!info.RunActive && (cardSet == CardSet.ULDUM || cardSet == CardSet.DALARAN))
            {
                Log.Info($"Inactive run for Set={cardSet.ToString()} - this is a new run");
                return;
            }
            if (cards.All(c => deck.Cards.Any(e => c.Id == e.Id && c.Count == e.Count)))
            {
                Log.Info("No new cards");
                return;
            }
            deck.Cards.Clear();
            Helper.SortCardCollection(cards, false);
            foreach (var card in cards)
            {
                deck.Cards.Add(card);
            }
            deck.LastEdited = DateTime.Now;
            DeckList.Save();
            Core.UpdatePlayerCards(true);
            Log.Info("Updated dungeon run deck");
        }
        public static async Task Export(Deck deck)
        {
            if (deck == null)
            {
                return;
            }
            string Current_Clipboard = "";

            try
            {
                if (Config.Instance.ExportPasteClipboard && Clipboard.ContainsText())
                {
                    Current_Clipboard = Clipboard.GetText();
                }
                Logger.WriteLine(string.Format("Exporting " + deck.GetDeckInfo()), "DeckExporter");
                var hsHandle = User32.GetHearthstoneWindow();

                if (!User32.IsHearthstoneInForeground())
                {
                    //restore window and bring to foreground
                    User32.ShowWindow(hsHandle, User32.SwRestore);
                    User32.SetForegroundWindow(hsHandle);
                    //wait it to actually be in foreground, else the rect might be wrong
                    await Task.Delay(500);
                }
                if (!User32.IsHearthstoneInForeground())
                {
                    MessageBox.Show("Can't find Heartstone window.");
                    Logger.WriteLine("Can't find Hearthstone window.", "DeckExporter");
                    return;
                }

                Logger.WriteLine("Waiting for " + Config.Instance.ExportStartDelay + " seconds before starting the export process", "DeckExporter");
                await Task.Delay(Config.Instance.ExportStartDelay * 1000);

                var hsRect = User32.GetHearthstoneRect(false);
                var ratio  = (4.0 / 3.0) / ((double)hsRect.Width / hsRect.Height);

                var searchBoxPos = new Point((int)(GetXPos(Config.Instance.ExportSearchBoxX, hsRect.Width, ratio)),
                                             (int)(Config.Instance.ExportSearchBoxY * hsRect.Height));
                var cardPosX  = GetXPos(Config.Instance.ExportCard1X, hsRect.Width, ratio);
                var card2PosX = GetXPos(Config.Instance.ExportCard2X, hsRect.Width, ratio);
                var cardPosY  = Config.Instance.ExportCardsY * hsRect.Height;


                Helper.MainWindow.Overlay.ForceHidden = true;
                Helper.MainWindow.Overlay.UpdatePosition();

                if (Config.Instance.AutoClearDeck)
                {
                    await ClearDeck(hsRect.Width, hsRect.Height, hsHandle, ratio);
                }

                if (Config.Instance.ExportSetDeckName)
                {
                    await SetDeckName(deck.Name, ratio, hsRect.Width, hsRect.Height, hsHandle);
                }

                await ClickAllCrystal(ratio, hsRect.Width, hsRect.Height, hsHandle);

                Logger.WriteLine("Creating deck...", "DeckExporter");
                deck.MissingCards.Clear();
                foreach (var card in deck.Cards)
                {
                    var missingCardsCount =
                        await AddCardToDeck(card, searchBoxPos, cardPosX, card2PosX, cardPosY, hsRect.Height, hsRect.Width, hsHandle);

                    if (missingCardsCount < 0)
                    {
                        return;
                    }
                    if (missingCardsCount > 0)
                    {
                        var missingCard = (Card)card.Clone();
                        missingCard.Count = missingCardsCount;
                        deck.MissingCards.Add(missingCard);
                    }
                }

                if (deck.MissingCards.Any())
                {
                    DeckList.Save();
                }

                // Clear search field now all cards have been entered

                await ClickOnPoint(hsHandle, searchBoxPos);

                SendKeys.SendWait("{DELETE}");
                SendKeys.SendWait("{ENTER}");

                if (Config.Instance.ExportPasteClipboard)
                {
                    Clipboard.Clear();
                }

                Logger.WriteLine("Done creating deck.", "DeckExporter");
            }
            catch (Exception e)
            {
                Logger.WriteLine("Error exporting deck: " + e, "DeckExporter");
            }
            finally
            {
                Helper.MainWindow.Overlay.ForceHidden = false;
                Helper.MainWindow.Overlay.UpdatePosition();
                if (Config.Instance.ExportPasteClipboard && Current_Clipboard != "")
                {
                    Clipboard.SetText(Current_Clipboard);
                }
            }
        }
        public static void ImportDecks(IEnumerable <ImportedDeck> decks, bool brawl, bool importNew = true, bool updateExisting = true, bool select = true)
        {
            Deck toSelect = null;

            foreach (var deck in decks)
            {
                if (deck.SelectedImportOption is NewDeck)
                {
                    if (!importNew)
                    {
                        continue;
                    }
                    Log.Info($"Saving {deck.Deck.Name} as new deck.");
                    var newDeck = new Deck {
                        Class = deck.Class,
                        Name  = deck.Deck.Name,
                        HsId  = deck.Deck.Id,
                        Cards = new ObservableCollection <Card>(deck.Deck.Cards.Select(x =>
                        {
                            var card   = Database.GetCardFromId(x.Id);
                            card.Count = x.Count;
                            return(card);
                        })),
                        LastEdited  = DateTime.Now,
                        IsArenaDeck = false
                    };
                    if (brawl)
                    {
                        newDeck.Tags.Add("Brawl");
                        newDeck.Name = Helper.ParseDeckNameTemplate(Config.Instance.BrawlDeckNameTemplate, newDeck);
                    }
                    DeckList.Instance.Decks.Add(newDeck);
                    toSelect = newDeck;
                }
                else
                {
                    if (!updateExisting)
                    {
                        continue;
                    }
                    var existing = deck.SelectedImportOption as ExistingDeck;
                    if (existing == null)
                    {
                        continue;
                    }
                    var target = existing.Deck;
                    target.HsId = deck.Deck.Id;
                    if (brawl && !target.Tags.Any(x => x.ToUpper().Contains("BRAWL")))
                    {
                        target.Tags.Add("Brawl");
                    }
                    if (existing.NewVersion.Major == 0)
                    {
                        Log.Info($"Assinging id to existing deck: {deck.Deck.Name}.");
                    }
                    else
                    {
                        Log.Info($"Saving {deck.Deck.Name} as {existing.NewVersion.ShortVersionString} (prev={target.Version.ShortVersionString}).");
                        DeckList.Instance.Decks.Remove(target);
                        var oldDeck = (Deck)target.Clone();
                        oldDeck.Versions  = new List <Deck>();
                        target.Name       = deck.Deck.Name;
                        target.LastEdited = DateTime.Now;
                        target.Versions.Add(oldDeck);
                        target.Version                  = existing.NewVersion;
                        target.SelectedVersion          = existing.NewVersion;
                        target.HearthStatsDeckVersionId = "";
                        target.Cards.Clear();
                        var cards = deck.Deck.Cards.Select(x =>
                        {
                            var card   = Database.GetCardFromId(x.Id);
                            card.Count = x.Count;
                            return(card);
                        });
                        foreach (var card in cards)
                        {
                            target.Cards.Add(card);
                        }
                        var clone = (Deck)target.Clone();
                        DeckList.Instance.Decks.Add(clone);
                        toSelect = clone;
                    }
                }
            }
            DeckList.Save();
            Core.MainWindow.DeckPickerList.UpdateDecks();
            Core.MainWindow.UpdateIntroLabelVisibility();
            if (select && toSelect != null)
            {
                Core.MainWindow.SelectDeck(toSelect, true);
            }
            Core.UpdatePlayerCards(true);
        }
        public static void UpdateDungeonRunDeck(DungeonInfo info, bool isPVPDR)
        {
            if (!Config.Instance.DungeonAutoImport)
            {
                return;
            }

            var isNewPVPDR = isPVPDR && !info.RunActive && info.SelectedLoadoutTreasureDbId > 0;

            Log.Info($"Found dungeon run deck Set={(CardSet)info.CardSet}, PVPDR={isPVPDR} (new={isNewPVPDR})");

            var allCards = info.DbfIds?.ToList() ?? new List <int>();

            // New PVPDR runs have all non-loadout cards in the DbfIds. We still add the picked loadout below.
            // So we don't want to replace allCards with baseDeck, as backDeck is empty, and we don't want to add
            // any loot or treasure, as these will be the ones from a previous run, if they exist.
            if (!isNewPVPDR)
            {
                var baseDeck = info.SelectedDeck ?? new List <int>();
                if (baseDeck.All(x => allCards.Contains(x)))
                {
                    if (info.PlayerChosenLoot > 0)
                    {
                        var loot   = new[] { info.LootA, info.LootB, info.LootC };
                        var chosen = loot[info.PlayerChosenLoot - 1];
                        for (var i = 1; i < chosen.Count; i++)
                        {
                            allCards.Add(chosen[i]);
                        }
                    }
                    if (info.PlayerChosenTreasure > 0)
                    {
                        allCards.Add(info.Treasure[info.PlayerChosenTreasure - 1]);
                    }
                }
                else
                {
                    allCards = baseDeck;
                }
            }

            var cards = allCards.GroupBy(x => x).Select(x =>
            {
                var card = Database.GetCardFromDbfId(x.Key, false);
                if (card == null)
                {
                    return(null);
                }
                card.Count = x.Count();
                return(card);
            }).Where(x => x != null).ToList();

            var loadoutCardId = info.LoadoutCardId;
            var loadout       = loadoutCardId != null?Database.GetCardFromId(loadoutCardId) : null;

            if (loadout != null && !allCards.Contains(loadout.DbfIf))
            {
                cards.Add(loadout);
            }

            if (!Config.Instance.DungeonRunIncludePassiveCards)
            {
                cards.RemoveAll(c => !c.Collectible && c.HideStats);
            }

            var cardSet = (CardSet)info.CardSet;

            string playerClass = null;

            if (cardSet == CardSet.ULDUM && loadout != null)
            {
                playerClass = DungeonRun.GetUldumHeroPlayerClass(loadout.PlayerClass);
            }
            else if (isPVPDR)
            {
                playerClass = HearthDbConverter.ConvertClass((CardClass)(info.HeroClass != 0 ? info.HeroClass : info.HeroCardClass));
            }
            else
            {
                if (allCards.Count == 10)
                {
                    playerClass = allCards.Select(x => Database.GetCardFromDbfId(x).PlayerClass).FirstOrDefault(x => x != null)?.ToUpperInvariant();
                }
                if (playerClass == null)
                {
                    playerClass = ((CardClass)info.HeroCardClass).ToString().ToUpperInvariant();
                }
            }

            var deck = DeckList.Instance.Decks.FirstOrDefault(x => (!isPVPDR && x.IsDungeonDeck || isPVPDR && x.IsDuelsDeck) && x.Class.ToUpperInvariant() == playerClass.ToUpperInvariant() &&
                                                              x.Cards.All(e => cards.Any(c => c.Id == e.Id && c.Count >= e.Count)) &&
                                                              !(x.IsDungeonRunCompleted ?? false) &&
                                                              !(x.IsDuelsRunCompleted ?? false));
            var baseDbfids = isPVPDR ? info.DbfIds : info.SelectedDeck;

            if (deck == null && (deck = CreateDungeonDeck(playerClass, cardSet, isPVPDR, baseDbfids, loadout)) == null)
            {
                Log.Info($"No existing deck - can't find default deck for {playerClass}");
                return;
            }
            if (!info.RunActive && (cardSet == CardSet.ULDUM || cardSet == CardSet.DALARAN))
            {
                Log.Info($"Inactive run for Set={cardSet.ToString()} - this is a new run");
                return;
            }
            if (cards.All(c => deck.Cards.Any(e => c.Id == e.Id && c.Count == e.Count)))
            {
                Log.Info("No new cards");
                return;
            }
            deck.Cards.Clear();
            Helper.SortCardCollection(cards, false);
            foreach (var card in cards)
            {
                deck.Cards.Add(card);
            }
            deck.LastEdited = DateTime.Now;
            DeckList.Save();
            Core.UpdatePlayerCards(true);
            Log.Info("Updated dungeon run deck");
        }
Example #26
0
        private async void SaveDeck(bool overwrite, SerializableVersion newVersion)
        {
            var deckName = TextBoxDeckName.Text;

            if (string.IsNullOrEmpty(deckName))
            {
                var settings = new MetroDialogSettings {
                    AffirmativeButtonText = "Set", DefaultText = deckName
                };

                var name = await this.ShowInputAsync("No name set", "Please set a name for the deck", settings);

                if (String.IsNullOrEmpty(name))
                {
                    return;
                }

                deckName             = name;
                TextBoxDeckName.Text = name;
            }

            /*while(DeckList.DecksList.Any(d => d.Name == deckName) && (!EditingDeck || !overwrite))
             * {
             *      var settings = new MetroDialogSettings {AffirmativeButtonText = "Set", DefaultText = deckName};
             *      var name =
             *              await
             *              this.ShowInputAsync("Name already exists", "You already have a deck with that name, please select a different one.", settings);
             *
             *      if(String.IsNullOrEmpty(name))
             *              return;
             *
             *      deckName = name;
             *      TextBoxDeckName.Text = name;
             * }*/

            if (_newDeck.Cards.Sum(c => c.Count) != 30)
            {
                var settings = new MetroDialogSettings {
                    AffirmativeButtonText = "Yes", NegativeButtonText = "No"
                };

                var result =
                    await
                    this.ShowMessageAsync("Not 30 cards",
                                          string.Format("Deck contains {0} cards. Is this what you want to save anyway?",
                                                        _newDeck.Cards.Sum(c => c.Count)), MessageDialogStyle.AffirmativeAndNegative, settings);

                if (result != MessageDialogResult.Affirmative)
                {
                    return;
                }
            }

            var previousVersion = _newDeck.Version;

            if (overwrite && (_newDeck.Version != newVersion))
            {
                AddDeckHistory();
                _newDeck.Version                  = newVersion;
                _newDeck.SelectedVersion          = newVersion;
                _newDeck.HearthStatsDeckVersionId = "";
                //UpdateDeckHistoryPanel(_newDeck, false);
            }

            if (EditingDeck && overwrite)
            {
                DeckList.Instance.Decks.Remove(_newDeck);
                //DeckPickerList.RemoveDeck(_newDeck);
            }

            var oldDeckName = _newDeck.Name;

            _newDeck.Name = deckName;

            var newDeckClone = (Deck)_newDeck.Clone();

            newDeckClone.Archived = false;

            DeckList.Instance.Decks.Add(newDeckClone);

            newDeckClone.LastEdited = DateTime.Now;

            DeckList.Save();

            Logger.WriteLine("Saved Decks", "SaveDeck");

            if (EditingDeck)
            {
                TagControlEdit.SetSelectedTags(new List <string>());
                if (deckName != oldDeckName)
                {
                    var statsEntry = DeckStatsList.Instance.DeckStats.FirstOrDefault(ds => ds.BelongsToDeck(_newDeck));
                    if (statsEntry != null)
                    {
                        if (overwrite)
                        {
                            statsEntry.Name = deckName;
                            Logger.WriteLine("Deck has new name, updated deckstats", "SaveDeck");
                        }
                        else
                        {
                            var newStatsEntry = DeckStatsList.Instance.DeckStats.FirstOrDefault(ds => ds.BelongsToDeck(_newDeck));
                            if (newStatsEntry == null)
                            {
                                newStatsEntry = new DeckStats(_newDeck);
                                DeckStatsList.Instance.DeckStats.Add(newStatsEntry);
                            }
                            foreach (var game in statsEntry.Games)
                            {
                                newStatsEntry.AddGameResult(game.CloneWithNewId());
                            }
                            Logger.WriteLine("cloned gamestats for \"Set as new\"", "SaveDeck");
                        }
                        DeckStatsList.Save();
                    }
                }
            }


            if (Config.Instance.HearthStatsAutoUploadNewDecks && HearthStatsAPI.IsLoggedIn)
            {
                Logger.WriteLine("auto uploading new/edited deck", "SaveDeck");
                if (EditingDeck)
                {
                    if (previousVersion != newVersion)
                    {
                        HearthStatsManager.UploadVersionAsync(newDeckClone, _originalDeck.HearthStatsIdForUploading, background: true);
                    }
                    else
                    {
                        HearthStatsManager.UpdateDeckAsync(newDeckClone, background: true);
                    }
                }
                else
                {
                    HearthStatsManager.UploadDeckAsync(newDeckClone, background: true);
                }
            }

            //after cloning the stats, otherwise new stats will be generated
            //DeckPickerList.AddAndSelectDeck(newDeckClone);

            EditingDeck = false;

            foreach (var tag in _newDeck.Tags)
            {
                SortFilterDecksFlyout.AddSelectedTag(tag);
            }

            DeckPickerList.SelectDeckAndAppropriateView(newDeckClone);
            CloseNewDeck();
            ClearNewDeckSection();
        }
Example #27
0
        private static async Task <Deck> ImportHsTopdeck(string url)
        {
            try
            {
                var doc = await GetHtmlDoc(url);

                //<div id="leftbar"><div class="headbar"><div style="float:left">ViaGame House Cup #3</div>
                var tournament = HttpUtility.HtmlDecode(doc.DocumentNode.SelectSingleNode("//div[@id='leftbar']/div[contains(@class, 'headbar')]/div").InnerText);

                // <div class="headbar"><div style="float:left">#5 - Hunter Face -<a href="search.php?q=ThijsNL&filter=current">ThijsNL</a>
                var deckName = HttpUtility.HtmlDecode(doc.DocumentNode.SelectSingleNode("//div[@id='center']/div[@class='headbar']/div").InnerText.Trim());

                var deck = new Deck();
                deck.Name = tournament + " - " + deckName;

                //<div class="cardname" ... <span class="basic">2 Abusive Sergeant</span>
                var cards = doc.DocumentNode.SelectNodes("//div[contains(@class, 'cardname')]/span");

                //<span class="midlarge"><span class="hunter">Hunter</span>-<span class="aggro">Aggro</span></span>
                var deckInfo = doc.DocumentNode.SelectSingleNode("//div[@id='contentfr']/div[@id='infos']").SelectNodes("//span[contains(@class, 'midlarge')]/span");
                if (deckInfo.Count == 2)
                {
                    deck.Class = HttpUtility.HtmlDecode(deckInfo[0].InnerText).Trim();

                    var decktype = HttpUtility.HtmlDecode(deckInfo[1].InnerText).Trim();
                    if (!String.IsNullOrEmpty(decktype) && decktype != "None" && Config.Instance.TagDecksOnImport)
                    {
                        if (!DeckList.Instance.AllTags.Contains(decktype))
                        {
                            DeckList.Instance.AllTags.Add(decktype);
                            DeckList.Save();
                            Helper.MainWindow.ReloadTags();
                        }
                        deck.Tags.Add(decktype);
                    }
                }

                foreach (var cardNode in cards)
                {
                    var nameString = HttpUtility.HtmlDecode(cardNode.InnerText);
                    var match      = Regex.Match(nameString, @"^\s*(\d+)\s+(.*)\s*$");

                    if (match.Success)
                    {
                        var count = match.Groups[1].Value;
                        var name  = match.Groups[2].Value;

                        var card = Game.GetCardFromName(name);
                        card.Count = count.Equals("2") ? 2 : 1;
                        deck.Cards.Add(card);
                        if (string.IsNullOrEmpty(deck.Class) && card.PlayerClass != "Neutral")
                        {
                            deck.Class = card.PlayerClass;
                        }
                    }
                }

                return(deck);
            }
            catch (Exception e)
            {
                Logger.WriteLine(e.ToString(), "DeckImporter");
                return(null);
            }
        }