public async Task <IEnumerable <RoundDto> > Handle(Command request, CancellationToken cancellationToken) { //Note to consider when chow tile: //-when chow tile user need to throw a tile. //assign tile ownership to current user var round = await _context.Rounds.FindAsync(request.RoundId); if (round == null) { throw new RestException(HttpStatusCode.NotFound, new { Round = "Could not find round" }); } //TODO only allow chow when it's user's turn if (request.ChowTiles == null || request.ChowTiles.Count() != 2) { throw new RestException(HttpStatusCode.BadRequest, new { Round = "invalid data to chow tiles" }); } var boardActiveTiles = round.RoundTiles.Where(t => t.Status == TileStatus.BoardActive); if (boardActiveTiles == null || boardActiveTiles.Count() > 1) { throw new RestException(HttpStatusCode.BadRequest, new { Round = "there are no tile or more than one tiles to chow" }); } var tileToChow = boardActiveTiles.First(); if (tileToChow.Tile.TileType == TileType.Dragon || tileToChow.Tile.TileType == TileType.Flower || tileToChow.Tile.TileType == TileType.Wind) { throw new RestException(HttpStatusCode.BadRequest, new { Round = "tile must be money, round, or stick for chow" }); } var dbTilesToChow = round.RoundTiles.Where(t => request.ChowTiles.Contains(t.Id)).ToList(); dbTilesToChow.Add(tileToChow); var sortedChowTiles = dbTilesToChow.OrderBy(t => t.Tile.TileValue).ToArray(); //check if its straight if (sortedChowTiles[0].Tile.TileValue + 1 == sortedChowTiles[1].Tile.TileValue && sortedChowTiles[1].Tile.TileValue + 1 == sortedChowTiles[2].Tile.TileValue) { int groupIndex = 1; var tileSets = round.RoundTiles.Where(t => t.Owner == request.UserName && t.TileSetGroup != TileSetGroup.None); if (tileSets.Count() > 0) { var lastIndex = tileSets.GroupBy(t => t.TileSetGroupIndex).Select(g => g.Last()).First().TileSetGroupIndex; groupIndex = lastIndex + 1; } sortedChowTiles.GoGraveyard(request.UserName, TileSetGroup.Chow, round.RoundTiles.GetLastGroupIndex(request.UserName)); } else { throw new RestException(HttpStatusCode.BadRequest, new { Round = "tile is not in sequence to chow" }); } var currentPlayer = round.RoundPlayers.FirstOrDefault(u => u.GamePlayer.Player.UserName == request.UserName); if (currentPlayer == null) { throw new RestException(HttpStatusCode.BadRequest, new { Round = "there are no user with this username in the round" }); } currentPlayer.IsMyTurn = true; currentPlayer.MustThrow = true; var otherPlayers = round.RoundPlayers.Where(u => u.IsMyTurn == true && u.GamePlayer.Player.UserName != request.UserName); foreach (var otherPlayerTurn in otherPlayers) { otherPlayerTurn.IsMyTurn = false; otherPlayerTurn.MustThrow = false; } if (round.IsEnding) { round.IsEnding = false; } //if user chow, then there's no way that user can win/pong/chow var actionsToBeRemoved = currentPlayer.RoundPlayerActions.Where(a => a.ActionType != ActionType.SelfKong).ToList(); foreach (var action in actionsToBeRemoved) { currentPlayer.RoundPlayerActions.Remove(action); } RoundHelper.CheckPossibleSelfKong(round, currentPlayer); try { var success = await _context.SaveChangesAsync() > 0; List <RoundDto> results = new List <RoundDto>(); foreach (var p in round.RoundPlayers) { results.Add(_mapper.Map <Round, RoundDto>(round, opt => opt.Items["MainRoundPlayer"] = p)); } if (success) { return(results); } } catch (DbUpdateConcurrencyException) { throw new RestException(HttpStatusCode.BadRequest, new { Round = "tile was modified" }); } throw new Exception("Problem chow ing tile"); }
public async Task <IEnumerable <RoundDto> > Handle(Command request, CancellationToken cancellationToken) { //Note to consider when pong tile: //-player turn changed //-flag when user can pong //-when pong tile user need to throw a tile. //assign tile ownership to current user var updatedTiles = new List <RoundTile>(); var round = await _context.Rounds.FindAsync(request.RoundId); if (round == null) { throw new RestException(HttpStatusCode.NotFound, new { Round = "Could not find round" }); } var boardActiveTiles = round.RoundTiles.Where(t => t.Status == TileStatus.BoardActive); if (boardActiveTiles == null) { throw new RestException(HttpStatusCode.BadRequest, new { Round = "there are no tile to pong" }); } var tileToPong = boardActiveTiles.First(); updatedTiles.Add(tileToPong); //check if user currently have two tile to pong var matchingUserTiles = round.RoundTiles .Where(t => t.Owner == request.UserName && t.Status == TileStatus.UserActive && t.Tile.TileType == tileToPong.Tile.TileType && t.Tile.TileValue == tileToPong.Tile.TileValue); if (matchingUserTiles == null || matchingUserTiles.Count() < 2) { throw new RestException(HttpStatusCode.BadRequest, new { Round = "there are more than one tiles to pong" }); } //if there is Userjustpicked status then pong is invalid var justPickedTile = round.RoundTiles.FirstOrDefault(t => t.Status == TileStatus.UserJustPicked); if (justPickedTile != null) { throw new RestException(HttpStatusCode.BadRequest, new { Round = "someone already picked tile, no pong is allowed" }); } foreach (var tile in matchingUserTiles.Take(2)) { updatedTiles.Add(tile); } updatedTiles.GoGraveyard(request.UserName, TileSetGroup.Pong, round.RoundTiles.GetLastGroupIndex(request.UserName)); var currentPlayer = round.RoundPlayers.FirstOrDefault(u => u.GamePlayer.Player.UserName == request.UserName); if (currentPlayer == null) { throw new RestException(HttpStatusCode.BadRequest, new { Round = "there are no user with this username in the round" }); } currentPlayer.IsMyTurn = true; currentPlayer.MustThrow = true; var actionsToBeRemoved = currentPlayer.RoundPlayerActions.Where(a => a.ActionType != ActionType.SelfKong).ToList(); foreach (var action in actionsToBeRemoved) { currentPlayer.RoundPlayerActions.Remove(action); } RoundHelper.CheckPossibleSelfKong(round, currentPlayer); if (round.IsEnding) { round.IsEnding = false; } var otherPlayers = round.RoundPlayers.Where(u => u.IsMyTurn == true && u.GamePlayer.Player.UserName != request.UserName); foreach (var otherPlayerTurn in otherPlayers) { otherPlayerTurn.IsMyTurn = false; otherPlayerTurn.MustThrow = false; } try { var success = await _context.SaveChangesAsync() > 0; List <RoundDto> results = new List <RoundDto>(); foreach (var p in round.RoundPlayers) { results.Add(_mapper.Map <Round, RoundDto>(round, opt => opt.Items["MainRoundPlayer"] = p)); } if (success) { return(results); } } catch (DbUpdateConcurrencyException) { throw new RestException(HttpStatusCode.BadRequest, new { Round = "tile was modified" }); } throw new Exception("Problem pong ing tile"); }