From 604e6295a65b3e64a66d585a5a51dbbaf9f626c7 Mon Sep 17 00:00:00 2001 From: Anders Nickelsen Date: Thu, 21 Apr 2016 10:03:02 +0200 Subject: [PATCH 1/3] Fix LotV apm by squeezing events into rescaled game minutes. --- sc2reader/factories/plugins/replay.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/sc2reader/factories/plugins/replay.py b/sc2reader/factories/plugins/replay.py index 4353d8c3..5940a59c 100644 --- a/sc2reader/factories/plugins/replay.py +++ b/sc2reader/factories/plugins/replay.py @@ -100,6 +100,15 @@ def APMTracker(replay): above actions divided by the number of seconds played by the player (not necessarily the whole game) multiplied by 60. """ + + speed_multiplier = 1 + if replay.expansion == 'LotV': + speed_multiplier = 1.4 + + game_seconds_per_second = 1.4 + if replay.expansion == 'LotV': + game_seconds_per_second = 1.4 + for player in replay.players: player.aps = defaultdict(int) player.apm = defaultdict(int) @@ -107,14 +116,14 @@ def APMTracker(replay): for event in player.events: if event.name == 'SelectionEvent' or 'AbilityEvent' in event.name or 'Hotkey' in event.name: - player.aps[event.second] += 1.4 - player.apm[int(event.second/60)] += 1.4 + player.aps[event.second/speed_multiplier] += game_seconds_per_second + player.apm[int(event.second/60/speed_multiplier)] += game_seconds_per_second elif event.name == 'PlayerLeaveEvent': - player.seconds_played = event.second + player.seconds_played = event.second/speed_multiplier if len(player.apm) > 0: - player.avg_apm = sum(player.aps.values())/float(player.seconds_played)*60 + player.avg_apm = sum(player.aps.values())/float(player.seconds_played)*60*speed_multiplier else: player.avg_apm = 0 From d8fa276e161ff6ba04756f0b4de7dee0a27ff32b Mon Sep 17 00:00:00 2001 From: Anders Nickelsen Date: Thu, 21 Apr 2016 10:27:36 +0200 Subject: [PATCH 2/3] Test for LotV apm fix. --- test_replays/test_all.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test_replays/test_all.py b/test_replays/test_all.py index d68b44e0..7d462e89 100644 --- a/test_replays/test_all.py +++ b/test_replays/test_all.py @@ -494,6 +494,17 @@ def test_lotv_time(self): self.assertEqual(replay.length.seconds, 1002) self.assertEqual(replay.real_length.seconds, 1002) + def test_lotv_apm(self): + from sc2reader.factories.plugins.replay import APMTracker, SelectionTracker, toJSON + factory = sc2reader.factories.SC2Factory() + factory.register_plugin("Replay", APMTracker()) + replay = factory.load_replay("test_replays/lotv/lotv1.SC2Replay") + for player in replay.players: + from pprint import pprint + pprint(player) + if player.name == 'Zenchii': + self.assertTrue(int(player.avg_apm) == 56) + class TestGameEngine(unittest.TestCase): class TestEvent(object): From f76229354bd5dcedd58032b310528e953c64672f Mon Sep 17 00:00:00 2001 From: Anders Nickelsen Date: Thu, 21 Apr 2016 16:22:03 +0200 Subject: [PATCH 3/3] Move multipliers into constants and make calulations easier to read. --- sc2reader/constants.py | 8 ++++++++ sc2reader/engine/plugins/apm.py | 12 ++++++++++-- sc2reader/factories/plugins/replay.py | 16 +++++++++------- test_replays/test_all.py | 2 +- 4 files changed, 28 insertions(+), 10 deletions(-) diff --git a/sc2reader/constants.py b/sc2reader/constants.py index f06fccf6..8eae94e6 100644 --- a/sc2reader/constants.py +++ b/sc2reader/constants.py @@ -83,6 +83,14 @@ }, } +LOTV_SPEEDUP = 1.4 + +GAME_SECONDS_PER_SECOND = { + 'WoL': 1.4, + 'HotS': 1.4, + 'LotV': 1 +} + GATEWAY_CODES = { 'US': 'Americas', 'KR': 'Asia', diff --git a/sc2reader/engine/plugins/apm.py b/sc2reader/engine/plugins/apm.py index 5eec2ac2..8a359cbd 100644 --- a/sc2reader/engine/plugins/apm.py +++ b/sc2reader/engine/plugins/apm.py @@ -2,6 +2,7 @@ from __future__ import absolute_import, print_function, unicode_literals, division from collections import defaultdict +from sc2reader.constants import LOTV_SPEEDUP, GAME_SECONDS_PER_SECOND class APMTracker(object): @@ -24,8 +25,15 @@ def handleInitGame(self, event, replay): human.seconds_played = replay.length.seconds def handlePlayerActionEvent(self, event, replay): - event.player.aps[event.second] += 1.4 - event.player.apm[int(event.second/60)] += 1.4 + speed_multiplier = 1 + if replay.expansion == 'LotV': + speed_multiplier = LOTV_SPEEDUP + + game_seconds_per_second = GAME_SECONDS_PER_SECOND[replay.expansion] + + game_second = int(event.second/speed_multiplier) + event.player.aps[game_second] += game_seconds_per_second + event.player.apm[int(game_second/60)] += game_seconds_per_second def handlePlayerLeaveEvent(self, event, replay): event.player.seconds_played = event.second diff --git a/sc2reader/factories/plugins/replay.py b/sc2reader/factories/plugins/replay.py index 5940a59c..e2082554 100644 --- a/sc2reader/factories/plugins/replay.py +++ b/sc2reader/factories/plugins/replay.py @@ -7,6 +7,7 @@ from sc2reader import log_utils from sc2reader.utils import Length from sc2reader.factories.plugins.utils import PlayerSelection, GameState, JSONDateEncoder, plugin +from sc2reader.constants import LOTV_SPEEDUP, GAME_SECONDS_PER_SECOND @plugin @@ -103,11 +104,11 @@ def APMTracker(replay): speed_multiplier = 1 if replay.expansion == 'LotV': - speed_multiplier = 1.4 + speed_multiplier = LOTV_SPEEDUP - game_seconds_per_second = 1.4 + game_seconds_per_second = GAME_SECONDS_PER_SECOND[replay.expansion] if replay.expansion == 'LotV': - game_seconds_per_second = 1.4 + game_seconds_per_second = 1 for player in replay.players: player.aps = defaultdict(int) @@ -115,15 +116,16 @@ def APMTracker(replay): player.seconds_played = replay.length.seconds for event in player.events: + game_second = int(event.second/speed_multiplier) if event.name == 'SelectionEvent' or 'AbilityEvent' in event.name or 'Hotkey' in event.name: - player.aps[event.second/speed_multiplier] += game_seconds_per_second - player.apm[int(event.second/60/speed_multiplier)] += game_seconds_per_second + player.aps[game_second] += game_seconds_per_second + player.apm[int(game_second/60)] += game_seconds_per_second elif event.name == 'PlayerLeaveEvent': - player.seconds_played = event.second/speed_multiplier + player.seconds_played = game_second if len(player.apm) > 0: - player.avg_apm = sum(player.aps.values())/float(player.seconds_played)*60*speed_multiplier + player.avg_apm = sum(player.aps.values())/float(player.seconds_played)*60 else: player.avg_apm = 0 diff --git a/test_replays/test_all.py b/test_replays/test_all.py index 7d462e89..8c6bdb2e 100644 --- a/test_replays/test_all.py +++ b/test_replays/test_all.py @@ -503,7 +503,7 @@ def test_lotv_apm(self): from pprint import pprint pprint(player) if player.name == 'Zenchii': - self.assertTrue(int(player.avg_apm) == 56) + self.assertEquals(int(player.avg_apm), 56) class TestGameEngine(unittest.TestCase):