Пример #1
0
        public async Task <GameResponse> JoinGameAsync(string connectionId, Guid gameId, string password)
        {
            if (!UsersByConnectionId.ContainsKey(connectionId))
            {
                Logger.LogError($"Got join game message for unknown connection id '{connectionId}'");
                return(GameResponse.Failure("Connection not found"));
            }

            var user = UsersByConnectionId[connectionId];

            if (!GamesById.ContainsKey(gameId))
            {
                Logger.LogError($"Got join game message for unknown game id '{gameId}'");
                return(GameResponse.Failure("Game not found"));
            }

            var game = GamesById[gameId];

            var joinResponse = game.Join(user, password);

            if (!joinResponse.Success)
            {
                return(joinResponse);
            }

            await subscriber.PublishAsync(RedisChannels.UpdateGame, JsonConvert.SerializeObject(game));

            return(joinResponse);
        }
Пример #2
0
        private async Task <LobbyGame> DisconnectedUserInternalAsync(string connectionId)
        {
            if (!UsersByConnectionId.ContainsKey(connectionId))
            {
                Logger.LogError($"Got user disconnect for unknown connection Id '{connectionId}'");
                return(null);
            }

            var user = UsersByConnectionId[connectionId];

            await subscriber.PublishAsync(RedisChannels.UserDisconnect, JsonConvert.SerializeObject(user));

            var game = FindGameForUser(user.Name);

            if (game == null || game.Started)
            {
                return(null);
            }

            game.PlayerDisconnected(user.Name);

            if (!game.IsEmpty())
            {
                return(game);
            }

            GamesById.Remove(game.Id);
            await subscriber.PublishAsync(RedisChannels.RemoveGame, game.Id.ToString());

            return(game);
        }
Пример #3
0
        public async Task <LobbyGame> LeaveGameAsync(string connectionId)
        {
            if (!UsersByConnectionId.ContainsKey(connectionId))
            {
                Logger.LogError($"Got leave game message for unknown connection id '{connectionId}'");
                return(null);
            }

            var user = UsersByConnectionId[connectionId];
            var game = FindGameForUser(user.Name);

            if (game == null || game.Started)
            {
                return(null);
            }

            game.PlayerLeave(user.Name);

            if (!game.IsEmpty())
            {
                await subscriber.PublishAsync(RedisChannels.UpdateGame, JsonConvert.SerializeObject(game));

                return(game);
            }

            GamesById.Remove(game.Id);

            await subscriber.PublishAsync(RedisChannels.RemoveGame, game.Id.ToString());

            return(game);
        }
Пример #4
0
        public void RemoveGame(Guid gameId)
        {
            if (!GamesById.ContainsKey(gameId))
            {
                Logger.LogWarning($"Got close for game {gameId} that we didn't know about");
                return;
            }

            GamesById.Remove(gameId);
        }
Пример #5
0
        public void Init()
        {
            subscriber.Subscribe(RedisChannels.NewUser, OnNewUserMessage);
            subscriber.Subscribe(RedisChannels.UserDisconnect, OnUserDisconnectMessage);

            subscriber.Publish(RedisChannels.LobbyHello, options.NodeName);

            var gameIds = database.SetMembers("games");

            foreach (var gameId in gameIds)
            {
                var gameString = database.StringGet($"game:{gameId}");
                var game       = JsonConvert.DeserializeObject <LobbyGame>(gameString);

                GamesById.Add(game.Id, game);
            }
        }
Пример #6
0
        private async Task <GameResponse> StartNewGameInternalAsync(string connectionId, StartNewGameRequest request)
        {
            if (!UsersByConnectionId.ContainsKey(connectionId))
            {
                Logger.LogError($"Got new game message for unknown connection id '{connectionId}'");
                return(GameResponse.Failure("Connection not found"));
            }

            var user = UsersByConnectionId[connectionId];

            var existingGame = FindGameForUser(user.Name);

            if (existingGame != null)
            {
                Logger.LogError($"Got new game message for user already in game '{user.Name}' '{existingGame.Name}'");
                return(GameResponse.Failure("You are already in a game so cannot start a new one"));
            }

            if (request.QuickJoin)
            {
                var pendingGame = GamesById.Values.OrderBy(g => g.Started).FirstOrDefault(game => game.CanQuickJoin(game.GameType));
                if (pendingGame != null)
                {
                }

                return(GameResponse.Succeeded(pendingGame));
            }

            var newGame = new LobbyGame(user.Name, request);

            newGame.NewGame(user);
            GamesById.Add(newGame.Id, newGame);

            await subscriber.PublishAsync(RedisChannels.NewGame, JsonConvert.SerializeObject(newGame));

            return(GameResponse.Succeeded(newGame));
        }
Пример #7
0
        private void DbClasses_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            DbHelper.Instance.IsChanged = true;

            if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
            {
                if (sender is ObservableCollection <Player> )
                {
                    PlayersById.Add(((Player)e.NewItems[0]).Id, (Player)e.NewItems[0]);
                    m_Logger.Debug("Added a player: " + (Player)e.NewItems[0]);
                    NotifyPropertyChanged("PlayersSorted");
                }
                else if (sender is ObservableCollection <GameFamily> )
                {
                    GameFamiliesById.Add(((GameFamily)e.NewItems[0]).Id, (GameFamily)e.NewItems[0]);
                    m_Logger.Debug("Added a game family: " + (GameFamily)e.NewItems[0]);
                    NotifyPropertyChanged("GameFamiliesFiltered");
                }
                else if (sender is ObservableCollection <Location> )
                {
                    LocationsById.Add(((Location)e.NewItems[0]).Id, (Location)e.NewItems[0]);
                    m_Logger.Debug("Added a Location: " + (Location)e.NewItems[0]);
                    NotifyPropertyChanged("LocationsSorted");
                }
                else if (sender is ObservableCollection <Game> )
                {
                    GamesById.Add(((Game)e.NewItems[0]).Id, (Game)e.NewItems[0]);
                    m_Logger.Debug("Added a Game: " + (Game)e.NewItems[0]);
                    NotifyPropertyChanged("GamesPointBased");
                    NotifyPropertyChanged("GamesSorted");
                }
                else if (sender is ObservableCollection <Result> )
                {
                    Result v_Result = (Result)e.NewItems[0];

                    // Hooking up the notifications for the new object.
                    v_Result.PropertyChanged += Result_PropertyChanged;

                    foreach (Score i_Score in v_Result.Scores)
                    {
                        i_Score.PropertyChanged += Result_PropertyChanged;
                    }

                    NotifyPropertyChanged("ResultsOrdered");
                }
                else
                {
                    throw new NotImplementedException(String.Format("Adding of [{0}] is not supported.", sender.GetType()));
                }
            }
            else if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove)
            {
                if (sender is ObservableCollection <Player> )
                {
                    PlayersById.Remove(((Player)e.OldItems[0]).Id);
                    NotifyPropertyChanged("PlayersSorted");
                }
                else if (sender is ObservableCollection <GameFamily> )
                {
                    GameFamiliesById.Remove(((GameFamily)e.OldItems[0]).Id);
                    NotifyPropertyChanged("GameFamiliesFiltered");
                }
                else if (sender is ObservableCollection <Location> )
                {
                    LocationsById.Remove(((Location)e.OldItems[0]).Id);
                    NotifyPropertyChanged("LocationsSorted");
                }
                else if (sender is ObservableCollection <Game> )
                {
                    GamesById.Remove(((Game)e.OldItems[0]).Id);
                    NotifyPropertyChanged("GamesPointBased");
                    NotifyPropertyChanged("GamesSorted");
                }
                else if (sender is ObservableCollection <Result> )
                {
                    NotifyPropertyChanged("ResultsOrdered");
                }
                else
                {
                    throw new NotImplementedException(String.Format("Removing of [{0}] is not supported.", sender.GetType()));
                }
            }
            else if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Reset)
            {
                m_Logger.Debug("Resetting collection for [" + sender.GetType() + "].");

                if (sender is ObservableCollection <Player> )
                {
                    PlayersById.Clear();
                    NotifyPropertyChanged("PlayersSorted");
                }
                else if (sender is ObservableCollection <GameFamily> )
                {
                    GameFamiliesById.Clear();
                    NotifyPropertyChanged("GameFamiliesFiltered");
                }
                else if (sender is ObservableCollection <Location> )
                {
                    LocationsById.Clear();
                    NotifyPropertyChanged("LocationsSorted");
                }
                else if (sender is ObservableCollection <Game> )
                {
                    GamesById.Clear();
                    NotifyPropertyChanged("GamesPointBased");
                    NotifyPropertyChanged("GamesSorted");
                }
                else if (sender is ObservableCollection <Result> )
                {
                    NotifyPropertyChanged("ResultsOrdered");
                }
                else
                {
                    throw new NotImplementedException(String.Format("Resetting of [{0}] is not supported.", sender.GetType()));
                }
            }
            else
            {
                throw new NotImplementedException(String.Format("Action {0} not supported on collection.", e.Action));
            }
        }
Пример #8
0
        /// <summary>
        /// Calculates the ELO score for all players and their results. By default we assume a score of 1500 for a new player.
        /// </summary>
        /// <param name="a_GameOrFamilyId">Three possible ways to use it: Either a Guid for a single game or a game family works.
        /// If the ID is null or invalid the whole results database will be used.</param>
        /// <returns>A dictionary with the Player as key and a ResultHelper object containing the calculated results.</returns>
        public Dictionary <Player, Result.ResultHelper> CalculateEloResults(Guid a_GameOrFamilyId)
        {
            Dictionary <Player, Result.ResultHelper> v_EloResults = new Dictionary <Player, Result.ResultHelper>();

            // Start with the standard ELO number for every player.
            foreach (Player i_Player in Players)
            {
                v_EloResults.Add(i_Player, new Result.ResultHelper(i_Player.Id, c_EloStartValue, 0));
            }

            // We want to start with the oldest results. The UI shows newest results on the top so we need to reverse order here.
            IEnumerable <Result> v_BeginningToEndResults = new ObservableCollection <Result>(Results.OrderBy(p => p.Date));

            if (GameFamiliesById.ContainsKey(a_GameOrFamilyId))
            {
                // First: Get all games from the given game family.
                var v_AllGamesFromFamily = Games.Where(p => p.IdGamefamilies.Contains(a_GameOrFamilyId));

                if (v_AllGamesFromFamily.Count() > 0)
                {
                    // Second: Get all results with games of the given game family.
                    v_BeginningToEndResults = v_BeginningToEndResults.Join(v_AllGamesFromFamily,
                                                                           result => result.IdGame,
                                                                           game => game.Id,
                                                                           (result, game) => result);
                }
                else
                {
                    v_BeginningToEndResults = new ObservableCollection <Result>();
                }
            }
            else if (GamesById.ContainsKey(a_GameOrFamilyId))
            {
                v_BeginningToEndResults = v_BeginningToEndResults.Where(p => p.IdGame == a_GameOrFamilyId);
            }

            foreach (Result i_Result in v_BeginningToEndResults)
            {
                Dictionary <Guid, Result.ResultHelper> v_TempEloResults = new Dictionary <Guid, Result.ResultHelper>();

                // We do not consider results of solo games.
                if (i_Result.Scores.Count == 1)
                {
                    continue;
                }

                foreach (Score i_Score in i_Result.Scores)
                {
                    v_TempEloResults.Add(i_Score.IdPlayer, v_EloResults[PlayersById[i_Score.IdPlayer]]);
                }

                if (GamesById[i_Result.IdGame].Type == Game.GameType.Ranks)
                {
                    i_Result.CalculateEloResultsForRanks(v_TempEloResults, i_Result.Date);
                }
                else
                {
                    i_Result.CalculateEloResults(v_TempEloResults, i_Result.Date);
                }
            }

            return(v_EloResults);
        }