Exemplo n.º 1
0
            public async Task <Photo> Handle(Command request, CancellationToken cancellationToken)
            {
                var photoUploadResult = _photoAccessor.AddPhoto(request.File);

                var user = await _context.Users.SingleOrDefaultAsync(x => x.UserName == _userAccessor.GetCurrentUserName());

                var photo = new Photo
                {
                    Url = photoUploadResult.Url,
                    Id  = photoUploadResult.PublicId
                };

                if (!user.Photos.Any(x => x.IsMain))
                {
                    photo.IsMain = true;
                }

                user.Photos.Add(photo);

                var success = await _context.SaveChangesAsync() > 0;

                if (success)
                {
                    return(photo);
                }

                throw new Exception("Problem saving changes");
            }
Exemplo n.º 2
0
            public async Task <Unit> Handle(Command request, CancellationToken cancellationToken)
            {
                //handler logic
                var game = await _context.Games.FirstOrDefaultAsync(g => g.Code == request.GameCode.ToUpper());

                if (game == null)
                {
                    throw new Exception("Could not find game");
                }

                var currentUserName = string.IsNullOrEmpty(request.UserName) ? _userAccessor.GetCurrentUserName() : request.UserName;

                var user = await _context.Users.SingleOrDefaultAsync(x => x.UserName == currentUserName);

                if (user == null)
                {
                    throw new Exception("invalid user");
                }

                if (game.HostId != user.Id)
                {
                    throw new Exception("only host can delete the game");
                }

                _context.Games.Remove(game);

                var success = await _context.SaveChangesAsync() > 0;

                if (success)
                {
                    return(Unit.Value);
                }

                throw new Exception("Problem saving changes");
            }
Exemplo n.º 3
0
            public async Task <GamePlayerDto> Handle(Command request, CancellationToken cancellationToken)
            {
                var game = await _context.Games.FirstOrDefaultAsync(g => g.Code == request.GameCode.ToUpper());

                if (game == null)
                {
                    throw new RestException(HttpStatusCode.NotFound, new { Game = "Could not find game" });
                }

                if (game.Status == GameStatus.Playing || game.Status == GameStatus.Over)
                {
                    throw new RestException(HttpStatusCode.NotFound, new { Game = "Can't sit on game that's already started/over" });
                }

                var user = await _context.Users.SingleOrDefaultAsync(x => x.UserName == request.UserName);

                var playerInGame = await _context.GamePlayers.SingleOrDefaultAsync(x => x.GameId == game.Id && x.PlayerId == user.Id);

                if (playerInGame == null)
                {
                    throw new RestException(HttpStatusCode.BadRequest, new { Connect = "Player not in the game" });
                }

                playerInGame.InitialSeatWind = request.InitialSeatWind;

                var success = await _context.SaveChangesAsync() > 0;

                if (success)
                {
                    return(_mapper.Map <GamePlayerDto>(playerInGame));
                }

                throw new Exception("Problem sitting to game");
            }
Exemplo n.º 4
0
            public async Task <Unit> Handle(Command request, CancellationToken cancellationToken)
            {
                var user = await _context.Users.SingleOrDefaultAsync(x => x.UserName == _userAccessor.GetCurrentUserName());

                var photo = user.Photos.FirstOrDefault(x => x.Id == request.Id);

                if (photo == null)
                {
                    throw new RestException(HttpStatusCode.NotFound, new { Photo = "Not found" });
                }

                if (photo.IsMain)
                {
                    throw new RestException(HttpStatusCode.BadRequest, new { Photo = "You cannot delete your main photo" });
                }

                var result = _photoAccessor.DeletePhoto(photo.Id);

                if (result == null)
                {
                    throw new System.Exception("Problem deleting the photo");
                }

                user.Photos.Remove(photo);

                var success = await _context.SaveChangesAsync() > 0;

                if (success)
                {
                    return(Unit.Value);
                }

                throw new Exception("Problem saving changes");
            }
Exemplo n.º 5
0
            public async Task <Unit> Handle(Command request, CancellationToken cancellationToken)
            {
                var user = await _context.Users.SingleOrDefaultAsync(x => x.UserName == _userAccessor.GetCurrentUserName());

                var photo = user.Photos.FirstOrDefault(x => x.Id == request.Id);

                if (photo == null)
                {
                    throw new RestException(HttpStatusCode.NotFound, new { Photo = "Not found" });
                }

                var currentMain = user.Photos.FirstOrDefault(x => x.IsMain);

                if (currentMain != null)
                {
                    currentMain.IsMain = false;
                }

                photo.IsMain = true;

                var success = await _context.SaveChangesAsync() > 0;

                if (success)
                {
                    return(Unit.Value);
                }

                throw new Exception("Problem saving changes");
            }
Exemplo n.º 6
0
            public async Task <ChatMsgDto> Handle(Command request, CancellationToken cancellationToken)
            {
                var game = await _context.Games.FirstOrDefaultAsync(g => g.Code == request.GameCode.ToUpper());

                if (game == null)
                {
                    throw new RestException(HttpStatusCode.NotFound, new { Game = "Game not found" });
                }

                var user = await _context.Users.SingleOrDefaultAsync(x => x.UserName == request.UserName);

                var chatMsg = new ChatMsg
                {
                    Author    = user,
                    Game      = game,
                    Body      = request.Body,
                    CreatedAt = DateTime.Now
                };

                game.ChatMsgs.Add(chatMsg);

                var success = await _context.SaveChangesAsync() > 0;

                if (success)
                {
                    return(_mapper.Map <ChatMsgDto>(chatMsg));
                }

                throw new Exception("Problem saving changes");
            }
Exemplo n.º 7
0
            public async Task <GameDto> Handle(Command request, CancellationToken cancellationToken)
            {
                var user = await _context.Users.SingleOrDefaultAsync(x => x.UserName == _userAccessor.GetCurrentUserName());

                //check if user spamming create game, if there is more than 5 games created within one minutes return 401 and lock user out lol
                var gamesWithinOneMin = _context.Games.Where(g => g.HostId == user.Id && g.Date > DateTime.Now.AddMinutes(-1));

                if (gamesWithinOneMin != null && gamesWithinOneMin.Count() > 5)
                {
                    user.LockoutEnd = DateTime.Now.AddMonths(1);
                    foreach (var rt in user.RefreshTokens)
                    {
                        rt.Revoked = DateTime.Now;
                    }
                    await _userManager.UpdateAsync(user);

                    throw new RestException(HttpStatusCode.Unauthorized);
                }

                var gameCode = _gameCodeGenerator.CreateCode();

                var minPoint = int.Parse(request.MinPoint);
                var maxPoint = int.Parse(request.MaxPoint);
                //TODO don't hard code min and maxpoint
                var game = new Game
                {
                    Title       = request.Title,
                    Code        = _gameCodeGenerator.CreateCode(),
                    Date        = DateTime.Now,
                    Host        = user,
                    Status      = GameStatus.Created,
                    MinPoint    = minPoint,
                    MaxPoint    = maxPoint == 0 ? 10 : maxPoint,
                    GamePlayers = new List <GamePlayer> {
                        new GamePlayer {
                            IsHost = true,
                            Player = user
                        }
                    }
                };

                _context.Games.Add(game);

                var success = await _context.SaveChangesAsync() > 0;

                var gameToReturn = _mapper.Map <Game, GameDto>(game);

                if (success)
                {
                    return(gameToReturn);
                }

                throw new Exception("Problem saving changes");
            }
Exemplo n.º 8
0
            public async Task <IEnumerable <GamePlayerDto> > Handle(Command request, CancellationToken cancellationToken)
            {
                var game = await _context.Games.FirstOrDefaultAsync(g => g.Code == request.GameCode.ToUpper());

                if (game == null)
                {
                    throw new RestException(HttpStatusCode.NotFound, new { Game = "Could not find game" });
                }

                if (game.Status == GameStatus.Playing || game.Status == GameStatus.Over)
                {
                    throw new RestException(HttpStatusCode.NotFound, new { Game = "Can't randomize wind to a game that's already started/over" });
                }

                var userInGames = game.GamePlayers.ToArray();

                if (userInGames.Count() != 4)
                {
                    throw new RestException(HttpStatusCode.BadRequest, new { players = "not enough player in the game" });
                }

                var user = await _context.Users.SingleOrDefaultAsync(x => x.UserName == request.UserName);

                var playerInGame = await _context.GamePlayers.SingleOrDefaultAsync(x => x.GameId == game.Id && x.PlayerId == user.Id);

                if (playerInGame == null)
                {
                    throw new RestException(HttpStatusCode.BadRequest, new { player = "user not in the game" });
                }

                //only host can randomize the intiial wind
                if (playerInGame.IsHost)
                {
                    WindDirection[] RandomWind = (WindDirection[])Enum.GetValues(typeof(WindDirection));
                    RandomWind.Shuffle();

                    for (int i = 0; i < 4; i++)
                    {
                        userInGames[i].InitialSeatWind = RandomWind[i];
                    }
                }
                try
                {
                    await _context.SaveChangesAsync();

                    return(_mapper.Map <IEnumerable <GamePlayer>, IEnumerable <GamePlayerDto> >(userInGames));
                }
                catch (Exception)
                {
                    throw new Exception("Problem randomizing user's wind");
                }
            }
Exemplo n.º 9
0
            public async Task <Unit> Handle(Command request, CancellationToken cancellationToken)
            {
                var user = await _context.Users.SingleOrDefaultAsync(x => x.UserName == _userAccessor.GetCurrentUserName());

                user.DisplayName = request.DisplayName ?? user.DisplayName;
                user.Bio         = request.Bio ?? user.Bio;

                var success = await _context.SaveChangesAsync() > 0;

                if (success)
                {
                    return(Unit.Value);
                }

                throw new Exception("Problem saving changes");
            }
Exemplo n.º 10
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 remainingTiles = round.RoundTiles.Where(t => string.IsNullOrEmpty(t.Owner));

                //can only call end round when only 1 tile left or no more tile

                if (remainingTiles.Count() <= 1)
                {
                    round.IsOver   = true;
                    round.IsTied   = true;
                    round.IsEnding = false;

                    round.RoundPlayers.ForEach(rp =>
                    {
                        round.RoundResults.Add(new RoundResult {
                            PlayResult = PlayResult.Tie, Player = rp.GamePlayer.Player, Points = 0
                        });
                    });

                    var success = await _context.SaveChangesAsync() > 0;

                    if (success)
                    {
                        List <RoundDto> results = new List <RoundDto>();

                        foreach (var p in round.RoundPlayers)
                        {
                            results.Add(_mapper.Map <Round, RoundDto>(round, opt => opt.Items["MainRoundPlayer"] = p));
                        }
                        return(results);
                    }
                }
                else
                {
                    throw new RestException(HttpStatusCode.BadRequest, new { Win = "Not enough point to win with this hand" });
                }

                throw new Exception("Problem calling end round");
            }
Exemplo n.º 11
0
            public async Task <GamePlayerDto> Handle(Command request, CancellationToken cancellationToken)
            {
                var game = await _context.Games.FirstOrDefaultAsync(x => x.Code == request.GameCode.ToUpper());

                if (game == null)
                {
                    throw new RestException(HttpStatusCode.NotFound, new { Game = "Could not find game" });
                }

                var user = await _context.Users.SingleOrDefaultAsync(x => x.UserName == request.UserName);

                var gamePlayer = await _context.GamePlayers.SingleOrDefaultAsync(x => x.GameId == game.Id && x.PlayerId == user.Id);

                if (gamePlayer == null)
                {
                    throw new RestException(HttpStatusCode.BadRequest, new { Connect = "Player already left the game" });
                }


                if (game.Status == GameStatus.Created)
                {
                    _context.Connections.RemoveRange(gamePlayer.Connections);
                    _context.GamePlayers.Remove(gamePlayer);
                }

                var currentConnection = gamePlayer.Connections.FirstOrDefault(c => c.Id == request.ConnectionId);

                if (currentConnection != null && game.Status == GameStatus.Playing)
                {
                    currentConnection.Connected = false;
                }

                try
                {
                    await _context.SaveChangesAsync();

                    return(_mapper.Map <GamePlayerDto>(gamePlayer));
                }
                catch (Exception)
                {
                    throw new Exception("Problem leaving from game");
                }
            }
Exemplo n.º 12
0
            public async Task <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 currentRoundPlayer = round.RoundPlayers.FirstOrDefault(p => p.GamePlayer.Player.UserName == request.UserName);

                if (currentRoundPlayer == null)
                {
                    throw new RestException(HttpStatusCode.NotFound, new { Round = "Could not find current player" });
                }

                currentRoundPlayer.IsManualSort = request.IsManualSort;
                //update the activetilecounter
                foreach (var t in request.RoundTiles)
                {
                    var updatedTile = round.RoundTiles.First(rt => rt.Id == t.Id);
                    updatedTile.ActiveTileCounter = t.ActiveTileCounter;
                }

                try
                {
                    var success = await _context.SaveChangesAsync() > 0;

                    var roundToReturn = _mapper.Map <Round, RoundDto>(round, opt => opt.Items["MainRoundPlayer"] = currentRoundPlayer);

                    if (success)
                    {
                        return(roundToReturn);
                    }
                }
                catch (DbUpdateConcurrencyException)
                {
                    throw new RestException(HttpStatusCode.BadRequest, new { Round = "tile was modified" });
                }

                throw new Exception("Problem sorting tile");
            }
Exemplo n.º 13
0
            public async Task <Unit> Handle(Command request, CancellationToken cancellationToken)
            {
                //handler logic
                var game = await _context.Games.FindAsync(request.Id);

                if (game == null)
                {
                    throw new Exception("Could not find game");
                }

                game.Title = request.Title ?? game.Title;

                var success = await _context.SaveChangesAsync() > 0;

                if (success)
                {
                    return(Unit.Value);
                }

                throw new Exception("Problem saving changes");
            }
Exemplo n.º 14
0
            public async Task <GameDto> Handle(Command request, CancellationToken cancellationToken)
            {
                var game = await _context.Games.FirstOrDefaultAsync(x => x.Code == request.GameCode.ToUpper());

                if (game == null)
                {
                    throw new Exception("Could not find game");
                }

                var user = await _context.Users.SingleOrDefaultAsync(x => x.UserName == _userAccessor.GetCurrentUserName());

                if (user == null)
                {
                    throw new Exception("Could not find user");
                }

                var hostPlayer = game.GamePlayers.FirstOrDefault(p => p.PlayerId == user.Id && p.IsHost == true);

                if (hostPlayer == null)
                {
                    throw new Exception("Only host can end the game");
                }

                var hasUnfinishedRound = game.Rounds.Any(r => !r.IsOver);

                game.Status = hasUnfinishedRound ? GameStatus.OverPrematurely : GameStatus.Over;

                var success = await _context.SaveChangesAsync() > 0;

                var gameToReturn = _mapper.Map <Game, GameDto>(game);

                if (success)
                {
                    return(gameToReturn);
                }

                throw new Exception("Problem saving changes");
            }
Exemplo n.º 15
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 remainingTiles = round.RoundTiles.Where(t => string.IsNullOrEmpty(t.Owner));

                //can only call end game when only 1 tile left or no more tile

                if (remainingTiles.Count() <= 1)
                {
                    round.IsEnding = true;

                    var success = await _context.SaveChangesAsync() > 0;

                    if (success)
                    {
                        List <RoundDto> results = new List <RoundDto>();

                        foreach (var p in round.RoundPlayers)
                        {
                            results.Add(_mapper.Map <Round, RoundDto>(round, opt => opt.Items["MainRoundPlayer"] = p));
                        }
                        return(results);
                    }
                }
                else
                {
                    throw new RestException(HttpStatusCode.BadRequest, new { Ending = "Can't set round to ending" });
                }

                throw new Exception("Problem calling ending round");
            }
Exemplo n.º 16
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 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" });
                }

                //existing 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;
                }

                var userJustPickedTile = round.RoundTiles.Where(t => t.Owner == request.UserName && t.Status == TileStatus.UserJustPicked);

                if (userJustPickedTile != null && userJustPickedTile.Count() > 0)
                {
                    foreach (var t in userJustPickedTile)
                    {
                        t.Status = TileStatus.UserActive;
                    }
                }
                var unopenTiles = round.RoundTiles.Where(t => string.IsNullOrEmpty(t.Owner));

                //throw all but one
                var tileCountMinusOne = unopenTiles.Count() - 1;

                foreach (var tileToThrow in unopenTiles.Take(tileCountMinusOne))
                {
                    tileToThrow.ThrownBy = request.UserName;
                    tileToThrow.Owner    = DefaultValue.board;
                    tileToThrow.Status   = TileStatus.BoardGraveyard;
                    tileToThrow.BoardGraveyardCounter = round.TileCounter;
                    round.TileCounter++;
                }

                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 all tile");
            }
Exemplo n.º 17
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");
            }
Exemplo n.º 18
0
            public async Task <IEnumerable <RoundDto> > Handle(Command request, CancellationToken cancellationToken)
            {
                //Note to consider when kong tile:
                //if player has pong in their graveyard, it can be kong
                //-player turn changed
                //-flag when user can kong
                //-when kong tile user need to grab a new tile.
                //-kong doesnt rely on board active tile when its "User's turn", it could be just from player list of active tiles
                //-user can kong anytime when it's their turn n it could be more than 1 set to kong
                //assign tile ownership to current user
                //weird situation is when it's user's turn, user can kong their active tiles and can kong board active tiles

                var updatedTiles = new List <RoundTile>();
                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(u => u.GamePlayer.Player.UserName == request.UserName);

                if (currentPlayer == null)
                {
                    throw new RestException(HttpStatusCode.BadRequest, new { Round = "there are no user with this username in the round" });
                }

                List <RoundTile> userActiveTilesToKong = new List <RoundTile>();
                var currentUserTiles = round.RoundTiles.Where(t => t.Owner == request.UserName);

                //if it's user's turn, check if user has all 4 same tiles first in the user active tiles
                //because the request has tile type and tile value, there can only one possible kong
                //if user has pong tile, user can kong matching tile
                var tilesToKong = currentUserTiles
                                  .Where(t => t.Tile.TileType == request.TileType &&
                                         t.Tile.TileValue == request.TileValue);

                if (tilesToKong.Count() == 4)
                {
                    if (currentPlayer.IsMyTurn)
                    {
                        //if its not konged already, then user can kong it
                        var kongedTile = tilesToKong.Where(t => t.TileSetGroup == TileSetGroup.Kong);
                        if (kongedTile.Count() == 0)
                        {
                            updatedTiles.AddRange(tilesToKong);
                        }
                    }
                }

                //this means that user need to kong from board
                if (tilesToKong.Count() == 3)
                {
                    //if user only have three and its already ponged, then player can't kong
                    var tilesAlreadyPonged = tilesToKong.Where(t => t.TileSetGroup == TileSetGroup.Pong);
                    if (tilesAlreadyPonged.Count() == 3)
                    {
                        throw new RestException(HttpStatusCode.BadRequest, new { Round = "Can't do kong when all tiles ponged" });
                    }

                    var boardActiveTiles = round.RoundTiles.FirstOrDefault(t => t.Status == TileStatus.BoardActive);
                    if (boardActiveTiles == null)
                    {
                        throw new RestException(HttpStatusCode.BadRequest, new { Round = "there are no board active tile to kong" });
                    }
                    var boardActiveMatchedWithRequest = (boardActiveTiles.Tile.TileType == request.TileType && boardActiveTiles.Tile.TileValue == request.TileValue);

                    if (boardActiveMatchedWithRequest)
                    {
                        //only have 3 active tiles then board must exist to kong
                        var allTilesAreActive = tilesToKong.Where(t => t.Status != TileStatus.UserGraveyard);
                        if (boardActiveMatchedWithRequest && allTilesAreActive.Count() == 3)
                        {
                            updatedTiles.AddRange(tilesToKong);
                            updatedTiles.Add(boardActiveTiles);
                        }
                    }
                }

                if (updatedTiles.Count() == 4)
                {
                    updatedTiles.GoGraveyard(request.UserName, TileSetGroup.Kong, round.RoundTiles.GetLastGroupIndex(request.UserName));
                }
                else
                {
                    throw new RestException(HttpStatusCode.BadRequest, new { Kong = "Not possible to kong" });
                }

                //set existing justpicked tile to useractive;
                var existingJustPicked = round.RoundTiles.FirstOrDefault(rt => rt.Owner == request.UserName && rt.Status == TileStatus.UserJustPicked);

                if (existingJustPicked != null)
                {
                    existingJustPicked.Status = TileStatus.UserActive;
                    updatedTiles.Add(existingJustPicked);
                }

                //clear existing action
                currentPlayer.RoundPlayerActions.Clear();

                //add new tile for user
                var newTiles = RoundTileHelper.PickTile(round, request.UserName, true);

                if (newTiles.Count() > 0)
                {
                    //assign new tile to user that kong the tile
                    foreach (var tile in newTiles)
                    {
                        updatedTiles.Add(tile);
                    }
                    RoundHelper.CheckSelfAction(round, currentPlayer, _pointsCalculator);
                }
                else
                {
                    //TODO: what if user kong when there is no more tile
                }

                currentPlayer.IsMyTurn = true;
                //because new tile automatically added, player must throw set to true
                currentPlayer.MustThrow = true;

                if (round.IsEnding)
                {
                    round.IsEnding = false;
                }

                var otherPlayers = round.RoundPlayers.Where(u => u.IsMyTurn == true && u.GamePlayer.Player.UserName != request.UserName);

                foreach (var otherPlayerTurn in otherPlayers)
                {
                    otherPlayerTurn.IsMyTurn = false;
                }

                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 = "tile was modified" });
                }

                throw new Exception("Problem kong ing tile");
            }
Exemplo n.º 19
0
            public async Task <GamePlayerDto> Handle(Command request, CancellationToken cancellationToken)
            {
                var game = await _context.Games.FirstOrDefaultAsync(g => g.Code == request.GameCode.ToUpper());

                if (game == null)
                {
                    throw new RestException(HttpStatusCode.NotFound, new { Game = "Could not find game" });
                }

                var user = await _context.Users.SingleOrDefaultAsync(x => x.UserName == request.UserName);

                var gamePlayer = _context.GamePlayers.FirstOrDefault(x => x.GameId == game.Id && x.PlayerId == user.Id);

                if (gamePlayer != null)
                {
                    foreach (var uc in gamePlayer.Connections)
                    {
                        if (uc.Id != request.ConnectionId)
                        {
                            _context.Connections.Remove(uc);
                        }
                    }
                }
                else
                {
                    if (game.Status == GameStatus.Playing || game.GamePlayers.Count == 4)
                    {
                        throw new RestException(HttpStatusCode.BadRequest, new { Game = "Reached max players" });
                    }

                    gamePlayer = new GamePlayer
                    {
                        Game   = game,
                        Player = user,
                        IsHost = false,
                    };
                    _context.GamePlayers.Add(gamePlayer);
                    _context.SaveChanges();
                }

                var existingConnection = _context.Connections.FirstOrDefault(c => c.Id == request.ConnectionId);

                if (existingConnection == null)
                {
                    gamePlayer.Connections.Add(new Connection
                    {
                        Id           = request.ConnectionId,
                        GamePlayerId = gamePlayer.Id,
                        Connected    = true,
                        UserAgent    = request.UserAgent
                    });
                }
                else
                {
                    existingConnection.GamePlayerId = gamePlayer.Id;
                    existingConnection.Connected    = true;
                    existingConnection.UserAgent    = request.UserAgent;
                }

                try
                {
                    await _context.SaveChangesAsync();

                    return(_mapper.Map <GamePlayerDto>(gamePlayer));
                }
                catch (Exception)
                {
                    throw new Exception("Problem joining to game");
                }
            }
Exemplo n.º 20
0
            public async Task <IEnumerable <RoundDto> > Handle(Command request, CancellationToken cancellationToken)
            {
                //Note to consider when chow tile:
                //-when chow tile user need to throw a tile.
                //assign tile ownership to current user
                var round = await _context.Rounds.FindAsync(request.RoundId);

                if (round == null)
                {
                    throw new RestException(HttpStatusCode.NotFound, new { Round = "Could not find round" });
                }

                //TODO only allow chow when it's user's turn

                if (request.ChowTiles == null || request.ChowTiles.Count() != 2)
                {
                    throw new RestException(HttpStatusCode.BadRequest, new { Round = "invalid data to chow tiles" });
                }

                var boardActiveTiles = round.RoundTiles.Where(t => t.Status == TileStatus.BoardActive);

                if (boardActiveTiles == null || boardActiveTiles.Count() > 1)
                {
                    throw new RestException(HttpStatusCode.BadRequest, new { Round = "there are no tile or more than one tiles to chow" });
                }

                var tileToChow = boardActiveTiles.First();

                if (tileToChow.Tile.TileType == TileType.Dragon || tileToChow.Tile.TileType == TileType.Flower || tileToChow.Tile.TileType == TileType.Wind)
                {
                    throw new RestException(HttpStatusCode.BadRequest, new { Round = "tile must be money, round, or stick for chow" });
                }

                var dbTilesToChow = round.RoundTiles.Where(t => request.ChowTiles.Contains(t.Id)).ToList();

                dbTilesToChow.Add(tileToChow);

                var sortedChowTiles = dbTilesToChow.OrderBy(t => t.Tile.TileValue).ToArray();

                //check if its straight
                if (sortedChowTiles[0].Tile.TileValue + 1 == sortedChowTiles[1].Tile.TileValue &&
                    sortedChowTiles[1].Tile.TileValue + 1 == sortedChowTiles[2].Tile.TileValue)
                {
                    int groupIndex = 1;
                    var tileSets   = round.RoundTiles.Where(t => t.Owner == request.UserName && t.TileSetGroup != TileSetGroup.None);
                    if (tileSets.Count() > 0)
                    {
                        var lastIndex = tileSets.GroupBy(t => t.TileSetGroupIndex).Select(g => g.Last()).First().TileSetGroupIndex;
                        groupIndex = lastIndex + 1;
                    }

                    sortedChowTiles.GoGraveyard(request.UserName, TileSetGroup.Chow, round.RoundTiles.GetLastGroupIndex(request.UserName));
                }
                else
                {
                    throw new RestException(HttpStatusCode.BadRequest, new { Round = "tile is not in sequence to chow" });
                }

                var currentPlayer = round.RoundPlayers.FirstOrDefault(u => u.GamePlayer.Player.UserName == request.UserName);

                if (currentPlayer == null)
                {
                    throw new RestException(HttpStatusCode.BadRequest, new { Round = "there are no user with this username in the round" });
                }

                currentPlayer.IsMyTurn  = true;
                currentPlayer.MustThrow = true;

                var otherPlayers = round.RoundPlayers.Where(u => u.IsMyTurn == true && u.GamePlayer.Player.UserName != request.UserName);

                foreach (var otherPlayerTurn in otherPlayers)
                {
                    otherPlayerTurn.IsMyTurn  = false;
                    otherPlayerTurn.MustThrow = false;
                }

                if (round.IsEnding)
                {
                    round.IsEnding = false;
                }

                //if user chow, then there's no way that user can win/pong/chow
                var actionsToBeRemoved = currentPlayer.RoundPlayerActions.Where(a => a.ActionType != ActionType.SelfKong).ToList();

                foreach (var action in actionsToBeRemoved)
                {
                    currentPlayer.RoundPlayerActions.Remove(action);
                }
                RoundHelper.CheckPossibleSelfKong(round, currentPlayer);

                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 = "tile was modified" });
                }

                throw new Exception("Problem chow ing tile");
            }
Exemplo n.º 21
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.NotFound, new { Game = "Could not find game" });
                }

                var round = game.Rounds.FirstOrDefault(r => r.Id == request.RoundId);

                if (round == null)
                {
                    throw new RestException(HttpStatusCode.NotFound, new { Round = "Could not find round" });
                }

                RoundPlayer roundPlayerWinner = round.RoundPlayers.FirstOrDefault(u => u.GamePlayer.Player.UserName == request.UserName);

                if (roundPlayerWinner == null)
                {
                    throw new RestException(HttpStatusCode.NotFound, new { Player = "Could not find player" });
                }

                //check for valid win:
                HandWorth handWorth = _pointCalculator.Calculate(round, request.UserName);

                if (handWorth == null)
                {
                    throw new RestException(HttpStatusCode.BadRequest, new { Win = "Invalid combination hand" });
                }

                if (handWorth.Points >= game.MinPoint)
                {
                    var winAction = roundPlayerWinner.RoundPlayerActions.FirstOrDefault(a => a.ActionType == ActionType.Win);
                    if (winAction != null)
                    {
                        winAction.ActionStatus = ActionStatus.Activated;
                    }

                    bool isSelfPick = false;

                    //set the game as over if all win action is settled
                    var playerWithUnsettledWin = round.RoundPlayers.Where(p => p.RoundPlayerActions.Any(pa => pa.ActionType == ActionType.Win && pa.ActionStatus == ActionStatus.Active));

                    if (playerWithUnsettledWin.Count() == 0)
                    {
                        round.IsOver   = true;
                        round.IsEnding = false;
                    }

                    //create the result and record who win and who lost
                    RoundResult winnerResult = new RoundResult
                    {
                        Player     = roundPlayerWinner.GamePlayer.Player,
                        PlayResult = PlayResult.Win,
                    };

                    if (round.RoundResults == null)
                    {
                        round.RoundResults = new List <RoundResult>();
                    }

                    //record hand type and extra points
                    foreach (var h in handWorth.HandTypes)
                    {
                        var point = _pointCalculator.HandTypeLookup[h];
                        winnerResult.RoundResultHands.Add(new RoundResultHand {
                            HandType = h, Point = point, Name = h.ToString()
                        });
                    }

                    foreach (var e in handWorth.ExtraPoints)
                    {
                        if (e == ExtraPoint.SelfPick)
                        {
                            isSelfPick = true;
                        }

                        var point = _pointCalculator.ExtraPointLookup[e];
                        winnerResult.RoundResultExtraPoints.Add(new RoundResultExtraPoint {
                            ExtraPoint = e, Point = point, Name = e.ToString()
                        });
                    }

                    //now that we have the winner hand type and extra point recorded, let's calculate the points

                    //if the handworth exceed game max point, cap the point to game's max point
                    var cappedPoint = handWorth.Points > game.MaxPoint ? game.MaxPoint : handWorth.Points;
                    var losingPoint = cappedPoint * -1;

                    if (isSelfPick)
                    {
                        //check if "bao"
                        //if there is AllOneSuit or SmallDragon or BigDragon or smallFourWind or bigFourWind
                        //then the one that "bao" will be the only one that pays to the winner

                        bool   isLoserBao        = false;
                        string baoPlayerUserName = string.Empty;
                        //check for allonesuit
                        var winnerTiles = round.RoundTiles.Where(t => t.Owner == roundPlayerWinner.GamePlayer.Player.UserName);
                        if (handWorth.HandTypes.Contains(HandType.AllOneSuit) ||
                            handWorth.HandTypes.Contains(HandType.SmallFourWind) ||
                            handWorth.HandTypes.Contains(HandType.BigFourWind))
                        {
                            //check if the 4th tilesetgroupindex has thrownby value
                            var fourthGroupTileIndex = winnerTiles.FirstOrDefault(t => t.TileSetGroupIndex == 4 && !string.IsNullOrEmpty(t.ThrownBy));
                            if (fourthGroupTileIndex != null)
                            {
                                isLoserBao        = true;
                                baoPlayerUserName = fourthGroupTileIndex.ThrownBy;
                            }
                        }

                        //check for dragon
                        if (handWorth.HandTypes.Contains(HandType.SmallDragon) || handWorth.HandTypes.Contains(HandType.BigDragon))
                        {
                            //find the index of first pong dragon
                            var pongOrKongDragons = winnerTiles.Where(t => (t.TileSetGroup == TileSetGroup.Pong || t.TileSetGroup == TileSetGroup.Kong) &&
                                                                      t.Tile.TileType == TileType.Dragon && !string.IsNullOrEmpty(t.ThrownBy));

                            //if there is 3rd set of dragon pong/kong, then its not a bao
                            //weird rule ever
                            //then find the index of second pong dragon and check thrown by
                            if (pongOrKongDragons.Count() == 2)
                            {
                                isLoserBao        = true;
                                baoPlayerUserName = pongOrKongDragons.OrderBy(t => t.TileSetGroupIndex).Last().ThrownBy;
                            }
                        }

                        if (isLoserBao)
                        {
                            //the loser that bao will pay the winning point times three
                            var winningPoint = cappedPoint * 3;
                            roundPlayerWinner.Points += winningPoint;
                            winnerResult.Points       = winningPoint;

                            RoundPlayer roundPlayerloser = round.RoundPlayers.FirstOrDefault(p => p.GamePlayer.Player.UserName == baoPlayerUserName);
                            roundPlayerloser.Points -= winningPoint;
                            round.RoundResults.Add(new RoundResult {
                                PlayResult = PlayResult.LostWithPenalty, Player = roundPlayerloser.GamePlayer.Player, Points = losingPoint * 3
                            });

                            //record users that are tied
                            var tiedPlayers = round.RoundPlayers.Where(p => p.GamePlayer.Player.UserName != baoPlayerUserName && p.GamePlayer.Player.UserName != roundPlayerWinner.GamePlayer.Player.UserName);
                            tiedPlayers.ForEach(tp =>
                            {
                                round.RoundResults.Add(new RoundResult {
                                    PlayResult = PlayResult.Tie, Player = tp.GamePlayer.Player, Points = 0
                                });
                            });
                        }
                        else
                        {
                            //if its self pick, and no bao, then all 3 other players needs to record the loss
                            var losers = round.RoundPlayers.Where(u => u.GamePlayer.Player.UserName != request.UserName);

                            //points will be times 3
                            var winningPoint = cappedPoint * 3;
                            roundPlayerWinner.Points += winningPoint;
                            winnerResult.Points       = winningPoint;

                            losers.ForEach(l =>
                            {
                                l.Points -= cappedPoint;
                                round.RoundResults.Add(new RoundResult {
                                    PlayResult = PlayResult.Lost, Player = l.GamePlayer.Player, Points = losingPoint
                                });
                            });
                        }
                    }
                    else
                    {
                        //otherwise there is only one loser that throw the tile to board
                        roundPlayerWinner.Points += cappedPoint;
                        winnerResult.Points       = cappedPoint;

                        var boardTile = round.RoundTiles.First(t => t.Owner == DefaultValue.board && t.Status == TileStatus.BoardActive);
                        var loser     = round.RoundPlayers.First(u => u.GamePlayer.Player.UserName == boardTile.ThrownBy);
                        loser.Points -= cappedPoint;
                        round.RoundResults.Add(new RoundResult {
                            PlayResult = PlayResult.Lost, Player = loser.GamePlayer.Player, Points = losingPoint
                        });

                        //check for multiple winners. If player has a valid win and already recorded as tie
                        var tieResultCouldWin = round.RoundResults.FirstOrDefault(rr => rr.PlayResult == PlayResult.Tie && rr.Player.UserName == roundPlayerWinner.GamePlayer.Player.UserName);

                        if (tieResultCouldWin != null)
                        {
                            //remove record that the player tie
                            round.RoundResults.Remove(tieResultCouldWin);
                        }
                        else
                        {
                            //record users that are tied
                            var tiedPlayers = round.RoundPlayers.Where(p => p.GamePlayer.Player.UserName != loser.GamePlayer.Player.UserName && p.GamePlayer.Player.UserName != roundPlayerWinner.GamePlayer.Player.UserName);
                            tiedPlayers.ForEach(tp =>
                            {
                                round.RoundResults.Add(new RoundResult {
                                    PlayResult = PlayResult.Tie, Player = tp.GamePlayer.Player, Points = 0
                                });
                            });
                        }
                    }
                    round.RoundResults.Add(winnerResult);

                    //tally the point in gameplayer
                    round.RoundPlayers.ForEach(rp =>
                    {
                        rp.GamePlayer.Points = rp.Points;
                    });

                    var success = await _context.SaveChangesAsync() > 0;

                    if (success)
                    {
                        List <RoundDto> results = new List <RoundDto>();

                        foreach (var p in round.RoundPlayers)
                        {
                            results.Add(_mapper.Map <Round, RoundDto>(round, opt => opt.Items["MainRoundPlayer"] = p));
                        }
                        return(results);
                    }
                }
                else
                {
                    throw new RestException(HttpStatusCode.BadRequest, new { Win = "Not enough point to win with this hand" });
                }

                throw new Exception("Problem calling win");
            }
Exemplo n.º 22
0
            public async Task <IEnumerable <RoundDto> > Handle(Command request, CancellationToken cancellationToken)
            {
                //Note to consider when pong tile:
                //-player turn changed
                //-flag when user can pong
                //-when pong tile user need to throw a tile.
                //assign tile ownership to current user

                var updatedTiles = new List <RoundTile>();
                var round        = await _context.Rounds.FindAsync(request.RoundId);

                if (round == null)
                {
                    throw new RestException(HttpStatusCode.NotFound, new { Round = "Could not find round" });
                }

                var boardActiveTiles = round.RoundTiles.Where(t => t.Status == TileStatus.BoardActive);

                if (boardActiveTiles == null)
                {
                    throw new RestException(HttpStatusCode.BadRequest, new { Round = "there are no tile to pong" });
                }

                var tileToPong = boardActiveTiles.First();

                updatedTiles.Add(tileToPong);

                //check if user currently have two tile to pong

                var matchingUserTiles = round.RoundTiles
                                        .Where(t => t.Owner == request.UserName &&
                                               t.Status == TileStatus.UserActive &&
                                               t.Tile.TileType == tileToPong.Tile.TileType &&
                                               t.Tile.TileValue == tileToPong.Tile.TileValue);

                if (matchingUserTiles == null || matchingUserTiles.Count() < 2)
                {
                    throw new RestException(HttpStatusCode.BadRequest, new { Round = "there are more than one tiles to pong" });
                }

                //if there is Userjustpicked status then pong is invalid
                var justPickedTile = round.RoundTiles.FirstOrDefault(t => t.Status == TileStatus.UserJustPicked);

                if (justPickedTile != null)
                {
                    throw new RestException(HttpStatusCode.BadRequest, new { Round = "someone already picked tile, no pong is allowed" });
                }

                foreach (var tile in matchingUserTiles.Take(2))
                {
                    updatedTiles.Add(tile);
                }

                updatedTiles.GoGraveyard(request.UserName, TileSetGroup.Pong, round.RoundTiles.GetLastGroupIndex(request.UserName));

                var currentPlayer = round.RoundPlayers.FirstOrDefault(u => u.GamePlayer.Player.UserName == request.UserName);

                if (currentPlayer == null)
                {
                    throw new RestException(HttpStatusCode.BadRequest, new { Round = "there are no user with this username in the round" });
                }

                currentPlayer.IsMyTurn  = true;
                currentPlayer.MustThrow = true;

                var actionsToBeRemoved = currentPlayer.RoundPlayerActions.Where(a => a.ActionType != ActionType.SelfKong).ToList();

                foreach (var action in actionsToBeRemoved)
                {
                    currentPlayer.RoundPlayerActions.Remove(action);
                }
                RoundHelper.CheckPossibleSelfKong(round, currentPlayer);

                if (round.IsEnding)
                {
                    round.IsEnding = false;
                }

                var otherPlayers = round.RoundPlayers.Where(u => u.IsMyTurn == true && u.GamePlayer.Player.UserName != request.UserName);

                foreach (var otherPlayerTurn in otherPlayers)
                {
                    otherPlayerTurn.IsMyTurn  = false;
                    otherPlayerTurn.MustThrow = false;
                }

                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 = "tile was modified" });
                }

                throw new Exception("Problem pong ing tile");
            }
Exemplo n.º 23
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");
            }
Exemplo n.º 24
0
            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");
            }
Exemplo n.º 25
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 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");
            }