1
1
from bisect import bisect
2
- from math import pi , sqrt , tanh
2
+ from math import inf , pi , sqrt , tanh
3
3
from operator import attrgetter , itemgetter
4
4
5
5
from django .db import transaction
19
19
VAR_LIM = (sqrt (VAR_PER_CONTEST ** 2 + 4 * BETA2 * VAR_PER_CONTEST ) - VAR_PER_CONTEST ) / 2
20
20
SD_LIM = sqrt (VAR_LIM )
21
21
TANH_C = sqrt (3 ) / pi
22
+ PERF_CEILING_INCREMENT = 400
22
23
23
24
24
25
def tie_ranker (iterable , key = attrgetter ('points' )):
@@ -77,7 +78,7 @@ def get_var(times_ranked, cache=[VAR_INIT]):
77
78
return cache [times_ranked ]
78
79
79
80
80
- def recalculate_ratings (ranking , old_mean , times_ranked , historical_p ):
81
+ def recalculate_ratings (ranking , old_mean , times_ranked , historical_p , perf_ceiling ):
81
82
n = len (ranking )
82
83
new_p = [0. ] * n
83
84
new_mean = [0. ] * n
@@ -96,7 +97,7 @@ def solve_idx(i, bounds=VALID_RANGE):
96
97
elif s < r : # s beats r
97
98
y_tg -= 1. / d
98
99
# Otherwise, this is a tie that counts as half a win, as per Elo-MMR.
99
- new_p [i ] = solve (p_tanh_terms , y_tg , bounds = bounds )
100
+ new_p [i ] = min ( perf_ceiling , solve (p_tanh_terms , y_tg , bounds = bounds ) )
100
101
101
102
# Fill all indices between i and j, inclusive. Use the fact that new_p is non-increasing.
102
103
def divconq (i , j ):
@@ -160,6 +161,9 @@ def rate_contest(contest):
160
161
users = users .exclude (last_rating__lt = contest .rating_floor )
161
162
if contest .rating_ceiling is not None :
162
163
users = users .exclude (last_rating__gt = contest .rating_ceiling )
164
+ perf_ceiling = contest .rating_ceiling + PERF_CEILING_INCREMENT
165
+ else :
166
+ perf_ceiling = inf
163
167
164
168
users = list (users )
165
169
participation_ids = list (map (itemgetter ('id' ), users ))
@@ -176,7 +180,7 @@ def rate_contest(contest):
176
180
idx = user_id_to_idx [h ['user_id' ]]
177
181
historical_p [idx ].append (h ['performance' ])
178
182
179
- rating , mean , performance = recalculate_ratings (ranking , old_mean , times_ranked , historical_p )
183
+ rating , mean , performance = recalculate_ratings (ranking , old_mean , times_ranked , historical_p , perf_ceiling )
180
184
181
185
now = timezone .now ()
182
186
ratings = [Rating (user_id = i , contest = contest , rating = r , mean = m , performance = perf ,
0 commit comments