def test_oneSubgraph(self):
     playedGames = [
         Game(MatchUp(Team("a", "", 0), Team("b", "", 1))),
         Game(MatchUp(Team("c", "", 2), Team("d", "", 3))),
         Game(MatchUp(Team("e", "", 4), Team("f", "", 5))),
         Game(MatchUp(Team("a", "", 0), Team("c", "", 2))),
         Game(MatchUp(Team("d", "", 3), Team("f", "", 5))),
         Game(MatchUp(Team("e", "", 4), Team("b", "", 1)))
     ]
     futureGames = [
         Game(MatchUp(Team("a", "", 0), Team("f", "", 5))),
         Game(MatchUp(Team("b", "", 1), Team("c", "", 2))),
         Game(MatchUp(Team("d", "", 3), Team("e", "", 4)))
     ]
     teams = [
         Team("a", "", 0),
         Team("b", "", 1),
         Team("c", "", 2),
         Team("d", "", 3),
         Team("e", "", 4),
         Team("f", "", 5)
     ]
     self.assertEqual(
         GraphRating.rateFutureGames(playedGames, futureGames, teams), 0)
     for i in range(0, 10):
         shuffle(playedGames)
         shuffle(futureGames)
         shuffle(teams)
         self.assertEqual(
             GraphRating.rateFutureGames(playedGames, futureGames, teams),
             0)
 def test_calculateTotalError(self):
     currentRanking = [Team("a", "", 0),
                       Team("b", "", 0),
                       Team("c", "", 0),
                       Team("d", "", 0)]
     results = [Game(MatchUp(Team("a", "", 0), Team("b", "", 0)), Result(0, 1, 2), None),
                Game(MatchUp(Team("c", "", 0), Team("d", "", 0)), Result(0, 1, 2), None)]
     mirroredResults = [Game(MatchUp(Team("b", "", 0), Team("a", "", 0)), Result(0, 2, 1), None),
                        Game(MatchUp(Team("d", "", 0), Team("c", "", 0)), Result(0, 2, 1), None)]
     self.assertEqual(RankingGenerator._calculateTotalError(currentRanking, results),
                      RankingGenerator._calculateTotalError(currentRanking, mirroredResults))
    def generateMatchUps(self, debug=False) -> List[Game]:
        """ Generate new matchups for given ranking and played games
        There will be no repetition of already played matchups.
        Under this condition, the matchup w/ minimal distance in the ranking table is sought.
        """
        # start recursive generation of matchups: all teams to distribute, no matchups, no loss yet
        self._genMatchUpRecursive(list(range(0, len(self.teams))), [], 0)
        # convert back to [MatchUp] (w/ str description)
        # select best matchup considering the connection ratings too
        bestFullyConnectedMatchUp = []
        bestWeightedLoss = sys.float_info.max
        for pair in self._bestMatchUpManager.bestMatchUps():
            loss = pair[0]
            goodMatchUpList = pair[1]
            convertedMatchUp = []
            for matchUpInt in goodMatchUpList:
                matchUp = Game(
                    MatchUp(self.ranking[matchUpInt.first],
                            self.ranking[matchUpInt.second]), None, None)
                convertedMatchUp.append(matchUp)
            rating = rateFutureGames(self.playedGames, convertedMatchUp,
                                     self.teams) * loss
            if rating < bestWeightedLoss:
                bestWeightedLoss = rating
                bestFullyConnectedMatchUp = convertedMatchUp

        # debug messages
        if debug:
            for matchUp in bestFullyConnectedMatchUp:
                print(matchUp.matchup.first.name, ":",
                      matchUp.matchup.second.name)
            print("Distance in ranking table: loss=", self.bestLoss)
        assert len(bestFullyConnectedMatchUp) > 0
        return bestFullyConnectedMatchUp
def genResult(game: Game) -> Game:
    # make results a bit more realistic by adding a random offset
    baseOffset = abs(np.random.normal(0, 4))
    baseOffset = min(max(baseOffset, 4), 0)
    paramsA = teamParams[game.matchup.first]
    paramsB = teamParams[game.matchup.second]
    resultA = genOneResult(baseOffset + paramsA[muPos], paramsA[sigmaUpPos],
                           paramsA[sigmaDownPos])
    resultB = genOneResult(baseOffset + paramsB[muPos], paramsB[sigmaUpPos],
                           paramsB[sigmaDownPos])
    game.result = Result(0, round(resultA), round(resultB))
    return game
 def test_twoSubgraphsAndLongNames(self):
     playedGames = [
         Game(MatchUp(Team("awww", "", 0), Team("bxxx", "", 0))),
         Game(MatchUp(Team("cyyy", "", 0), Team("dzzz", "", 0)))
     ]
     futureGames = [
         Game(MatchUp(Team("bxxx", "", 0), Team("cyyy", "", 0))),
         Game(MatchUp(Team("awww", "", 0), Team("dzzz", "", 0)))
     ]
     teams = [
         Team("awww", "", 0),
         Team("bxxx", "", 0),
         Team("cyyy", "", 0),
         Team("dzzz", "", 0)
     ]
     self.assertEqual(
         GraphRating.rateFutureGames(playedGames, futureGames, teams), 0)
     for i in range(0, 5):
         shuffle(playedGames)
         shuffle(futureGames)
         shuffle(teams)
         self.assertEqual(
             GraphRating.rateFutureGames(playedGames, futureGames, teams),
             0)
 def test_insertGame(self):
     print("########## testing inserting next game ############")
     teams = self.instance.getListOfAllTeams(
         divisionId_Swissdraw)  # get a list of teams
     result = Result(-1, 0, 0, 0, 0)  # set a result
     slots = self.instance.getListOfSlotsOfUpcomingRound(
         divisionId_Swissdraw)  # get upcompiung slots
     if len(slots) != 0:
         matchup = MatchUp(
             teams[0], teams[1]
         )  # set up matchups with 2 (random, the first 2) teams from all teams
         game: Game = Game(
             matchup, result, slots[0]
         )  # set up game with matchup, result, and the first slot
         self.instance.insertNextGame(
             game, GameState.COMPLETED, 1
         )  # insert nextgames in debug mode (no real insertion in db). don' use second parameter for productive system
     else:
         print("no available Slots found")
Esempio n. 7
0
def update(forceDBToBeUsed: str = "",
           finalRoundState: RoundState = RoundState.FINAL_PREDICTION):
    api = DataAPI(forceDBToBeUsed=forceDBToBeUsed)

    # check if optimizations need to be done
    stillRoundsToBeOptimized = False
    for division in api.getSwissDrawDivisions():
        if api.getRoundNumberToBeOptimized(division.divisionId) is not None:
            stillRoundsToBeOptimized = True
            break

    # TODO remove this, only a hack for MC19
    for division in api.getSwissDrawDivisions():
        divisionId = division.divisionId
        if api.getRoundNumberToBeOptimized(divisionId) is None:
            teams = api.getListOfAllTeams(divisionId)
            gamesRelevantForRanking = api.getListOfGames(
                gameStates=[GameState.COMPLETED, GameState.RUNNING],
                divisionId=divisionId)
            ranking = generateNewRanking(teams, gamesRelevantForRanking)
            roundNumber = 4
            api.insertRanking(ranking, roundNumber, divisionId)

    #if not stillRoundsToBeOptimized:
    #    return False
    #TODO remove this, only a hack for MC19
    if not stillRoundsToBeOptimized:
        return True

    for division in api.getSwissDrawDivisions():
        divisionId = division.divisionId
        # create ranking
        teams = api.getListOfAllTeams(divisionId)
        gamesRelevantForRanking = api.getListOfGames(
            gameStates=[GameState.COMPLETED, GameState.RUNNING],
            divisionId=divisionId)
        ranking = generateNewRanking(teams, gamesRelevantForRanking)
        roundNumber = api.getRoundNumberToBeOptimized(divisionId)
        if roundNumber is None:
            continue
        api.insertRanking(ranking, roundNumber, divisionId)

        # create matchups
        allGames = api.getListOfGames(gameStates=[
            GameState.COMPLETED, GameState.RUNNING, GameState.NOT_YET_STARTED
        ],
                                      divisionId=divisionId)
        matchUpGenerator = MatchUpGenerator(ranking, allGames)
        futureMatchUps = matchUpGenerator.generateMatchUps(True)

        # schedule games
        futureSlots = []
        for slot in api.getListOfSlotsOfUpcomingRound(divisionId=divisionId):
            futureSlots.append(Game(None, None, slot))
        if len(futureSlots) == 0:
            _setRoundState(roundNumber, divisionId, api, finalRoundState)
            continue

        #TODO do something sensible if there are no games to be scheduled
        scheduler = SwissGameScheduler()
        nextGames = scheduler.maximizeGain(allGames, futureSlots,
                                           futureMatchUps)

        # update games in DB
        gameState = GameState.NOT_YET_STARTED
        api.insertNextGames(nextGames, gameState)

        _setRoundState(roundNumber, divisionId, api, finalRoundState)

    return True
    Team("Caracals", "", 0),
    Team("Drehst'n Deckel", "", 0),
    Team("Airpussies", "", 0),
    Team("Cakes", "", 0),
    Team("RotPot", "", 0),
    Team("Paradisco", "", 0),
]

dataDir = "./testData/fourth_round"
# read results from CSV into list[Result]
results = []
resultsFile = open(join(dataDir, "results.csv"))
resultsCsv = csv.reader(resultsFile, delimiter=';')
for row in resultsCsv:
    results.append(
        Game(MatchUp(Team(row[0], "", 0), Team(row[1], "", 0)),
             Result(0, int(row[2]), int(row[3])), None))
resultsFile.close()

# read previous matches from CSV into list[Match]
previousMatches = []
previousMatchesFile = open(join(dataDir, "previousMatches.csv"))
previousMatchesCsv = csv.reader(previousMatchesFile, delimiter=';')
for row in previousMatchesCsv:
    previousMatches.append(
        Game(MatchUp(Team(row[0], "", 0), Team(row[1], "", 0)), None,
             Slot(hhmmTom(row[2]), hhmmTom(row[3]), int(row[4]), 0, 0)))
previousMatchesFile.close()

# generate current ranking (debug=True)
# XXX currently expensive
t0 = time()
 def test_emptyLists3(self):
     playedGames = [Game()]
     futureGames = [Game()]
     teams = []
     self.assertRaises(Exception, GraphRating.rateFutureGames, playedGames,
                       futureGames, teams)
 def test_threeSubgraphsLarge(self):
     playedGames = [
         # subgraph0
         Game(MatchUp(Team("a", "", 0), Team("b", "", 0))),
         Game(MatchUp(Team("a", "", 0), Team("f", "", 0))),
         Game(MatchUp(Team("b", "", 0), Team("c", "", 0))),
         Game(MatchUp(Team("c", "", 0), Team("d", "", 0))),
         Game(MatchUp(Team("d", "", 0), Team("e", "", 0))),
         Game(MatchUp(Team("e", "", 0), Team("f", "", 0))),
         # subgraph1
         Game(MatchUp(Team("m", "", 0), Team("n", "", 0))),
         Game(MatchUp(Team("m", "", 0), Team("k", "", 0))),
         Game(MatchUp(Team("n", "", 0), Team("l", "", 0))),
         Game(MatchUp(Team("l", "", 0), Team("k", "", 0))),
         # subgraph2
         Game(MatchUp(Team("j", "", 0), Team("g", "", 0))),
         Game(MatchUp(Team("j", "", 0), Team("i", "", 0))),
         Game(MatchUp(Team("g", "", 0), Team("h", "", 0))),
         Game(MatchUp(Team("h", "", 0), Team("i", "", 0)))
     ]
     futureGames = [
         Game(MatchUp(Team("f", "", 0), Team("g", "", 0))),
         Game(MatchUp(Team("m", "", 0), Team("a", "", 0)))
     ]
     teams = [
         "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
         "n"
     ]
     teams = [
         Team("a", "", 0),
         Team("b", "", 0),
         Team("c", "", 0),
         Team("d", "", 0),
         Team("e", "", 0),
         Team("f", "", 0),
         Team("g", "", 0),
         Team("h", "", 0),
         Team("i", "", 0),
         Team("j", "", 0),
         Team("k", "", 0),
         Team("l", "", 0),
         Team("m", "", 0),
         Team("n", "", 0)
     ]
     self.assertAlmostEqual(
         GraphRating.rateFutureGames(playedGames, futureGames, teams),
         0.666666, 5)
     for i in range(0, 10):
         shuffle(playedGames)
         shuffle(futureGames)
         shuffle(teams)
         self.assertAlmostEqual(
             GraphRating.rateFutureGames(playedGames, futureGames, teams),
             0.666666, 5)
def evalFunction(numRounds):
    ranking = [
        Team("a", "", 0),
        Team("b", "", 1),
        Team("c", "", 2),
        Team("d", "", 3),
        Team("e", "", 4),
        Team("f", "", 5),
        Team("g", "", 6),
        Team("h", "", 7),
        Team("i", "", 8),
        Team("j", "", 9),
        Team("k", "", 10),
        Team("l", "", 11),
        Team("m", "", 12),
        Team("n", "", 13),
        Team("o", "", 14),
        Team("p", "", 15),
    ]
    futureSlots = [
        [
            Game(None, None, Slot(0, 35, hall1, 0, 0)),
            Game(None, None, Slot(0, 35, hall2, 1, 0)),
            Game(None, None, Slot(0, 35, hall3, 2, 0)),
            Game(None, None, Slot(40, 75, hall1, 3, 0)),
            Game(None, None, Slot(40, 75, hall2, 4, 0)),
            Game(None, None, Slot(40, 75, hall3, 5, 0)),
            Game(None, None, Slot(80, 115, hall1, 6, 0)),
            Game(None, None, Slot(80, 115, hall2, 7, 0)),
        ],
        [
            Game(None, None, Slot(120, 155, hall1, 8, 1)),
            Game(None, None, Slot(120, 155, hall2, 9, 1)),
            Game(None, None, Slot(120, 155, hall3, 10, 1)),
            Game(None, None, Slot(160, 195, hall1, 11, 1)),
            Game(None, None, Slot(160, 195, hall2, 12, 1)),
            Game(None, None, Slot(160, 195, hall3, 13, 1)),
            Game(None, None, Slot(200, 235, hall1, 14, 1)),
            Game(None, None, Slot(200, 235, hall3, 15, 1)),
        ],
        [
            Game(None, None, Slot(240, 275, hall1, 16, 2)),
            Game(None, None, Slot(240, 275, hall2, 17, 2)),
            Game(None, None, Slot(240, 275, hall3, 18, 2)),
            Game(None, None, Slot(280, 315, hall1, 19, 2)),
            Game(None, None, Slot(280, 315, hall2, 20, 2)),
            Game(None, None, Slot(280, 315, hall3, 21, 2)),
            Game(None, None, Slot(320, 355, hall2, 22, 2)),
            Game(None, None, Slot(320, 355, hall3, 23, 2)),
        ],
        [
            Game(None, None, Slot(360, 395, hall1, 24, 3)),
            Game(None, None, Slot(360, 395, hall2, 25, 3)),
            Game(None, None, Slot(360, 395, hall3, 26, 3)),
            Game(None, None, Slot(400, 435, hall1, 27, 3)),
            Game(None, None, Slot(400, 435, hall2, 28, 3)),
            Game(None, None, Slot(400, 435, hall3, 29, 3)),
            Game(None, None, Slot(440, 475, hall1, 30, 3)),
            Game(None, None, Slot(440, 475, hall2, 31, 3)),
        ],
        [
            Game(None, None, Slot(480, 515, hall1, 32, 4)),
            Game(None, None, Slot(480, 515, hall2, 33, 4)),
            Game(None, None, Slot(480, 515, hall3, 34, 4)),
            Game(None, None, Slot(520, 555, hall1, 35, 4)),
            Game(None, None, Slot(520, 555, hall2, 36, 4)),
            Game(None, None, Slot(520, 555, hall3, 37, 4)),
            Game(None, None, Slot(560, 595, hall1, 38, 4)),
            Game(None, None, Slot(560, 595, hall3, 39, 4)),
        ],
    ]
    results = [
        Game(MatchUp(Team("a", "", 0), Team("b", "", 1)), Result(0, 10, 11),
             Slot(-40, -5, hall1, 0, -1)),
        Game(MatchUp(Team("c", "", 2), Team("d", "", 3)), Result(0, 10, 11),
             Slot(-40, -5, hall2, 0, -1)),
        Game(MatchUp(Team("e", "", 4), Team("f", "", 5)), Result(0, 10, 11),
             Slot(-40, -5, hall3, 0, -1)),
        Game(MatchUp(Team("g", "", 6), Team("h", "", 7)), Result(0, 10, 11),
             Slot(-40, -5, hall1, 0, -1)),
        Game(MatchUp(Team("i", "", 8), Team("j", "", 9)), Result(0, 10, 11),
             Slot(-40, -5, hall2, 0, -1)),
        Game(MatchUp(Team("k", "", 10), Team("l", "", 11)), Result(0, 10, 11),
             Slot(-40, -5, hall3, 0, -1)),
        Game(MatchUp(Team("m", "", 12), Team("n", "", 13)), Result(0, 10, 11),
             Slot(-40, -5, hall1, 0, -1)),
        Game(MatchUp(Team("o", "", 14), Team("p", "", 15)), Result(0, 10, 11),
             Slot(-40, -5, hall2, 0, -1)),
    ]
    rankingLosses = []
    for i in range(0, numRounds):
        # generate matchups
        matchUpGenerator = MatchUpGenerator(ranking, results)
        futureMatchUps = matchUpGenerator.generateMatchUps(False)
        # schedule matchups
        scheduler = SwissGameScheduler()
        returnedGames = scheduler.maximizeGain(results, futureSlots[i],
                                               futureMatchUps)
        # generate results
        for game in returnedGames:
            results.append(genResult(game))
        # generate ranking
        ranking = generateNewRanking(ranking, results, False)
        rankingLosses.append(calculateRankingLoss(expectedRanking, ranking))

    timesPlayedHall3 = [0] * len(expectedRanking)
    for game in results:
        if (game.slot.locationId == hall3):
            timesPlayedHall3[expectedRanking.index(game.matchup.first)] += 1
            timesPlayedHall3[expectedRanking.index(game.matchup.second)] += 1

    return np.array(rankingLosses), np.array(timesPlayedHall3)
    def getListOfGames(self,
                       divisionId: int,
                       gameStates: List[GameState],
                       locationId: int = None) -> List[Game]:

        if divisionId == None or divisionId < 0:
            raise ValueError("divisionId must not be None nor negative")
        if locationId == None:
            locationId = -1
        if len(gameStates) <= 0:
            gameStates = [
                GameState.NOT_YET_STARTED, GameState.COMPLETED,
                GameState.RUNNING
            ]

        games = []
        if self.conn.is_connected():

            gameStateStringList = ""
            for x in range(len(gameStates)):
                if x == 0:
                    gameStateStringList += "%s"
                else:
                    gameStateStringList += ",%s"

            gameStateArgs = ()
            for gameState in gameStates:
                gameStateArgs += (gameState, )

            format_strings = ','.join(['\'%s\''] * len(gameStates))
            query = "SELECT team1.team_name AS team1_name, team1.team_acronym AS team1_acronym, team1.team_id AS team1_id,  team1.team_seed AS team1_seed, "\
                    "team2.team_name AS team2_name, team2.team_acronym AS team2_acronym, team2.team_id AS team2_id, team2.team_seed AS team2_seed, "\
                    "matchup.matchup_id AS matchup_id, matchup.matchup_team1_timeouts AS team1_timeouts, "\
                    "matchup.matchup_team1_score AS team1_score, matchup.matchup_team2_timeouts AS team2_timeouts, "\
                    "matchup.matchup_team2_score AS team2_score, slot.slot_id AS slot_id, "\
                    "slot.slot_start AS slot_start, slot.slot_end AS slot_end, slot.location_id AS location_id, "\
                    "round.round_number AS round_number, game.game_id AS game_id "\
                    "FROM game "\
                    "INNER JOIN matchup ON game.matchup_id = matchup.matchup_id "\
                    "INNER JOIN team AS team1 ON matchup.matchup_team1_id = team1.team_id "\
                    "INNER JOIN team AS team2 ON matchup.matchup_team2_id = team2.team_id "\
                    "INNER JOIN slot ON game.slot_id = slot.slot_id "\
                    "INNER JOIN round ON slot.round_id = round.round_id "\
                    "WHERE game.game_state IN ("+gameStateStringList+") "\
                    "AND round.division_id = %s"

            args = gameStateArgs + (divisionId, )
            #print(query)

            if locationId >= 0:
                query += " AND slot.location_id = %s"
                args += (locationId, )

            try:
                cursor = self.conn.cursor(dictionary=True)
                cursor.execute(query, args)
                row = cursor.fetchone()
                while row is not None:
                    #print(row)
                    team1 = Team(row["team1_name"], row["team1_acronym"],
                                 row["team1_id"], row["team1_seed"])
                    team2 = Team(row["team2_name"], row["team2_acronym"],
                                 row["team2_id"], row["team2_seed"])
                    matchup = MatchUp(team1, team2, row["matchup_id"])
                    slot = Slot(row["slot_start"], row["slot_end"],
                                row["location_id"], row["slot_id"],
                                row["round_number"])
                    result = Result(row["matchup_id"], row["team1_score"],
                                    row["team2_score"], row["team1_timeouts"],
                                    row["team2_timeouts"])
                    game = Game(matchup, result, slot, row["game_id"])
                    games.append(game)
                    row = cursor.fetchone()

            except Error as e:
                print(e)

            finally:
                cursor.close()
        else:
            raise NoDatabaseConnection()

        return games