Skip to content

Commit 50d09ae

Browse files
committed
Patch #57 to count and remove bad indexes.
Adds a new integer selection_errors attribute to all player objects that represents the number of selections with detectable errors per player. This can be compared to the len(player.selections.keys()) to get a rough idea of how flawed the selection stats might be.
1 parent 2ade143 commit 50d09ae

File tree

2 files changed

+24
-6
lines changed

2 files changed

+24
-6
lines changed

sc2reader/plugins/replay.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,11 +98,13 @@ def SelectionTracker(replay):
9898

9999
for person in replay.people:
100100
# TODO: A more robust person interface might be nice
101+
person.selection_errors = 0
101102
person.selection = GameState(PlayerSelection())
102103
for event in filter(efilter, person.events):
103104
if replay.opt.debug:
104105
logger.debug("Event bytes: "+event.bytes.encode("hex"))
105106

107+
error = False
106108
selection = person.selection[event.frame]
107109

108110
if isinstance(event, SetToHotkeyEvent):
@@ -111,21 +113,25 @@ def SelectionTracker(replay):
111113
logger.info("[{0}] {1} set hotkey {2} to current selection".format(Length(seconds=event.second),person.name,event.hotkey))
112114

113115
elif isinstance(event, AddToHotkeyEvent):
114-
selection[event.hotkey].deselect(*event.deselect)
116+
error = not selection[event.hotkey].deselect(*event.deselect)
115117
selection[event.hotkey].select(selection[0x0A].objects)
116118
logger.info("[{0}] {1} added current selection to hotkey {2}".format(Length(seconds=event.second),person.name,event.hotkey))
117119

118120
elif isinstance(event, GetFromHotkeyEvent):
119121
# For some reason they leave the hotkey buffer unmodified so make a copy
120122
selection[0x0A] = selection[event.hotkey].copy()
121-
selection[0x0A].deselect(*event.deselect)
123+
error = not selection[0x0A].deselect(*event.deselect)
122124
logger.info("[{0}] {1} retrieved hotkey {2}, {3} units: {4}".format(Length(seconds=event.second),person.name,event.hotkey,len(selection[0x0A].objects),selection[0x0A]))
123125

124126
elif isinstance(event, SelectionEvent):
125-
selection[0x0A].deselect(*event.deselect)
127+
error = not selection[0x0A].deselect(*event.deselect)
126128
selection[0x0A].select(event.objects)
127129
logger.info("[{0}] {1} selected {2} units: {3}".format(Length(seconds=event.second),person.name,len(selection[0x0A].objects),selection[0x0A]))
128130

129131
# TODO: The event level interface here should be improved
130132
# Possibly use 'added' and 'removed' unit lists as well
131133
event.selected = selection[0x0A].objects
134+
if error:
135+
person.selection_errors += 1
136+
if replay.opt.debug:
137+
logger.warn("Error detected in deselection mode {}.".format(event.deselect[0]))

sc2reader/plugins/utils.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,22 +69,34 @@ def select(self, new_objects):
6969
self.objects = sorted(new_set,key=lambda obj: obj.id)
7070

7171
def deselect(self, mode, data):
72+
"""Returns false if there was a data error when deselecting"""
73+
size = len(self.objects)
74+
7275
if mode == 0x01:
7376
""" Deselect objects according to deselect mask """
7477
mask = data
75-
if len(mask) < len(self.objects):
78+
if len(mask) < size:
7679
# pad to the right
7780
mask = mask+[False,]*(len(self.objects)-len(mask))
81+
7882
self.logger.debug("Deselection Mask: {0}".format(mask))
7983
self.objects = [ obj for (slct, obj) in filter(lambda (slct, obj): not slct, zip(mask, self.objects)) ]
84+
return len(mask) <= size
8085

8186
elif mode == 0x02:
8287
""" Deselect objects according to indexes """
83-
self.objects = [ self.objects[i] for i in range(len(self.objects)) if i not in data ]
88+
clean_data = filter(lambda i: i < size, data)
89+
self.objects = [ self.objects[i] for i in range(len(self.objects)) if i not in clean_data ]
90+
return len(clean_data) == len(data)
8491

8592
elif mode == 0x03:
8693
""" Deselect objects according to indexes """
87-
self.objects = [ self.objects[i] for i in data ]
94+
clean_data = filter(lambda i: i < size, data)
95+
self.objects = [ self.objects[i] for i in clean_data ]
96+
return len(clean_data) == len(data)
97+
98+
else:
99+
return True
88100

89101
def __str__(self):
90102
return ', '.join(str(obj) for obj in self.objects)

0 commit comments

Comments
 (0)