]> git.xonotic.org Git - xonotic/xonstat.git/blobdiff - xonstat/glicko.py
Work on the process() method.
[xonotic/xonstat.git] / xonstat / glicko.py
index 2c0b5e089b85bd4ec8552b2da14bac4a4c9c8770..85d2641c80f7575e00479ff3710f81b046aaf402 100644 (file)
@@ -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):
         """