#pragma warning disable 4014
		public async void HandleGameEnd()
		{
			if(_game.CurrentGameStats == null || _handledGameEnd)
			{
				Logger.WriteLine("HandleGameEnd was already called.", "HandleGameEnd");
				return;
			}
			//deal with instant concedes
			if(_game.CurrentGameMode == Casual || _game.CurrentGameMode == None)
				DetectRanks();
			_handledGameEnd = true;
			TurnTimer.Instance.Stop();
			Core.Overlay.HideTimers();
			Logger.WriteLine("Game ended...", "HandleGameEnd");
			if(_game.CurrentGameMode == Spectator && !Config.Instance.RecordSpectator)
			{
				if(Config.Instance.ReselectLastDeckUsed && DeckList.Instance.ActiveDeck == null)
				{
					Core.MainWindow.SelectLastUsedDeck();
					Config.Instance.ReselectLastDeckUsed = false;
					Logger.WriteLine("ReselectLastUsedDeck set to false", "HandleGameEnd");
					Config.Save();
				}
				Logger.WriteLine("Game is in Spectator mode, discarded. (Record Spectator disabled)", "HandleGameEnd");
				_assignedDeck = null;
				return;
			}
			var player = _game.Entities.FirstOrDefault(e => e.Value.IsPlayer);
			var opponent = _game.Entities.FirstOrDefault(e => e.Value.HasTag(PLAYER_ID) && !e.Value.IsPlayer);
			if(player.Value != null)
				_game.CurrentGameStats.PlayerName = player.Value.Name;
			if(opponent.Value != null && CardIds.HeroIdDict.ContainsValue(_game.CurrentGameStats.OpponentHero))
				_game.CurrentGameStats.OpponentName = opponent.Value.Name;
			else
				_game.CurrentGameStats.OpponentName = _game.CurrentGameStats.OpponentHero;

			_game.CurrentGameStats.Turns = LogReaderManager.GetTurnNumber();
			if(Config.Instance.DiscardZeroTurnGame && _game.CurrentGameStats.Turns < 1)
			{
				Logger.WriteLine("Game has 0 turns, discarded. (DiscardZeroTurnGame)", "HandleGameEnd");
				_assignedDeck = null;
				GameEvents.OnGameEnd.Execute();
				return;
			}
			_game.CurrentGameStats.GameEnd();
			GameEvents.OnGameEnd.Execute();
			var selectedDeck = DeckList.Instance.ActiveDeck;
			if(selectedDeck != null)
			{
				if(Config.Instance.DiscardGameIfIncorrectDeck
				   && !_game.Player.DrawnCards.All(
				                                   c =>
				                                   c.IsCreated
				                                   || selectedDeck.GetSelectedDeckVersion().Cards.Any(c2 => c.Id == c2.Id && c.Count <= c2.Count)))
				{
					if(Config.Instance.AskBeforeDiscardingGame)
					{
						var discardDialog = new DiscardGameDialog(_game.CurrentGameStats) {Topmost = true};
						discardDialog.ShowDialog();
						if(discardDialog.Result == DiscardGameDialogResult.Discard)
						{
							Logger.WriteLine("Assigned current game to NO deck - selected deck does not match cards played (dialogresult: discard)",
							                 "HandleGameEnd");
							_game.CurrentGameStats.DeleteGameFile();
							_assignedDeck = null;
							return;
						}
						if(discardDialog.Result == DiscardGameDialogResult.MoveToOther)
						{
							var moveDialog = new MoveGameDialog(DeckList.Instance.Decks.Where(d => d.Class == _game.CurrentGameStats.PlayerHero))
							{
								Topmost = true
							};
							moveDialog.ShowDialog();
							var targetDeck = moveDialog.SelectedDeck;
							if(targetDeck != null)
							{
								selectedDeck = targetDeck;
								_game.CurrentGameStats.PlayerDeckVersion = moveDialog.SelectedVersion;
								_game.CurrentGameStats.HearthStatsDeckVersionId = targetDeck.GetVersion(moveDialog.SelectedVersion).HearthStatsDeckVersionId;
								//...continue as normal
							}
							else
							{
								Logger.WriteLine("No deck selected in move game dialog after discard dialog, discarding game", "HandleGameEnd");
								_game.CurrentGameStats.DeleteGameFile();
								_assignedDeck = null;
								return;
							}
						}
					}
					else
					{
						Logger.WriteLine("Assigned current game to NO deck - selected deck does not match cards played (no dialog)", "HandleGameEnd");
						_game.CurrentGameStats.DeleteGameFile();
						_assignedDeck = null;
						return;
					}
				}
				else
				{
					_game.CurrentGameStats.PlayerDeckVersion = DeckList.Instance.ActiveDeckVersion.Version;
					_game.CurrentGameStats.HearthStatsDeckVersionId = DeckList.Instance.ActiveDeckVersion.HearthStatsDeckVersionId;
				}

				_lastGame = _game.CurrentGameStats;
				selectedDeck.DeckStats.AddGameResult(_lastGame);
				selectedDeck.StatsUpdated();
				if(Config.Instance.ArenaRewardDialog && selectedDeck.IsArenaRunCompleted.HasValue && selectedDeck.IsArenaRunCompleted.Value)
					_arenaRewardDialog = new ArenaRewardDialog(selectedDeck);

				if(Config.Instance.ShowNoteDialogAfterGame && !Config.Instance.NoteDialogDelayed && !_showedNoteDialog)
				{
					_showedNoteDialog = true;
					new NoteDialog(_game.CurrentGameStats);
				}
				Logger.WriteLine("Assigned current game to deck: " + selectedDeck.Name, "HandleGameEnd");
				_assignedDeck = selectedDeck;

				// Unarchive the active deck after we have played a game with it
				if(_assignedDeck.Archived)
				{
					Logger.WriteLine("Automatically unarchiving deck " + selectedDeck.Name + " after assigning current game", "HandleGameEnd");
					Core.MainWindow.ArchiveDeck(_assignedDeck, false);
				}

				if(HearthStatsAPI.IsLoggedIn && Config.Instance.HearthStatsAutoUploadNewGames)
				{
					Logger.WriteLine("Waiting for game mode detection...", "HandleGameEnd");
					await _game.GameModeDetection();
					Logger.WriteLine("Detected game mode, continuing.", "HandleGameEnd");
					Logger.WriteLine("Waiting for game mode to be saved to game...", "HandleGameEnd");
					await GameModeSaved(15);
					Logger.WriteLine("Game mode was saved, continuing.", "HandleGameEnd");
					if(_game.CurrentGameMode == Arena)
						HearthStatsManager.UploadArenaMatchAsync(_lastGame, selectedDeck, background: true);
					else if(_game.CurrentGameMode != Brawl)
						HearthStatsManager.UploadMatchAsync(_lastGame, selectedDeck, background: true);
				}
				_lastGame = null;
			}
			else
			{
				try
				{
					DefaultDeckStats.Instance.GetDeckStats(_game.Player.Class).AddGameResult(_game.CurrentGameStats);
					Logger.WriteLine($"Assigned current deck to default {_game.Player.Class} deck.", "HandleGameEnd");
				}
				catch(Exception ex)
				{
					Logger.WriteLine("Error saving to DefaultDeckStats: " + ex, "HandleGameEnd");
				}
				_assignedDeck = null;
			}

			if(Config.Instance.ReselectLastDeckUsed && selectedDeck == null)
			{
				Core.MainWindow.SelectLastUsedDeck();
				Config.Instance.ReselectLastDeckUsed = false;
				Logger.WriteLine("ReselectLastUsedDeck set to false", "HandleGameEnd");
				Config.Save();
			}
		}
示例#2
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();
        }
#pragma warning disable 4014
		public static async void HandleGameEnd()
		{
			Helper.MainWindow.Overlay.HideTimers();
			if(Game.CurrentGameStats == null)
				return;
			if(Game.CurrentGameMode == GameMode.Spectator && !Config.Instance.RecordSpectator)
			{
				Logger.WriteLine("Game is in Spectator mode, discarded. (Record Spectator disabled)", "GameEventHandler");
				_assignedDeck = null;
				return;
			}
			var player = Game.Entities.FirstOrDefault(e => e.Value.IsPlayer);
			var opponent = Game.Entities.FirstOrDefault(e => e.Value.HasTag(GAME_TAG.PLAYER_ID) && !e.Value.IsPlayer);
			if(player.Value != null)
				Game.CurrentGameStats.PlayerName = player.Value.Name;
			if(opponent.Value != null && CardIds.HeroIdDict.ContainsValue(Game.CurrentGameStats.OpponentHero))
				Game.CurrentGameStats.OpponentName = opponent.Value.Name;
			else
				Game.CurrentGameStats.OpponentName = Game.CurrentGameStats.OpponentHero;

			Game.CurrentGameStats.Turns = HsLogReader.Instance.GetTurnNumber();
			if(Config.Instance.DiscardZeroTurnGame && Game.CurrentGameStats.Turns < 1)
			{
				Logger.WriteLine("Game has 0 turns, discarded. (DiscardZeroTurnGame)", "GameEventHandler");
				_assignedDeck = null;
				GameEvents.OnGameEnd.Execute();
				return;
			}
			Game.CurrentGameStats.GameEnd();
			GameEvents.OnGameEnd.Execute();
			var selectedDeck = DeckList.Instance.ActiveDeck;
			if(selectedDeck != null)
			{
				if(Config.Instance.DiscardGameIfIncorrectDeck
				   && !Game.PlayerDrawn.All(
				                            c =>
				                            c.IsStolen
				                            || selectedDeck.GetSelectedDeckVersion().Cards.Any(c2 => c.Id == c2.Id && c.Count <= c2.Count)))
				{
					if(Config.Instance.AskBeforeDiscardingGame)
					{
						var discardDialog = new DiscardGameDialog(Game.CurrentGameStats);
						discardDialog.Topmost = true;
						discardDialog.ShowDialog();
						if(discardDialog.Result == DiscardGameDialogResult.Discard)
						{
							Logger.WriteLine("Assigned current game to NO deck - selected deck does not match cards played (dialogresult: discard)",
							                 "GameEventHandler");
							Game.CurrentGameStats.DeleteGameFile();
							_assignedDeck = null;
							return;
						}
						if(discardDialog.Result == DiscardGameDialogResult.MoveToOther)
						{
							var moveDialog = new MoveGameDialog(DeckList.Instance.Decks.Where(d => d.Class == Game.CurrentGameStats.PlayerHero));
							moveDialog.Topmost = true;
							moveDialog.ShowDialog();
							var targetDeck = moveDialog.SelectedDeck;
							if(targetDeck != null)
							{
								selectedDeck = targetDeck;
								Game.CurrentGameStats.PlayerDeckVersion = moveDialog.SelectedVersion;
								Game.CurrentGameStats.HearthStatsDeckVersionId = targetDeck.GetVersion(moveDialog.SelectedVersion).HearthStatsDeckVersionId;
								//...continue as normal
							}
							else
							{
								Logger.WriteLine("No deck selected in move game dialog after discard dialog, discarding game", "GameEventHandler");
								Game.CurrentGameStats.DeleteGameFile();
								_assignedDeck = null;
								return;
							}
						}
					}
					else
					{
						Logger.WriteLine("Assigned current game to NO deck - selected deck does not match cards played (no dialog)", "GameEventHandler");
						Game.CurrentGameStats.DeleteGameFile();
						_assignedDeck = null;
						return;
					}
				}
				else
				{
					Game.CurrentGameStats.PlayerDeckVersion = DeckList.Instance.ActiveDeckVersion.Version;
					Game.CurrentGameStats.HearthStatsDeckVersionId = DeckList.Instance.ActiveDeckVersion.HearthStatsDeckVersionId;
				}

				_lastGame = Game.CurrentGameStats;
				selectedDeck.DeckStats.AddGameResult(_lastGame);
				selectedDeck.StatsUpdated();
				if(Config.Instance.ShowNoteDialogAfterGame && !Config.Instance.NoteDialogDelayed && !_showedNoteDialog)
				{
					_showedNoteDialog = true;
					new NoteDialog(Game.CurrentGameStats);
				}
				Logger.WriteLine("Assigned current game to deck: " + selectedDeck.Name, "GameStats");
				_assignedDeck = selectedDeck;

				// Unarchive the active deck after we have played a game with it
				if(_assignedDeck.Archived)
				{
					Logger.WriteLine("Automatically unarchiving deck " + selectedDeck.Name + " after assigning current game", "GameEventHandler");
					Helper.MainWindow.ArchiveDeck(_assignedDeck, false);
				}

				if(HearthStatsAPI.IsLoggedIn && Config.Instance.HearthStatsAutoUploadNewGames)
				{
					if(Game.CurrentGameMode == GameMode.None)
						await GameModeDetection(300); //give the user 5 minutes to get out of the victory/defeat screen
					if(Game.CurrentGameMode == GameMode.Casual)
						await HsLogReader.Instance.RankedDetection();
					if(Game.CurrentGameMode == GameMode.Ranked && !_lastGame.HasRank)
						await RankDetection(5);
					await GameModeSaved(15);
					if(Game.CurrentGameMode == GameMode.Arena)
						HearthStatsManager.UploadArenaMatchAsync(_lastGame, selectedDeck, background: true);
					if(Game.CurrentGameMode == GameMode.Brawl)
						{ /* do nothing */ }
					else
						HearthStatsManager.UploadMatchAsync(_lastGame, selectedDeck, background: true);
				}
				_lastGame = null;
			}
			else
			{
				DefaultDeckStats.Instance.GetDeckStats(Game.PlayingAs).AddGameResult(Game.CurrentGameStats);
				Logger.WriteLine(string.Format("Assigned current deck to default {0} deck.", Game.PlayingAs), "GameStats");
				_assignedDeck = null;
			}
		}
#pragma warning disable 4014
		public async void HandleGameEnd()
		{
			if(_game.CurrentGameStats == null || _handledGameEnd)
			{
				Log.Warn("HandleGameEnd was already called.");
				return;
			}
			_handledGameEnd = true;
			TurnTimer.Instance.Stop();
			Core.Overlay.HideTimers();
			DeckManager.ResetAutoSelectCount();
			Log.Info("Game ended...");
			if(_game.CurrentGameMode == Spectator && !Config.Instance.RecordSpectator)
			{
				if(Config.Instance.ReselectLastDeckUsed && DeckList.Instance.ActiveDeck == null)
				{
					Core.MainWindow.SelectLastUsedDeck();
					Config.Instance.ReselectLastDeckUsed = false;
					Log.Info("ReselectLastUsedDeck set to false");
					Config.Save();
				}
				Log.Info("Game is in Spectator mode, discarded. (Record Spectator disabled)");
				_assignedDeck = null;
				return;
			}
			var player = _game.Entities.FirstOrDefault(e => e.Value.IsPlayer).Value;
			var opponent = _game.Entities.FirstOrDefault(e => e.Value.HasTag(PLAYER_ID) && !e.Value.IsPlayer);
			if(player != null)
			{
				_game.CurrentGameStats.PlayerName = player.Name;
				_game.CurrentGameStats.Coin = !player.HasTag(FIRST_PLAYER);
			}
			if(opponent.Value != null && CardIds.HeroIdDict.ContainsValue(_game.CurrentGameStats.OpponentHero))
				_game.CurrentGameStats.OpponentName = opponent.Value.Name;
			else
				_game.CurrentGameStats.OpponentName = _game.CurrentGameStats.OpponentHero;

			_game.CurrentGameStats.Turns = LogReaderManager.GetTurnNumber();
			if(Config.Instance.DiscardZeroTurnGame && _game.CurrentGameStats.Turns < 1)
			{
				Log.Info("Game has 0 turns, discarded. (DiscardZeroTurnGame)");
				_assignedDeck = null;
				GameEvents.OnGameEnd.Execute();
				return;
			}
			_game.CurrentGameStats.GameMode = _game.CurrentGameMode;
			if(_game.CurrentGameMode == Ranked || _game.CurrentGameMode == Casual)
			{
				_game.CurrentGameStats.Format = _game.CurrentFormat;
				Log.Info("Format: " + _game.CurrentGameStats.Format);
				if(_game.CurrentGameMode == Ranked && _game.MatchInfo != null)
				{
					var wild = _game.CurrentFormat == Format.Wild;
					_game.CurrentGameStats.Rank = wild ? _game.MatchInfo.LocalPlayer.WildRank : _game.MatchInfo.LocalPlayer.StandardRank;
					_game.CurrentGameStats.OpponentRank = wild ? _game.MatchInfo.OpposingPlayer.WildRank : _game.MatchInfo.OpposingPlayer.StandardRank;
					_game.CurrentGameStats.LegendRank = wild ? _game.MatchInfo.LocalPlayer.WildLegendRank : _game.MatchInfo.LocalPlayer.StandardLegendRank;
					_game.CurrentGameStats.OpponentLegendRank = wild ? _game.MatchInfo.OpposingPlayer.WildLegendRank : _game.MatchInfo.OpposingPlayer.StandardLegendRank;
					_game.CurrentGameStats.Stars = wild ? _game.MatchInfo.LocalPlayer.WildStars : _game.MatchInfo.LocalPlayer.StandardStars;
				}
			}
			_game.CurrentGameStats.SetPlayerCards(DeckList.Instance.ActiveDeckVersion, _game.Player.RevealedCards.ToList());
			_game.CurrentGameStats.SetOpponentCards(_game.Opponent.OpponentCardList.Where(x => !x.IsCreated).ToList());
			_game.CurrentGameStats.GameEnd();
			GameEvents.OnGameEnd.Execute();
			Influx.OnGameEnd(HearthDbConverter.GetGameType(_game.CurrentGameStats.GameMode, _game.CurrentGameStats.Format));
			var selectedDeck = DeckList.Instance.ActiveDeck;
			if(selectedDeck != null)
			{
				if(Config.Instance.DiscardGameIfIncorrectDeck
				   && !_game.Player.RevealedEntities.Where(x => (x.IsMinion || x.IsSpell || x.IsWeapon) && !x.Info.Created && !x.Info.Stolen)
				   .GroupBy(x => x.CardId).All(x => selectedDeck.GetSelectedDeckVersion().Cards.Any(c2 => x.Key == c2.Id && x.Count() <= c2.Count)))
				{
					if(Config.Instance.AskBeforeDiscardingGame)
					{
						var discardDialog = new DiscardGameDialog(_game.CurrentGameStats) {Topmost = true};
						discardDialog.ShowDialog();
						if(discardDialog.Result == DiscardGameDialogResult.Discard)
						{
							Log.Info("Assigned current game to NO deck - selected deck does not match cards played (dialogresult: discard)");
							_game.CurrentGameStats.DeleteGameFile();
							_assignedDeck = null;
							return;
						}
						if(discardDialog.Result == DiscardGameDialogResult.MoveToOther)
						{
							var moveDialog = new MoveGameDialog(DeckList.Instance.Decks.Where(d => d.Class == _game.CurrentGameStats.PlayerHero))
							{
								Topmost = true
							};
							moveDialog.ShowDialog();
							var targetDeck = moveDialog.SelectedDeck;
							if(targetDeck != null)
							{
								selectedDeck = targetDeck;
								_game.CurrentGameStats.PlayerDeckVersion = moveDialog.SelectedVersion;
								_game.CurrentGameStats.HearthStatsDeckVersionId = targetDeck.GetVersion(moveDialog.SelectedVersion).HearthStatsDeckVersionId;
								//...continue as normal
							}
							else
							{
								Log.Info("No deck selected in move game dialog after discard dialog, discarding game");
								_game.CurrentGameStats.DeleteGameFile();
								_assignedDeck = null;
								return;
							}
						}
					}
					else
					{
						Log.Info("Assigned current game to NO deck - selected deck does not match cards played (no dialog)");
						_game.CurrentGameStats.DeleteGameFile();
						_assignedDeck = null;
						return;
					}
				}
				else
				{
					_game.CurrentGameStats.PlayerDeckVersion = DeckList.Instance.ActiveDeckVersion.Version;
					_game.CurrentGameStats.HearthStatsDeckVersionId = DeckList.Instance.ActiveDeckVersion.HearthStatsDeckVersionId;
				}

				_lastGame = _game.CurrentGameStats;
				selectedDeck.DeckStats.AddGameResult(_lastGame);
				if(Config.Instance.ArenaRewardDialog && selectedDeck.IsArenaRunCompleted.HasValue && selectedDeck.IsArenaRunCompleted.Value)
					_arenaRewardDialog = new ArenaRewardDialog(selectedDeck);

				if(Config.Instance.ShowNoteDialogAfterGame && !Config.Instance.NoteDialogDelayed && !_showedNoteDialog)
				{
					_showedNoteDialog = true;
					new NoteDialog(_game.CurrentGameStats);
				}
				Log.Info("Assigned current game to deck: " + selectedDeck.Name);
				_assignedDeck = selectedDeck;

				// Unarchive the active deck after we have played a game with it
				if(_assignedDeck.Archived)
				{
					Log.Info("Automatically unarchiving deck " + selectedDeck.Name + " after assigning current game");
					Core.MainWindow.ArchiveDeck(_assignedDeck, false);
				}

				if(HearthStatsAPI.IsLoggedIn && Config.Instance.HearthStatsAutoUploadNewGames)
				{
					Log.Info("Waiting for game mode to be saved to game...");
					await GameModeSaved(15);
					Log.Info("Game mode was saved, continuing.");
					if(_game.CurrentGameMode == Arena)
						HearthStatsManager.UploadArenaMatchAsync(_lastGame, selectedDeck, background: true);
					else if(_game.CurrentGameMode != Brawl)
						HearthStatsManager.UploadMatchAsync(_lastGame, selectedDeck, background: true);
				}
				_lastGame = null;
			}
			else
			{
				try
				{
					DefaultDeckStats.Instance.GetDeckStats(_game.Player.Class).AddGameResult(_game.CurrentGameStats);
					Log.Info($"Assigned current deck to default {_game.Player.Class} deck.");
				}
				catch(Exception ex)
				{
					Log.Error("Error saving to DefaultDeckStats: " + ex);
				}
				_assignedDeck = null;
			}

			if(Config.Instance.ReselectLastDeckUsed && selectedDeck == null)
			{
				Core.MainWindow.SelectLastUsedDeck();
				Config.Instance.ReselectLastDeckUsed = false;
				Log.Info("ReselectLastUsedDeck set to false");
				Config.Save();
			}
		}
示例#5
0
#pragma warning disable 4014
        public async void HandleGameEnd()
        {
            try
            {
                if (_game.CurrentGameStats == null || _handledGameEnd)
                {
                    Log.Warn("HandleGameEnd was already called.");
                    return;
                }
                _handledGameEnd = true;
                TurnTimer.Instance.Stop();
                Core.Overlay.HideTimers();
                DeckManager.ResetAutoSelectCount();
                LiveDataManager.Stop();
                Log.Info("Game ended...");
                _game.InvalidateMatchInfoCache();
                if (_game.CurrentGameMode == Spectator && _game.CurrentGameStats.Result == GameResult.None)
                {
                    Log.Info("Game was spectator mode without a game result. Probably exited spectator mode early.");
                    return;
                }
                var player   = _game.Entities.FirstOrDefault(e => e.Value?.IsPlayer ?? false).Value;
                var opponent = _game.Entities.FirstOrDefault(e => e.Value != null && e.Value.HasTag(PLAYER_ID) && !e.Value.IsPlayer).Value;
                if (player != null)
                {
                    _game.CurrentGameStats.PlayerName = player.Name;
                    _game.CurrentGameStats.Coin       = !player.HasTag(FIRST_PLAYER);
                }
                if (opponent != null && CardIds.HeroIdDict.ContainsValue(_game.CurrentGameStats.OpponentHero))
                {
                    _game.CurrentGameStats.OpponentName = opponent.Name;
                }
                else
                {
                    _game.CurrentGameStats.OpponentName = _game.CurrentGameStats.OpponentHero;
                }

                _game.CurrentGameStats.Turns = _game.GetTurnNumber();
                if (Config.Instance.DiscardZeroTurnGame && _game.CurrentGameStats.Turns < 1)
                {
                    Log.Info("Game has 0 turns, discarded. (DiscardZeroTurnGame)");
                    _assignedDeck = null;
                    GameEvents.OnGameEnd.Execute();
                    return;
                }
                _game.CurrentGameStats.GameMode = _game.CurrentGameMode;
                _game.CurrentGameStats.Format   = _game.CurrentFormat;
                Log.Info("Format: " + _game.CurrentGameStats.Format);
                if (_game.CurrentGameMode == Ranked && _game.MatchInfo != null)
                {
                    var wild = _game.CurrentFormat == Format.Wild;
                    _game.CurrentGameStats.Rank               = wild ? _game.MatchInfo.LocalPlayer.WildRank : _game.MatchInfo.LocalPlayer.StandardRank;
                    _game.CurrentGameStats.OpponentRank       = wild ? _game.MatchInfo.OpposingPlayer.WildRank : _game.MatchInfo.OpposingPlayer.StandardRank;
                    _game.CurrentGameStats.LegendRank         = wild ? _game.MatchInfo.LocalPlayer.WildLegendRank : _game.MatchInfo.LocalPlayer.StandardLegendRank;
                    _game.CurrentGameStats.OpponentLegendRank = wild ? _game.MatchInfo.OpposingPlayer.WildLegendRank : _game.MatchInfo.OpposingPlayer.StandardLegendRank;
                    _game.CurrentGameStats.Stars              = wild ? _game.MatchInfo.LocalPlayer.WildStars : _game.MatchInfo.LocalPlayer.StandardStars;
                }
                else if (_game.CurrentGameMode == Arena)
                {
                    _game.CurrentGameStats.ArenaWins   = DeckImporter.ArenaInfoCache?.Wins ?? 0;
                    _game.CurrentGameStats.ArenaLosses = DeckImporter.ArenaInfoCache?.Losses ?? 0;
                }
                else if (_game.CurrentGameMode == Brawl && _game.BrawlInfo != null)
                {
                    _game.CurrentGameStats.BrawlWins   = _game.BrawlInfo.Wins;
                    _game.CurrentGameStats.BrawlLosses = _game.BrawlInfo.Losses;
                }
                _game.CurrentGameStats.GameType           = _game.CurrentGameType;
                _game.CurrentGameStats.ServerInfo         = _game.MetaData.ServerInfo;
                _game.CurrentGameStats.PlayerCardbackId   = _game.MatchInfo?.LocalPlayer.CardBackId ?? 0;
                _game.CurrentGameStats.OpponentCardbackId = _game.MatchInfo?.OpposingPlayer.CardBackId ?? 0;
                _game.CurrentGameStats.FriendlyPlayerId   = _game.MatchInfo?.LocalPlayer.Id ?? 0;
                _game.CurrentGameStats.ScenarioId         = _game.MatchInfo?.MissionId ?? 0;
                _game.CurrentGameStats.BrawlSeasonId      = _game.MatchInfo?.BrawlSeasonId ?? 0;
                _game.CurrentGameStats.RankedSeasonId     = _game.MatchInfo?.RankedSeasonId ?? 0;
                var confirmedCards = _game.Player.RevealedCards.Where(x => x.Collectible)
                                     .Concat(_game.Player.KnownCardsInDeck.Where(x => x.Collectible && !x.IsCreated))
                                     .ToList();
                if (_game.CurrentSelectedDeck != null && _game.CurrentSelectedDeck.Id > 0)
                {
                    _game.CurrentGameStats.HsDeckId = _game.CurrentSelectedDeck.Id;
                    _game.CurrentGameStats.SetPlayerCards(_game.CurrentSelectedDeck, confirmedCards);
                }
                else
                {
                    _game.CurrentGameStats.HsDeckId = DeckList.Instance.ActiveDeckVersion?.HsId ?? 0;
                    _game.CurrentGameStats.SetPlayerCards(DeckList.Instance.ActiveDeckVersion, confirmedCards);
                }
                _game.CurrentGameStats.SetOpponentCards(_game.Opponent.OpponentCardList.Where(x => !x.IsCreated).ToList());
                _game.CurrentGameStats.GameEnd();
                GameEvents.OnGameEnd.Execute();
                _game.CurrentSelectedDeck = null;
                var selectedDeck = DeckList.Instance.ActiveDeck;
                if (selectedDeck != null)
                {
                    var revealed = _game.Player.RevealedEntities.Where(x => x != null).ToList();
                    if (Config.Instance.DiscardGameIfIncorrectDeck &&
                        !revealed.Where(x => x.IsPlayableCard && !x.Info.Created && !x.Info.Stolen && x.Card.Collectible)
                        .GroupBy(x => x.CardId).All(x => selectedDeck.GetSelectedDeckVersion().Cards.Any(c2 => x.Key == c2.Id && x.Count() <= c2.Count)))
                    {
                        if (Config.Instance.AskBeforeDiscardingGame)
                        {
                            var discardDialog = new DiscardGameDialog(_game.CurrentGameStats)
                            {
                                Topmost = true
                            };
                            discardDialog.ShowDialog();
                            if (discardDialog.Result == DiscardGameDialogResult.Discard)
                            {
                                Log.Info("Assigned current game to NO deck - selected deck does not match cards played (dialogresult: discard)");
                                _assignedDeck = null;
                                return;
                            }
                            if (discardDialog.Result == DiscardGameDialogResult.MoveToOther)
                            {
                                var moveDialog = new MoveGameDialog(DeckList.Instance.Decks.Where(d => d.Class == _game.CurrentGameStats.PlayerHero))
                                {
                                    Topmost = true
                                };
                                moveDialog.ShowDialog();
                                var targetDeck = moveDialog.SelectedDeck;
                                if (targetDeck != null)
                                {
                                    selectedDeck = targetDeck;
                                    _game.CurrentGameStats.PlayerDeckVersion = moveDialog.SelectedVersion;
                                    //...continue as normal
                                }
                                else
                                {
                                    Log.Info("No deck selected in move game dialog after discard dialog, discarding game");
                                    _assignedDeck = null;
                                    return;
                                }
                            }
                        }
                        else
                        {
                            Log.Info("Assigned current game to NO deck - selected deck does not match cards played (no dialog)");
                            _assignedDeck = null;
                            return;
                        }
                    }
                    else
                    {
                        _game.CurrentGameStats.PlayerDeckVersion = selectedDeck.GetSelectedDeckVersion().Version;
                    }

                    _lastGame = _game.CurrentGameStats;
                    selectedDeck.DeckStats.AddGameResult(_lastGame);

                    if (Config.Instance.ArenaRewardDialog && (selectedDeck.IsArenaRunCompleted ?? false))
                    {
                        if (selectedDeck.ArenaReward.Packs[0] == ArenaRewardPacks.None)
                        {
                            selectedDeck.ArenaReward.Packs[0] = Enum.GetValues(typeof(ArenaRewardPacks)).OfType <ArenaRewardPacks>().Max();
                        }

                        _arenaRewardDialog = new ArenaRewardDialog(selectedDeck);
                    }
                    if (Config.Instance.ShowNoteDialogAfterGame && !Config.Instance.NoteDialogDelayed && !_showedNoteDialog)
                    {
                        _showedNoteDialog = true;
                        new NoteDialog(_game.CurrentGameStats);
                    }
                    Log.Info("Assigned current game to deck: " + selectedDeck.Name);
                    _assignedDeck = selectedDeck;

                    // Unarchive the active deck after we have played a game with it
                    if (_assignedDeck.Archived)
                    {
                        Log.Info("Automatically unarchiving deck " + selectedDeck.Name + " after assigning current game");
                        Core.MainWindow.ArchiveDeck(_assignedDeck, false);
                    }
                    _lastGame = null;
                }
                else
                {
                    try
                    {
                        DefaultDeckStats.Instance.GetDeckStats(_game.Player.Class).AddGameResult(_game.CurrentGameStats);
                        Log.Info($"Assigned current deck to default {_game.Player.Class} deck.");
                    }
                    catch (Exception ex)
                    {
                        Log.Error("Error saving to DefaultDeckStats: " + ex);
                    }
                    _assignedDeck = null;
                }

                if (_game.StoredGameStats != null)
                {
                    _game.CurrentGameStats.StartTime = _game.StoredGameStats.StartTime;
                }

                await SaveReplays();

                if (Config.Instance.ShowGameResultNotifications && RecordCurrentGameMode)
                {
                    var deckName = _assignedDeck == null ? "No deck - " + _game.CurrentGameStats.PlayerHero : _assignedDeck.NameAndVersion;
                    ToastManager.ShowGameResultToast(deckName, _game.CurrentGameStats);
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex);
            }
        }
        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 = Helper.MainWindow.DeckList.DecksList.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
            selectedDeck.DeckStats.Games.Add(selectedGame);
            DeckStatsList.Save();
            Helper.MainWindow.WriteDecks();
            Refresh();
            Helper.MainWindow.DeckPickerList.UpdateList();
        }
		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 = Core.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);
					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).Forget();
			}
			DeckStatsList.Save();
			DeckList.Save();
			Refresh();
			Core.MainWindow.DeckPickerList.UpdateDecks();
		}
示例#8
0
#pragma warning disable 4014
        public static async void HandleGameEnd()
        {
            Helper.MainWindow.Overlay.HideTimers();
            if (Game.CurrentGameStats == null)
            {
                return;
            }
            if (Game.CurrentGameMode == GameMode.Spectator && !Config.Instance.RecordSpectator)
            {
                Logger.WriteLine("Game is in Spectator mode, discarded. (Record Spectator disabled)", "GameEventHandler");
                _assignedDeck = null;
                return;
            }
            var player   = Game.Entities.FirstOrDefault(e => e.Value.IsPlayer);
            var opponent = Game.Entities.FirstOrDefault(e => e.Value.HasTag(GAME_TAG.PLAYER_ID) && !e.Value.IsPlayer);

            if (player.Value != null)
            {
                Game.CurrentGameStats.PlayerName = player.Value.Name;
            }
            if (opponent.Value != null && CardIds.HeroIdDict.ContainsValue(Game.CurrentGameStats.OpponentHero))
            {
                Game.CurrentGameStats.OpponentName = opponent.Value.Name;
            }
            else
            {
                Game.CurrentGameStats.OpponentName = Game.CurrentGameStats.OpponentHero;
            }

            Game.CurrentGameStats.Turns = HsLogReader.Instance.GetTurnNumber();
            if (Config.Instance.DiscardZeroTurnGame && Game.CurrentGameStats.Turns < 1)
            {
                Logger.WriteLine("Game has 0 turns, discarded. (DiscardZeroTurnGame)", "GameEventHandler");
                _assignedDeck = null;
                GameEvents.OnGameEnd.Execute();
                return;
            }
            Game.CurrentGameStats.GameEnd();
            GameEvents.OnGameEnd.Execute();
            var selectedDeck = DeckList.Instance.ActiveDeck;

            if (selectedDeck != null)
            {
                if (Config.Instance.DiscardGameIfIncorrectDeck &&
                    !Game.PlayerDrawn.All(
                        c =>
                        c.IsStolen ||
                        selectedDeck.GetSelectedDeckVersion().Cards.Any(c2 => c.Id == c2.Id && c.Count <= c2.Count)))
                {
                    if (Config.Instance.AskBeforeDiscardingGame)
                    {
                        var discardDialog = new DiscardGameDialog(Game.CurrentGameStats);
                        discardDialog.Topmost = true;
                        discardDialog.ShowDialog();
                        if (discardDialog.Result == DiscardGameDialogResult.Discard)
                        {
                            Logger.WriteLine("Assigned current game to NO deck - selected deck does not match cards played (dialogresult: discard)",
                                             "GameEventHandler");
                            Game.CurrentGameStats.DeleteGameFile();
                            _assignedDeck = null;
                            return;
                        }
                        if (discardDialog.Result == DiscardGameDialogResult.MoveToOther)
                        {
                            var moveDialog = new MoveGameDialog(DeckList.Instance.Decks.Where(d => d.Class == Game.CurrentGameStats.PlayerHero));
                            moveDialog.Topmost = true;
                            moveDialog.ShowDialog();
                            var targetDeck = moveDialog.SelectedDeck;
                            if (targetDeck != null)
                            {
                                selectedDeck = targetDeck;
                                Game.CurrentGameStats.PlayerDeckVersion        = moveDialog.SelectedVersion;
                                Game.CurrentGameStats.HearthStatsDeckVersionId = targetDeck.GetVersion(moveDialog.SelectedVersion).HearthStatsDeckVersionId;
                                //...continue as normal
                            }
                            else
                            {
                                Logger.WriteLine("No deck selected in move game dialog after discard dialog, discarding game", "GameEventHandler");
                                Game.CurrentGameStats.DeleteGameFile();
                                _assignedDeck = null;
                                return;
                            }
                        }
                    }
                    else
                    {
                        Logger.WriteLine("Assigned current game to NO deck - selected deck does not match cards played (no dialog)", "GameEventHandler");
                        Game.CurrentGameStats.DeleteGameFile();
                        _assignedDeck = null;
                        return;
                    }
                }
                else
                {
                    Game.CurrentGameStats.PlayerDeckVersion        = DeckList.Instance.ActiveDeckVersion.Version;
                    Game.CurrentGameStats.HearthStatsDeckVersionId = DeckList.Instance.ActiveDeckVersion.HearthStatsDeckVersionId;
                }

                _lastGame = Game.CurrentGameStats;
                selectedDeck.DeckStats.AddGameResult(_lastGame);
                selectedDeck.StatsUpdated();
                if (Config.Instance.ShowNoteDialogAfterGame && !Config.Instance.NoteDialogDelayed && !_showedNoteDialog)
                {
                    _showedNoteDialog = true;
                    new NoteDialog(Game.CurrentGameStats);
                }
                Logger.WriteLine("Assigned current game to deck: " + selectedDeck.Name, "GameStats");
                _assignedDeck = selectedDeck;

                // Unarchive the active deck after we have played a game with it
                if (_assignedDeck.Archived)
                {
                    Logger.WriteLine("Automatically unarchiving deck " + selectedDeck.Name + " after assigning current game", "GameEventHandler");
                    Helper.MainWindow.ArchiveDeck(_assignedDeck, false);
                }

                if (HearthStatsAPI.IsLoggedIn && Config.Instance.HearthStatsAutoUploadNewGames)
                {
                    if (Game.CurrentGameMode == GameMode.None)
                    {
                        await GameModeDetection(300);                         //give the user 5 minutes to get out of the victory/defeat screen
                    }
                    if (Game.CurrentGameMode == GameMode.Casual)
                    {
                        await HsLogReader.Instance.RankedDetection();
                    }
                    if (Game.CurrentGameMode == GameMode.Ranked && !_lastGame.HasRank)
                    {
                        await RankDetection(5);
                    }
                    await GameModeSaved(15);

                    if (Game.CurrentGameMode == GameMode.Arena)
                    {
                        HearthStatsManager.UploadArenaMatchAsync(_lastGame, selectedDeck, background: true);
                    }
                    else
                    {
                        HearthStatsManager.UploadMatchAsync(_lastGame, selectedDeck, background: true);
                    }
                }
                _lastGame = null;
            }
            else
            {
                DefaultDeckStats.Instance.GetDeckStats(Game.PlayingAs).AddGameResult(Game.CurrentGameStats);
                Logger.WriteLine(string.Format("Assigned current deck to default {0} deck.", Game.PlayingAs), "GameStats");
                _assignedDeck = null;
            }
        }
        private void BtnMoveToOtherDeck_Click(object sender, RoutedEventArgs e)
        {
            var selectedGame = DataGridGames.SelectedItem as GameStats;

            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.OrderByDescending(x => x.Value).First().Key;

            var possibleTargets = Helper.MainWindow.DeckList.DecksList.Where(d => d.Class == heroPlayed);

            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;
            }

            _deck.DeckStats.Games.Remove(selectedGame);
            selectedDeck.DeckStats.Games.Add(selectedGame);
            DeckStatsList.Save();
            Helper.MainWindow.WriteDecks();
            Refresh();
            Helper.MainWindow.DeckPickerList.UpdateList();
        }
		private void BtnMoveToOtherDeck_Click(object sender, RoutedEventArgs e)
		{
			var selectedGame = DataGridGames.SelectedItem as GameStats;
			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.OrderByDescending(x => x.Value).First().Key;

			var possibleTargets = Helper.MainWindow.DeckList.DecksList.Where(d => d.Class == heroPlayed);

			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;

			_deck.DeckStats.Games.Remove(selectedGame);
			selectedDeck.DeckStats.Games.Add(selectedGame);
			DeckStatsList.Save();
			Helper.MainWindow.WriteDecks();
			Refresh();
			Helper.MainWindow.DeckPickerList.UpdateList();
		}
#pragma warning disable 4014
		public async void HandleGameEnd()
		{
			try
			{
				if(_game.CurrentGameStats == null || _handledGameEnd)
				{
					Log.Warn("HandleGameEnd was already called.");
					return;
				}
				_handledGameEnd = true;
				TurnTimer.Instance.Stop();
				Core.Overlay.HideTimers();
				DeckManager.ResetAutoSelectCount();
				Log.Info("Game ended...");
				_game.InvalidateMatchInfoCache();
				if(_game.CurrentGameMode == Spectator && _game.CurrentGameStats.Result == GameResult.None)
				{
					Log.Info("Game was spectator mode without a game result. Probably exited spectator mode early.");
					return;
				}
				var player = _game.Entities.FirstOrDefault(e => e.Value?.IsPlayer ?? false).Value;
				var opponent = _game.Entities.FirstOrDefault(e => e.Value != null && e.Value.HasTag(PLAYER_ID) && !e.Value.IsPlayer).Value;
				if(player != null)
				{
					_game.CurrentGameStats.PlayerName = player.Name;
					_game.CurrentGameStats.Coin = !player.HasTag(FIRST_PLAYER);
				}
				if(opponent != null && CardIds.HeroIdDict.ContainsValue(_game.CurrentGameStats.OpponentHero))
					_game.CurrentGameStats.OpponentName = opponent.Name;
				else
					_game.CurrentGameStats.OpponentName = _game.CurrentGameStats.OpponentHero;

				_game.CurrentGameStats.Turns = LogReaderManager.GetTurnNumber();
				if(Config.Instance.DiscardZeroTurnGame && _game.CurrentGameStats.Turns < 1)
				{
					Log.Info("Game has 0 turns, discarded. (DiscardZeroTurnGame)");
					_assignedDeck = null;
					GameEvents.OnGameEnd.Execute();
					return;
				}
				_game.CurrentGameStats.GameMode = _game.CurrentGameMode;
				_game.CurrentGameStats.Format = _game.CurrentFormat;
				Log.Info("Format: " + _game.CurrentGameStats.Format);
				if(_game.CurrentGameMode == Ranked && _game.MatchInfo != null)
				{
					var wild = _game.CurrentFormat == Format.Wild;
					_game.CurrentGameStats.Rank = wild ? _game.MatchInfo.LocalPlayer.WildRank : _game.MatchInfo.LocalPlayer.StandardRank;
					_game.CurrentGameStats.OpponentRank = wild ? _game.MatchInfo.OpposingPlayer.WildRank : _game.MatchInfo.OpposingPlayer.StandardRank;
					_game.CurrentGameStats.LegendRank = wild ? _game.MatchInfo.LocalPlayer.WildLegendRank : _game.MatchInfo.LocalPlayer.StandardLegendRank;
					_game.CurrentGameStats.OpponentLegendRank = wild ? _game.MatchInfo.OpposingPlayer.WildLegendRank : _game.MatchInfo.OpposingPlayer.StandardLegendRank;
					_game.CurrentGameStats.Stars = wild ? _game.MatchInfo.LocalPlayer.WildStars : _game.MatchInfo.LocalPlayer.StandardStars;
				}
				else if(_game.CurrentGameMode == Arena)
				{
					_game.CurrentGameStats.ArenaWins = DeckImporter.ArenaInfoCache?.Wins ?? 0;
					_game.CurrentGameStats.ArenaLosses = DeckImporter.ArenaInfoCache?.Losses ?? 0;
				}
				_game.CurrentGameStats.GameType = _game.CurrentGameType;
				_game.CurrentGameStats.ServerInfo = _game.MetaData.ServerInfo;
				_game.CurrentGameStats.PlayerCardbackId = _game.MatchInfo?.LocalPlayer.CardBackId ?? 0;
				_game.CurrentGameStats.OpponentCardbackId = _game.MatchInfo?.OpposingPlayer.CardBackId ?? 0;
				_game.CurrentGameStats.FriendlyPlayerId = _game.MatchInfo?.LocalPlayer.Id ?? 0;
				_game.CurrentGameStats.ScenarioId = _game.MatchInfo?.MissionId ?? 0;
				_game.CurrentGameStats.BrawlSeasonId = _game.MatchInfo?.BrawlSeasonId ?? 0;
				_game.CurrentGameStats.RankedSeasonId = _game.MatchInfo?.RankedSeasonId ?? 0;
				_game.CurrentGameStats.HsDeckId = DeckList.Instance.ActiveDeckVersion?.HsId ?? 0;
				_game.CurrentGameStats.SetPlayerCards(DeckList.Instance.ActiveDeckVersion, _game.Player.RevealedCards.Where(x => x.Collectible).ToList());
				_game.CurrentGameStats.SetOpponentCards(_game.Opponent.OpponentCardList.Where(x => !x.IsCreated).ToList());
				_game.CurrentGameStats.GameEnd();
				GameEvents.OnGameEnd.Execute();
				Influx.OnGameEnd(HearthDbConverter.GetGameType(_game.CurrentGameStats.GameMode, _game.CurrentGameStats.Format));
				var selectedDeck = DeckList.Instance.ActiveDeck;
				if(selectedDeck != null)
				{
					var revealed = _game.Player.RevealedEntities.Where(x => x != null).ToList();
					if(Config.Instance.DiscardGameIfIncorrectDeck
					   && !revealed.Where(x => (x.IsMinion || x.IsSpell || x.IsWeapon) && !x.Info.Created && !x.Info.Stolen && x.Card.Collectible)
					   .GroupBy(x => x.CardId).All(x => selectedDeck.GetSelectedDeckVersion().Cards.Any(c2 => x.Key == c2.Id && x.Count() <= c2.Count)))
					{
						if(Config.Instance.AskBeforeDiscardingGame)
						{
							var discardDialog = new DiscardGameDialog(_game.CurrentGameStats) {Topmost = true};
							discardDialog.ShowDialog();
							if(discardDialog.Result == DiscardGameDialogResult.Discard)
							{
								Log.Info("Assigned current game to NO deck - selected deck does not match cards played (dialogresult: discard)");
								_game.CurrentGameStats.DeleteGameFile();
								_assignedDeck = null;
								return;
							}
							if(discardDialog.Result == DiscardGameDialogResult.MoveToOther)
							{
								var moveDialog = new MoveGameDialog(DeckList.Instance.Decks.Where(d => d.Class == _game.CurrentGameStats.PlayerHero))
								{
									Topmost = true
								};
								moveDialog.ShowDialog();
								var targetDeck = moveDialog.SelectedDeck;
								if(targetDeck != null)
								{
									selectedDeck = targetDeck;
									_game.CurrentGameStats.PlayerDeckVersion = moveDialog.SelectedVersion;
									_game.CurrentGameStats.HearthStatsDeckVersionId = targetDeck.GetVersion(moveDialog.SelectedVersion).HearthStatsDeckVersionId;
									//...continue as normal
								}
								else
								{
									Log.Info("No deck selected in move game dialog after discard dialog, discarding game");
									_game.CurrentGameStats.DeleteGameFile();
									_assignedDeck = null;
									return;
								}
							}
						}
						else
						{
							Log.Info("Assigned current game to NO deck - selected deck does not match cards played (no dialog)");
							_game.CurrentGameStats.DeleteGameFile();
							_assignedDeck = null;
							return;
						}
					}
					else
					{
						_game.CurrentGameStats.PlayerDeckVersion = selectedDeck.GetSelectedDeckVersion().Version;
						_game.CurrentGameStats.HearthStatsDeckVersionId = selectedDeck.GetSelectedDeckVersion().HearthStatsDeckVersionId;
					}

					_lastGame = _game.CurrentGameStats;
					selectedDeck.DeckStats.AddGameResult(_lastGame);

					if(Config.Instance.ArenaRewardDialog && (selectedDeck.IsArenaRunCompleted ?? false))
						_arenaRewardDialog = new ArenaRewardDialog(selectedDeck);

					if(Config.Instance.ShowNoteDialogAfterGame && !Config.Instance.NoteDialogDelayed && !_showedNoteDialog)
					{
						_showedNoteDialog = true;
						new NoteDialog(_game.CurrentGameStats);
					}
					Log.Info("Assigned current game to deck: " + selectedDeck.Name);
					_assignedDeck = selectedDeck;

					// Unarchive the active deck after we have played a game with it
					if(_assignedDeck.Archived)
					{
						Log.Info("Automatically unarchiving deck " + selectedDeck.Name + " after assigning current game");
						Core.MainWindow.ArchiveDeck(_assignedDeck, false);
					}

					UploadHearthStatsAsync(selectedDeck).Forget();
					_lastGame = null;
				}
				else
				{
					try
					{
						DefaultDeckStats.Instance.GetDeckStats(_game.Player.Class).AddGameResult(_game.CurrentGameStats);
						Log.Info($"Assigned current deck to default {_game.Player.Class} deck.");
					}
					catch(Exception ex)
					{
						Log.Error("Error saving to DefaultDeckStats: " + ex);
					}
					_assignedDeck = null;
				}

				if(_game.StoredGameStats != null)
					_game.CurrentGameStats.StartTime = _game.StoredGameStats.StartTime;

				await SaveReplays();

				if(Config.Instance.ShowGameResultNotifications && RecordCurrentGameMode)
				{
					var deckName = _assignedDeck == null ? "No deck - " + _game.CurrentGameStats.PlayerHero : _assignedDeck.NameAndVersion;
					ToastManager.ShowGameResultToast(deckName, _game.CurrentGameStats);
				}
			}
			catch(Exception ex)
			{
				Log.Error(ex);
			}
		}
		private void BtnMoveToOtherDeck_Click(object sender, RoutedEventArgs e)
		{
			var selectedGame = DataGridGames.SelectedItem as GameStats;
			if(selectedGame == null) return;

			var possibleTargets = Helper.MainWindow.DeckList.DecksList.Where(d => d.Class == _deck.Class);

			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;

			_deck.DeckStats.Games.Remove(selectedGame);
			selectedDeck.DeckStats.Games.Add(selectedGame);
			DeckStatsList.Save();
			Helper.MainWindow.WriteDecks();
			Refresh();
			Helper.MainWindow.DeckPickerList.UpdateList();
		}