From: Ant Zucaro Date: Sat, 21 Jul 2012 01:59:10 +0000 (-0400) Subject: Don't dock Elo points if the player won. X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=9ec79a0c28ea3a6f7958188bac04808564ea1f02;p=xonotic%2Fxonstat.git Don't dock Elo points if the player won. After much debate I've included this enhancement. It prevents losing Elo points if you've won the game. While this makes the algorithm not *true* Elo, it prevents the negative perception in the community. People were turning off their tracking for fear of losing Elo points even if they won, and this hopefully will fix that situation. --- diff --git a/xonstat/models.py b/xonstat/models.py index 05a50ea..e8eb3a3 100644 --- a/xonstat/models.py +++ b/xonstat/models.py @@ -113,8 +113,10 @@ class Game(object): scores = {} alivetimes = {} - for (p,s,a) in session.query(PlayerGameStat.player_id, - PlayerGameStat.score, PlayerGameStat.alivetime).\ + winners = [] + for (p,s,a,r,t) in session.query(PlayerGameStat.player_id, + PlayerGameStat.score, PlayerGameStat.alivetime, + PlayerGameStat.rank, PlayerGameStat.team).\ filter(PlayerGameStat.game_id==self.game_id).\ filter(PlayerGameStat.alivetime > timedelta(seconds=0)).\ filter(PlayerGameStat.player_id > 2).\ @@ -123,6 +125,11 @@ class Game(object): scores[p] = s/float(a.seconds) alivetimes[p] = a.seconds + # winners are either rank 1 or on the winning team + # team games are where the team is set (duh) + if r == 1 or (t == self.winner and t is not None): + winners.append(p) + player_ids = scores.keys() elos = {} @@ -144,7 +151,7 @@ class Game(object): del(scores[pid]) del(alivetimes[pid]) - elos = self.update_elos(session, elos, scores, ELOPARMS) + elos = self.update_elos(session, elos, scores, winners, ELOPARMS) # add the elos to the session for committing for e in elos: @@ -155,7 +162,7 @@ class Game(object): # self.process_elos(session, "dm") - def update_elos(self, session, elos, scores, ep): + def update_elos(self, session, elos, scores, winners, ep): eloadjust = {} for pid in elos.keys(): eloadjust[pid] = 0 @@ -207,13 +214,16 @@ class Game(object): for pid in pids: new_elo = max(float(elos[pid].elo) + eloadjust[pid] * elos[pid].k * ep.global_K / float(len(elos) - 1), ep.floor) - # delta is new minus old - elo_deltas[pid] = new_elo - float(elos[pid].elo) - - log.debug("Player {0}'s Elo going from {1} to {2}.".format(pid, + log.debug("Player {0}'s Elo would be going from {1} to {2}.".format(pid, elos[pid].elo, new_elo)) - elos[pid].elo = new_elo + # winners are not penalized with negative elo + if pid in winners and new_elo < elos[pid].elo: + elo_deltas[pid] = 0.0 + else: + elos[pid].elo = new_elo + elo_deltas[pid] = new_elo - float(elos[pid].elo) + elos[pid].games += 1 self.save_elo_deltas(session, elo_deltas) diff --git a/xonstat/views/submission.py b/xonstat/views/submission.py index 950450f..d584915 100644 --- a/xonstat/views/submission.py +++ b/xonstat/views/submission.py @@ -378,19 +378,19 @@ def create_player_game_stat(session=None, player=None, for (key,value) in player_events.items(): if key == 'n': pgstat.nick = value[:128] - if key == 't': pgstat.team = value - if key == 'rank': pgstat.rank = value + if key == 't': pgstat.team = int(value) + if key == 'rank': pgstat.rank = int(value) if key == 'alivetime': pgstat.alivetime = datetime.timedelta(seconds=int(round(float(value)))) - if key == 'scoreboard-drops': pgstat.drops = value - if key == 'scoreboard-returns': pgstat.returns = value - if key == 'scoreboard-fckills': pgstat.carrier_frags = value - if key == 'scoreboard-pickups': pgstat.pickups = value - if key == 'scoreboard-caps': pgstat.captures = value - if key == 'scoreboard-score': pgstat.score = value - if key == 'scoreboard-deaths': pgstat.deaths = value - if key == 'scoreboard-kills': pgstat.kills = value - if key == 'scoreboard-suicides': pgstat.suicides = value + if key == 'scoreboard-drops': pgstat.drops = int(value) + if key == 'scoreboard-returns': pgstat.returns = int(value) + if key == 'scoreboard-fckills': pgstat.carrier_frags = int(value) + if key == 'scoreboard-pickups': pgstat.pickups = int(value) + if key == 'scoreboard-caps': pgstat.captures = int(value) + if key == 'scoreboard-score': pgstat.score = int(value) + if key == 'scoreboard-deaths': pgstat.deaths = int(value) + if key == 'scoreboard-kills': pgstat.kills = int(value) + if key == 'scoreboard-suicides': pgstat.suicides = int(value) # check to see if we had a name, and if # not use an anonymous handle @@ -405,7 +405,7 @@ def create_player_game_stat(session=None, player=None, # if the player is ranked #1 and it is a team game, set the game's winner # to be the team of that player # FIXME: this is a hack, should be using the 'W' field (not present) - if pgstat.rank == '1' and pgstat.team: + if pgstat.rank == 1 and pgstat.team: game.winner = pgstat.team session.add(game)