Skip to content

Commit 3b97464

Browse files
committed
Move event level filtering to listeners.
Previously you specified the events sent to a listener on initial registration. It made more sense to move this to a listener.accepts function because 9/10 times the events will always be the same and that edge case can be covered by configuring the Listener before registration.
1 parent 6e9fada commit 3b97464

File tree

5 files changed

+34
-45
lines changed

5 files changed

+34
-45
lines changed

sc2reader/factories.py

Lines changed: 11 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ def reset(self):
107107
self.options = utils.AttributeDict(self.default_options)
108108
self.registered_readers = defaultdict(list)
109109
self.registered_datapacks = list()
110-
self.registered_listeners = defaultdict(list)
110+
self.registered_listeners = list()
111111

112112
def load_resources(self, resources, resource_loader, options=None, **new_options):
113113
"""
@@ -286,42 +286,30 @@ def get_datapack(self, replay):
286286
return None
287287

288288
def get_listeners(self, replay):
289-
listeners = defaultdict(list)
290-
for event_class in self.registered_listeners.keys():
291-
for callback, listener in self.registered_listeners[event_class]:
292-
if callback(replay):
293-
listeners[event_class].append(listener)
289+
listeners = list()
290+
for callback, listener in self.registered_listeners:
291+
if callback(replay):
292+
listeners.append(listener)
294293
return listeners
295294

296295

297-
def register_listener(self, events, listener, filterfunc=lambda r: True):
296+
def register_listener(self, listener, filterfunc=lambda r: True):
298297
"""
299298
Allows you to specify event listeners for adding new features to the
300299
:class:`Replay` objects on :meth:`~Replay.play`. sc2reader comes with a
301300
small collection of :class:`Listener` classes that you can apply to your
302-
replays as needed.
303-
304-
Events are sent to listeners in registration order as they come up. By
305-
specifying a parent class you can register a listener to a set of events
306-
at once instead of listing them out individually. See the tutorials for
307-
more information.
308-
309-
:param events: A list of event classes you want sent to this listener.
310-
Registration to a single event can be done by specifying a single
311-
event class instead of a list. An isinstance() check is used so
312-
you can catch sets of classes at once by supplying a parent class.
301+
replays as needed. Events are sent to listeners in registration order as
302+
they come up. See the tutorials for more information.
313303
314304
:param listener: The :class:`Listener` object you want events sent to.
305+
You must pass an instanciated object NOT a class. This gives you an
306+
opportunity to configure the listener before registration.
315307
316308
:param filterfunc: A function that accepts a partially loaded
317309
:class:`Replay` object as an argument and returns true if the
318310
reader should be used on this replay.
319311
"""
320-
try:
321-
for event in events:
322-
self.registered_listeners[event].append((filterfunc, listener))
323-
except TypeError:
324-
self.registered_listeners[events].append((filterfunc, listener))
312+
self.registered_listeners.append((filterfunc, listener))
325313

326314
def register_reader(self, data_file, reader, filterfunc=lambda r: True):
327315
"""

sc2reader/listeners/apm.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from __future__ import absolute_import
22

3+
from sc2reader.events import GameEvent
34
from sc2reader.listeners.utils import ListenerBase
45

56
from collections import defaultdict
@@ -12,12 +13,14 @@ def setup(self, replay):
1213
player.apm = defaultdict(int)
1314
player.avg_apm = 0
1415

16+
def accepts(self, event):
17+
return isinstance(sc2reader.events.GameEvent) and event.is_local and event.is_player_action
18+
1519
def __call__(self, event, replay):
16-
if event.is_local and event.is_player_action:
17-
player = event.player
18-
if not player.is_observer:
19-
# Count up the APS, APM
20-
minute = event.second/60.0
21-
player.aps[event.second] += 1
22-
player.apm[int(minutes)] += 1
23-
player.avg_apm = sum(player.apm.values())/minutes
20+
player = event.player
21+
if not player.is_observer:
22+
# Count up the APS, APM
23+
minute = event.second/60.0
24+
player.aps[event.second] += 1
25+
player.apm[int(minutes)] += 1
26+
player.avg_apm = sum(player.apm.values())/minutes

sc2reader/listeners/selection.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -72,13 +72,10 @@ def setup(self, replay):
7272
for player in replay.people:
7373
player.selections = GameState(PlayerSelection())
7474

75-
def __call__(self, event, replay):
76-
# TODO: The whole register_listener thing is really clunky
77-
# right now. In some cases, listeners already know what
78-
# they want to listen to.
79-
if not (isinstance(event, events.SelectionEvent) or isinstance(event, events.HotkeyEvent)):
80-
return
75+
def accepts(self, event):
76+
return isinstance(event, events.SelectionEvent) or isinstance(event, events.HotkeyEvent)
8177

78+
def __call__(self, event, replay):
8279
if replay.opt.debug:
8380
self.logger.debug("Event bytes: "+event.bytes.encode("hex"))
8481

sc2reader/listeners/utils.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,7 @@
22

33
class ListenerBase(object):
44
def __init__(self):
5-
self.logger = log_utils.get_logger(self.__class__)
5+
self.logger = log_utils.get_logger(self.__class__)
6+
7+
def accepts(self, event):
8+
return true

sc2reader/resources.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -355,15 +355,13 @@ def load_events(self, datapack=None):
355355
def start(self):
356356
self.stopped = False
357357

358-
for event_type, listeners in self.listeners.iteritems():
359-
for listener in listeners:
360-
listener.setup(self)
358+
for listener in self.listeners:
359+
listener.setup(self)
361360

362361
for event in self.events:
363-
for event_type, listeners in self.listeners.iteritems():
364-
if isinstance(event, event_type):
365-
for listener in listeners:
366-
listener(event, self)
362+
for listener in self.listeners:
363+
if listener.accepts(event):
364+
listener(event, self)
367365

368366

369367
class Map(Resource):

0 commit comments

Comments
 (0)