public async Task <Games.NinthPlanet> CreateNewGameAsync(
            int ownerId,
            NinthPlanetNewGameOptions newGameOptions,
            CancellationToken cancellationToken)
        {
            await semaphore.WaitAsync(cancellationToken);

            try
            {
                var gameInfo = new DbGameInfo
                {
                    GameType = GameType.NinthPlanet,
                    Name     = newGameOptions.Name,
                    MaximumNumberOfPlayers = newGameOptions.MaxNumberOfPlayers,
                    IsPublic = newGameOptions.IsPublic,
                    OwnerId  = ownerId
                };

                var gameServer = gameServerFactory.CreateNewGame(gameInfo);
                var state      = gameServer.SaveCurrentState();
                NinthPlanetGameState dbGameState = ToStoredState(gameInfo, state);
                dbContext.NinthPlanetGames.Add(dbGameState);
                await dbContext.SaveChangesAsync(cancellationToken);

                var game = new Games.NinthPlanet(gameServer);
                this.gameCache.TryAddGame(gameInfo.Id, game);
                return(game);
            }
            finally
            {
                semaphore.Release();
            }
        }
        private NinthPlanetGameState ToStoredState(DbGameInfo gameInfo, SavedGameState state)
        {
            var playerStates = state.PlayersInLobby
                               .Select(x => new NinthPlanetPlayerState {
                PlayerId = x
            })
                               .ToList();

            var dbGameState = new NinthPlanetGameState
            {
                GameInfo          = gameInfo,
                RoundIsInProgress = state.RoundState != null,
                PlayerStates      = playerStates,
            };

            if (state.RoundState != null)
            {
                foreach (var playerState in state.RoundState.PlayerStates)
                {
                    var storedState = playerStates.First(x => x.PlayerId == playerState.Key);
                    storedState.PlayOrder = state.RoundState.PlayerOrder.IndexOf(playerState.Key);

                    storedState.FinishedTasks              = playerState.Value.FinishedTasks;
                    storedState.UnfinishedTasks            = playerState.Value.UnfinishedTasks;
                    storedState.CardsInHand                = playerState.Value.CardsInHand;
                    storedState.ComunicatedCardColor       = playerState.Value.DisplayedCard.Color;
                    storedState.ComunicatedCardValue       = playerState.Value.DisplayedCard.Value;
                    storedState.CommunicationTokenPosition = playerState.Value.DisplayedCardTokenPosition;
                }
            }

            return(dbGameState);
        }
        private Games.NinthPlanet StartGameFromState(NinthPlanetGameState dbGameState)
        {
            SavedGameState gameState = ToGameState(dbGameState);

            var gameServer = gameServerFactory.CreateGameFromState(gameState);
            var game       = new Games.NinthPlanet(gameServer);

            this.gameCache.TryAddGame(dbGameState.GameId, game);
            return(game);
        }
        private SavedGameState ToGameState(NinthPlanetGameState dbGameState)
        {
            var gameState = new SavedGameState
            {
                GameInfo       = dbGameState.GameInfo,
                PlayersInLobby = dbGameState.PlayerStates.Select(x => x.PlayerId).ToList(),
            };

            if (dbGameState.RoundIsInProgress)
            {
                var playerOrder = dbGameState.PlayerStates
                                  .Where(x => x.PlayOrder.HasValue)
                                  .OrderBy(x => x.PlayOrder.Value)
                                  .Select(x => x.PlayerId)
                                  .ToList();

                var playerStates = dbGameState.PlayerStates
                                   .Where(x => x.PlayOrder.HasValue)
                                   .ToDictionary(
                    x => x.PlayerId,
                    x => new PlayerPrivateState
                {
                    CardsInHand   = x.CardsInHand,
                    DisplayedCard = x.ComunicatedCardValue.HasValue ? new Card
                    {
                        Value = x.ComunicatedCardValue.Value,
                        Color = x.ComunicatedCardColor.Value
                    } : null,
                    DisplayedCardTokenPosition = x.CommunicationTokenPosition,
                    UnfinishedTasks            = x.UnfinishedTasks,
                    FinishedTasks = x.FinishedTasks,
                });

                gameState.RoundState = new SavedRoundState
                {
                    PlayerOrder         = playerOrder,
                    CurrentPlayerId     = dbGameState.CurrentPlayerId,
                    CaptainPlayerId     = dbGameState.CaptainPlayerId,
                    ColorOfCurrentTrick = dbGameState.ColorOfCurrentTrick,
                    PlayerStates        = playerStates,
                };
            }

            return(gameState);
        }