Example #1
0
def test_deprecated_individual_rating_groups():
    r1, r2, r3 = Rating(50, 1), Rating(10, 5), Rating(15, 5)
    with raises(TypeError):
        deprecated_call(rate, [r1, r2, r3])
    with raises(TypeError):
        deprecated_call(quality, [r1, r2, r3])
    assert t.transform_ratings([r1, r2, r3]) == rate([(r1,), (r2,), (r3,)])
    assert t.match_quality([r1, r2, r3]) == quality([(r1,), (r2,), (r3,)])
    deprecated_call(t.transform_ratings, [r1, r2, r3])
    deprecated_call(t.match_quality, [r1, r2, r3])
Example #2
0
def test_deprecated_individual_rating_groups():
    r1, r2, r3 = Rating(50, 1), Rating(10, 5), Rating(15, 5)
    with raises(TypeError):
        deprecated_call(rate, [r1, r2, r3])
    with raises(TypeError):
        deprecated_call(quality, [r1, r2, r3])
    assert t.transform_ratings([r1, r2, r3]) == rate([(r1, ), (r2, ), (r3, )])
    assert t.match_quality([r1, r2, r3]) == quality([(r1, ), (r2, ), (r3, )])
    deprecated_call(t.transform_ratings, [r1, r2, r3])
    deprecated_call(t.match_quality, [r1, r2, r3])
Example #3
0
	def Update(self,ladder_id,match,db):
		#print 'match id %d'%match.id
		scores, result_dict = calculateWinnerOrder(match,db)
		session = db.session()

		teams = defaultdict(tuple)
		player_id_map = defaultdict(list)
		def constant_factory(value):
			import itertools
			return itertools.repeat(value).next
		minteam_score = defaultdict(constant_factory(100000))
		for name,result in result_dict.iteritems():
			score = scores[name] * -1
			player_id = session.query( Player ).filter( Player.nick == name ).first().id
			rank = session.query( TrueskillRanks ).filter( TrueskillRanks.ladder_id == ladder_id ).filter( TrueskillRanks.player_id == player_id ).first()
			if not rank:
				rank = TrueskillRanks()
				rank.ladder_id = ladder_id
				rank.player_id = player_id
			session.add(rank)

			rank.rank = score
			l = list(teams[result.team])
			l.append(rank.rating)
			teams[result.team] = tuple(l)
			player_id_map[result.team].append(player_id)
			minteam_score[result.team] = min(minteam_score[result.team],score)
		session.commit()

		ordered_teams = []
		ordered_minteam_score = []
		team_ids = teams.keys()
		team_ids.sort()
		for i in range(len(teams)):
			ordered_teams.append(teams[team_ids[i]])
			ordered_minteam_score.append(minteam_score[team_ids[i]])
		i = 0
		if len(ordered_teams) < 2:
			Log.error('less than 2 teams, cannot update ranking')
			raise Exception('not enough teams')
		for team_ratings in trueskill.transform_ratings(ordered_teams,ordered_minteam_score):
			j = 0
			current_team = team_ids[i]
			q = session.query( TrueskillRanks ).filter( TrueskillRanks.ladder_id == ladder_id )
			for rating in team_ratings:
				pids = player_id_map[current_team]
				pid = pids[j]
				rank = q.filter( TrueskillRanks.player_id == pid ).one()
				rank.rating = rating
				session.add( rank )
				j += 1
			i += 1
		session.commit()
		session.close()
def create_match(session, user1, user2, timestamp, games):
    """Creates and adds a match to the session given two users a unix timestamp and a list of score pairs."""
    match = Match(timestamp, int(time.time()))
    
    p1 = Participation()
    user1.participations.append(p1)
    match.participations.append(p1)
    
    p2 = Participation()
    user2.participations.append(p2)
    match.participations.append(p2)
    
    p1_wins = len(filter(lambda g: g[0] > g[1], games))
    p2_wins = len(filter(lambda g: g[0] < g[1], games))
    
    u1ratings = get_most_recent_ratings(user1.id)
    u2ratings = get_most_recent_ratings(user2.id)
    u1ratings.pop('exposure')
    u2ratings.pop('exposure')
    
    p1rating = trueskill.Rating(**u1ratings)
    p2rating = trueskill.Rating(**u2ratings)
    
    if p1_wins > p2_wins:
        ranks = [0, 1]
    else:
        ranks = [1, 0]
    
    new_ratings = trueskill.transform_ratings([(p1rating,), (p2rating,)], ranks=ranks)
    (p1rating,), (p2rating,) = new_ratings
    
    true_skill_rating1 = TrueSkillCache(p1rating.sigma, p1rating.mu, p1rating.exposure)
    match.true_skill_ratings.append(true_skill_rating1)
    user1.true_skill_ratings.append(true_skill_rating1)
    
    true_skill_rating2 = TrueSkillCache(p2rating.sigma, p2rating.mu, p2rating.exposure)
    match.true_skill_ratings.append(true_skill_rating2)
    user2.true_skill_ratings.append(true_skill_rating2)
    
    for game_scores in games:
        game = Game(match)
        
        s1 = Score(game_scores[0])
        game.scores.append(s1)
        user1.scores.append(s1)
        
        s2 = Score(game_scores[1])
        game.scores.append(s2)
        user2.scores.append(s2)
        
        match.games.append(game)
        
    session.add(match)
Example #5
0
def test_6_players_no_draws():
    r1 = trueskill.Rating()
    r2 = trueskill.Rating()
    r3 = trueskill.Rating()
    r4 = trueskill.Rating()
    r5 = trueskill.Rating()
    r6 = trueskill.Rating()
    sigma0 = r1.sigma
    [(r1, ), (r2, ), (r3, ), (r4, ), (r5, ), (r6, )] = \
        trueskill.transform_ratings([(r1, ), (r2, ), (r3, ), (r4, ), (r5, ),
                                     (r6, )])
    assert r1.mu > r2.mu > r3.mu > r4.mu > r5.mu > r6.mu
    for rating in [r1, r2, r3, r4, r5, r6]:
        assert rating.sigma < sigma0
Example #6
0
def test_3_player_draw():
    r1 = trueskill.Rating()
    r2 = trueskill.Rating()
    r3 = trueskill.Rating()
    sigma0 = r1.sigma
    [(r1, ), (r2, ), (r3, )] = trueskill.transform_ratings([(r1, ), (r2, ),
                                                            (r3, )],
                                                           ranks=(1, 1, 3))
    # We would hope it would be zero, but trueskill isn't that accurate.
    assert abs(r1.mu - r2.mu) < 0.01
    assert r1.mu > r3.mu
    assert r2.mu > r3.mu
    for rating in [r1, r2, r3]:
        assert rating.sigma < sigma0
Example #7
0
def test_6_players_no_draws():
    r1 = trueskill.Rating()
    r2 = trueskill.Rating()
    r3 = trueskill.Rating()
    r4 = trueskill.Rating()
    r5 = trueskill.Rating()
    r6 = trueskill.Rating()
    sigma0 = r1.sigma
    [(r1, ), (r2, ), (r3, ), (r4, ), (r5, ), (r6, )] = \
        trueskill.transform_ratings([(r1, ), (r2, ), (r3, ), (r4, ), (r5, ),
                                     (r6, )])
    assert r1.mu > r2.mu > r3.mu > r4.mu > r5.mu > r6.mu
    for rating in [r1, r2, r3, r4, r5, r6]:
        assert rating.sigma < sigma0
Example #8
0
def test_3_player_draw():
    r1 = trueskill.Rating()
    r2 = trueskill.Rating()
    r3 = trueskill.Rating()
    sigma0 = r1.sigma
    [(r1, ), (r2, ), (r3, )] = trueskill.transform_ratings([(r1, ),
                                                            (r2, ),
                                                            (r3, )],
                                                           ranks=(1, 1, 3))
    # We would hope it would be zero, but trueskill isn't that accurate.
    assert abs(r1.mu - r2.mu) < 0.01
    assert r1.mu > r3.mu
    assert r2.mu > r3.mu
    for rating in [r1, r2, r3]:
        assert rating.sigma < sigma0
Example #9
0
    def process(self, line):
        """Process a line denoting one match, and update the ratings."""
        line = line.strip()
        if not line or line.startswith("#"):
            return
        parts = line.split(",")
        assert len(parts) >= 2
        winners = [parts[0]]
        losers = parts[1:]
        winner_lists = explode(winners)
        loser_lists = explode(losers)

        for winner_list in winner_lists:
            for winner in winner_list:
                self.wins[winner] += 1
        for loser_list in loser_lists:
            for loser in loser_list:
                self.losses[loser] += 1

        # Fetch old ratings for combatants
        all_ratings = []
        for team in winner_lists + loser_lists:
            team_ratings = []
            for name in team:
                team_ratings.append(self.ratings[name])
            team_ratings = tuple(team_ratings)
            all_ratings.append(team_ratings)

        # Calculate new ratings for combatants
        new_ratings = trueskill.transform_ratings(all_ratings)

        # Store new ratings for combatants
        for ii, team in enumerate(winner_lists + loser_lists):
            new_team_ratings = new_ratings[ii]
            for jj, name in enumerate(team):
                self.ratings[name] = new_team_ratings[jj]
Example #10
0
    def save_game(self, game):
        """Save a finished Game to the results database.

        XXX This involves a non-trivial amount of computation and I/O, so
        maybe it should be run from a thread to avoid blocking the reactor.
        But sqlite is not thread-safe so we can't reuse connections.
        """
        logging.info("")
        with self.connection:
            cursor = self.connection.cursor()
            for player in game.players:
                logging.info("%s %s", player.player_class, player.player_info)

                # See if that player is already in the database
                query = """SELECT player_id FROM player
                           where name = ? AND class = ?"""
                cursor.execute(query, (player.name, player.player_class))
                row = cursor.fetchone()
                # If not, insert it.
                if row is None:
                    query = """INSERT INTO player
                               (name, class, info, mu, sigma)
                               VALUES (?, ?, ?, ?, ?)"""
                    cursor.execute(
                        query, (player.name, player.player_class, player.player_info, DEFAULT_MU, DEFAULT_SIGMA)
                    )
                    # And fetch the player_id.
                    query = """SELECT player_id FROM player
                               where class = ? AND info = ?"""
                    cursor.execute(query, (player.player_class, player.player_info))
                    row = cursor.fetchone()
                else:
                    player_id = row["player_id"]
                    # We may need to update info, if new fields were added.
                    query = """UPDATE player SET info = ?
                               where player_id = ?"""
                    cursor.execute(query, (player.player_info, player_id))

                player_id = row["player_id"]

            # Add the game.
            query = """INSERT INTO game (name, start_time, finish_time)
                       VALUES (?, ?, ?)"""
            cursor.execute(query, (game.name, int(game.start_time), int(game.finish_time)))
            # Find the game_id for the just-inserted game.
            query = """SELECT game_id FROM game WHERE
                       name = ? AND start_time = ? AND finish_time = ?"""
            cursor.execute(query, (game.name, int(game.start_time), int(game.finish_time)))
            row = cursor.fetchone()
            game_id = row["game_id"]
            rank = 1
            for tup in game.finish_order:
                for player in tup:
                    # Find the player_id
                    query = """SELECT player_id FROM player
                               WHERE name = ? AND class = ? AND info = ?"""
                    cursor.execute(query, (player.name, player.player_class, player.player_info))
                    row = cursor.fetchone()
                    player_id = row["player_id"]
                    # Add to rank.
                    query = """INSERT INTO rank(player_id, game_id, rank)
                               VALUES (?, ?, ?)"""
                    cursor.execute(query, (player_id, game_id, rank))
                rank += len(tup)

            # Update trueskill values
            # There is a slight bias when there are ties, so we process tied
            # players in random order.
            query = """SELECT p.player_id, p.mu, p.sigma, r.rank
                       FROM player p, rank r
                       WHERE p.player_id = r.player_id AND r.game_id = ?
                       ORDER BY r.rank, RANDOM()"""
            cursor.execute(query, (game_id,))
            rows = cursor.fetchall()
            player_ids = []
            rating_tuples = []
            ranks = []
            for row in rows:
                player_id = row["player_id"]
                player_ids.append(player_id)
                rank = row["rank"]
                ranks.append(rank)
                mu = row["mu"]
                sigma = row["sigma"]
                rating = trueskill.Rating(mu=mu, sigma=sigma)
                rating_tuples.append((rating,))
            rating_tuples2 = trueskill.transform_ratings(rating_tuples, ranks)
            while player_ids:
                player_id = player_ids.pop()
                rating = rating_tuples2.pop()[0]
                mu = rating.mu
                sigma = rating.sigma
                query = """UPDATE player set mu = ?, sigma = ?
                           WHERE player_id = ?"""
                cursor.execute(query, (mu, sigma, player_id))
        logging.info("")
Example #11
0
    def save_game(self, game):
        """Save a finished Game to the results database.

        XXX This involves a non-trivial amount of computation and I/O, so
        maybe it should be run from a thread to avoid blocking the reactor.
        But sqlite is not thread-safe so we can't reuse connections.
        """
        logging.info("")
        with self.connection:
            cursor = self.connection.cursor()
            for player in game.players:
                logging.info("%s %s", player.player_class, player.player_info)

                # See if that player is already in the database
                query = """SELECT player_id FROM player
                           where name = ? AND class = ?"""
                cursor.execute(query, (player.name, player.player_class))
                row = cursor.fetchone()
                # If not, insert it.
                if row is None:
                    query = """INSERT INTO player
                               (name, class, info, mu, sigma)
                               VALUES (?, ?, ?, ?, ?)"""
                    cursor.execute(
                        query, (player.name, player.player_class,
                                player.player_info, DEFAULT_MU, DEFAULT_SIGMA))
                    # And fetch the player_id.
                    query = """SELECT player_id FROM player
                               where class = ? AND info = ?"""
                    cursor.execute(query,
                                   (player.player_class, player.player_info))
                    row = cursor.fetchone()
                else:
                    player_id = row["player_id"]
                    # We may need to update info, if new fields were added.
                    query = """UPDATE player SET info = ?
                               where player_id = ?"""
                    cursor.execute(query, (player.player_info, player_id))

                player_id = row["player_id"]

            # Add the game.
            query = """INSERT INTO game (name, start_time, finish_time)
                       VALUES (?, ?, ?)"""
            cursor.execute(
                query,
                (game.name, int(game.start_time), int(game.finish_time)))
            # Find the game_id for the just-inserted game.
            query = """SELECT game_id FROM game WHERE
                       name = ? AND start_time = ? AND finish_time = ?"""
            cursor.execute(
                query,
                (game.name, int(game.start_time), int(game.finish_time)))
            row = cursor.fetchone()
            game_id = row["game_id"]
            rank = 1
            for tup in game.finish_order:
                for player in tup:
                    # Find the player_id
                    query = """SELECT player_id FROM player
                               WHERE name = ? AND class = ? AND info = ?"""
                    cursor.execute(
                        query,
                        (player.name, player.player_class, player.player_info))
                    row = cursor.fetchone()
                    player_id = row["player_id"]
                    # Add to rank.
                    query = """INSERT INTO rank(player_id, game_id, rank)
                               VALUES (?, ?, ?)"""
                    cursor.execute(query, (player_id, game_id, rank))
                rank += len(tup)

            # Update trueskill values
            # There is a slight bias when there are ties, so we process tied
            # players in random order.
            query = """SELECT p.player_id, p.mu, p.sigma, r.rank
                       FROM player p, rank r
                       WHERE p.player_id = r.player_id AND r.game_id = ?
                       ORDER BY r.rank, RANDOM()"""
            cursor.execute(query, (game_id, ))
            rows = cursor.fetchall()
            player_ids = []
            rating_tuples = []
            ranks = []
            for row in rows:
                player_id = row["player_id"]
                player_ids.append(player_id)
                rank = row["rank"]
                ranks.append(rank)
                mu = row["mu"]
                sigma = row["sigma"]
                rating = trueskill.Rating(mu=mu, sigma=sigma)
                rating_tuples.append((rating, ))
            rating_tuples2 = trueskill.transform_ratings(rating_tuples, ranks)
            while player_ids:
                player_id = player_ids.pop()
                rating = rating_tuples2.pop()[0]
                mu = rating.mu
                sigma = rating.sigma
                query = """UPDATE player set mu = ?, sigma = ?
                           WHERE player_id = ?"""
                cursor.execute(query, (mu, sigma, player_id))
        logging.info("")