X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=xonstat%2Fglicko.py;h=85d2641c80f7575e00479ff3710f81b046aaf402;hb=e26be81d2e0ce455c83f432527c73de63b464187;hp=2c0b5e089b85bd4ec8552b2da14bac4a4c9c8770;hpb=b04a0bd16b13a9e69891bbc1aafa3a06450ee31c;p=xonotic%2Fxonstat.git diff --git a/xonstat/glicko.py b/xonstat/glicko.py index 2c0b5e0..85d2641 100644 --- a/xonstat/glicko.py +++ b/xonstat/glicko.py @@ -13,6 +13,9 @@ log = logging.getLogger(__name__) # the default system volatility constant TAU = 0.3 +# how much ping influences results +LATENCY_TREND_FACTOR = 0.2 + def calc_g(phi): return 1 / math.sqrt(1 + (3 * phi ** 2) / (math.pi ** 2)) @@ -251,7 +254,7 @@ class GlickoProcessor(object): pgstat.alivetime = game.duration # ensure players played enough of the match to be included - k = KREDUCTION.eval(pgstat.alivetime.seconds, game.duration.seconds) + k = KREDUCTION.eval(pgstat.alivetime.total_seconds(), game.duration.total_seconds()) if k <= 0.0: continue else: @@ -303,8 +306,9 @@ class GlickoProcessor(object): # pi/j => ping ratio for player i/j for i in xrange(0, len(pgstats)): wipi = self._load_glicko_wip(pgstats[i].player_id, game_type_cd, category) - ki = KREDUCTION.eval(pgstats[i].alivetime.seconds, game.duration.seconds) - si = pgstats[i].score/float(game.duration.seconds) + ki = KREDUCTION.eval(pgstats[i].alivetime.total_seconds(), + game.duration.total_seconds()) + si = pgstats[i].score/float(game.duration.total_seconds()) for j in xrange(i+1, len(pgstats)): # ping factor is opponent-specific @@ -312,7 +316,8 @@ class GlickoProcessor(object): pj = 1.0 - pi wipj = self._load_glicko_wip(pgstats[j].player_id, game_type_cd, category) - kj = KREDUCTION.eval(pgstats[j].alivetime.seconds, game.duration.seconds) + kj = KREDUCTION.eval(pgstats[j].alivetime.total_seconds(), + game.duration.total_seconds()) sj = pgstats[j].score/float(game.duration.seconds) # normalize scores @@ -338,9 +343,24 @@ class GlickoProcessor(object): def process(self): """ Calculate the Glicko2 ratings, deviations, and volatility updates for the records loaded. - :return: bool """ - pass + for wip in self.wips.values(): + new_pg = rate(wip.pg, wip.opponents, wip.results) + + log.debug("New rating for player {} before factors: mu={} phi={} sigma={}" + .format(pg.player_id, new_pg.mu, new_pg.phi, new_pg.sigma)) + + avg_k_factor = sum(wip.k_factors)/len(wip.k_factors) + avg_ping_factor = LATENCY_TREND_FACTOR * sum(wip.ping_factors)/len(wip.ping_factors) + + points_delta = (new_pg.mu - wip.pg.mu) * avg_k_factor * avg_ping_factor + + wip.pg.mu += points_delta + wip.pg.phi = new_pg.phi + wip.pg.sigma = new_pg.sigma + + log.debug("New rating for player {} after factors: mu={} phi={} sigma={}" + .format(wip.pg.player_id, wip.pg.mu, wip.pg.phi, wip.pg.sigma)) def save(self, session): """