From c80e4990cb636ef64595b3ef63dc012dd23e08cf Mon Sep 17 00:00:00 2001 From: Ant Zucaro Date: Thu, 12 Jan 2012 21:12:16 -0500 Subject: [PATCH] It works! Still need to remove the commented out sections, however. --- xonstat/elo.py | 53 ----------------------------------------------- xonstat/models.py | 23 ++++++++++++-------- 2 files changed, 14 insertions(+), 62 deletions(-) diff --git a/xonstat/elo.py b/xonstat/elo.py index 4ba3553..9d1d467 100755 --- a/xonstat/elo.py +++ b/xonstat/elo.py @@ -36,58 +36,6 @@ class KReduction: return k -# For team games where multiple scores and elos are at play, the elos -# must be adjusted according to their strength relative to the player -# in the next-lowest scoreboard position. -def update(elos, ep): - for x in elos: - if x.elo == None: - x.elo = ep.initial - x.eloadjust = 0 - if len(elos) < 2: - return elos - for i in xrange(0, len(elos)): - ei = elos[i] - for j in xrange(i+1, len(elos)): - ej = elos[j] - si = ei.score - sj = ej.score - - # normalize scores - ofs = min(0, si, sj) - si -= ofs - sj -= ofs - if si + sj == 0: - si, sj = 1, 1 # a draw - - # real score factor - scorefactor_real = si / float(si + sj) - - # estimated score factor by elo - elodiff = min(ep.maxlogdistance, max(-ep.maxlogdistance, (ei.elo - ej.elo) * ep.logdistancefactor)) - scorefactor_elo = 1 / (1 + math.exp(-elodiff)) - - # how much adjustment is good? - # scorefactor(elodiff) = 1 / (1 + e^(-elodiff * logdistancefactor)) - # elodiff(scorefactor) = -ln(1/scorefactor - 1) / logdistancefactor - # elodiff'(scorefactor) = 1 / ((scorefactor) (1 - scorefactor) logdistancefactor) - # elodiff'(scorefactor) >= 4 / logdistancefactor - - # adjust'(scorefactor) = K1 + K2 - - # so we want: - # K1 + K2 <= 4 / logdistancefactor <= elodiff'(scorefactor) - # as we then don't overcompensate - - adjustment = scorefactor_real - scorefactor_elo - ei.eloadjust += adjustment - ej.eloadjust -= adjustment - for x in elos: - x.elo = max(x.elo + x.eloadjust * x.k * ep.global_K / float(len(elos) - 1), ep.floor) - x.games += 1 - return elos - - # parameters for K reduction # this may be touched even if the DB already exists KREDUCTION = KReduction(600, 120, 0.5, 0, 32, 0.2) @@ -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 # we start at K=200, and fall to K=40 over the first 20 games ELOPARMS = EloParms(global_K = 200) - diff --git a/xonstat/models.py b/xonstat/models.py index efe14ac..b320158 100755 --- a/xonstat/models.py +++ b/xonstat/models.py @@ -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 "" % (self.player_id, self.game_type_cd, - self.elo) + return "" % \ + (self.player_id, self.game_type_cd, self.elo) def initialize_db(engine=None): -- 2.39.2