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