def rank_players(ratings): ordered = sorted(ratings.items(), key=lambda x: ts.expose(x[1]), reverse=True) result = [] for rank in ordered: player, rating = rank result.append((player, rating, ts.expose(rating))) return result
def generate_ranking(dao, now=datetime.now()): player_date_map = {} player_id_to_player_map = {} tournaments = dao.get_all_tournaments(regions=[dao.region_id]) for tournament in tournaments: print 'Processing:', tournament.name for player_id in tournament.players: player_date_map[player_id] = tournament.date # TODO add a default rating entry when we add it to the map for match in tournament.matches: if not match.winner in player_id_to_player_map: db_player = dao.get_player_by_id(match.winner) db_player.ratings[dao.region_id] = DEFAULT_RATING player_id_to_player_map[match.winner] = db_player if not match.loser in player_id_to_player_map: db_player = dao.get_player_by_id(match.loser) db_player.ratings[dao.region_id] = DEFAULT_RATING player_id_to_player_map[match.loser] = db_player winner = player_id_to_player_map[match.winner] loser = player_id_to_player_map[match.loser] rating_calculators.update_trueskill_ratings(dao.region_id, winner=winner, loser=loser) print 'Checking for player inactivity...' i = 1 players = player_id_to_player_map.values() sorted_players = sorted( players, key=lambda player: trueskill.expose(player.ratings[dao.region_id].trueskill_rating), reverse=True) ranking = [] for player in sorted_players: player_last_active_date = player_date_map.get(player.id) if player_last_active_date == None or dao.is_inactive(player, now) or not dao.region_id in player.regions: pass # do nothing, skip this player else: ranking.append(RankingEntry(i, player.id, trueskill.expose(player.ratings[dao.region_id].trueskill_rating))) i += 1 print 'Updating players...' for i, p in enumerate(players, start=1): dao.update_player(p) print 'Updated player %d of %d' % (i, len(players)) print 'Inserting new ranking...' dao.insert_ranking(Ranking(dao.region_id, now, [t.id for t in tournaments], ranking)) print 'Done!'
def generate_ranking(dao, now=datetime.now(), day_limit=60, num_tourneys=2): player_date_map = {} player_id_to_player_map = {} tournaments = dao.get_all_tournaments(regions=[dao.region_id]) for tournament in tournaments: print 'Processing:', tournament.name.encode('utf-8') for player_id in tournament.players: player_date_map[player_id] = tournament.date # TODO add a default rating entry when we add it to the map for match in tournament.matches: if not match.winner in player_id_to_player_map: db_player = dao.get_player_by_id(match.winner) db_player.ratings[dao.region_id] = DEFAULT_RATING player_id_to_player_map[match.winner] = db_player if not match.loser in player_id_to_player_map: db_player = dao.get_player_by_id(match.loser) db_player.ratings[dao.region_id] = DEFAULT_RATING player_id_to_player_map[match.loser] = db_player winner = player_id_to_player_map[match.winner] loser = player_id_to_player_map[match.loser] rating_calculators.update_trueskill_ratings(dao.region_id, winner=winner, loser=loser) print 'Checking for player inactivity...' rank = 1 players = player_id_to_player_map.values() sorted_players = sorted( players, key=lambda player: trueskill.expose(player.ratings[dao.region_id].trueskill_rating), reverse=True) ranking = [] for player in sorted_players: player_last_active_date = player_date_map.get(player.id) if player_last_active_date == None or dao.is_inactive(player, now, day_limit, num_tourneys) or not dao.region_id in player.regions: pass # do nothing, skip this player else: ranking.append(RankingEntry(rank, player.id, trueskill.expose(player.ratings[dao.region_id].trueskill_rating))) rank += 1 print 'Updating players...' for i, p in enumerate(players, start=1): dao.update_player(p) print 'Updated player %d of %d' % (i, len(players)) print 'Inserting new ranking...' dao.insert_ranking(Ranking(dao.region_id, now, [t.id for t in tournaments], ranking)) print 'Done!'
def quality_and_probability(players, names): p0, p1 = players[names[0]], players[names[1]] quality = trueskill.quality_1vs1(p0, p1) probability = arduino_map((1-quality)*100, 0, 100, 50, 100)/100 ex0, ex1 = trueskill.expose(p0), trueskill.expose(p1) if ex0 == ex1: favor = None elif ex0>ex1: favor = names[0] else: favor = names[1] return quality, probability, favor
def clout(self) -> int: """ Return a public-facing estimation of the skill rating. This is the (conservative) min-rating clout or 2 sigmas below current actual """ return int(expose(self.rating) * SCALAR)
def __init__(self, pid, name, skill, updated): self.pid = pid self.name = name self._ts_mu = skill.mu self._ts_sigma = skill.sigma self.rating = trueskill.expose(skill) self.updated = updated
def display(request): #this is the main view #it's going to get all of our awesome players from the database #and create a leaderboard time thing from them based on their #ratings...it sounds stupid simple but it will probably be harder than anything else here all_players = player.objects.all() player_list = {} final_list = [] player_skills = [] player_rounded_skills = [] for each in all_players: if each.wins + each.losses > 5: player_mu = each.mu player_sigma = each.sigma player_rating = Decimal(expose(Rating(float(player_mu), float(player_sigma)))) #if player_rating in player_list: # player_rating += Decimal(.000000000000000000000000001) player_list[player_rating] = each sorted_player_list = sorted(player_list, reverse=True) for each in sorted_player_list: final_list.append(player_list[each]) player_skills.append(each) index_list = range(1, len(all_players)+1) for each in player_skills: player_rounded_skills.append(round(each, 1)) zipped_list = zip(final_list, player_rounded_skills, index_list) return render(request, 'display.html', {'player_list': final_list, 'skill_list': player_skills, 'zipped_list':zipped_list, 'index_list': index_list, })
def GetSortedRanking_(players): rankings = {} for p in players: rankings[p] = (ts.expose(players[p]), players[p]) return sorted(rankings.items(), key=lambda kv: (kv[1][0], kv[0]), reverse=True)
def calculate_score(self, comparison_pairs): """ Calculate scores for a set of comparison_pairs :param comparison_pairs: array of comparison_pairs :return: dictionary key -> ScoredObject """ self.storage = {} self.opponents = {} self.ratings = {} trueskill.setup() keys = self.get_keys_from_comparison_pairs(comparison_pairs) # create default ratings for every available key for key in keys: rating = trueskill.Rating() self.ratings[key] = rating self.opponents[key] = set() self.storage[key] = ScoredObject(key=key, score=trueskill.expose(rating), variable1=rating.mu, variable2=rating.sigma, rounds=0, opponents=0, wins=0, loses=0) # calculate rating by for every match for comparison_pair in comparison_pairs: key1 = comparison_pair.key1 key2 = comparison_pair.key2 winner = comparison_pair.winner # skip incomplete comparisosns if winner is None: self._update_rounds_only(key1) self._update_rounds_only(key2) continue r1 = self.ratings[key1] r2 = self.ratings[key2] key1_winner = winner == ComparisonWinner.key1 key2_winner = winner == ComparisonWinner.key2 if key1_winner: r1, r2 = trueskill.rate_1vs1(r1, r2) elif key2_winner: r2, r1 = trueskill.rate_1vs1(r2, r1) elif winner == ComparisonWinner.draw: r1, r2 = trueskill.rate_1vs1(r1, r2, drawn=True) else: raise InvalidWinnerException self._update_rating(key1, r1, key2, key1_winner, key2_winner) self._update_rating(key2, r2, key1, key2_winner, key1_winner) # return comparison results return self.storage
def compute_ratings(matches): ratings = {} histories = {} new_player_history = [] stats = {} new_player_stats = [] for _, match in matches.iterrows(): for name in set(itertools.chain(stats.keys(), match['player_stats'])): stats.setdefault(name, new_player_stats[:]) if name in match['player_stats']: stats[name].append(match['player_stats'][name]) else: stats[name].append(None) new_player_stats.append(None) new_ratings = trueskill.rate(( { name: ratings.get(name, trueskill.Rating()) for name in match["win"] }, { name: ratings.get(name, trueskill.Rating()) for name in match["loss"] }, )) for new_rating in new_ratings: ratings.update(new_rating) new_player_history.append(trueskill.Rating()) for name in ratings: histories.setdefault(name, new_player_history[:]) histories[name].append(ratings[name]) rows = [(name, rating, stats[name], histories[name]) for name, rating in ratings.items()] ratings = pd.DataFrame.from_records( rows, columns=["Name", "trueskill.Rating", "stats", "history"], index="Name") ratings.index.name = None boundaries = compute_division_boundaries() ratings["μ"] = ratings["trueskill.Rating"].apply(lambda rating: rating.mu) ratings["σ"] = ratings["trueskill.Rating"].apply( lambda rating: rating.sigma) ratings["Rating"] = ratings["trueskill.Rating"].apply( lambda rating: trueskill.expose(rating)) ratings["Rank"] = ratings["Rating"].apply( lambda rating: find_division(boundaries, rating)) ratings["Record"] = ratings["stats"].apply( lambda stats: compute_record(stats)) ratings["Streak"] = ratings["stats"].apply( lambda stats: compute_streak(stats)) ratings["Champs"] = ratings["stats"].apply( lambda stats: tuple(game["champ"] for game in stats if game)) ratings.sort_values("Rating", ascending=False, inplace=True) return ratings
def elo(self): rating = trueskill.expose(self.rating) # Set elo floor to 0 if rating < 0.05: return 0 else: return int(rating)
def calculate_score(self, comparison_pairs): """ Calculate scores for a set of comparisons :param comparisons: array of :return: dictionary key -> ScoredObject """ self.storage = {} self.opponents = {} self.ratings = {} trueskill.setup() keys = self.get_keys_from_comparison_pairs(comparison_pairs) # create default ratings for every available key for key in keys: rating = trueskill.Rating() self.ratings[key] = rating self.opponents[key] = set() self.storage[key] = ScoredObject( key=key, score=trueskill.expose(rating), variable1=rating.mu, variable2=rating.sigma, rounds=0, opponents=0, wins=0, loses=0, ) # calculate rating by for every match for comparison_pair in comparison_pairs: key1 = comparison_pair.key1 key2 = comparison_pair.key2 winning_key = comparison_pair.winning_key # skip incomplete comparisosns if winning_key is None: self._update_rounds_only(key1) self._update_rounds_only(key2) continue r1 = self.ratings[key1] r2 = self.ratings[key2] if winning_key == comparison_pair.key1: r1, r2 = trueskill.rate_1vs1(r1, r2) elif winning_key == comparison_pair.key2: r2, r1 = trueskill.rate_1vs1(r2, r1) else: raise InvalidWinningKeyException self._update_rating(key1, r1, key2, winning_key) self._update_rating(key2, r2, key1, winning_key) # return comparison results return self.storage
def skill(self, new_skill): try: mu, sigma = new_skill.mu, new_skill.sigma rating = trueskill.expose(new_skill) except AttributeError: # swallow the exception but don't modify values pass else: self._ts_mu, self._ts_sigma = mu, sigma self.rating = rating
def generate_ranking(dao): dao.reset_all_player_ratings() player_date_map = {} now = datetime.now() player_id_to_player_map = dict((p.id, p) for p in dao.get_all_players()) tournaments = dao.get_all_tournaments() for tournament in tournaments: print 'Processing:', tournament.name for player_id in tournament.players: player_date_map[player_id] = tournament.date for match in tournament.matches: winner = player_id_to_player_map[match.winner] loser = player_id_to_player_map[match.loser] rating_calculators.update_trueskill_ratings(winner=winner, loser=loser) excluded_players = set([p.id for p in dao.get_excluded_players()]) i = 1 players = player_id_to_player_map.values() sorted_players = sorted(players, key=lambda player: trueskill.expose(player.rating.trueskill_rating), reverse=True) ranking = [] for player in sorted_players: player_last_active_date = player_date_map.get(player.id) if player_last_active_date == None or dao.is_inactive(player, now) or player.id in excluded_players: pass # do nothing, skip this player else: ranking.append(RankingEntry(i, player.id, trueskill.expose(player.rating.trueskill_rating))) i += 1 print 'Updating players...' for p in players: dao.update_player(p) print 'Inserting new ranking...' dao.insert_ranking(Ranking(now, [t.id for t in tournaments], ranking)) print 'Done!'
def quality_json(rating): """ Convert a Rating into something more JSON serializeable, includes 'exposure' data :type rating: Rating :param rating: the rating to convert :param result: the result sent in initial payload :rtype: dict :return: dict """ return {'mu':rating.mu, 'sigma':rating.sigma, 'exposure':trueskill.expose(rating)}
def new_trueskill_rating(self, player_id, game_id, rating) -> None: """ :param player_id: The id of the player to update :param game_id: The id of the game that cause the update :param Rating rating: The new player rating :return: """ trueskill_update = (player_id, game_id, rating.mu, rating.sigma, expose(rating)) sql = ''' INSERT INTO trueskills(discord_id, game_id, mu, sigma, trueskill) VALUES(?, ?, ?, ?, ?) ''' cur = self.conn.cursor() cur.execute(sql, trueskill_update) self.conn.commit()
def forwards(self, orm): ids = orm['auth.User'].objects.values_list('id', flat=True) users = {i: trueskill.Rating() for i in ids} for game in orm.Game.objects.filter(confirmed=True).order_by('date_created'): wid = game.winner.id lid = game.loser.id users[wid], users[lid] = trueskill.rate_1vs1(users[wid], users[lid]) for id, rating in users.iteritems(): u = orm.Rating.objects.get(user__id=id) u.ts_rating = rating u.exposure = trueskill.expose(u.ts_rating) u.save()
def main(): parser = argparse.ArgumentParser(description='MadCars Bot Competition') parser.add_argument('-n', '--num-games', type=int, help='Total number of games', required=True) parser.add_argument('-d', '--model-dir', type=str, help='NN model root directory', required=True) parser.add_argument('-l', '--log-interval', type=int, help='Rating print interval', default=50) parser.add_argument('-c', '--cache-path', type=str, default='competition_cache.json', help='Ragings JSON cache') args = parser.parse_args() model_dir: str = args.model_dir num_games: int = args.num_games cache_path: str = args.cache_path log_interval: int = args.log_interval ts.setup(draw_probability=0.0001) loop = events.new_event_loop() events.set_event_loop(loop) clients = get_simple_bots() + get_nn_bots(model_dir) clients = load_ratings(cache_path, clients) games_played = 0 while games_played < num_games: games_played += log_interval ratings = run_competition(clients, log_interval) ratings = sorted(ratings, key=lambda t: -ts.expose(t[1])) save_ratings(cache_path, clients) print(f'-- RATINGS {games_played} --') for name, rating in ratings: print( f'{ts.expose(rating):4.1f} ({rating.mu:4.1f} +- {rating.sigma * 3:4.1f}): {name:<32}' )
def _update_rating(self, key, new_rating, opponent_key, did_win, did_lose): self.ratings[key] = new_rating self.opponents[key].add(opponent_key) wins = self.storage[key].wins loses = self.storage[key].loses # winner == None should not increase total wins or loses self.storage[key] = ScoredObject( key=key, score=trueskill.expose(new_rating), variable1=new_rating.mu, variable2=new_rating.sigma, rounds=self.storage[key].rounds + 1, opponents=len(self.opponents[key]), wins=wins + 1 if did_win else wins, loses=loses + 1 if did_lose else loses, )
def _update_rating(self, key, new_rating, opponent_key, winning_key): self.ratings[key] = new_rating self.opponents[key].add(opponent_key) wins = self.storage[key].wins loses = self.storage[key].loses # winning_key == None should not increase total wins or loses self.storage[key] = ScoredObject( key=key, score=trueskill.expose(new_rating), variable1=new_rating.mu, variable2=new_rating.sigma, rounds=self.storage[key].rounds + 1, opponents=len(self.opponents[key]), wins=wins + 1 if winning_key == key else wins, loses=loses + 1 if winning_key == opponent_key else loses, )
def plot_historical_rankings(historical_ratings): fig = plt.figure(figsize=(10, 5)) ax = plt.subplot(111) for player, history in historical_ratings.items(): rating_values = [ts.expose(x) for x in history] ax.plot(range(len(rating_values)), rating_values, label=player, marker='x') ax.grid() ax.set_xlabel("# Games") ax.set_ylabel("Rank") ax.set_title("Ranking over time") # Some fancy stuff to put the legend outside the plot box = ax.get_position() ax.set_position([box.x0, box.y0, box.width * 0.8, box.height]) ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))
def signup(): db = get_db() try: rating = ts.Rating() db.execute(''' INSERT INTO player (alias, nick, mu, sigma, exposure, won, lost, active) VALUES (?, ?, ?, ?, ?, 0, 0, 1);''', (request.form['alias'], request.form['nick'], rating.mu, rating.sigma, ts.expose(rating))) db.commit() except sqlite3.IntegrityError as e: flash(str(e)) return redirect(url_for('index'))
def to_series(self) -> pd.Series: return pd.Series({ 'name': self.name, 'rating': trueskill.expose(self.rating), 'wins': self.wins, 'losses': self.losses, 'kills': self.kills, 'deaths': self.deaths, 'assists': self.assists, 'kda': (self.kills + self.assists) / (self.deaths or 1), 'champs': self.unique_champs, })
def update(match_id, season_id, r_ids, b_ids, r_score, b_score): def get_rates(ids): # Get musigma user / create it if none res = [] for user_id in ids: pl = orm.to_json( orm.get_user_musigma_team.first(user_id, season_id)) rating = Rating(float(pl['mu']), float( pl['sigma'])) if pl is not None else Rating() res.append(rating) return res env_name = 'global' if not season_id else 'season' set_trueskill_env(env_name) env = get_trueskill_env(env_name) r_ids = [user_id for user_id in r_ids if user_id is not None] b_ids = [user_id for user_id in b_ids if user_id is not None] r_rates = get_rates(r_ids) b_rates = get_rates(b_ids) new_r_rates, new_b_rates = rate([r_rates, b_rates], ranks=[b_score, r_score]) # Lower is better new_rates = new_r_rates + new_b_rates new_expositions = [expose(r) for r in new_rates] with orm.transaction(): for idx, user_id in enumerate(r_ids + b_ids): # Init user to default stats if not already in base user_musigma_team = orm.to_json( orm.get_user_musigma_team(user_id, season_id)) if len(user_musigma_team) == 0: init_user(user_id, season_id) orm.create_user_musigma_team(user_id, match_id, season_id, new_expositions[idx], new_rates[idx].mu, new_rates[idx].sigma)
def get_score(self): """ :rtype : float """ return (trueskill.expose(self.rating) + trueskill.global_env().mu) * 3
def exposure(self): return trueskill.expose(self._rating)
def calculate_score_1vs1(self, key1_scored_object, key2_scored_object, winning_key, other_comparison_pairs): """ Calcualtes the scores for a new 1vs1 comparison without re-calculating all previous scores :param key1_scored_object: Contains score parameters for key1 :param key2_scored_object: Contains score parameters for key2 :param winning_key: indicates with key is the winning key :param other_comparison_pairs: Contains all previous comparison_pairs that the 2 keys took part in. This is a subset of all comparison pairs and is used to calculate round, wins, loses, and opponent counts :return: tuple of ScoredObject (key1, key2) """ self.storage = {} self.opponents = {} self.ratings = {} trueskill.setup() key1 = key1_scored_object.key key2 = key2_scored_object.key # Note: if value are None, trueskill.Rating will use default mu 25 and sigma 8.333 r1 = trueskill.Rating(mu=key1_scored_object.variable1, sigma=key1_scored_object.variable2) r2 = trueskill.Rating(mu=key2_scored_object.variable1, sigma=key2_scored_object.variable2) if winning_key == key1: r1, r2 = trueskill.rate_1vs1(r1, r2) elif winning_key == key2: r2, r1 = trueskill.rate_1vs1(r2, r1) else: raise InvalidWinningKeyException self.ratings[key1] = r1 self.ratings[key2] = r2 for key in [key1, key2]: self.opponents[key] = set() self.storage[key] = ScoredObject( key=key, score=trueskill.expose(self.ratings[key]), variable1=self.ratings[key].mu, variable2=self.ratings[key].sigma, rounds=0, opponents=0, wins=0, loses=0, ) # calculate opponents, wins, loses, rounds for every match for key1 and key2 for comparison_pair in other_comparison_pairs + [ComparisonPair(key1, key2, winning_key)]: cp_key1 = comparison_pair.key1 cp_key2 = comparison_pair.key2 cp_winning_key = comparison_pair.winning_key if cp_key1 == key1 or cp_key1 == key2: if cp_winning_key is None: self._update_rounds_only(cp_key1) else: self._update_result_stats(cp_key1, cp_key2, cp_winning_key) if cp_key2 == key1 or cp_key2 == key2: if cp_winning_key is None: self._update_rounds_only(cp_key2) else: self._update_result_stats(cp_key2, cp_key1, cp_winning_key) return (self.storage[key1], self.storage[key2])
def calculate_score_1vs1(self, key1_scored_object, key2_scored_object, winner, other_comparison_pairs): """ Calculates the scores for a new 1vs1 comparison without re-calculating all previous scores :param key1_scored_object: Contains score parameters for key1 :param key2_scored_object: Contains score parameters for key2 :param winner: indicates comparison winner :param other_comparison_pairs: Contains all previous comparison_pairs that the 2 keys took part in. This is a subset of all comparison pairs and is used to calculate round, wins, loses, and opponent counts :return: tuple of ScoredObject (key1, key2) """ self.storage = {} self.opponents = {} self.ratings = {} trueskill.setup() key1 = key1_scored_object.key key2 = key2_scored_object.key # Note: if value are None, trueskill.Rating will use default mu 25 and sigma 8.333 r1 = trueskill.Rating(mu=key1_scored_object.variable1, sigma=key1_scored_object.variable2) r2 = trueskill.Rating(mu=key2_scored_object.variable1, sigma=key2_scored_object.variable2) if winner == ComparisonWinner.key1: r1, r2 = trueskill.rate_1vs1(r1, r2) elif winner == ComparisonWinner.key2: r2, r1 = trueskill.rate_1vs1(r2, r1) elif winner == ComparisonWinner.draw: r1, r2 = trueskill.rate_1vs1(r1, r2, drawn=True) else: raise InvalidWinnerException self.ratings[key1] = r1 self.ratings[key2] = r2 for key in [key1, key2]: self.opponents[key] = set() self.storage[key] = ScoredObject(key=key, score=trueskill.expose( self.ratings[key]), variable1=self.ratings[key].mu, variable2=self.ratings[key].sigma, rounds=0, opponents=0, wins=0, loses=0) # calculate opponents, wins, loses, rounds for every match for key1 and key2 for comparison_pair in (other_comparison_pairs + [ComparisonPair(key1, key2, winner)]): cp_key1 = comparison_pair.key1 cp_key2 = comparison_pair.key2 cp_winner = comparison_pair.winner cp_key1_winner = cp_winner == ComparisonWinner.key1 cp_key2_winner = cp_winner == ComparisonWinner.key2 if cp_key1 == key1 or cp_key1 == key2: if cp_winner is None: self._update_rounds_only(cp_key1) else: self._update_result_stats(cp_key1, cp_key2, cp_key1_winner, cp_key2_winner) if cp_key2 == key1 or cp_key2 == key2: if cp_winner is None: self._update_rounds_only(cp_key2) else: self._update_result_stats(cp_key2, cp_key1, cp_key2_winner, cp_key1_winner) return (self.storage[key1], self.storage[key2])
def display_player(request, given_player): player_name = player.objects.get(name=given_player) matches = match.objects.filter(players__name=player_name.name) player_rating = expose(Rating(float(player_name.mu), float(player_name.sigma))) return render(request,'player_display.html',{'matches':matches, 'player':player_name, 'rating': player_rating})
def update_ratings_log(tm_rtngs, event, cnt): d = {tm: trueskill.expose(rtng) for (tm, rtng) in tm_rtngs.items()} d['event'] = event d['cnt'] = cnt return d
def record(): db = get_db() p1 = request.form['p1'] s1 = int(request.form['s1']) p2 = request.form['p2'] s2 = int(request.form['s2']) hi, lo = max(s1, s2), min(s1, s2) if (not ((hi == 2 and lo == 0) or (hi == 2 and lo == 1) or (hi == 3 and lo == 0) or (hi == 3 and lo == 1) or (hi == 3 and lo == 2))): flash('Ladder is based on 3 or 5 game matches only') return redirect(url_for('index')) if p1 == p2: flash('Match players must be different.') return redirect(url_for('index')) # check if this was a scheduled match scheduledrow = db.execute(''' SELECT (s.id) FROM schedule s JOIN player p1 ON s.p1 = p1.id JOIN player p2 ON s.p2 = p2.id WHERE p1.alias=? AND p2.alias=? OR p1.alias=? AND p2.alias=?;''', (p1, p2, p2, p1)).fetchone() scheduled = scheduledrow is not None if scheduled: db.execute('DELETE FROM schedule WHERE id=?;', (scheduledrow[0],)) if s1 > s2: win_alias, win_score, lose_alias, lose_score = p1, s1, p2, s2 else: win_alias, win_score, lose_alias, lose_score = p2, s2, p1, s1 date_string = request.form['date'] + ' ' if ':' in request.form['time']: date_string += request.form['time'] + ' ' else: date_string += request.form['time'] + ':00 ' date_string += 'PM' if 'ampm' in request.form else 'AM' try: date = datetime.strptime(date_string, "%m/%d/%Y %I:%M %p") except: flash('Invalid time format') return redirect(url_for('index')) db.execute(''' INSERT INTO match (winner, loser, winscore, losescore, date, scheduled) SELECT w.id, l.id, ?, ?, ?, ? FROM player w JOIN player l WHERE w.alias = ? AND l.alias = ?;''', (win_score, lose_score, date, scheduled, win_alias, lose_alias)) def get_rating(alias): sql = 'SELECT mu, sigma FROM player WHERE alias=?;' row = db.execute(sql, (alias,)).fetchone() if row is None: flash('Alias ' + alias + ' does not exist.') return None return ts.Rating(mu=row['mu'], sigma=row['sigma']) win_rating = get_rating(win_alias) lose_rating = get_rating(lose_alias) if win_rating is None or lose_rating is None: return redirect(url_for('index')) win_rating, lose_rating = ts.rate_1vs1(win_rating, lose_rating) win_exposure = ts.expose(win_rating); lose_exposure = ts.expose(lose_rating); db.execute(''' UPDATE player SET exposure=?, mu=?, sigma=?, won=won+1 WHERE alias=?;''', (win_exposure, win_rating.mu, win_rating.sigma, win_alias)); db.execute(''' UPDATE player SET exposure=?, mu=?, sigma=?, lost=lost+1 WHERE alias=?;''', (lose_exposure, lose_rating.mu, lose_rating.sigma, lose_alias)); db.commit() return redirect(url_for('index'))
continue # duel if len(set(thisRating)) != len(thisRating): print('Players are not unique') continue # same players print('Game is ok') thisRates = [] for player in thisRating: if player not in players: rating[player] = trueskill.Rating() players.add(player) thisRates.append((rating[player], )) thisRates = trueskill.rate(thisRates) for (player, rate) in zip(thisRating, thisRates): rating[player] = rate[0] return rating rating = getRating() sortedRating = sorted(rating.items(), key=lambda kv: trueskill.expose(kv[1]), reverse=True) result = "" for (num, rate) in enumerate(sortedRating): result += '{}) [{}](https://aicups.ru{}) ({})\n'.format( num + 1, rate[0][0], rate[0][1], str(rate[1])) with open('rating.txt', 'w', encoding='utf8') as f: f.write(result)
def generate_ranking(dao, now=datetime.now(), day_limit=60, num_tourneys=2, tournament_qualified_day_limit=999): try: logger.info('Beginning ranking calculation for ' + str(dao.region_id)) player_date_map = {} player_id_to_player_map = {} ranking_tournaments = [] tournament_qualified_date = ( now - timedelta(days=tournament_qualified_day_limit)) print('Qualified Date: ' + str(tournament_qualified_date)) logger.info('Qualified Date: ' + str(tournament_qualified_date)) tournaments = dao.get_all_tournaments(regions=[dao.region_id]) for tournament in tournaments: if tournament.excluded is True: print 'Tournament Excluded:' print 'Excluded - ' + str(tournament.name) logger.warning('Tournament Excluded: ' + str(tournament.name)) continue if tournament_qualified_date <= tournament.date: ranking_tournaments.append(tournament) print 'Processing:', tournament.name.encode('utf-8'), str( tournament.date) logger.info('Processing: ' + tournament.name.encode('utf-8') + ", " + str(tournament.date)) for player_id in tournament.players: player_date_map[player_id] = tournament.date # TODO add a default rating entry when we add it to the map for match in tournament.matches: if match.excluded is True: print('match excluded:') print('Tournament: ' + str(tournament.name)) print(str(match)) logger.debug('Match excluded: ' + str(match) + ' Tournament: ' + str(tournament.name)) continue logger.debug('Getting winner and loser') # don't count matches where either player is OOR winner = dao.get_player_by_id(match.winner) logger.debug('Winner: ' + str(winner)) if winner is None: logger.warning( 'Player found as NoneType. Skipping match') continue elif dao.region_id not in winner.regions: continue loser = dao.get_player_by_id(match.loser) logger.debug('Loser: ' + str(loser)) if loser is None: logger.warning( 'Player found as NoneType. Skipping match') continue elif dao.region_id not in loser.regions: continue if match.winner not in player_id_to_player_map: db_player = dao.get_player_by_id(match.winner) db_player.ratings[dao.region_id] = model.Rating() player_id_to_player_map[match.winner] = db_player if match.loser not in player_id_to_player_map: db_player = dao.get_player_by_id(match.loser) db_player.ratings[dao.region_id] = model.Rating() player_id_to_player_map[match.loser] = db_player winner = player_id_to_player_map[match.winner] loser = player_id_to_player_map[match.loser] rating_calculators.update_trueskill_ratings(dao.region_id, winner=winner, loser=loser) else: logger.debug('Tournament ' + str(tournament.name) + ' outside qualified date. Skipping.') print 'Checking for player inactivity...' logger.info('Checking for player inactivity...') rank = 1 players = player_id_to_player_map.values() sorted_players = sorted( players, key=lambda player: trueskill.expose(player.ratings[dao.region_id]. trueskill_rating()), reverse=True) ranking = [] for player in sorted_players: if player is None: logger.warning( 'NoneType player found while checking inactivity. Skipping.' ) continue player_last_active_date = player_date_map.get(player.id) if player_last_active_date is None or \ dao.is_inactive(player, now, day_limit, num_tourneys) or \ dao.region_id not in player.regions: logger.debug('Player ' + player.name + ' outside of ranking criteria. Skipping.') pass # do nothing, skip this player else: logger.debug('Player ' + player.name + ' updating.') ranking.append( model.RankingEntry( rank=rank, player=player.id, rating=trueskill.expose( player.ratings[dao.region_id].trueskill_rating()))) rank += 1 print 'Updating players...' logger.info('Updating players...') for i, p in enumerate(players, start=1): if p is None: logger.warning( 'NoneType player found while updating. Skipping.') continue logger.debug('Updating player ' + p.name) dao.update_player(p) # TODO: log somewhere later # print 'Updated player %d of %d' % (i, len(players)) print 'Inserting new ranking...' logger.info('Inserting new ranking...') dao.insert_ranking( model.Ranking(id=ObjectId(), region=dao.region_id, time=now, tournaments=[t.id for t in ranking_tournaments], ranking=ranking)) print 'Done!' logger.info('Done!') except Exception as e: print str(e) logger.error(str(e)) tb = traceback.format_exc() logging.error(tb)
def calc_leaderboard(state): return [(p, ts.expose(r)) for p, r in state.items()]
def public_rating(self): # trueskill mu-3*sigma ratings are usually from 0-50, # so we double them to 0-100 return 2*trueskill.expose(self.rating)
def elo(self, rating=None): if rating is None: rating = self.rating return trueskill.expose(rating)
def ComputeRatingsAndRecords(conn, singles, doubles, verbose): temp_players = GetAllPlayers(conn) playerNames = GetIdPlayerNameDict(conn) players = {} playerRecords = {} playerProgress = {} for p in temp_players: pid = p['id'] players[pid] = ts.Rating() playerRecords[pid] = (0, 0, 0) playerProgress[pid] = [] games = GetAllGames(conn) tSkill = ts.TrueSkill() lastId = 0 for g in games: p = (g['player1'], g['player2'], g['player3'], g['player4']) ok = False if p[1] == 0 and singles: team1 = {p[0]: players[p[0]]} team2 = {p[2]: players[p[2]]} ok = True if p[1] != 0 and doubles: team1 = {p[0]: players[p[0]], p[1]: players[p[1]]} team2 = {p[2]: players[p[2]], p[3]: players[p[3]]} ok = True if not ok: continue s = (g['score1'], g['score2']) am = g['gametype'] == 1 for i in range(0, 4): if p[i] == 0: continue (win, draw, loss) = playerRecords[p[i]] myScoreIndex = 0 if i < 2 else 1 otherScoreIndex = 1 - myScoreIndex if s[0] == s[1]: draw += 1 if s[myScoreIndex] > s[otherScoreIndex]: win += 1 if s[myScoreIndex] < s[otherScoreIndex]: loss += 1 playerRecords[p[i]] = (win, draw, loss) newRatings = flatten(PlayGame_(tSkill, team1, team2, s[0], s[1], am)) if verbose: if p[1] == 0: print("({}) vs ({}) {}-{} {}".format( playerNames[p[0]], playerNames[p[2]], s[0], s[1], "Americano" if am else "")) else: print("({} {}) vs ({} {}) {}-{} {}".format( playerNames[p[0]], playerNames[p[1]], playerNames[p[2]], playerNames[p[3]], s[0], s[1], "Americano" if am else "")) for t in newRatings: exp = ts.expose(newRatings[t]) if verbose: diffMu = newRatings[t].mu - players[t].mu diffRank = exp - ts.expose(players[t]) print("\t{}: mu:{} rank:{}".format(playerNames[t], diffMu, diffRank)) players[t] = newRatings[t] if len(playerProgress[t]) == 0: playerProgress[t].append((g['id'] - 1, 0.0)) playerProgress[t].append((g['id'], exp)) lastId = g['id'] toRemove = [] for t in playerProgress: if len(playerProgress[t]) == 0: toRemove.append(t) else: last = playerProgress[t][-1] if last != None and last[0] != lastId: playerProgress[t].append((lastId, last[1])) if singles != doubles and len(toRemove) > 0: for t in toRemove: del players[t] del playerRecords[t] del playerProgress[t] return (players, playerRecords, playerProgress)
winners.append(team_ratings[team]) losers = [] for team in match['alliances'][loser]['team_keys']: if team not in team_ratings: team_ratings[team] = trueskill.Rating() losers.append(team_ratings[team]) ratings_obj = [tuple(winners), tuple(losers)] ratings_obj = trueskill.rate(ratings_obj, ranks=outcome) for idx, team in enumerate(match['alliances'][winner]['team_keys']): team_ratings[team] = ratings_obj[0][idx] for idx, team in enumerate(match['alliances'][loser]['team_keys']): team_ratings[team] = ratings_obj[1][idx] ratings_list = [] for team in team_ratings: ratings_list.append({ 'team': team, 'rating': trueskill.expose(team_ratings[team]) }) ratings_list = sorted(ratings_list, key=lambda k: k['rating'], reverse=True) gen.listOfDictToCSV(dist + ' TrueSkill Ratings', ratings_list, ['team', 'rating'])
def _create_ranking_from_tournament_list( dao, tournaments, now, day_limit, num_tourneys, tournament_qualified_day_limit, ranking_to_diff_against): player_date_map = {} player_id_to_player_map = {} tournament_qualified_date = (now - timedelta(days=tournament_qualified_day_limit)) print('Qualified Date: ' + str(tournament_qualified_date)) for tournament in tournaments: if tournament_qualified_date <= tournament.date: print 'Processing:', tournament.name.encode('utf-8'), str(tournament.date) for player_id in tournament.players: player_date_map[player_id] = tournament.date # TODO add a default rating entry when we add it to the map for match in tournament.matches: if match.excluded is True: print('match excluded:') print('Tournament: ' + str(tournament.name)) print(str(match)) continue if match.winner not in player_id_to_player_map: db_player = dao.get_player_by_id(match.winner) db_player.ratings[dao.region_id] = model.Rating() player_id_to_player_map[match.winner] = db_player if match.loser not in player_id_to_player_map: db_player = dao.get_player_by_id(match.loser) db_player.ratings[dao.region_id] = model.Rating() player_id_to_player_map[match.loser] = db_player winner = player_id_to_player_map[match.winner] loser = player_id_to_player_map[match.loser] rating_calculators.update_trueskill_ratings( dao.region_id, winner=winner, loser=loser) print 'Checking for player inactivity...' rank = 1 players = player_id_to_player_map.values() sorted_players = sorted( players, key=lambda player: (trueskill.expose(player.ratings[dao.region_id].trueskill_rating()), player.name), reverse=True) ranking = [] for player in sorted_players: player_last_active_date = player_date_map.get(player.id) if _is_player_inactive(dao, player, tournaments, player_last_active_date, now, day_limit, num_tourneys): pass # do nothing, skip this player else: ranking.append(model.RankingEntry( rank=rank, player=player.id, rating=trueskill.expose(player.ratings[dao.region_id].trueskill_rating()), previous_rank=ranking_to_diff_against.get_ranking_for_player_id(player.id) if ranking_to_diff_against else None)) rank += 1 print 'Updating players...' for i, p in enumerate(players, start=1): dao.update_player(p) # TODO: log somewhere later # print 'Updated player %d of %d' % (i, len(players)) print 'Returning new ranking...' return model.Ranking( id=ObjectId(), region=dao.region_id, time=now, tournaments=[t.id for t in tournaments], ranking=ranking)
def generate_ranking(dao, now=datetime.now(), day_limit=60, num_tourneys=2, tournament_qualified_day_limit=999): player_date_map = {} player_id_to_player_map = {} tournament_qualified_date = (now - timedelta(days=tournament_qualified_day_limit)) print('Qualified Date: ' + str(tournament_qualified_date)) tournaments = dao.get_all_tournaments(regions=[dao.region_id]) for tournament in tournaments: if tournament.excluded is True: print 'Tournament Excluded:' print 'Excluded - ' + str(tournament.name) continue if tournament_qualified_date <= tournament.date: print 'Processing:', tournament.name.encode('utf-8'), str(tournament.date) for player_id in tournament.players: player_date_map[player_id] = tournament.date # TODO add a default rating entry when we add it to the map for match in tournament.matches: if match.excluded is True: print('match excluded:') print('Tournament: ' + str(tournament.name)) print(str(match)) continue # don't count matches where either player is OOR winner = dao.get_player_by_id(match.winner) if dao.region_id not in winner.regions: continue loser = dao.get_player_by_id(match.loser) if dao.region_id not in loser.regions: continue if match.winner not in player_id_to_player_map: db_player = dao.get_player_by_id(match.winner) db_player.ratings[dao.region_id] = model.Rating() player_id_to_player_map[match.winner] = db_player if match.loser not in player_id_to_player_map: db_player = dao.get_player_by_id(match.loser) db_player.ratings[dao.region_id] = model.Rating() player_id_to_player_map[match.loser] = db_player winner = player_id_to_player_map[match.winner] loser = player_id_to_player_map[match.loser] rating_calculators.update_trueskill_ratings( dao.region_id, winner=winner, loser=loser) print 'Checking for player inactivity...' rank = 1 players = player_id_to_player_map.values() sorted_players = sorted( players, key=lambda player: trueskill.expose(player.ratings[dao.region_id].trueskill_rating()), reverse=True) ranking = [] for player in sorted_players: player_last_active_date = player_date_map.get(player.id) if player_last_active_date is None or \ dao.is_inactive(player, now, day_limit, num_tourneys) or \ dao.region_id not in player.regions: pass # do nothing, skip this player else: ranking.append(model.RankingEntry( rank=rank, player=player.id, rating=trueskill.expose(player.ratings[dao.region_id].trueskill_rating()))) rank += 1 print 'Updating players...' for i, p in enumerate(players, start=1): dao.update_player(p) # TODO: log somewhere later # print 'Updated player %d of %d' % (i, len(players)) print 'Inserting new ranking...' dao.insert_ranking(model.Ranking( id=ObjectId(), region=dao.region_id, time=now, tournaments=[t.id for t in tournaments], ranking=ranking)) print 'Done!'
beta=100.0, tau=2.0, draw_probability=0.01, backend="scipy") env = gym.make("hex-v0", opponent_policy=None, board_size=5) env.reset() sim = env.simulator agent_pool = [MCTSAgent(sim, depth=d) for d in [10, 50, 100, 250, 500, 750, 1000, 1250, 1500]] agent_pool += [RandomAgent(board_size=5)] for game_idx in range(5000): # pick the agent we are most uncertain about sigmas = [agent.rating.sigma for agent in agent_pool] player1_idx = np.argmax(sigmas) player1 = agent_pool[player1_idx] player2 = find_match(player1, agent_pool) print("---") print(f"MATCH {game_idx}: {player1} vs. {player2}") play_match(player1, player2, sim=sim) leaderboard = sorted(agent_pool, key=lambda x: trueskill.expose(x.rating), reverse=True) for agent in leaderboard: print(f" {agent} mu:{agent.rating.mu:.2f} sigma:{agent.rating.sigma:.2f}") ratings = {str(agent): {"mu": agent.rating.mu, "sigma": agent.rating.sigma} for agent in agent_pool} with open("mcts_eval.json", "w") as json_file: json.dump(ratings, json_file)
def save(self, *args, **kwargs): self.exposure = trueskill.expose(self.ts_rating) super(Rating, self).save(*args, **kwargs)
def generate_ranking(dao, now=datetime.now(), day_limit=60, num_tourneys=2, tournament_qualified_day_limit=999): player_date_map = {} player_id_to_player_map = {} tournament_qualified_date = ( now - timedelta(days=tournament_qualified_day_limit)) print('Qualified Date: ' + str(tournament_qualified_date)) tournaments = dao.get_all_tournaments(regions=[dao.region_id]) for tournament in tournaments: if tournament.excluded is True: print 'Tournament Excluded:' print 'Excluded - ' + str(tournament.name) continue if tournament_qualified_date <= tournament.date: print 'Processing:', tournament.name.encode('utf-8'), str( tournament.date) for player_id in tournament.players: player_date_map[player_id] = tournament.date # TODO add a default rating entry when we add it to the map for match in tournament.matches: if match.excluded is True: print('match excluded:') print('Tournament: ' + str(tournament.name)) print(str(match)) continue # don't count matches where either player is OOR winner = dao.get_player_by_id(match.winner) if dao.region_id not in winner.regions: continue loser = dao.get_player_by_id(match.loser) if dao.region_id not in loser.regions: continue if match.winner not in player_id_to_player_map: db_player = dao.get_player_by_id(match.winner) db_player.ratings[dao.region_id] = model.Rating() player_id_to_player_map[match.winner] = db_player if match.loser not in player_id_to_player_map: db_player = dao.get_player_by_id(match.loser) db_player.ratings[dao.region_id] = model.Rating() player_id_to_player_map[match.loser] = db_player winner = player_id_to_player_map[match.winner] loser = player_id_to_player_map[match.loser] rating_calculators.update_trueskill_ratings(dao.region_id, winner=winner, loser=loser) print 'Checking for player inactivity...' rank = 1 players = player_id_to_player_map.values() sorted_players = sorted(players, key=lambda player: trueskill.expose(player.ratings[ dao.region_id].trueskill_rating()), reverse=True) ranking = [] for player in sorted_players: player_last_active_date = player_date_map.get(player.id) if player_last_active_date is None or \ dao.is_inactive(player, now, day_limit, num_tourneys) or \ dao.region_id not in player.regions: pass # do nothing, skip this player else: ranking.append( model.RankingEntry( rank=rank, player=player.id, rating=trueskill.expose( player.ratings[dao.region_id].trueskill_rating()))) rank += 1 print 'Updating players...' for i, p in enumerate(players, start=1): dao.update_player(p) # TODO: log somewhere later # print 'Updated player %d of %d' % (i, len(players)) print 'Inserting new ranking...' dao.insert_ranking( model.Ranking(id=ObjectId(), region=dao.region_id, time=now, tournaments=[t.id for t in tournaments], ranking=ranking)) print 'Done!'