예제 #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");
            }
예제 #2
0
            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");
            }