Example #1
0
            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");
            }