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"); }
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"); }
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"); }
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"); }
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"); }
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"); }
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"); }
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"); } }
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"); }
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"); }
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"); } }
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"); }
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"); }
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"); }
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"); }
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"); }
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) { //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"); }
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"); } }
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"); }
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"); }
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"); }
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"); }
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"); }
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"); }