1
1
# -*- coding: utf-8 -*-
2
2
from __future__ import absolute_import , print_function , unicode_literals , division
3
3
4
- from itertools import dropwhile
5
4
from sets import Set
6
5
from Image import open as PIL_open
7
6
from Image import ANTIALIAS
8
7
from StringIO import StringIO
9
8
from collections import defaultdict
9
+ from itertools import tee
10
10
11
11
# The creep tracker plugin
12
12
class CreepTracker (object ):
@@ -16,40 +16,62 @@ class CreepTracker(object):
16
16
This uses the creep_tracker class to calculate the features
17
17
'''
18
18
def handleInitGame (self , event , replay ):
19
+ try :
19
20
if len ( replay .tracker_events ) == 0 :
20
21
return
21
22
if replay .map is None :
22
23
replay .load_map ()
23
24
self .creepTracker = creep_tracker (replay )
24
25
for player in replay .players :
26
+ if player .play_race [0 ] == 'Z' :
25
27
self .creepTracker .init_cgu_lists (player .pid )
28
+ except Exception as e :
29
+ print ("Whoa! {}" .format (e ))
30
+ pass
26
31
27
32
def handleUnitDiedEvent (self , event , replay ):
33
+ try :
28
34
self .creepTracker .remove_from_list (event .unit_id ,event .second )
35
+ except Exception as e :
36
+ print ("Whoa! {}" .format (e ))
37
+ pass
38
+
29
39
30
40
def handleUnitInitEvent (self ,event ,replay ):
41
+ try :
31
42
if event .unit_type_name in ["CreepTumor" , "Hatchery" ,"NydusCanal" ] :
32
43
self .creepTracker .add_to_list (event .control_pid ,event .unit_id ,\
33
44
(event .x , event .y ), event .unit_type_name ,event .second )
45
+ except Exception as e :
46
+ print ("Whoa! {}" .format (e ))
47
+ pass
34
48
35
49
def handleUnitBornEvent (self ,event ,replay ):
50
+ try :
36
51
if event .unit_type_name == "Hatchery" :
37
52
self .creepTracker .add_to_list (event .control_pid , event .unit_id ,\
38
53
(event .x ,event .y ),event .unit_type_name ,event .second )
54
+ except Exception as e :
55
+ print ("Whoa! {}" .format (e ))
56
+ pass
39
57
40
58
def handleEndGame (self , event , replay ):
59
+ try :
41
60
if len ( replay .tracker_events ) == 0 :
42
61
return
43
- for player_id in replay .player :
44
- self .creepTracker .reduce_cgu_per_minute (player_id )
45
62
for player in replay .players :
63
+ if player .play_race [0 ] == 'Z' :
64
+ self .creepTracker .reduce_cgu_per_minute (player .pid )
46
65
player .creep_spread_by_minute = self .creepTracker .get_creep_spread_area (player .pid )
47
- for player in replay .players :
48
66
if player .creep_spread_by_minute :
49
67
player .max_creep_spread = max (player .creep_spread_by_minute .items (),key = lambda x :x [1 ])
50
68
else :
51
69
## Else statement is for players with no creep spread(ie: not Zerg)
52
70
player .max_creep_spread = 0
71
+ except Exception as e :
72
+ print ("Whoa! {}" .format (e ))
73
+ pass
74
+
53
75
54
76
## The class used to used to calculate the creep spread
55
77
class creep_tracker ():
@@ -76,7 +98,6 @@ def __init__(self,replay):
76
98
for x in self .unit_name_to_radius :
77
99
self .radius_to_coordinates [self .unit_name_to_radius [x ]] = \
78
100
self .radius_to_map_positions (self .unit_name_to_radius [x ])
79
-
80
101
#Get map information
81
102
replayMap = replay .map
82
103
# extract image from replay package
@@ -95,7 +116,7 @@ def __init__(self,replay):
95
116
self .minimap_image = cropped .resize (minimapSize , ANTIALIAS )
96
117
mapOffsetX = replayMap .map_info .camera_left
97
118
mapOffsetY = replayMap .map_info .camera_bottom
98
- mapCenter = [mapOffsetX + cropsize [0 ]/ 2.0 , mapOffsetY + cropsize [1 ]/ 2.0 ]
119
+ mapCenter = [mapOffsetX + cropsize [0 ]/ 2.0 , mapOffsetY + cropsize [1 ]/ 2.0 ]
99
120
# this is the center of the minimap image, in pixel coordinates
100
121
imageCenter = [(self .map_width / 2 ), self .map_height / 2 ]
101
122
# this is the scaling factor to go from the SC2 coordinate
@@ -148,40 +169,42 @@ def remove_from_list(self,unit_id,time_frame):
148
169
length_cgu_list = len (self .creep_gen_units [player_id ])
149
170
if length_cgu_list == 0 :
150
171
break
151
- cgu_per_player = self .creep_gen_units [player_id ]\
152
- [length_cgu_list - 1 ]
153
- creep_generating_died = dropwhile (lambda x : x [0 ] != \
154
- unit_id , cgu_per_player )
172
+ cgu_per_player = self .creep_gen_units [player_id ] [length_cgu_list - 1 ]
173
+ creep_generating_died = filter (lambda x :x [0 ]== unit_id ,cgu_per_player )
155
174
for creep_generating_died_unit in creep_generating_died :
156
- cgu_per_player . remove ( creep_generating_died_unit )
157
- self .creep_gen_units [player_id ].append (cgu_per_player )
175
+ new_cgu_per_player = filter ( lambda x : x != creep_generating_died_unit , cgu_per_player )
176
+ self .creep_gen_units [player_id ].append (new_cgu_per_player )
158
177
self .creep_gen_units_times [player_id ].append (time_frame )
159
178
179
+ def cgu_gen_times_to_chunks (self ,cgu_time_list ):
180
+ ## this function returns the index and value of every cgu time
181
+ maximum_cgu_time = max (cgu_time_list )
182
+ for i in range (0 , maximum_cgu_time ):
183
+ a = filter (lambda (x ,y ): int (y / 60 )== i , enumerate (cgu_time_list ))
184
+ if len (a )> 0 :
185
+ yield a
186
+
187
+ def cgu_in_min_to_cgu_units (self ,player_id ,cgu_in_minutes ):
188
+ ## this function takes index and value of CGU times and returns
189
+ ## the cgu units with the maximum length
190
+ for cgu_per_minute in cgu_in_minutes :
191
+ indexes = map (lambda x :x [0 ], cgu_per_minute )
192
+ cgu_units = list ()
193
+ for index in indexes :
194
+ cgu_units .append (self .creep_gen_units [player_id ][index ])
195
+ cgu_max_in_minute = max (cgu_units ,key = len )
196
+ yield cgu_max_in_minute
197
+
160
198
def reduce_cgu_per_minute (self ,player_id ):
161
199
#the creep_gen_units_lists contains every single time frame
162
200
#where a CGU is added,
163
201
#To reduce the calculations required, the time frame containing
164
202
#the most cgus every minute will be used to represent that minute
165
- last_minute_found = 0
166
- cgu_per_player_new = list ()
167
- cgu_time_per_player_new = list ()
168
- cgu_last_minute_list = list ()
169
- for index ,cgu_time in enumerate (self .creep_gen_units_times [player_id ]):
170
- cgu_last_minute_list .append (self .creep_gen_units [player_id ][index ])
171
- if (cgu_time / 60 ) == 0 :
172
- cgu_per_player_new .append (self .creep_gen_units [player_id ][0 ])
173
- cgu_time_per_player_new .append (0 )
174
- cgu_last_minute_list = list ()
175
- if (cgu_time / 60 )> last_minute_found :
176
- cgu_max_in_min = max (cgu_last_minute_list ,key = len )
177
- cgu_per_player_new .append (cgu_max_in_min )
178
- cgu_max_in_min_index = self .creep_gen_units [player_id ].index (cgu_max_in_min )
179
- cgu_time_per_player_new .append (self .creep_gen_units_times [player_id ][cgu_max_in_min_index ])
180
- last_minute_found = cgu_time / 60
181
- cgu_last_minute_list = list ()
182
-
183
- self .creep_gen_units [player_id ] = cgu_per_player_new
184
- self .creep_gen_units_times [player_id ] = cgu_time_per_player_new
203
+ cgu_per_minute1 , cgu_per_minute2 = tee (self .cgu_gen_times_to_chunks (self .creep_gen_units_times [player_id ]))
204
+ cgu_unit_max_per_minute = self .cgu_in_min_to_cgu_units (player_id ,cgu_per_minute1 )
205
+ minutes = map (lambda x :int (x [0 ][1 ]/ 60 )* 60 , cgu_per_minute2 )
206
+ self .creep_gen_units [player_id ] = list (cgu_unit_max_per_minute )
207
+ self .creep_gen_units_times [player_id ] = list (minutes )
185
208
186
209
def get_creep_spread_area (self ,player_id ):
187
210
## iterates through all cgus and and calculate the area
@@ -192,12 +215,14 @@ def get_creep_spread_area(self,player_id):
192
215
# convert event coords to minimap coords
193
216
cgu_radius = self .convert_cgu_radius_event_to_map_coord (cgu_radius )
194
217
creep_area_positions = self .cgu_radius_to_map_positions (cgu_radius ,self .radius_to_coordinates )
195
- cgu_last_event_time = self .creep_gen_units_times [player_id ][index ]/ 60
218
+ cgu_event_time = self .creep_gen_units_times [player_id ][index ]
219
+ cgu_event_time_str = str (int (cgu_event_time / 60 ))+ ":" + str (cgu_event_time % 60 )
196
220
if self .debug :
197
- self .print_image (creep_area_positions ,player_id ,cgu_last_event_time )
221
+ self .print_image (creep_area_positions ,player_id ,cgu_event_time_str )
198
222
creep_area = len (creep_area_positions )
199
- self .creep_spread_by_minute [player_id ][cgu_last_event_time ]= \
223
+ self .creep_spread_by_minute [player_id ][cgu_event_time ]= \
200
224
float (creep_area )/ self .mapSize * 100
225
+
201
226
return self .creep_spread_by_minute [player_id ]
202
227
203
228
def cgu_radius_to_map_positions (self ,cgu_radius ,radius_to_coordinates ):
@@ -229,7 +254,7 @@ def print_image(self,total_points_on_map,player_id,time_stamp):
229
254
creeped_image .save (creeped_imageIO , "png" )
230
255
self .creep_spread_image_by_minute [player_id ][time_stamp ]= creeped_imageIO
231
256
##debug for print out the images
232
- f = open (str (player_id )+ 'image' + str ( time_stamp ) + '.png' ,'w' )
257
+ f = open (str (player_id )+ 'image' + time_stamp + '.png' ,'w' )
233
258
f .write (creeped_imageIO .getvalue ())
234
259
creeped_imageIO .close ()
235
260
f .close ()
@@ -256,6 +281,3 @@ def convert_event_coord_to_map_coord(self,x,y):
256
281
imageX = int (self .map_height - self .transX + self .image_scale * x )
257
282
imageY = int (self .transY - self .image_scale * y )
258
283
return imageX , imageY
259
-
260
-
261
-
0 commit comments