]> de.git.xonotic.org Git - xonotic/xonstat.git/commitdiff
It works! Still need to remove the commented out sections, however.
authorAnt Zucaro <azucaro@gmail.com>
Fri, 13 Jan 2012 02:12:16 +0000 (21:12 -0500)
committerAnt Zucaro <azucaro@gmail.com>
Fri, 13 Jan 2012 02:12:16 +0000 (21:12 -0500)
xonstat/elo.py
xonstat/models.py

index 4ba3553b272c1ef76fb3ec07f22861465146b46c..9d1d4674e08eaced689890b8e2821200764395c7 100755 (executable)
@@ -36,58 +36,6 @@ class KReduction:
         return k\r
 \r
 \r
-# For team games where multiple scores and elos are at play, the elos\r
-# must be adjusted according to their strength relative to the player\r
-# in the next-lowest scoreboard position.\r
-def update(elos, ep):\r
-    for x in elos:\r
-        if x.elo == None:\r
-            x.elo = ep.initial\r
-        x.eloadjust = 0\r
-    if len(elos) < 2:\r
-        return elos\r
-    for i in xrange(0, len(elos)):\r
-        ei = elos[i]\r
-        for j in xrange(i+1, len(elos)):\r
-            ej = elos[j]\r
-            si = ei.score\r
-            sj = ej.score\r
-\r
-            # normalize scores\r
-            ofs = min(0, si, sj)\r
-            si -= ofs\r
-            sj -= ofs\r
-            if si + sj == 0:\r
-                si, sj = 1, 1 # a draw\r
-\r
-            # real score factor\r
-            scorefactor_real = si / float(si + sj)\r
-\r
-            # estimated score factor by elo\r
-            elodiff = min(ep.maxlogdistance, max(-ep.maxlogdistance, (ei.elo - ej.elo) * ep.logdistancefactor))\r
-            scorefactor_elo = 1 / (1 + math.exp(-elodiff))\r
-\r
-            # how much adjustment is good?\r
-            # scorefactor(elodiff) = 1 / (1 + e^(-elodiff * logdistancefactor))\r
-            # elodiff(scorefactor) = -ln(1/scorefactor - 1) / logdistancefactor\r
-            # elodiff'(scorefactor) = 1 / ((scorefactor) (1 - scorefactor) logdistancefactor)\r
-            # elodiff'(scorefactor) >= 4 / logdistancefactor\r
-\r
-            # adjust'(scorefactor) = K1 + K2\r
-\r
-            # so we want:\r
-            # K1 + K2 <= 4 / logdistancefactor <= elodiff'(scorefactor)\r
-            # as we then don't overcompensate\r
-\r
-            adjustment = scorefactor_real - scorefactor_elo\r
-            ei.eloadjust += adjustment\r
-            ej.eloadjust -= adjustment\r
-    for x in elos:\r
-        x.elo = max(x.elo + x.eloadjust * x.k * ep.global_K / float(len(elos) - 1), ep.floor)\r
-        x.games += 1\r
-    return elos\r
-\r
-\r
 # parameters for K reduction\r
 # this may be touched even if the DB already exists\r
 KREDUCTION = KReduction(600, 120, 0.5, 0, 32, 0.2)\r
@@ -96,4 +44,3 @@ KREDUCTION = KReduction(600, 120, 0.5, 0, 32, 0.2)
 # only global_K may be touched even if the DB already exists\r
 # we start at K=200, and fall to K=40 over the first 20 games\r
 ELOPARMS = EloParms(global_K = 200)\r
-\r
index efe14ac421becaf1ef4aa596cfe5253073152d88..b3201589406a7ba1a39e26afc8319633bb067a6d 100755 (executable)
@@ -95,7 +95,8 @@ class Game(object):
                 filter(PlayerGameStat.alivetime > timedelta(seconds=0)).\
                 filter(PlayerGameStat.player_id > 2).\
                 all():
-                    scores[p] = s
+                    # scores are per second
+                    scores[p] = s/float(a.seconds)
                     alivetimes[p] = a.seconds
 
         player_ids = scores.keys()
@@ -120,7 +121,8 @@ class Game(object):
         for e in elos:
             session.add(elos[e])
 
-        # TODO: duels are also logged as DM for elo purposes
+        if game_type_cd == 'duel':
+            self.process_elos(session, "dm")
 
     def update_elos(self, elos, scores, ep):
         eloadjust = {}
@@ -150,7 +152,8 @@ class Game(object):
                 scorefactor_real = si / float(si + sj)
 
                 # estimated score factor by elo
-                elodiff = min(ep.maxlogdistance, max(-ep.maxlogdistance, (ei.elo - ej.elo) * ep.logdistancefactor))
+                elodiff = min(ep.maxlogdistance, max(-ep.maxlogdistance,
+                    (float(ei.elo) - float(ej.elo)) * ep.logdistancefactor))
                 scorefactor_elo = 1 / (1 + math.exp(-elodiff))
 
                 # how much adjustment is good?
@@ -167,9 +170,11 @@ class Game(object):
 
                 adjustment = scorefactor_real - scorefactor_elo
                 eloadjust[ei.player_id] += adjustment
-                eloadjust[ei.player_id] -= adjustment
+                eloadjust[ej.player_id] -= adjustment
+                log.debug("elo adjustment values:")
+                log.debug(eloadjust)
         for pid in pids:
-            elos[pid].elo = max(elos[pid].elo + eloadjust[pid] * elos[pid].k * ep.global_K / float(len(elos) - 1), ep.floor)
+            elos[pid].elo = max(float(elos[pid].elo) + eloadjust[pid] * elos[pid].k * ep.global_K / float(len(elos) - 1), ep.floor)
             elos[pid].games += 1
         return elos
 
@@ -241,16 +246,16 @@ class PlayerNick(object):
 
 class PlayerElo(object):
     def __init__(self, player_id=None, game_type_cd=None):
+
         self.player_id = player_id
         self.game_type_cd = game_type_cd
-        self.elo = 0
-        self.k = 0.0
         self.score = 0
         self.games = 0
+        self.elo = ELOPARMS.initial
 
     def __repr__(self):
-        return "<PlayerElo(%s, %s, %s)>" % (self.player_id, self.game_type_cd,
-                self.elo)
+        return "<PlayerElo(pid=%s, gametype=%s, elo=%s)>" % \
+                (self.player_id, self.game_type_cd, self.elo)
 
 
 def initialize_db(engine=None):