From c259baac03d45565db88e8215dbb5091511b4273 Mon Sep 17 00:00:00 2001 From: Ant Zucaro Date: Wed, 20 Jun 2012 10:17:10 -0400 Subject: [PATCH] Add elo delta tracking. An elo delta is the amount by which a player's elo goes up or down per match. This is useful for tracking purposes and competitions. The decimal formatting here is a bit hacky, and I don't like it, but Mako refuses to do a proper format string on a decimal.Decimal. This is even thought on the interactive command line it works! Argh. --- xonstat/models.py | 41 ++++++++++++++++++++++++++++--- xonstat/templates/scoreboard.mako | 7 ++++++ xonstat/views/game.py | 7 ++++++ 3 files changed, 52 insertions(+), 3 deletions(-) diff --git a/xonstat/models.py b/xonstat/models.py index 39c6586..6d38888 100644 --- a/xonstat/models.py +++ b/xonstat/models.py @@ -144,7 +144,7 @@ class Game(object): del(scores[pid]) del(alivetimes[pid]) - elos = self.update_elos(elos, scores, ELOPARMS) + elos = self.update_elos(session, elos, scores, ELOPARMS) # add the elos to the session for committing for e in elos: @@ -153,7 +153,8 @@ class Game(object): if game_type_cd == 'duel': self.process_elos(session, "dm") - def update_elos(self, elos, scores, ep): + + def update_elos(self, session, elos, scores, ep): eloadjust = {} for pid in elos.keys(): eloadjust[pid] = 0 @@ -200,12 +201,46 @@ class Game(object): adjustment = scorefactor_real - scorefactor_elo eloadjust[ei.player_id] += adjustment eloadjust[ej.player_id] -= adjustment + elo_deltas = {} for pid in pids: - elos[pid].elo = max(float(elos[pid].elo) + eloadjust[pid] * elos[pid].k * ep.global_K / float(len(elos) - 1), ep.floor) + elo_delta = eloadjust[pid] * elos[pid].k * ep.global_K / float(len(elos) - 1) + + if float(elos[pid].elo) + elo_delta < ep.floor: + elo_deltas[pid] = elos[pid].elo - ep.floor + else: + elo_deltas[pid] = elo_delta + + # can't go below the floor + elos[pid].elo = max(float(elos[pid].elo) + elo_delta, ep.floor) elos[pid].games += 1 + + self.save_elo_deltas(session, elo_deltas) + return elos + def save_elo_deltas(self, session, elo_deltas): + """ + Saves the amount by which each player's Elo goes up or down + in a given game in the PlayerGameStat row, allowing for scoreboard display. + + elo_deltas is a dictionary such that elo_deltas[player_id] is the elo_delta + for that player_id. + """ + pgstats = {} + for pgstat in session.query(PlayerGameStat).\ + filter(PlayerGameStat.game_id == self.game_id).\ + all(): + pgstats[pgstat.player_id] = pgstat + + for pid in elo_deltas.keys(): + try: + pgstats[pid].elo_delta = elo_deltas[pid] + session.add(pgstats[pid]) + except: + log.debug("Unable to save Elo delta value for player_id {0}".format(pid)) + + class PlayerGameStat(object): def __init__(self, player_game_stat_id=None, create_dt=None): self.player_game_stat_id = player_game_stat_id diff --git a/xonstat/templates/scoreboard.mako b/xonstat/templates/scoreboard.mako index 288e271..7b4d940 100644 --- a/xonstat/templates/scoreboard.mako +++ b/xonstat/templates/scoreboard.mako @@ -16,6 +16,11 @@ ${scoreboard_header(game_type_cd, pgstats[0])} ${scoreboard_row(game_type_cd, pgstat)} ${pgstat.score} + % if pgstat.elo_delta == "0.00": + + % else: + ${pgstat.elo_delta} + % endif % endfor @@ -32,6 +37,7 @@ ${scoreboard_header(game_type_cd, pgstats[0])} Deaths Suicides Score + Points % endif @@ -46,6 +52,7 @@ ${scoreboard_header(game_type_cd, pgstats[0])} FCK Returns Score + Points % endif diff --git a/xonstat/views/game.py b/xonstat/views/game.py index 6147c5f..04774fe 100644 --- a/xonstat/views/game.py +++ b/xonstat/views/game.py @@ -69,6 +69,13 @@ def _game_info_data(request): order_by(PlayerGameStat.score).\ all() + # mako is an absolute bastard when dealing with decimals, so... + for pgstat in pgstats: + try: + pgstat.elo_delta = "{0:+4.2f}".format(float(pgstat.elo_delta)) + except: + pgstat.elo_delta = "0.00" + pwstats = {} for (pwstat, pgstat, weapon) in DBSession.query(PlayerWeaponStat, PlayerGameStat, Weapon).\ filter(PlayerWeaponStat.game_id == game_id).\ -- 2.39.2