public async Task <IEnumerable <RoundDto> > Handle(Command request, CancellationToken cancellationToken) { var round = await _context.Rounds.FindAsync(request.RoundId); if (round == null) { throw new RestException(HttpStatusCode.NotFound, new { Round = "Could not find round" }); } var tileToThrow = round.RoundTiles.FirstOrDefault(t => t.Id == request.TileId); if (tileToThrow == null) { throw new RestException(HttpStatusCode.NotFound, new { RoundTile = "Could not find the tile" }); } 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" }); } if (!currentPlayer.MustThrow && !currentPlayer.IsMyTurn) { throw new RestException(HttpStatusCode.NotFound, new { Round = "Player not suppose to throw" }); } //clear all player actions initially every time throw command invoked round.RoundPlayers.ForEach(p => { p.RoundPlayerActions.Clear(); }); //previous active tile on board to be no longer active var existingActiveTileOnBoard = round.RoundTiles.FirstOrDefault(t => t.Status == TileStatus.BoardActive); if (existingActiveTileOnBoard != null) { existingActiveTileOnBoard.Status = TileStatus.BoardGraveyard; } //mark current user's just picked tile to be active var userJustPickedTile = round.RoundTiles.Where(t => t.Owner == request.UserName && t.Status == TileStatus.UserJustPicked); if (userJustPickedTile != null && userJustPickedTile.Count() > 0) { userJustPickedTile.ForEach(t => { t.Status = TileStatus.UserActive; }); } //update thrown tile props and increase the tilecounter tileToThrow.ThrownBy = request.UserName; tileToThrow.Owner = DefaultValue.board; tileToThrow.Status = TileStatus.BoardActive; tileToThrow.BoardGraveyardCounter = round.TileCounter; round.TileCounter++; //don't change user's turn if there is player with action //---------------------------------------------------------- var gotAction = AssignPlayerActions(round, currentPlayer); if (gotAction) { //action has priority list: win > pong|kong > chow var winActionPlayer = round.RoundPlayers.Where(rp => rp.RoundPlayerActions.Any(rpa => rpa.ActionType == ActionType.Win)); if (winActionPlayer.Count() > 0) { bool multipleWinners = winActionPlayer.Count() > 1; foreach (var winner in winActionPlayer) { if (multipleWinners) { winner.RoundPlayerActions.Where(ac => ac.ActionType == ActionType.Win).ForEach(a => a.ActionStatus = ActionStatus.Active); } else { winner.RoundPlayerActions.ForEach(a => a.ActionStatus = ActionStatus.Active); } } } else { var pongOrKongActionPlayer = round.RoundPlayers.Where( rp => rp.RoundPlayerActions.Any( rpa => rpa.ActionType == ActionType.Pong || rpa.ActionType == ActionType.Kong ) ).FirstOrDefault(); if (pongOrKongActionPlayer != null) { pongOrKongActionPlayer.RoundPlayerActions.ForEach(a => a.ActionStatus = ActionStatus.Active); } //check if next player has chow action else { var chowActionPlayer = round.RoundPlayers.Where(rp => rp.RoundPlayerActions.Any(rpa => rpa.ActionType == ActionType.Chow)).FirstOrDefault(); if (chowActionPlayer != null) { chowActionPlayer.RoundPlayerActions.ForEach(a => a.ActionStatus = ActionStatus.Active); } } } } else { RoundHelper.SetNextPlayer(round, _pointCalculator); currentPlayer.IsMyTurn = false; //check if theres more remaining tile, if no more tiles, then set round to ending var remainingTiles = round.RoundTiles.FirstOrDefault(t => string.IsNullOrEmpty(t.Owner)); if (remainingTiles == null) { round.IsEnding = true; } } currentPlayer.MustThrow = false; if (!currentPlayer.IsManualSort) { var playerAliveTiles = round.RoundTiles.Where(rt => rt.Owner == request.UserName && (rt.Status == TileStatus.UserActive || rt.Status == TileStatus.UserJustPicked)).ToList(); RoundTileHelper.AssignAliveTileCounter(playerAliveTiles); } 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); } throw new Exception("Problem throwing tile"); }
public async Task <IEnumerable <RoundDto> > Handle(Command request, CancellationToken cancellationToken) { var round = await _context.Rounds.FindAsync(request.RoundId); if (round == null) { throw new RestException(HttpStatusCode.NotFound, new { Round = "Could not find round" }); } var playerThatSkippedAction = round.RoundPlayers.FirstOrDefault(p => p.GamePlayer.Player.UserName == request.UserName); if (playerThatSkippedAction == null) { throw new RestException(HttpStatusCode.NotFound, new { Round = "Could not find current player" }); } var activeActions = playerThatSkippedAction.RoundPlayerActions.Where(a => a.ActionStatus == ActionStatus.Active); if (activeActions.Count() == 0) { throw new RestException(HttpStatusCode.BadRequest, new { Action = "no active action to skip" }); } activeActions.ForEach(ac => ac.ActionStatus = ActionStatus.Skipped); //check in case of multiple winner and this winner skip the option to win because too greedy! var otherWinnerActiveAction = round.RoundPlayers.Where( rp => rp.GamePlayer.Player.UserName != playerThatSkippedAction.GamePlayer.Player.UserName && rp.RoundPlayerActions.Any( rpa => rpa.ActionType == ActionType.Win && rpa.ActionStatus == ActionStatus.Active ) ).FirstOrDefault(); if (otherWinnerActiveAction != null) { //then we gotta wait other winner skip the win } else { //weird case when multiple winner, there is one declared win but somehow other player can win but skip lol wth then just set the round to be over var activatedWin = round.RoundPlayers.Where(p => p.RoundPlayerActions.Any(a => a.ActionType == ActionType.Win && a.ActionStatus == ActionStatus.Activated)); if (activatedWin.Count() > 0) { round.IsOver = true; round.IsEnding = false; } else { //prioritize user that has pong or kong action var pongOrKongActionPlayer = round.RoundPlayers.FirstOrDefault(rp => rp.RoundPlayerActions.Any( rpa => (rpa.ActionType == ActionType.Pong && rpa.ActionStatus == ActionStatus.Inactive) || (rpa.ActionType == ActionType.Kong && rpa.ActionStatus == ActionStatus.Inactive))); if (pongOrKongActionPlayer != null) { pongOrKongActionPlayer.RoundPlayerActions .Where(rpa => rpa.ActionType == ActionType.Pong || rpa.ActionType == ActionType.Kong) .ForEach(a => a.ActionStatus = ActionStatus.Active); } else { //now check other player that has chow action var chowActionPlayer = round.RoundPlayers.FirstOrDefault(u => u.RoundPlayerActions.Any(a => a.ActionType == ActionType.Chow && a.ActionStatus == ActionStatus.Inactive)); if (chowActionPlayer != null) { chowActionPlayer.RoundPlayerActions .Where(rpa => rpa.ActionType == ActionType.Chow) .ForEach(a => a.ActionStatus = ActionStatus.Active); } else { RoundHelper.SetNextPlayer(round, _pointCalculator); } } } } 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); } throw new Exception("Problem skipping action"); }