11# -*- coding: utf-8 -*-
22from __future__ import absolute_import , print_function , unicode_literals , division
33
4- from itertools import dropwhile
54from sets import Set
65from Image import open as PIL_open
76from Image import ANTIALIAS
87from StringIO import StringIO
98from collections import defaultdict
9+ from itertools import tee
1010
1111# The creep tracker plugin
1212class CreepTracker (object ):
@@ -16,40 +16,62 @@ class CreepTracker(object):
1616 This uses the creep_tracker class to calculate the features
1717 '''
1818 def handleInitGame (self , event , replay ):
19+ try :
1920 if len ( replay .tracker_events ) == 0 :
2021 return
2122 if replay .map is None :
2223 replay .load_map ()
2324 self .creepTracker = creep_tracker (replay )
2425 for player in replay .players :
26+ if player .play_race [0 ] == 'Z' :
2527 self .creepTracker .init_cgu_lists (player .pid )
28+ except Exception as e :
29+ print ("Whoa! {}" .format (e ))
30+ pass
2631
2732 def handleUnitDiedEvent (self , event , replay ):
33+ try :
2834 self .creepTracker .remove_from_list (event .unit_id ,event .second )
35+ except Exception as e :
36+ print ("Whoa! {}" .format (e ))
37+ pass
38+
2939
3040 def handleUnitInitEvent (self ,event ,replay ):
41+ try :
3142 if event .unit_type_name in ["CreepTumor" , "Hatchery" ,"NydusCanal" ] :
3243 self .creepTracker .add_to_list (event .control_pid ,event .unit_id ,\
3344 (event .x , event .y ), event .unit_type_name ,event .second )
45+ except Exception as e :
46+ print ("Whoa! {}" .format (e ))
47+ pass
3448
3549 def handleUnitBornEvent (self ,event ,replay ):
50+ try :
3651 if event .unit_type_name == "Hatchery" :
3752 self .creepTracker .add_to_list (event .control_pid , event .unit_id ,\
3853 (event .x ,event .y ),event .unit_type_name ,event .second )
54+ except Exception as e :
55+ print ("Whoa! {}" .format (e ))
56+ pass
3957
4058 def handleEndGame (self , event , replay ):
59+ try :
4160 if len ( replay .tracker_events ) == 0 :
4261 return
43- for player_id in replay .player :
44- self .creepTracker .reduce_cgu_per_minute (player_id )
4562 for player in replay .players :
63+ if player .play_race [0 ] == 'Z' :
64+ self .creepTracker .reduce_cgu_per_minute (player .pid )
4665 player .creep_spread_by_minute = self .creepTracker .get_creep_spread_area (player .pid )
47- for player in replay .players :
4866 if player .creep_spread_by_minute :
4967 player .max_creep_spread = max (player .creep_spread_by_minute .items (),key = lambda x :x [1 ])
5068 else :
5169 ## Else statement is for players with no creep spread(ie: not Zerg)
5270 player .max_creep_spread = 0
71+ except Exception as e :
72+ print ("Whoa! {}" .format (e ))
73+ pass
74+
5375
5476## The class used to used to calculate the creep spread
5577class creep_tracker ():
@@ -76,7 +98,6 @@ def __init__(self,replay):
7698 for x in self .unit_name_to_radius :
7799 self .radius_to_coordinates [self .unit_name_to_radius [x ]] = \
78100 self .radius_to_map_positions (self .unit_name_to_radius [x ])
79-
80101 #Get map information
81102 replayMap = replay .map
82103 # extract image from replay package
@@ -95,7 +116,7 @@ def __init__(self,replay):
95116 self .minimap_image = cropped .resize (minimapSize , ANTIALIAS )
96117 mapOffsetX = replayMap .map_info .camera_left
97118 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 ]
99120 # this is the center of the minimap image, in pixel coordinates
100121 imageCenter = [(self .map_width / 2 ), self .map_height / 2 ]
101122 # this is the scaling factor to go from the SC2 coordinate
@@ -148,40 +169,42 @@ def remove_from_list(self,unit_id,time_frame):
148169 length_cgu_list = len (self .creep_gen_units [player_id ])
149170 if length_cgu_list == 0 :
150171 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 )
155174 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 )
158177 self .creep_gen_units_times [player_id ].append (time_frame )
159178
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+
160198 def reduce_cgu_per_minute (self ,player_id ):
161199 #the creep_gen_units_lists contains every single time frame
162200 #where a CGU is added,
163201 #To reduce the calculations required, the time frame containing
164202 #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 )
185208
186209 def get_creep_spread_area (self ,player_id ):
187210 ## iterates through all cgus and and calculate the area
@@ -192,12 +215,14 @@ def get_creep_spread_area(self,player_id):
192215 # convert event coords to minimap coords
193216 cgu_radius = self .convert_cgu_radius_event_to_map_coord (cgu_radius )
194217 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 )
196220 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 )
198222 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 ]= \
200224 float (creep_area )/ self .mapSize * 100
225+
201226 return self .creep_spread_by_minute [player_id ]
202227
203228 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):
229254 creeped_image .save (creeped_imageIO , "png" )
230255 self .creep_spread_image_by_minute [player_id ][time_stamp ]= creeped_imageIO
231256 ##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' )
233258 f .write (creeped_imageIO .getvalue ())
234259 creeped_imageIO .close ()
235260 f .close ()
@@ -256,6 +281,3 @@ def convert_event_coord_to_map_coord(self,x,y):
256281 imageX = int (self .map_height - self .transX + self .image_scale * x )
257282 imageY = int (self .transY - self .image_scale * y )
258283 return imageX , imageY
259-
260-
261-
0 commit comments