def get_new_ratings(players, teams): """ Affect new ratings to players from teams results """ nb_players_team0 = len(teams[0]) nb_players_team1 = len(teams[1]) winner = players[teams[0][0]] loser = players[teams[1][0]] if nb_players_team0 == 1 and nb_players_team1 == 1: new_r1, new_r3 = rate_1vs1(winner,loser) elif nb_players_team0 == 1 and nb_players_team1 > 1: team_loser = [loser, players[teams[1][1]]] (new_r1), (new_r3, new_r4) = rate([winner, team_loser], ranks=[0, 1]) elif nb_players_team0 > 1 and nb_players_team1 == 1: team_winner = [winner, players[teams[0][1]]] (new_r1, new_r2), (new_r3) = rate([team_winner, loser], ranks=[0, 1]) else: team_loser = [loser, players[teams[1][1]]] team_winner = [winner, players[teams[0][1]]] (new_r1, new_r2), (new_r3, new_r4) = rate([team_winner, team_loser], ranks=[0, 1]) player1 = {'name': teams[0][0], 'mu': new_r1.mu, 'sigma': new_r1.sigma} player3 = {'name': teams[1][0], 'mu': new_r3.mu, 'sigma': new_r3.sigma} if nb_players_team0 > 1: player2 = {'name': teams[0][1], 'mu': new_r2.mu, 'sigma': new_r2.sigma} if nb_players_team1 > 1: player4 = {'name': teams[1][1], 'mu': new_r4.mu, 'sigma': new_r4.sigma} if nb_players_team0 > 1: return [player1, player2, player3, player4] return [player1, player2, player4] return [player1, player3]
def update_trueskill(self): """ Updates the game’s participants TrueSkill values based on the game result. """ import trueskill session = object_session(self) # participant.trueskill represents pre-game values # p.player.ratings[p.role] is the PlayerRating relevant to the game that was scored team_ratings = { team: { p.player.ratings[p.role]: trueskill.Rating(p.trueskill_mu, p.trueskill_sigma) for p in self.participants.values() if p.team == team } for team in ["blue", "red"] } if self.winner == "blue": new_ratings = trueskill.rate( [team_ratings["blue"], team_ratings["red"]]) else: new_ratings = trueskill.rate( [team_ratings["red"], team_ratings["blue"]]) for team in new_ratings: for player_rating in team: player_rating.trueskill_mu = team[player_rating].mu player_rating.trueskill_sigma = team[player_rating].sigma session.add(player_rating) session.commit()
def form_valid(self, form): from trueskill import Rating, rate match = form.save(commit=False) histories = [] if match.score_team2 > match.score_team1: # put winning team first (match.score_team1, match.team1_player1, match.team1_player2, match.score_team2, match.team2_player1, match.team2_player2) = \ (match.score_team2, match.team2_player1, match.team2_player2, match.score_team1, match.team1_player1, match.team1_player2) player_list = (match.team1_player1, match.team1_player2, match.team2_player1, match.team2_player2) ratings = [Rating(mu=p.mu, sigma=p.sigma) for p in player_list] seperate_ratings = [ (Rating(mu=a.attacker_mu, sigma=a.attacker_sigma), Rating(mu=d.defender_mu, sigma=d.defender_sigma)) for a, d in [player_list[0:2], player_list[2:4]] ] ranks = [match.score_team2 > match.score_team1, match.score_team2 < match.score_team1] new_ratings = rate([ratings[0:2], ratings[2:4]], ranks=ranks) new_ratings = new_ratings[0] + new_ratings[1] new_seperate_ratings = rate(seperate_ratings, ranks=ranks) new_seperate_ratings = \ new_seperate_ratings[0] + new_seperate_ratings[1] match.save() for i in range(len(player_list)): p = player_list[i] s = new_seperate_ratings[i] p.mu = new_ratings[i].mu p.sigma = new_ratings[i].sigma p.rank = p.mu - 3 * p.sigma h = PlayerHistory(match=match, player=p, mu=p.mu, sigma=p.sigma, rank=p.rank, seperate_mu=s.mu, seperate_sigma=s.sigma, seperate_rank=(s.mu - 3 * s.sigma)) if not i % 2: h.was_attacker = True p.attacker_mu = s.mu p.attacker_sigma = s.sigma p.attacker_rank = s.mu - 3 * s.sigma else: h.was_attacker = False p.defender_mu = s.mu p.defender_sigma = s.sigma p.defender_rank = s.mu - 3 * s.sigma p.save() p.old_mu = ratings[i].mu p.old_sigma = ratings[i].sigma p.old_rank = p.old_mu - 3 * p.old_sigma histories.append(h) PlayerHistory.objects.bulk_create(histories) context = { 'match': match, 'player_list': player_list, 'ratings': ratings, } return render(self.request, 'league/match_enter_success.html', context)
def update_trueskill(game: Game, session): """ Updates the player’s rating based on the game’s result """ blue_team_ratings = { participant.player.ratings[participant.role]: trueskill.Rating(mu=participant.trueskill_mu, sigma=participant.trueskill_sigma) for participant in game.teams.BLUE } red_team_ratings = { participant.player.ratings[participant.role]: trueskill.Rating(mu=participant.trueskill_mu, sigma=participant.trueskill_sigma) for participant in game.teams.RED } if game.winner == "BLUE": new_ratings = trueskill.rate([blue_team_ratings, red_team_ratings]) else: new_ratings = trueskill.rate([red_team_ratings, blue_team_ratings]) for ratings in new_ratings: for player_rating in ratings: # This is the PlayerRating object player_rating.trueskill_mu = ratings[player_rating].mu player_rating.trueskill_sigma = ratings[player_rating].sigma session.merge(player_rating)
def calculate_doubles_ratings(game_df, rating_object=Rating(), return_type='dataframe'): for col in game_df.columns: if 'player' in col: game_df[col] = game_df[col].apply(remove_whitespace) all_players = set( list(game_df.player_a_team_a.unique()) + list(game_df.player_b_team_a.unique()) + list(game_df.player_a_team_b.unique()) + list(game_df.player_b_team_b.unique())) ratings = {k: rating_object for k in all_players} for row in game_df.iterrows(): player_a_team_a = ratings[row[1]['player_a_team_a']] player_b_team_a = ratings[row[1]['player_b_team_a']] player_a_team_b = ratings[row[1]['player_a_team_b']] player_b_team_b = ratings[row[1]['player_b_team_b']] t_a = player_a_team_a, player_b_team_a t_b = player_a_team_b, player_b_team_b if row[1]['score_team_a'] > row[1]['score_team_b']: t_a, t_b = rate([t_a, t_b], ranks=[0, 1]) elif row[1]['score_team_a'] < row[1]['score_team_b']: t_a, t_b = rate([t_a, t_b], ranks=[1, 0]) else: t_a, t_b = rate([t_a, t_b], ranks=[0, 0]) player_a_team_a, player_b_team_a = t_a player_a_team_b, player_b_team_b = t_b ratings[row[1]['player_a_team_a']] = player_a_team_a ratings[row[1]['player_b_team_a']] = player_b_team_a ratings[row[1]['player_a_team_b']] = player_a_team_b ratings[row[1]['player_b_team_b']] = player_b_team_b if return_type == 'dict': return ratings elif return_type == 'dataframe': rating_df = pd.DataFrame() for k, v in ratings.iteritems(): rating_df.loc[k, 'rating'] = v.mu rating_df.loc[k, 'sigma'] = v.sigma rating_df.loc[k, 'tau'] = v.tau rating_df.loc[k, 'pi'] = v.pi rating_df.loc[k, 'trueskill'] = v.exposure rating_df.reset_index(inplace=True) return rating_df
def test_compatibility_with_another_rating_systems(): """All rating system modules should implement ``rate_1vs1`` and ``quality_1vs1`` to provide shortcuts for 1 vs 1 simple competition games. """ r1, r2 = Rating(30, 3), Rating(20, 2) assert quality_1vs1(r1, r2) == quality([(r1,), (r2,)]) rated = rate([(r1,), (r2,)]) assert rate_1vs1(r1, r2) == (rated[0][0], rated[1][0]) rated = rate([(r1,), (r2,)], [0, 0]) assert rate_1vs1(r1, r2, drawn=True) == (rated[0][0], rated[1][0])
def test_compatibility_with_another_rating_systems(): """All rating system modules should implement ``rate_1vs1`` and ``quality_1vs1`` to provide shortcuts for 1 vs 1 simple competition games. """ r1, r2 = Rating(30, 3), Rating(20, 2) assert quality_1vs1(r1, r2) == quality([(r1, ), (r2, )]) rated = rate([(r1, ), (r2, )]) assert rate_1vs1(r1, r2) == (rated[0][0], rated[1][0]) rated = rate([(r1, ), (r2, )], [0, 0]) assert rate_1vs1(r1, r2, drawn=True) == (rated[0][0], rated[1][0])
def handle_match_elo(match: Match) -> None: global matches_added, verbose print("Handling match", match.key) match_alliances = match.alliances.all() print("\tDetermining Alliance and Team Winners...") drawn = False if match.winner is None: drawn = True ally_winner = match_alliances[0] team_winners = ally_winner.teams.all() else: ally_winner = match.winner team_winners = ally_winner.teams.all() print("\tSelecting losing alliance...") ally_loser = next(x for x in match_alliances if x.id != match.winner_id) team_losers = ally_loser.teams.all() print("\tRunning Alliance TrueSkill calculations...") ally_winner_ts = Rating(ally_winner.elo_mu, ally_winner.elo_sigma) ally_loser_ts = Rating(ally_loser.elo_mu, ally_loser.elo_sigma) (ally_winner_result, ally_loser_result) = rate_1vs1(ally_winner_ts, ally_loser_ts, drawn=drawn) ally_winner.elo_mu = ally_winner_result.mu ally_winner.elo_sigma = ally_winner_result.sigma ally_loser.elo_mu = ally_loser_result.mu ally_loser.elo_sigma = ally_loser_result.sigma team_winner_ts_pairs = [(t, Rating(t.elo_mu, t.elo_sigma)) for t in team_winners] team_loser_ts_pairs = [(t, Rating(t.elo_mu, t.elo_sigma)) for t in team_losers] print("\tRunning Team TrueSkill calculations...") if drawn: team_results = rate([[x[1] for x in team_winner_ts_pairs], [x[1] for x in team_loser_ts_pairs]], ranks=[0, 0]) else: team_results = rate([[x[1] for x in team_winner_ts_pairs], [x[1] for x in team_loser_ts_pairs]]) print("\tUpdating team mu and sigma...") result_and_teams = zip(team_results[0], team_winners, team_results[1], team_losers) for winner_result, winner_team, loser_result, loser_team in result_and_teams: winner_team.elo_mu = winner_result.mu winner_team.elo_sigma = winner_result.sigma loser_team.elo_mu = loser_result.mu loser_team.elo_sigma = loser_result.sigma print("\tSaving...") ally_winner.save(update_fields=['elo_mu', 'elo_sigma']) ally_loser.save(update_fields=['elo_mu', 'elo_sigma']) Team.objects.bulk_update([*team_winners, *team_losers], update_fields=['elo_mu', 'elo_sigma']) print("Done!") matches_added += 1
def main(): a, b = Rating(25), Rating(30) c = Rating() d = Rating() for i in range(9): t1 = [a, b] t2 = [c, d] (a, b), (c, d) = rate([t1, t2], ranks=[0, 1]) print(a) (a, b), (c, d) = rate([t1, t2], ranks=[1, 0]) print(a)
def eval_match(team1, team2, score1, score2): # Update players in dictionary for player in team1: if player not in p: p[player] = Player(player) for player in team2: if player not in p: p[player] = Player(player) global m m += 1 # Update elos s = 0.5 if score1 > score2: s = 1 elif score1 < score2: s = 0 global matches matches.append((team1, team2, s)) # game counter for player in team1: p[player].add_game(s, score1) for player in team2: p[player].add_game(1 - s, score2) t1 = [p[x].last_rating(ELO_MODEL) for x in team1] t2 = [p[x].last_rating(ELO_MODEL) for x in team2] t1_new, t2_new = elo.rate_match(t1, t2, s, 1 - s) for player in team1: p[player].add_rating(ELO_MODEL, t1_new.pop(0), m) for player in team2: p[player].add_rating(ELO_MODEL, t2_new.pop(0), m) # Update trueskills ranks = [0.5, 0.5] if score1 > score2: ranks = [0, 1] elif score1 < score2: ranks = [1, 0] t1 = [p[x].last_rating(TRUESKILL_MODEL) for x in team1] t2 = [p[x].last_rating(TRUESKILL_MODEL) for x in team2] t1_new, t2_new = ts.rate([t1, t2], ranks=ranks) t1_new = list(t1_new) t2_new = list(t2_new) for player in team1: p[player].add_rating(TRUESKILL_MODEL, t1_new.pop(0), m) for player in team2: p[player].add_rating(TRUESKILL_MODEL, t2_new.pop(0), m)
def RatingRecount(): player_ratings = {p: Rating() for p in Player.objects.all()} team_ratings = {t: Rating() for t in Team.objects.all()} print "#"*60 print "RECOUNTING #"*4 print "#"*60 for match in Match.objects.order_by("id"): # Get ratings for players winners = {p: player_ratings[p] for p in match.winner.players.all()} losers = {p: player_ratings[p] for p in match.loser.players.all()} # Score the match new_team_ratings = rate([winners, losers]) # Returns a list with a one or many dicts for team in new_team_ratings: for player, new_rating in team.iteritems(): player_ratings[player] = new_rating # save to database # Team ranking team_ratings[match.winner], team_ratings[match.loser] = rate_1vs1(team_ratings[match.winner], team_ratings[match.loser]) for player, rating in player_ratings.iteritems(): print player, " - ", rating.mu player.mu = rating.mu player.sigma = rating.sigma player.save() for team, rating in team_ratings.iteritems(): print team, " - ", rating.mu, team.mu
def getAdjList_Similarity3(self, QuestionList): from trueskill import Rating, rate AdjList = [] ext = '' margin = 4 trainPairs = self.trainPairs # compute trueSkill value RatingDict = dict() for i in trainPairs["Aer"].drop_duplicates().values.tolist(): RatingDict[i] = (Rating(), ) step1 = trainPairs.groupby(["Qid"]) for i, j in step1: if int(i) in QuestionList: IdList = j["Aer"].values.tolist() rating = j["Credible"].apply( lambda x: 1 - int(x)).values.tolist() for i, j in zip( IdList, rate([RatingDict[x] for x in IdList], ranks=rating)): RatingDict[i] = j trainPairs["Rating"] = trainPairs["Aer"] trainPairs["Rating"] = trainPairs["Rating"].apply( lambda x: RatingDict[x][0].mu - 3 * RatingDict[x][0].sigma) trainPairs["Link"] = [0 for i in range(len(trainPairs))] self.Rating = trainPairs[["PairId", "Rating"]] # create clique using trueSkill value step2 = trainPairs.groupby(["Qid"]) idxList1 = [] idxList2 = [] for i, j in step2: tempScore = sorted(j["Rating"].values.tolist()) if tempScore[-1] - tempScore[-2] >= margin: idxList1.append(j["Rating"].idxmax()) if tempScore[1] - tempScore[0] >= margin / 2: idxList2.append(j["Rating"].idxmin()) trainPairs.loc[idxList1, "Link"] = 1 trainPairs.loc[idxList2, "Link"] = 2 trainPairs["Credible"] = trainPairs["Credible"].apply(lambda x: int(x)) step3 = trainPairs[trainPairs["Link"].isin([1, 2])].groupby( ["Aer", "Link"]) for i, j in step3: if len(j) >= 2: for i in combinations(j["PairId"].tolist(), 2): AdjList.append(i) #exit() AdjList = pd.DataFrame(data=AdjList, columns=["Nid1", "Nid2"]) AdjList = AdjList.drop_duplicates() #AdjList = AdjList.sample(500) print "similarity3:", len(AdjList) edges = AdjList.sort_values(by=["Nid1", "Nid2"], ascending=True).values with open(self.rootFolder + "/" + 'edges_' + 'line' + '.pkl', 'w') as f: pickle.dump(edges, f) return edges
def rate_outcome(race, runners, results, cache): """do rating from results, not finishingPosition (it is also 0 for non-placed)""" parts = [r for r in runners if r['has_odds']] logger.debug('{} participants'.format(len(parts))) team = [(Rating(p['rating_mu'], p['rating_sigma']), ) for p in parts] logger.debug('team = {}'.format(team)) for p in parts: p['pos'] = 5 for i, result in enumerate(results): for n in result: for p in parts: if p['runnerNumber'] == n: logger.debug( 'outcome found: n {} and p {} at rank {}'.format( n, p['runnerNumber'], i + 1)) p['pos'] = i + 1 break pos = [p['pos'] for p in parts] try: new_ratings = rate(team, pos) logger.debug('new ratings {}'.format(new_ratings)) except: logger.info(team) logger.info(pos) raise save_players(race, parts, new_ratings, cache)
def skill_commit_match_result(party_1, party_2, match_1_result): """ Adjust team's elo based on result - Saves Player Models Returns delta in ELO """ party_1_skill = skill_build_party_rating(party_1) party_2_skill = skill_build_party_rating(party_2) party_rosters = [party_1.players.all(), party_2.players.all()] result_arr = [0, 1] if match_1_result else [1, 0] result = rate([party_1_skill, party_2_skill], ranks=result_arr) p_idx = 0 t_idx = 0 elo_deltas = [ abs(result[0][0].mu - party_rosters[0][0].elo), abs(result[1][0].mu - party_rosters[1][0].elo) ] for roster in party_rosters: for player in roster: print("%s -> %s" % ( int(player.elo), int(result[t_idx][p_idx].mu), )) player.elo = int(result[t_idx][p_idx].mu) player.elo_weight = float(result[t_idx][p_idx].sigma) player.save() p_idx += 1 t_idx += 1 # Increase team index p_idx = 0 # Reset player index return elo_deltas
def run(self): for game in Game.objects.filter(status__in=self.active_statuses): try: status = game.update_from_engine() if game.is_leaderboard_game and game.status == Game.Status.COMPLETE: sorted_snakes = sorted(sorted(status['snakes'].items(), key=lambda s: s[1]['death']), key=lambda s: s[1]['turn'], reverse=True) game_snake_ids = [s[0] for s in sorted_snakes] game_snakes = GameSnake.objects.filter( id__in=game_snake_ids) snake_ids = [gs.snake_id for gs in game_snakes] snakes = UserSnake.objects.filter(snake_id__in=snake_ids) lb = [ UserSnakeLeaderboard.objects.get(user_snake=s) for s in snakes ] ratings = [(self.create_rating(l), ) for l in lb] new_rankings = trueskill.rate(ratings, ranks=list( range(0, len(ratings)))) for x in range(0, len(ratings)): r = new_rankings[x] lb[x].mu = r[0].mu lb[x].sigma = r[0].sigma lb[x].save() except Exception as e: game.status = Game.Status.ERROR game.save() # Something wrong with this game, don't care print(f'Unable to update game {game.id}', e) pass
def compute_player_skills(rounds: [RoundRow], teams: [dict], current_ratings: {int: trueskill.Rating} = None) \ -> ({int: trueskill.Rating}, [SkillHistory]): ratings = {} if current_ratings is not None: ratings.update(current_ratings) skill_history = [] for round in rounds: rating_groups = ( { player_id: ratings.get(player_id, trueskill.Rating()) for player_id in teams[round.winner] }, { player_id: ratings.get(player_id, trueskill.Rating()) for player_id in teams[round.loser] }, ) new_ratings = trueskill.rate(rating_groups) for rating in new_ratings: ratings.update(rating) for player_id, skill in rating.items(): skill_history.append( SkillHistory(round_id=round.round_id, player_id=player_id, skill=skill)) return ratings, skill_history
def update_player_skill_values(self): winner_ratings = [] for winner in self.winners.all(): winner_ratings.append( trueskill.Rating(winner.rating_mu, winner.rating_sigma) ) winner_ratings = tuple(winner_ratings) loser_ratings = [] for loser in self.losers.all(): loser_ratings.append( trueskill.Rating(loser.rating_mu, loser.rating_sigma) ) loser_ratings = tuple(loser_ratings) match_rating_result = trueskill.rate([winner_ratings, loser_ratings]) i = 0 for winner in self.winners.all(): winner.rating_mu = match_rating_result[0][i].mu winner.rating_sigma = match_rating_result[0][i].sigma winner.save(update_fields=["rating_mu", "rating_sigma"]) i += 1 i = 0 for loser in self.losers.all(): loser.rating_mu = match_rating_result[1][i].mu loser.rating_sigma = match_rating_result[1][i].sigma loser.save(update_fields=["rating_mu", "rating_sigma"]) i += 1
def test_rating_dicts(): class Player(object): def __init__(self, name, rating, team): self.name = name self.rating = rating self.team = team p1 = Player('Player A', Rating(), 0) p2 = Player('Player B', Rating(), 0) p3 = Player('Player C', Rating(), 1) rated = rate([{p1: p1.rating, p2: p2.rating}, {p3: p3.rating}]) assert len(rated) == 2 assert isinstance(rated[0], dict) assert isinstance(rated[1], dict) assert len(rated[0]) == 2 assert len(rated[1]) == 1 assert p1 in rated[0] assert p2 in rated[0] assert p3 in rated[1] assert p1 not in rated[1] assert p2 not in rated[1] assert p3 not in rated[0] assert isinstance(rated[0][p1], Rating) p1.rating = rated[p1.team][p1] p2.rating = rated[p2.team][p2] p3.rating = rated[p3.team][p3]
def rank(self, game): logger.info(f"ranking game id={game.id}") status = game.engine_status() sorted_snakes = sorted( status["snakes"].items(), key=lambda i: game.turn + 1 if i[1]["death"] == "pending" else i[1]["turn"], reverse=True, ) lookup = [] for s in sorted_snakes: gs = game.gamesnake_set.get(id=s[0]) lookup.append({ "rating": (self.create_rating(gs.snake.snakeleaderboard_set.first()), ), "snake": gs.snake, }) ratings = [i["rating"] for i in lookup] new_rankings = trueskill.rate(ratings, ranks=get_rankings(sorted_snakes)) for index, new_rank in enumerate(new_rankings): t = lookup[index] sl = t["snake"].snakeleaderboard_set.first() sl.mu = new_rank[0].mu sl.sigma = new_rank[0].sigma sl.save() LeaderboardResult.objects.create( snake=t["snake"].snakeleaderboard_set.first(), game=game, mu_change=new_rank[0].mu - t["rating"][0].mu, sigma_change=new_rank[0].sigma - t["rating"][0].sigma, )
def applyTrueskill(games, players): for player in players: players[player]['rating'] = ts.Rating() for i in games.index: [(players[games.ix[i, 't1p1']]['rating'], players[games.ix[i, 't1p2']]['rating'], players[games.ix[i, 't1p3']]['rating'], players[games.ix[i, 't1p4']]['rating'], players[games.ix[i, 't1p5']]['rating']), (players[games.ix[i, 't2p1']]['rating'], players[games.ix[i, 't2p2']]['rating'], players[games.ix[i, 't2p3']]['rating'], players[games.ix[i, 't2p4']]['rating'], players[games.ix[i, 't2p5']]['rating'])] = ts.rate( [(players[games.ix[i, 't1p1']]['rating'], players[games.ix[i, 't1p2']]['rating'], players[games.ix[i, 't1p3']]['rating'], players[games.ix[i, 't1p4']]['rating'], players[games.ix[i, 't1p5']]['rating']), (players[games.ix[i, 't2p1']]['rating'], players[games.ix[i, 't2p2']]['rating'], players[games.ix[i, 't2p3']]['rating'], players[games.ix[i, 't2p4']]['rating'], players[games.ix[i, 't2p5']]['rating'])], [1 - games.ix[i, 'result'], games.ix[i, 'result']])
def save(self, *args, **kwargs): winner_rating = Rating(mu=self.winner.mu, sigma=self.winner.sigma) loser_rating = Rating(mu=self.loser.mu, sigma=self.loser.sigma) new_winner_rating, new_loser_rating = rate_1vs1( winner_rating, loser_rating) self.winner.mu = new_winner_rating.mu self.winner.sigma = new_winner_rating.sigma self.winner.save() self.loser.mu = new_loser_rating.mu self.loser.sigma = new_loser_rating.sigma self.loser.save() # Personal rating winners = { p: Rating(mu=p.mu, sigma=p.sigma) for p in self.winner.players.all() } losers = { p: Rating(mu=p.mu, sigma=p.sigma) for p in self.loser.players.all() } # Score the match new_team_ratings = rate([winners, losers ]) # Returns a list with a one or many dicts for team in new_team_ratings: for player, new_rating in team.iteritems(): player.mu = new_rating.mu player.sigma = new_rating.sigma player.save() super(Match, self).save(*args, **kwargs)
def compute(self): games = sorted(self.games.values(), key=lambda g: g.last_update) for g in games: results = sorted(g.results.values(), key=lambda res: -res['vp']) if len(results) < 2: continue teams = [] ranks = [] weights = [] rank = 0 prev = None for res in results: vp = res['vp'] if prev and vp < prev: rank += 1 prev = vp ranks.append(rank) weights.append((1, options.faction_weight)) teams.append((res['player_ref']['rating'], res['faction_ref']['rating'])) new = trueskill.rate(teams, ranks, weights) i = 0 for res in results: (res['player_ref']['rating'], res['faction_ref']['rating']) = new[i] i += 1
def calculate_mmr(self, r): if not r: return None #get current rating mmr_team0 = OrderedDict( ) # key = account | val = list(current_mmr, new_mmr) mmr_team1 = OrderedDict() for player in r.team0.memberList: mmr_team0[r.players[player]][0] = trueskill.Rating( self.get_mmr(r.players[player].toonHandle)) for player in r.team1.memberList: mmr_team1[r.players[player]][0] = trueskill.Rating( self.get_mmr(r.players[player].toonHandle)) ratings = trueskill.rate([[x for x in mmr_team0.itervalues()], [x for x in mmr_team1.itervalues()]], ranks=[r.team0.isLoser, r.team0.isWinner]) for player in r.team0.memberList: mmr_team0[player][1] = ratings[player] for player in r.team1.memberList: mmr_team1[player][1] = ratings[player + len(r.team0.memberList) - 1] return mmr_team0, mmr_team1
def calculate_and_adjust(players_per_side: int, team1: List['Skill'], team2: List['Skill'], did_team_1_win: bool): """Calculates and adjusts a game.""" ranks = [0, 1] if did_team_1_win else [1, 0] # Apply a weighting based on the number of players in the roster. # This way, the game is always kept "fair" as if each player is subbed out at regular intervals. if len(team1) < players_per_side: team1_weights = (1, ) * len(team1) else: team1_weights = (players_per_side / len(team1), ) * len(team1) if len(team2) < players_per_side: team2_weights = (1, ) * len(team2) else: team2_weights = (players_per_side / len(team2), ) * len(team2) teams = trueskill.rate(rating_groups=[ tuple([t1.rating for t1 in team1]), tuple([t2.rating for t2 in team2]) ], ranks=ranks, weights=[team1_weights, team2_weights]) for i in range(0, len(teams[0])): team1[i].rating = teams[0][i] for i in range(0, len(teams[1])): team2[i].rating = teams[1][i]
def do_game(game, players, style="allplayer-trueskill"): # Takes a game and stores the results game_rank_list = [] player_list = [] rating_groups = [] rankable_users = [] if style == "allplayer-trueskill": rankable_users = game.users elif style == "topbottom-trueskill": rankable_users = [game.users[0], game.users[-1]] for user_data in rankable_users: if user_data.user_name not in players: players[user_data.user_name] = Player(user_data.user_name) rating_groups.append( {user_data.user_name: players[user_data.user_name].rating}) game_rank_list.append(user_data.rank) player_list.append(user_data.user_name) rated_list = rate(rating_groups, game_rank_list) for i in range(len(rankable_users)): if rankable_users[i].user_name not in players: players[rankable_users[i].user_name] = Player( rankable_users.user_name) players[rankable_users[i].user_name].record_match( game.timestamp, rated_list[i][rankable_users[i].user_name])
def update_ranking(self, match_ranking: Dict[str, int]): # Transform the usernames to be lowercase for compatibility with database match_ranking = { key.lower(): value for key, value in match_ranking.items() } # Get the current trueskill ratings for each player entries = self.get_multi(*match_ranking.keys()) old_trueskill_rankings = [{ str(name): Rating(mu=mu, sigma=sigma) } for name, _, mu, sigma in entries] ordered_match_rankings = [ match_ranking[name] for name, _, _, _ in entries ] # Update rankings using trueskill algorithm new_trueskill_rankings = rate(old_trueskill_rankings, ordered_match_rankings) # Update database with new rankings cursor = self.__db.cursor() with self.__db_lock: for name, rating in ChainMap(*new_trueskill_rankings).items(): cursor.execute( "UPDATE userz SET mu=?, sigma=? WHERE username=?", (rating.mu, rating.sigma, name)) self.__db.commit()
def update_ratings(game, session, elos, players): if len(elos) < 2: return [] oldRatings = [] ranks = [] for pid in players: p = elos[pid] #fixme if len(oldRatings) < 8: oldRatings.append((Rating(mu=p.mu, sigma=p.sigma), )) ranks.append(players[pid].rank) newRatings = rate(oldRatings, ranks) elo_deltas = {} i = 0 for pid in players: if i >= 8: continue old = oldRatings[i][0] new = newRatings[i][0] elo_deltas[pid] = (new.mu - 3 * new.sigma) - (old.mu - 3 * old.sigma) elos[pid].mu = new.mu elos[pid].sigma = new.sigma elos[pid].ts_games += 1 i = i + 1 log.debug( str(pid) + ": mu=" + str(new.mu) + ", sigma=" + str(new.sigma)) save_rating_deltas(game, session, elo_deltas) return elos
def test_partial_play(): t1, t2 = (Rating(), ), (Rating(), Rating()) # each results from C# Skills: assert rate([t1, t2], weights=[(1, ), (1, 1)]) == rate([t1, t2]) assert _rate([t1, t2], weights=[(1,), (1, 1)]) == \ [(33.730, 7.317), (16.270, 7.317), (16.270, 7.317)] assert _rate([t1, t2], weights=[(0.5,), (0.5, 0.5)]) == \ [(33.939, 7.312), (16.061, 7.312), (16.061, 7.312)] assert _rate([t1, t2], weights=[(1,), (0, 1)]) == \ [(29.440, 7.166), (25.000, 8.333), (20.560, 7.166)] assert _rate([t1, t2], weights=[(1,), (0.5, 1)]) == \ [(32.417, 7.056), (21.291, 8.033), (17.583, 7.056)] # match quality of partial play t1, t2, t3 = (Rating(), ), (Rating(), Rating()), (Rating(), ) assert _quality([t1, t2, t3], [(1, ), (0.25, 0.75), (1, )]) == 0.2 assert _quality([t1, t2, t3], [(1, ), (0.8, 0.9), (1, )]) == 0.0809
def rank(self, force=False): if self.ranked and not force: return if self.players.all().count() != self.game.player_count: return self.refresh_from_db() arg = [] for player in self.players.all(): arg.append((player.get_rating_for_game(self.game).rating_obj, )) results = rate(arg) for i, player in enumerate(self.players.all()): rating = player.get_rating_for_game(self.game) rating.rating_obj = results[i] rating.match_count += 1 rating.save() if self.game is not None: rating = player.get_rating_for_game(None) rating.rating_obj = results[i] rating.save() self.ranked = True self.save()
def update_trueskill_by_match(match): w_ratings = [] l_ratings = [] for p in match.winning_players: mu, sigma = p.get_current_trueskill() w_ratings.append(ts.Rating(mu, sigma)) for p in match.losing_players: mu, sigma = p.get_current_trueskill() l_ratings.append(ts.Rating(mu, sigma)) rating_groups = [w_ratings, l_ratings] new_ratings = ts.rate(rating_groups, ranks=[0, 1]) players = match.winning_players + match.losing_players new_ratings_flat = [item for sublist in new_ratings for item in sublist] for player, rating in zip(players, new_ratings_flat): r_m = Rating( user=player, match=match, rating_type='trueskill_mu', rating_value=rating.mu, timestamp=match.timestamp, ) r_s = Rating( user=player, match=match, rating_type='trueskill_sigma', rating_value=rating.sigma, timestamp=match.timestamp, ) db.session.add_all([r_m, r_s]) db.session.commit()
def update_trueskill(scores, ratings): env = TrueSkill() # Parallel arrays! All of these are for the given game players = [] teams = [] ranks = [] expose_before = {} # Sanity check, some bad data in test systems if len(scores) < 4: return for s in scores: if s.player_id not in ratings.keys(): ratings[s.player_id] = Rating() # Default mu=25, sigma=8.333 r = ratings[s.player_id] expose_before[s.player_id] = env.expose(r) players.append(s.player_id) teams.append([r]) ranks.append(s.rank) # Crunch the numbers new_ratings = rate(teams, ranks) for i in range(0, len(new_ratings)): ratings[players[i]] = new_ratings[i][0] for s in scores: s.trueskill = ratings[s.player_id].mu s.trueskill_confidence = ratings[s.player_id].sigma s.trueskill_change = round(env.expose(ratings[s.player_id]) - expose_before[s.player_id], 1) s.save()
def main(games_file: str, ratings_file: str): # Load data. players = defaultdict(lambda: ts.Rating()) games = pd.read_csv(games_file) # Sort data based on date. games.sort_values(by=[DATE_COLUMN], inplace=True) games.fillna("", inplace=True) for _, (date, pl1, pl2, sc1, sc2, pl3, pl4) in games.iterrows(): team1 = [] skills1 = [] team2 = [] skills2 = [] team1, skills1 = append(pl1, players, team1, skills1) team1, skills1 = append(pl2, players, team1, skills1) team2, skills2 = append(pl3, players, team2, skills2) team2, skills2 = append(pl4, players, team2, skills2) ranks = compute_rank(sc1, sc2) ratings1, ratings2 = ts.rate([skills1, skills2], ranks=ranks) update(players, team1, ratings1) update(players, team2, ratings2) # Save ratings. result = [] for name, rating in players.items(): result.append({"Name": name, "Mu": rating.mu, "Sigma": rating.sigma}) df = pd.DataFrame(result) df.to_csv(ratings_file, index=False)
def update_player_ratings(self, match): ratings_a = [p.get_rating() for p in match.teams[0]] ratings_b = [p.get_rating() for p in match.teams[1]] # Sort by score and get rank indices rank = list(zip(match.score, range(len(match.score)))) rank.sort(key=lambda r: r[0], reverse=True) rank_indices = list(zip(*rank))[1] # Check for Draw # TODO: make this generic for more than 2 teams if match.score[0] == match.score[1]: rank_indices = [0, 0] # Calculate new Ratings using trueskill algorithm new_ratings = trueskill.rate([ratings_a, ratings_b], ranks=rank_indices, weights=self.team_weights( ratings_a, ratings_b)) for r, p in zip(new_ratings[0], match.teams[0]): p.set_rating(r) p.add_match(match) for r, p in zip(new_ratings[1], match.teams[1]): p.set_rating(r) p.add_match(match)
def test_partial_play(): t1, t2 = (Rating(),), (Rating(), Rating()) # each results from C# Skills: assert rate([t1, t2], weights=[(1,), (1, 1)]) == rate([t1, t2]) assert _rate([t1, t2], weights=[(1,), (1, 1)]) == \ [(33.730, 7.317), (16.270, 7.317), (16.270, 7.317)] assert _rate([t1, t2], weights=[(0.5,), (0.5, 0.5)]) == \ [(33.939, 7.312), (16.061, 7.312), (16.061, 7.312)] assert _rate([t1, t2], weights=[(1,), (0, 1)]) == \ [(29.440, 7.166), (25.000, 8.333), (20.560, 7.166)] assert _rate([t1, t2], weights=[(1,), (0.5, 1)]) == \ [(32.417, 7.056), (21.291, 8.033), (17.583, 7.056)] # match quality of partial play t1, t2, t3 = (Rating(),), (Rating(), Rating()), (Rating(),) assert _quality([t1, t2, t3], [(1,), (0.25, 0.75), (1,)]) == 0.2 assert _quality([t1, t2, t3], [(1,), (0.8, 0.9), (1,)]) == 0.0809
def update_ratings(game, session, elos, players): if len(elos) < 2: return [] oldRatings = [] ranks = [] for pid in players: p = elos[pid] #fixme if len(oldRatings) < 8: oldRatings.append((Rating(mu=p.mu, sigma=p.sigma),)) ranks.append(players[pid].rank) newRatings = rate(oldRatings, ranks); elo_deltas = {} i=0 for pid in players: if i>=8: continue old = oldRatings[i][0] new = newRatings[i][0] elo_deltas[pid] = (new.mu - 3*new.sigma) - (old.mu - 3*old.sigma) elos[pid].mu = new.mu elos[pid].sigma = new.sigma elos[pid].ts_games += 1 i = i + 1 log.debug(str(pid) + ": mu=" + str(new.mu) + ", sigma=" + str(new.sigma)); save_rating_deltas(game, session, elo_deltas) return elos
def add_match(conn, bots, results): winner = None for id_str, stats in results['stats'].items(): if stats['rank'] == 1: winner = int(id_str) if winner is None: raise ValueError('Could not detect winner of game') query = 'insert into games (datetime, winner, participants, results) values (?, ?, ?, ?)' del results['final_snapshot'] current_time = datetime.datetime.now().isoformat() conn.execute(query, (current_time, bots[winner]['id'], json.dumps(bots), json.dumps(results))) for bot in bots: history_query = 'insert into rank_history (bot_id, datetime, rank, mu, sigma) values (?, ?, ?, ?, ?)' conn.execute( history_query, (bot['id'], current_time, bot['rank'], bot['mu'], bot['sigma'])) games_played_query = 'update bots set games_played=games_played + 1 where id = ?' conn.execute(games_played_query, (bot['id'], )) trueskill.setup(tau=0.008, draw_probability=0.001) teams = [[trueskill.Rating(mu=bot["mu"], sigma=bot["sigma"])] for bot in bots] ranks = [results["stats"][str(b)]["rank"] - 1 for b in range(len(bots))] new_ratings = trueskill.rate(teams, ranks) update_query = 'update bots set mu=?, sigma=? where id=?' for bot, rating in zip(bots, new_ratings): conn.execute(update_query, (rating[0].mu, rating[0].sigma, bot['id'])) rerank_bots(conn)
def update_ratings(players: dict, game: Game) -> None: if not game.score: return if game.score == '1': ranks = [0, 1] elif game.score == '2': ranks = [1, 0] elif game.score == 'D': ranks = [0, 0] else: return for player_id in game.team1: if not player_id in players: players[player_id] = Player() for player_id in game.team2: if not player_id in players: players[player_id] = Player() team1_ratings = list(map(lambda id: players[id].rating, game.team1)) team2_ratings = list(map(lambda id: players[id].rating, game.team2)) team1_ratings, team2_ratings = trueskill.rate( [team1_ratings, team2_ratings], ranks=ranks) for i, player in enumerate(game.team1): players[player].rating = team1_ratings[i] for i, player in enumerate(game.team2): players[player].rating = team2_ratings[i]
def test_microsoft_research_example(): # http://research.microsoft.com/en-us/projects/trueskill/details.aspx alice, bob, chris, darren, eve, fabien, george, hillary = \ Rating(), Rating(), Rating(), Rating(), \ Rating(), Rating(), Rating(), Rating() _rated = rate([{ 'alice': alice }, { 'bob': bob }, { 'chris': chris }, { 'darren': darren }, { 'eve': eve }, { 'fabien': fabien }, { 'george': george }, { 'hillary': hillary }]) rated = {} list(map(rated.update, _rated)) assert almost(rated['alice']) == (36.771, 5.749) assert almost(rated['bob']) == (32.242, 5.133) assert almost(rated['chris']) == (29.074, 4.943) assert almost(rated['darren']) == (26.322, 4.874) assert almost(rated['eve']) == (23.678, 4.874) assert almost(rated['fabien']) == (20.926, 4.943) assert almost(rated['george']) == (17.758, 5.133) assert almost(rated['hillary']) == (13.229, 5.749)
def _updateRankings(winningTeam,losingTeam): """ Updates the Rankings of the PongUsers who played the Game. Keyword arguments: winningTeam -- the Team who won the Game losingTeam -- the Team who lost the Game Contributors: Richard Douglas Output: None """ #obtain the Ranking objects winningRankings = _obtainRankings(winningTeam) losingRankings = _obtainRankings(losingTeam) #obtain the corresponding TrueSkill Rating objects oldWinningRatings = _obtainRatings(winningRankings) oldLosingRatings = _obtainRatings(losingRankings) #have TrueSkill rate the Game newWinningRatings, newLosingRatings = rate([oldWinningRatings,oldLosingRatings], ranks = [0,1]) #update Ranking objects with their new Mu and Sigma values _writeRatingsToRankings(newWinningRatings,winningRankings) _writeRatingsToRankings(newLosingRatings,losingRankings) return
def test_issue4(): """The `issue #4`_, opened by @sublee. numpy.float64 handles floating-point error by different way. For example, it can just warn RuntimeWarning on n/0 problem instead of throwing ZeroDivisionError. .. _issue #4: https://github.com/sublee/trueskill/issues/4 """ import numpy r1, r2 = Rating(105.247, 0.439), Rating(27.030, 0.901) # make numpy to raise FloatingPointError instead of warning # RuntimeWarning old_settings = numpy.seterr(divide='raise') try: rate([(r1,), (r2,)]) finally: numpy.seterr(**old_settings)
def update_trueskills(chao_trueskills): """ makes updates to the trueskills based on the order :param chao_trueskills: list of chao trueskills in the order in which they placed :return: new list of trueskills for chaos in the same order in which they placed (were received) """ rating_groups = [(x,) for x in chao_trueskills] rated = trueskill.rate(rating_groups) return [rated[i][0] for i in xrange(len(rated))]
def test_rating_tuples(): r1, r2, r3 = Rating(), Rating(), Rating() rated = rate([(r1, r2), (r3,)]) assert len(rated) == 2 assert isinstance(rated[0], tuple) assert isinstance(rated[1], tuple) assert len(rated[0]) == 2 assert len(rated[1]) == 1 assert isinstance(rated[0][0], Rating)
def test_setup_global_environment(): try: setup(draw_probability=.50) t1, t2 = generate_teams([1, 1]) rated = rate([t1, t2]) assert almost(rated) == [(30.267, 7.077), (19.733, 7.077)] finally: # rollback setup()
def loadMatches(self, matches): for match in matches: rating_group = [dict(zip(match.radiant, [self.players[p] for p in match.radiant])), dict(zip(match.dire, [self.players[p] for p in match.dire])), ] result = rate(rating_group, ranks = match.result) for side in result: for p in side.keys(): self.players[p] = side[p]
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])
def test_partial_play_with_weights_dict(): t1, t2 = (Rating(),), (Rating(), Rating()) assert rate([t1, t2], weights={(0, 0): 0.5, (1, 0): 0.5, (1, 1): 0.5}) == \ rate([t1, t2], weights=[[0.5], [0.5, 0.5]]) assert rate([t1, t2], weights={(1, 0): 0}) == \ rate([t1, t2], weights=[[1], [0, 1]]) assert rate([t1, t2], weights={(1, 0): 0.5}) == \ rate([t1, t2], weights=[[1], [0.5, 1]])
def process_match(self, line): players = list(map(str, line[:4])) score = list(map(int, line[4:])) locker_room = self.locker_room for player in players: if player not in locker_room: locker_room[player] = Rating() t1 = [locker_room.pop(players[i]) for i in range(2)] t2 = [locker_room.pop(players[i]) for i in range(2, 4)] ranks = [score[1] > score[0], score[1] < score[0]] t1, t2 = rate([t1, t2], ranks=ranks) for i in range(2): locker_room[players[i]] = t1[i] locker_room[players[i + 2]] = t2[i]
def test_issue3(): """The `issue #3`_, opened by @youknowone. These inputs led to ZeroDivisionError before 0.1.4. Also another TrueSkill implementations cannot calculate this case. .. _issue #3: https://github.com/sublee/trueskill/issues/3 """ # @konikos's case 1 t1 = (Rating(42.234, 3.728), Rating(43.290, 3.842)) t2 = (Rating(16.667, 0.500), Rating(16.667, 0.500), Rating(16.667, 0.500), Rating(16.667, 0.500), Rating(16.667, 0.500), Rating(16.667, 0.500), Rating(16.667, 0.500), Rating(16.667, 0.500), Rating(16.667, 0.500), Rating(16.667, 0.500), Rating(16.667, 0.500), Rating(16.667, 0.500), Rating(16.667, 0.500), Rating(16.667, 0.500), Rating(16.667, 0.500)) rate([t1, t2], [6, 5]) # @konikos's case 2 t1 = (Rating(25.000, 0.500), Rating(25.000, 0.500), Rating(25.000, 0.500), Rating(25.000, 0.500), Rating(33.333, 0.500), Rating(33.333, 0.500), Rating(33.333, 0.500), Rating(33.333, 0.500), Rating(41.667, 0.500), Rating(41.667, 0.500), Rating(41.667, 0.500), Rating(41.667, 0.500)) t2 = (Rating(42.234, 3.728), Rating(43.291, 3.842)) rate([t1, t2], [0, 28])
def rate_players(): (ranked, teams) = build_ranked() ranked = trueskill.rate(ranked) # JSONify result = [] for t, team in enumerate(ranked): rated_team = [] for i, player in enumerate(team): rated_team.append(jsonify_rating(player, teams[t][i])) result.append(rated_team) return {'teams': result}
def record_match_and_update_ratings(win_team, lose_team, loser_win_count): # calculate new ratings updated_ratings = rate([win_team.ratings, lose_team.ratings]) updated_ratings_dict = {} updated_ratings_dict.update(updated_ratings[0]) updated_ratings_dict.update(updated_ratings[1]) for role, rating in updated_ratings_dict.iteritems(): role.rating_mu = rating.mu role.rating_sigma = rating.sigma role.save() result = MatchResult.objects.create( winners=win_team, losers=lose_team, loser_win_count=loser_win_count, created_on=datetime.datetime.now())
def update_trueskill(match): winner = match.winner if match.team_1 == winner: loser = match.team_2 else: loser = match.team_1 winners = winner.players.all() losers = loser.players.all() winner_ratings = [] loser_ratings = [] for w in winners: winner_ratings.append(Rating(w.current_mu, w.current_sigma)) for l in losers: loser_ratings.append(Rating(l.current_mu, l.current_sigma)) winner_ratings, loser_ratings = rate([winner_ratings, loser_ratings]) for counter, p in enumerate(winners): p.ts_mu = winner_ratings[counter].mu p.ts_sigma = winner_ratings[counter].sigma p.save() sh, _ = StatHistory.objects.get_or_create(player=p, match=match, ) sh.season = match.season sh.ts_mu = winner_ratings[counter].mu sh.ts_sigma = winner_ratings[counter].sigma sh.save() # p.save() for counter, p in enumerate(losers): p.ts_mu = loser_ratings[counter].mu p.ts_sigma = loser_ratings[counter].sigma p.save() sh, _ = StatHistory.objects.get_or_create(player=p, match=match, ) sh.season = match.season sh.ts_mu = loser_ratings[counter].mu sh.ts_sigma = loser_ratings[counter].sigma sh.save()
def test_issue9_weights_dict_with_object_keys(): """The `issue #9`_, opened by @. .. _issue #9: https://github.com/sublee/trueskill/issues/9 """ class Player(object): def __init__(self, rating, team): self.rating = rating self.team = team p1 = Player(Rating(), 0) p2 = Player(Rating(), 0) p3 = Player(Rating(), 1) teams = [{p1: p1.rating, p2: p2.rating}, {p3: p3.rating}] rated = rate(teams, weights={(0, p1): 1, (0, p2): 0.5, (1, p3): 1}) assert rated[0][p1].mu > rated[0][p2].mu assert rated[0][p1].sigma < rated[0][p2].sigma assert rated[0][p1].sigma == rated[1][p3].sigma
def test_microsoft_research_example(): # http://research.microsoft.com/en-us/projects/trueskill/details.aspx alice, bob, chris, darren, eve, fabien, george, hillary = \ Rating(), Rating(), Rating(), Rating(), \ Rating(), Rating(), Rating(), Rating() _rated = rate([{'alice': alice}, {'bob': bob}, {'chris': chris}, {'darren': darren}, {'eve': eve}, {'fabien': fabien}, {'george': george}, {'hillary': hillary}]) rated = {} list(map(rated.update, _rated)) assert almost(rated['alice']) == (36.771, 5.749) assert almost(rated['bob']) == (32.242, 5.133) assert almost(rated['chris']) == (29.074, 4.943) assert almost(rated['darren']) == (26.322, 4.874) assert almost(rated['eve']) == (23.678, 4.874) assert almost(rated['fabien']) == (20.926, 4.943) assert almost(rated['george']) == (17.758, 5.133) assert almost(rated['hillary']) == (13.229, 5.749)
def compute_rating(self, rating='global'): """ Compute new ratings :param rating: 'global' or 'ladder' :return: rating groups of the form: >>> p1,p2,p3,p4 = Player() >>> [{p1: p1.rating, p2: p2.rating}, {p3: p3.rating, p4: p4.rating}] """ assert self.state == GameState.LIVE or self.state == GameState.ENDED team_scores = {} ffa_scores = [] for player in sorted(self.players, key=lambda p: self.get_player_option(p.id, 'Army') or -1): team = self.get_player_option(player.id, 'Team') army = self.get_player_option(player.id, 'Army') if army < 0: self._logger.info("Skipping {}".format(player)) continue if not team: raise GameError("Missing team for player id: {}".format(player.id)) if team != 1: if team not in team_scores: team_scores[team] = 0 try: team_scores[team] += self.get_army_result(army) except KeyError: team_scores[team] += 0 self._logger.info("Missing game result for {army}: {player}".format(army=army, player=player)) elif team == 1: ffa_scores.append((player, self.get_army_result(army))) ranks = [-score for team, score in sorted(team_scores.items(), key=lambda t: t[0])] rating_groups = [] for team in sorted(self.teams): if team != 1: rating_groups += [{player: Rating(*getattr(player, '{}_rating'.format(rating))) for player in self.players if self.get_player_option(player.id, 'Team') == team}] for player, score in sorted(ffa_scores, key=lambda x: self.get_player_option(x[0].id, 'Army')): rating_groups += [{player: Rating(*getattr(player, '{}_rating'.format(rating)))}] ranks.append(-score) self._logger.debug("Rating groups: {}".format(rating_groups)) self._logger.debug("Ranks: {}".format(ranks)) return trueskill.rate(rating_groups, ranks)
def rate(cls, names): """ :type names: list[str] """ if not isinstance(names, list): raise TypeError("Argument must be a list") if len(names) != 4: raise ValueError("Please specify 4 players") players = [] missing = [] for name in names: player = cls.get_player(name) if not player: missing.append(name) else: players.append(player) if missing: raise RuntimeError("Players not registered: %s" % missing) winner1 = players[0] winner2 = players[1] loser1 = players[2] loser2 = players[3] winners = [winner1.rating, winner2.rating] losers = [loser1.rating, loser2.rating] winners, losers = trueskill.rate([winners, losers]) winner1.rating = winners[0] winner2.rating = winners[1] loser1.rating = losers[0] loser2.rating = losers[1] Store.get_store().set_player(winner1) Store.get_store().set_player(winner2) Store.get_store().set_player(loser1) Store.get_store().set_player(loser2) Store.get_store().log_results(names)
def calculate_mmr(self, r): if not r: return None #get current rating mmr_team0 = OrderedDict() # key = account | val = list(current_mmr, new_mmr) mmr_team1 = OrderedDict() for player in r.team0.memberList: mmr_team0[r.players[player]][0] = trueskill.Rating(self.get_mmr(r.players[player].toonHandle)) for player in r.team1.memberList: mmr_team1[r.players[player]][0] = trueskill.Rating(self.get_mmr(r.players[player].toonHandle)) ratings = trueskill.rate([[x for x in mmr_team0.itervalues()], [x for x in mmr_team1.itervalues()]], ranks=[r.team0.isLoser, r.team0.isWinner]) for player in r.team0.memberList: mmr_team0[player][1] = ratings[player] for player in r.team1.memberList: mmr_team1[player][1] = ratings[player + len(r.team0.memberList) - 1] return mmr_team0, mmr_team1
def rate_skill(names, results, metrics): from trueskill import Rating, rate, setup MU = 1000 setup(MU, MU / 3, MU * 5, MU / 5000) started = time.clock() ratings = {x : Rating() for x in names} for entry in results: adjusted = rate([(ratings[x[0]],) for x in entry], [(int(not x[1]),) for x in entry]) for index, rating in enumerate(adjusted): ratings[entry[index][0]] = rating[0] print("Completed rankings in", str(int(time.clock() - started)), "seconds") print("") descending = sorted(ratings.items(), key=lambda x:x[1], reverse=True) for index, (name, rating) in enumerate(descending): metrics[name]["Rank"] = index metrics[name]["Mu"] = "%.0f" % rating.mu metrics[name]["Sigma"] = "%.0f" % rating.sigma
def test_1_vs_n(): t1, = generate_teams([1]) # 1 vs 2 t2, = generate_teams([2]) assert _quality([t1, t2]) == 0.135 assert _rate([t1, t2]) == \ [(33.730, 7.317), (16.270, 7.317), (16.270, 7.317)] assert _rate([t1, t2], [0, 0]) == \ [(31.660, 7.138), (18.340, 7.138), (18.340, 7.138)] # 1 vs 3 t2, = generate_teams([3]) assert _quality([t1, t2]) == 0.012 assert _rate([t1, t2]) == \ [(36.337, 7.527), (13.663, 7.527), (13.663, 7.527), (13.663, 7.527)] assert almost(rate([t1, t2], [0, 0]), 2) == \ [(34.990, 7.455), (15.010, 7.455), (15.010, 7.455), (15.010, 7.455)] # 1 vs 7 t2, = generate_teams([7]) assert _quality([t1, t2]) == 0 assert _rate([t1, t2]) == \ [(40.582, 7.917), (9.418, 7.917), (9.418, 7.917), (9.418, 7.917), (9.418, 7.917), (9.418, 7.917), (9.418, 7.917), (9.418, 7.917)]