예제 #1
0
        public async Task Should_set_step()
        {
            var game = new TicTacToeBuilder()
                       .Game(b => b
                             .TicTacToe
                             .FirstPlayerEinstein
                             .SecondPlayerEiffel
                             .RandomId
                             .InGame)
                       .TickCell(2)
                       .Build();
            var savedGame = await _gameRepository.CreateGameAsync(game);

            // Act
            await _ticTacToeRepository.SetTicTacToeStepAsync(game, 5);

            var updatedGame = await _gameRepository.GetAsync <TicTacToe>(game.Id !);

            updatedGame.Should().NotBeNull();
            updatedGame !.Cells.Should().BeEquivalentTo(new TicTacToe.CellData?[]
            {
                null,
                null,
                new TicTacToe.CellData {
                    Number = 0
                },
                null,
                null,
                new TicTacToe.CellData {
                    Number = 1
                },
                null,
                null,
                null
            }, options => options.WithStrictOrdering());
            updatedGame.NextPlayer.Id.Should().Be(GameBuilder.Einstein.Id);
            updatedGame.Status.Should().Be(GameStatus.InGame);
            updatedGame.Version.Should().Be(game.Version + 1);
            updatedGame.EndedAt.Should().BeNull();
        }
            public async Task <TicTacToe> Handle(AddTicTacToeStepCommand request, CancellationToken cancellationToken)
            {
                var game = await _gameRepository.GetAsync <TicTacToe>(request.GameId);

                if (game == null)
                {
                    throw new ItemNotFoundException();
                }

                if (game.Status != GameStatus.InGame)
                {
                    throw new ValidationException("Game is not yet or no longer playable");
                }

                if (request.CellIndex < 0 || request.CellIndex >= TicTacToe.CellCount)
                {
                    throw new ValidationException($"Invalid cell index, it should be greather than zero and less than {TicTacToe.CellCount}");
                }

                if (game.Cells[request.CellIndex] != null)
                {
                    throw new ValidationException("This cell has already a value");
                }

                var nextPlayer = game.NextPlayer;

                if (nextPlayer.Id != _playerIdentity.Id)
                {
                    throw new ValidationException($"It is not your turn to play, current player is {nextPlayer.Id}");
                }

                game.Cells[request.CellIndex] = new TicTacToe.CellData()
                {
                    Number = game.TickedCellsCount + 1
                };
                var won = game.HasWon();

                game.Status = won || game.AllCellsTicked
                    ? GameStatus.Finished
                    : GameStatus.InGame;

                if (game.Status != GameStatus.InGame)
                {
                    foreach (var player in game.Players)
                    {
                        bool isMe = player.Id == _playerIdentity.Id;
                        player.Status = (won, isMe) switch {
                            (true, true) => player.Status  = PlayerGameStatus.Won,
                            (true, false) => player.Status = PlayerGameStatus.Lost,
                            _ => PlayerGameStatus.Draw
                        };
                    }
                }

                await _ticTacToeRepository.SetTicTacToeStepAsync(game, request.CellIndex);

                // remark: we should probably use a transaction as we update both Collections
                if (game.Status != GameStatus.InGame)
                {
                    foreach (var player in game.Players)
                    {
                        // since game status changed we want to reflect that in Player collection
                        await _gameRepository.AddOrUpdatePlayerGameAsync(player.Id, Player.Game.From(player.Id, game));
                    }
                }

                await _gameHub.CustomAsync <TicTacToe, TransferObjects.TicTacToe>("GameStepAdded", game);

                return(game);
            }