prologin2014_ranking

Scripts to compute the final ranking of Prologin 2014
git clone https://esimon.eu/repos/prologin2014_ranking
Log | Files | Refs | README

commit 972e2af4bbf850f03de2459ef45470f91b412069
parent 10c4d0f280921a79b3c89e44b41bd1eb39d49ede
Author: Étienne Simon <esimon@esimon.eu>
Date:   Sun,  3 May 2015 19:34:35 +0000

Commenting

Diffstat:
Mrank.py | 28+++++++++++++++++++++++++---
1 file changed, 25 insertions(+), 3 deletions(-)

diff --git a/rank.py b/rank.py @@ -13,13 +13,27 @@ sys.path.insert(0, '/root/sadm/python-lib') from django.contrib.auth.models import User from prologin.concours.stechec.models import * -sample_size = 1 +# Number of players per game party_size = 4 + +# Quality of sampling new members for a party +sample_size = 1 + +# The conservative score (aka "at least this good") is : mean - conservativeness * stddev conservativeness = 3 + +# Number of matches running at the same time max_concurrent_matches = 250 + +# Maximum number of simultaneous matches per player concurrent_match_per_player = 50 + +# Maximum difference in number of concurrent matches between the player who is playing the most and the one who is playing the least min_ppp_margin = 2 + +# Frequency (in number of launched games) at which game results are gathered update_score_frequency = 100 + tournament_name='Tournoi final' filepath=sys.argv[1] @@ -31,6 +45,7 @@ nb_match_per_player = {} champions = {} users = {} for user in ratings.keys(): + # The last non deleted champion of a user champion = Champion.objects.filter(author__username=user).order_by('-ts').exclude(deleted=True)[0].pk nb_match_per_player[user] = 0 champions[user] = champion @@ -77,21 +92,26 @@ def can_enter_match(user): return nb_match_per_player[user] < concurrent_match_per_player def match_making(): + # Number of game of the player who is playing the least min_ppp = min(nb_match_per_player.values()) pick_from_me = [ user for user in ratings.keys() if nb_match_per_player[user] <= min_ppp + min_ppp_margin] ready = list(filter(can_enter_match, ratings.keys())) + + # The player with the most uncertain rating, he'll be in the party no matter what fuzziest = max(pick_from_me, key=lambda x: ratings[x].sigma) ready.remove(fuzziest) - sample_me = [] + # Fill sample_me with available ("ready") players, the remaining (party_size-1) players to be picked will be consecutive players in this array + # The //x*x is done so that sample_me is extend with arrays of size multiple of (party_size-1), this mean we can't sample a party from two different shuffled ready arrays, since doing so might result in a match with the same player appearing twice + sample_me = [] for _ in range(sample_size): shuffle(ready) sample_me += ready[:len(ready)//(party_size-1)*(party_size-1)] + # We pick the remaining (party_size-1) players from sample_me to maximize the match quality max_qual = -1 max_party = None - for i in range(len(sample_me)//(party_size-1)): party_minus_1 = sample_me[(party_size-1)*i:(party_size-1)*(i+1)] party = party_minus_1 + [ fuzziest ] @@ -104,6 +124,7 @@ def match_making(): return max_party +# update ratings given the result of a match in a dictionary {user: score} def update(scores): for key in scores: nb_match_per_player[key] -= 1 @@ -119,6 +140,7 @@ def update(scores): with open(filepath, 'wb') as f: pickle.dump(ratings, f) +# Check if any matches finished and update ratings accordingly def update_scores(): global current_matches remove_me = []