Example #1
0
        public GameModel(Game source)
        {
            if (source == null)
            {
                throw new ArgumentException($"{nameof(source)} cannot be null");
            }

            var decompressedBoardState = new DecompressedBoardState(source.BoardHistory);

            Id        = source.Id;
            PlayerOne = source.PlayerOne;
            PlayerTwo = source.PlayerTwo;
            if (source.GameState == Db.Models.GameState.InProgress)
            {
                switch (decompressedBoardState.CurrentPlayer)
                {
                case BoardPlayer.PlayerOne: CurrentTurnPlayer = source.PlayerOne; break;

                case BoardPlayer.PlayerTwo: CurrentTurnPlayer = source.PlayerTwo; break;
                }
            }
            BoardState     = decompressedBoardState.ToString();
            GameResult     = source.GameResult;
            GameState      = source.GameState;
            LastActionDate = source.LastActionDate;
            CreatedDate    = source.CreatedDate;
        }
Example #2
0
        public async Task CleanupStaleGames()
        {
            var staleGames = await _dbContext.Games
                             .Where(x =>
                                    x.GameState == GameState.InProgress &&
                                    x.LastActionDate < DateTime.UtcNow.AddMinutes(-_ticTacToeSettings.StaleInMinutes))
                             .ToListAsync();

            foreach (var game in staleGames)
            {
                game.GameState = GameState.Aborted;
                var decompressedBoardState = new DecompressedBoardState(game.BoardHistory);
                game.GameResult = decompressedBoardState.CurrentTurn % 2 == 0 ? GameResult.WinPlayerTwo : GameResult.WinPlayerOne;

                _logger.LogInformation("Player forfeited due to inaction, {@details}", new
                {
                    GameId         = game.Id,
                    StaleInMinutes = _ticTacToeSettings.StaleInMinutes
                });
            }

            await _dbContext.SaveChangesAsync();
        }
Example #3
0
        public async Task <ReasonResult <GameModel> > TakeTurnAsync(int id, int turnX, int turnY, ClaimsUser user)
        {
            var game = await _dbContext.Games
                       .FirstOrDefaultAsync(x => x.Id == id);

            if (game == null)
            {
                return(ReasonResult <GameModel> .NotFound());
            }

            BoardPlayer player;

            if (game.PlayerOne == user.Id)
            {
                player = BoardPlayer.PlayerOne;
            }
            else if (game.PlayerTwo == user.Id)
            {
                player = BoardPlayer.PlayerTwo;
            }
            else
            {
                return(ReasonResult <GameModel> .NotFound());
            }

            if (game.GameState != GameState.InProgress)
            {
                _logger.LogInformation("Player tried to take turn on game with incorrect state, {@details}", new
                {
                    GameId    = game.Id,
                    GameState = game.GameState,
                    UserId    = user.Id,
                });

                return(ReasonResult <GameModel> .BadRequest(new[] { GameInWrongState }));
            }

            var oldDecompressedBoardState = new DecompressedBoardState(game.BoardHistory);
            var takeTurnResult            = oldDecompressedBoardState.TryTakeTurn(turnX, turnY, player, out var newDecompressedBoardState);

            switch (takeTurnResult)
            {
            case TakeTurnResult.Success:
            {
                _logger.LogInformation("Player took turn, {@details}", new
                    {
                        GameId          = game.Id,
                        UserId          = user.Id,
                        GameState       = game.GameState,
                        X               = turnX,
                        Y               = turnY,
                        OldBoardHistory = oldDecompressedBoardState.BoardHistory,
                        NewBoardHistory = newDecompressedBoardState.BoardHistory,
                        Snapshot        = newDecompressedBoardState.ToString(),
                    });

                UpdateGameUsingDecompressedBoardState(game, newDecompressedBoardState);

                await _dbContext.SaveChangesAsync();

                return(ReasonResult <GameModel> .Success(new GameModel(game)));
            }

            case TakeTurnResult.NotInProgress:
                return(ReasonResult <GameModel> .BadRequest(new[] { GameInWrongState }));

            case TakeTurnResult.TileAlreadySet:
                return(ReasonResult <GameModel> .BadRequest(new[] { TileAlreadySet }));

            case TakeTurnResult.WrongPlayer:
                return(ReasonResult <GameModel> .BadRequest(new[] { ActingOnWrongTurn }));

            default:
                throw new Exception($"Unknown failure state reached during {nameof(DecompressedBoardState)}.{nameof(DecompressedBoardState.TryTakeTurn)}");
            }
        }
Example #4
0
        private void UpdateGameUsingDecompressedBoardState(Game game, DecompressedBoardState decompressedBoardState)
        {
            game.BoardHistory   = decompressedBoardState.BoardHistory;
            game.LastActionDate = DateTime.UtcNow;

            switch (decompressedBoardState.BoardResult)
            {
            case BoardResult.InProgress:
            {
                game.GameResult = null;
                game.GameState  = GameState.InProgress;
            }
            break;

            case BoardResult.WinPlayerOne:
            {
                game.GameResult = GameResult.WinPlayerOne;
                game.GameState  = GameState.Completed;

                _logger.LogInformation("Game Completed, {@details}", new
                    {
                        GameId       = game.Id,
                        GameResult   = game.GameResult,
                        Winner       = game.PlayerOne,
                        Turn         = decompressedBoardState.CurrentTurn,
                        BoardHistory = decompressedBoardState.BoardHistory,
                        Snapshot     = decompressedBoardState.ToString(),
                    });
            }
            break;

            case BoardResult.WinPlayerTwo:
            {
                game.GameResult = GameResult.WinPlayerTwo;
                game.GameState  = GameState.Completed;

                _logger.LogInformation("Game Completed, {@details}", new
                    {
                        GameId       = game.Id,
                        GameResult   = game.GameResult,
                        Winner       = game.PlayerTwo,
                        Turn         = decompressedBoardState.CurrentTurn,
                        BoardHistory = decompressedBoardState.BoardHistory,
                        Snapshot     = decompressedBoardState.ToString(),
                    });
            }
            break;

            case BoardResult.Draw:
            {
                game.GameResult = GameResult.Draw;
                game.GameState  = GameState.Completed;

                _logger.LogInformation("Game Completed, {@details}", new
                    {
                        GameId     = game.Id,
                        GameResult = game.GameResult,
                        Turn       = decompressedBoardState.CurrentTurn,
                        Snapshot   = decompressedBoardState.ToString(),
                    });
            }
            break;
            }
        }