private bool AssignPlayerActions(Round round, RoundPlayer throwerPlayer) { //TODO: Support multiple winner bool foundActionForUser = false; var roundTiles = round.RoundTiles; //there will be action except for the player that throw the tile var players = round.RoundPlayers.Where(rp => rp.GamePlayer.Player.UserName != throwerPlayer.GamePlayer.Player.UserName); var boardActiveTile = roundTiles.FirstOrDefault(rt => rt.Status == TileStatus.BoardActive); if (boardActiveTile == null) { throw new RestException(HttpStatusCode.NotFound, new { Round = "Could not find active board tile" }); } var nextPlayer = RoundHelper.GetNextPlayer(round.RoundPlayers, throwerPlayer.Wind); //there could be more than one possible action given user's turn and the tile's thrown foreach (var player in players) { var userTiles = roundTiles.Where(rt => rt.Owner == player.GamePlayer.Player.UserName); List <RoundPlayerAction> rpas = new List <RoundPlayerAction>(); if (RoundHelper.DetermineIfUserCanWin(round, player, _pointCalculator)) { rpas.Add(new RoundPlayerAction { ActionType = ActionType.Win, ActionStatus = ActionStatus.Inactive }); } if (DetermineIfUserCanKongFromBoard(userTiles, boardActiveTile)) { rpas.Add(new RoundPlayerAction { ActionType = ActionType.Kong, ActionStatus = ActionStatus.Inactive }); } if (DetermineIfUserCanPong(userTiles, boardActiveTile)) { rpas.Add(new RoundPlayerAction { ActionType = ActionType.Pong, ActionStatus = ActionStatus.Inactive }); } if (player.GamePlayer.Player.UserName == nextPlayer.GamePlayer.Player.UserName) { var nextPlayerTiles = round.RoundTiles.Where(rt => rt.Owner == nextPlayer.GamePlayer.Player.UserName); if (DetermineIfUserCanChow(nextPlayerTiles, boardActiveTile)) { rpas.Add(new RoundPlayerAction { ActionType = ActionType.Chow, ActionStatus = ActionStatus.Inactive }); } } if (rpas.Count() > 0) { foundActionForUser = true; foreach (var pa in rpas) { player.RoundPlayerActions.Add(pa); } } } return(foundActionForUser); }
public async Task <IEnumerable <RoundDto> > Handle(Command request, CancellationToken cancellationToken) { //Note to consider when picking tile: //-tile is flower //-no more tile to pick //-only 1 more tile to pick because player have an option not to take the last tile. var round = await _context.Rounds.FindAsync(request.RoundId); if (round == null) { throw new RestException(HttpStatusCode.NotFound, new { Round = "Could not find round" }); } var currentPlayer = round.RoundPlayers.FirstOrDefault(p => p.GamePlayer.Player.UserName == request.UserName); if (currentPlayer == null) { throw new RestException(HttpStatusCode.NotFound, new { Round = "Could not find current player" }); } currentPlayer.MustThrow = true; //TODO only allow pick tile when it's player's turn var newTiles = RoundTileHelper.PickTile(round, request.UserName); if (newTiles == null) { round.IsEnding = true; } //pick action now only available on last tile //check if user can win if they pick on last tile var remainingTiles = round.RoundTiles.FirstOrDefault(t => string.IsNullOrEmpty(t.Owner)); if (remainingTiles == null) { currentPlayer.RoundPlayerActions.Clear(); if (RoundHelper.DetermineIfUserCanWin(round, currentPlayer, _pointCalculator)) { currentPlayer.RoundPlayerActions.Add(new RoundPlayerAction { ActionType = ActionType.Win }); } } 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 = "player status was modified" }); } throw new Exception("Problem picking tile"); }