Instantly share code, notes, and snippets.

# klenwell/trueskill.py Last active Aug 29, 2015

Trueskill Prediction Simulation
 import random from math import sqrt from trueskill import TrueSkill, Rating, quality_1vs1, rate_1vs1, BETA from trueskill.backends import cdf # From https://github.com/sublee/trueskill/issues/1#issuecomment-10491635 def win_probability(team_rating, opponent_rating): delta_mu = team_rating.mu - opponent_rating.mu denom = sqrt(2 * (BETA * BETA) + pow(team_rating.sigma, 2) + pow(opponent_rating.sigma, 2)) win_prob = cdf(delta_mu / denom) return win_prob NUM_MATCHES = 1000 total_predictions = 0 correct_predictions = 0 class Player: def __init__(self, name, talent): self.name = name self.talent = talent self.rating = Rating() self.wins = 0 self.losses = 0 self.draws = 0 @property def record(self): return '%d-%d-%d' % (self.wins, self.losses, self.draws) @property def mu_sigma(self): return '%d~%d' % (round(self.rating.mu * 10), round(self.rating.sigma * 10)) def __repr__(self): return 'Player(%s) %s [%s]' % (self.name, self.record, self.mu_sigma) # Create players players = [ Player('Alice', 50), Player('Bob', 60), Player('Carol', 66), Player('Dave', 67), Player('Emily', 67), Player('Felix', 75) ] for n in range(NUM_MATCHES): away, home = random.sample(players, 2) match_quality = quality_1vs1(away.rating, home.rating) away_win_prob = win_probability(away.rating, home.rating) if away_win_prob < .33: prediction = 'LOSS' elif away_win_prob > .66: prediction = 'WIN' else: prediction = 'TOSS-UP' print 'Matchup: %s (%s) at %s (%s)' % ( away.name, away.record, home.name, home.record, ) print 'Rating Before: %s / %s' % (away.mu_sigma, home.mu_sigma) print 'Match Quality: %.2f' % (match_quality) print '%s odds winning: %.1f%% [predict: %s]' % ( away.name, away_win_prob * 100, prediction ) away_score = random.randint(0, away.talent) home_score = random.randint(0, home.talent) is_draw = away_score == home_score if is_draw: away.draws += 1 home.draws += 1 away.rating, home.rating = rate_1vs1(away.rating, home.rating, drawn=True) print '%s and %s tied at %d' % (away.name, home.name, away_score) else: winner = (away_score > home_score) and away or home loser = (away_score < home_score) and away or home winner.rating, loser.rating = rate_1vs1(winner.rating, loser.rating) winner.wins += 1 loser.losses += 1 print '%s beats %s (%d - %d)' % (winner.name, loser.name, max(away_score, home_score), min(away_score, home_score)) # Update prediction prediction_result = None if prediction == 'WIN': total_predictions += 1 if winner == away: correct_predictions += 1 prediction_result = 'SUCCESS' else: prediction_result = 'FAIL' elif prediction == 'LOSS': total_predictions += 1 if loser == away: correct_predictions += 1 prediction_result = 'SUCCESS' else: prediction_result = 'FAIL' print 'Prediction: %s --> %s' % (prediction, prediction_result) print 'Rating After: %s / %s' % (away.mu_sigma, home.mu_sigma) print "\n" for player in players: print player print "Predicted: %d of %d (%.1f%%)" % ( correct_predictions, total_predictions, float(correct_predictions) / total_predictions * 100 )
Owner Author

### klenwell commented Jan 19, 2015

 Sample output: ``````Matchup: Felix (83-73-2) at Emily (89-73-3) Rating Before: 255~8 / 261~8 Match Quality: 0.98 Felix odds winning: 29.1% [predict: LOSS] Felix beats Emily (44 - 5) Prediction: LOSS --> FAIL Rating After: 256~8 / 260~8 ... Player(Alice) 52-117-4 [227~8] Player(Bob) 87-79-3 [253~8] Player(Carol) 96-72-1 [249~8] Player(Dave) 83-76-5 [256~8] Player(Emily) 89-74-3 [260~8] Player(Felix) 84-73-2 [256~8] Predicted: 205 of 362 (56.6%) ``````