public List <MatchedPlayers> Run(
            Func <MatchedPlayers, Task> onMatched,
            Func <MatchedPlayers, string, Task> onPlaying,
            Func <MatchedPlayers, Task> onError,
            int playersPerMatch = 2,
            int scoreLimit      = 300
            )
        {
            if (!_matchmakerPoolSingleton.CanStart())
            {
                return(null);
            }
            var matches = new List <MatchedPlayers>();

            try {
                var matcher = new GroupAndSortMatcher(_matchmakerPoolSingleton.ListPlayers());
                matcher.createPotentialMatches(playersPerMatch);
                matches = matcher.getMatches(scoreLimit);

                foreach (var matchedPlayers in matches)
                {
                    _matchmakerPoolSingleton.MatchPlayers(matchedPlayers);
                    onMatched(matchedPlayers);
                    try {
                        var players   = matchedPlayers.Randomize();
                        var playerIds = players.Select(int.Parse).ToList();
                        var matchId   = _matchService.CreateMatch(playerIds);
                        _schotten2Service.Start(players, matchId.ToString());
                        onPlaying(matchedPlayers, matchId.ToString());
                        _matchmakerLogService.SetMatchId(playerIds, matchId);

                        // TODO: Enable _notificationService.MatchCreated(matchId);
                    } catch (Exception ex) {
                        _matchmakerPoolSingleton.UnmatchPlayers(matchedPlayers);
                        onError(matchedPlayers);
                        _notificationService.ExceptionCaught(ex);
                    }
                }
                ;
            } catch (Exception ex) {
                _notificationService.ExceptionCaught(ex);
            }
            _matchmakerPoolSingleton.Stop();
            return(matches);
        }