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 game = await _context.Games.FirstOrDefaultAsync(x => x.Code == request.GameCode.ToUpper()); if (game == null) { throw new RestException(HttpStatusCode.BadRequest, new { Game = "Game does not exist" }); } Round lastRound = game.Rounds.OrderByDescending(r => r.DateCreated).FirstOrDefault(); if (lastRound != null && !lastRound.IsOver) { throw new RestException(HttpStatusCode.BadRequest, new { Round = "Last round is not over" }); } var newRound = new Round { GameId = game.Id, DateCreated = DateTime.Now, RoundTiles = RoundTileHelper.CreateTiles(_context).Shuffle(), RoundPlayers = new List <RoundPlayer>(), RoundResults = new List <RoundResult>() }; List <RoundPlayer> roundPlayers = new List <RoundPlayer>(); if (lastRound == null) { game.Status = GameStatus.Playing; Player firstDealer = game.GamePlayers.First(u => u.InitialSeatWind == WindDirection.East).Player; newRound.Wind = WindDirection.East; newRound.RoundCounter = 1; foreach (var gp in game.GamePlayers) { var rp = new RoundPlayer { GamePlayerId = gp.Id, GamePlayer = gp, Round = newRound, Wind = gp.InitialSeatWind.Value, Points = gp.Points }; if (gp.PlayerId == firstDealer.Id) { rp.IsInitialDealer = true; rp.IsDealer = true; rp.IsMyTurn = true; rp.MustThrow = true; } roundPlayers.Add(rp); } } else { newRound.RoundCounter = lastRound.RoundCounter + 1; var lastRoundDealer = lastRound.RoundPlayers.First(u => u.IsDealer); //if this is not the first round //last round check //1.) if the winner of last round == dealer then no wind change //2.) if last round "IsTied" set to true then no wind change if (lastRound.IsTied) { newRound.Wind = lastRound.Wind; roundPlayers.AddRange(GetNewUserRounds(lastRound.RoundPlayers, sameRound: true, lastRoundDealer.Wind)); } else { //if last game is not tied, then there gotta be a winner here //could be more than one winners here var lastRoundWinners = lastRound.RoundResults.Where(x => x.PlayResult == PlayResult.Win); var dealerWonLastRound = lastRoundWinners.Any(x => x.PlayerId == lastRoundDealer.GamePlayer.Player.Id); if (dealerWonLastRound) { newRound.Wind = lastRound.Wind; roundPlayers.AddRange(GetNewUserRounds(lastRound.RoundPlayers, sameRound: true, lastRoundDealer.Wind)); } else { //determine nextdealer var windOfNextDealer = NextWindClockWise(lastRoundDealer.Wind); roundPlayers.AddRange(GetNewUserRounds(lastRound.RoundPlayers, sameRound: false, windOfNextDealer)); var roundWindChanged = roundPlayers.Any(p => p.IsDealer == true && p.IsInitialDealer == true); newRound.Wind = roundWindChanged ? NextWindClockWise(lastRound.Wind) : lastRound.Wind; } } } foreach (var ur in roundPlayers) { newRound.RoundPlayers.Add(ur); } var theDealer = roundPlayers.First(u => u.IsDealer); var dealerId = theDealer.GamePlayerId; //for debugging //RoundTileHelper.SetupForWinPongChowPriority(newRound.RoundTiles); //tiles assignment and sorting foreach (var gamePlayer in game.GamePlayers) { if (gamePlayer.Id == dealerId) { RoundTileHelper.AssignTilesToUser(14, gamePlayer.Player.UserName, newRound.RoundTiles); //set one tile status to be justpicked newRound.RoundTiles.First(rt => rt.Owner == gamePlayer.Player.UserName && rt.Tile.TileType != TileType.Flower).Status = TileStatus.UserJustPicked; var playerTiles = newRound.RoundTiles.Where(rt => rt.Owner == gamePlayer.Player.UserName && (rt.Status == TileStatus.UserActive || rt.Status == TileStatus.UserJustPicked)).ToList(); RoundTileHelper.AssignAliveTileCounter(playerTiles); } else { RoundTileHelper.AssignTilesToUser(13, gamePlayer.Player.UserName, newRound.RoundTiles); var playerTiles = newRound.RoundTiles.Where(rt => rt.Owner == gamePlayer.Player.UserName && rt.Status == TileStatus.UserActive).ToList(); RoundTileHelper.AssignAliveTileCounter(playerTiles); } } _context.Rounds.Add(newRound); var success = await _context.SaveChangesAsync() > 0; List <RoundDto> results = new List <RoundDto>(); foreach (var p in newRound.RoundPlayers) { results.Add(_mapper.Map <Round, RoundDto>(newRound, opt => opt.Items["MainRoundPlayer"] = p)); } if (success) { return(results); } throw new Exception("Problem creating a new round"); }