11from data import races
2+ from collections import defaultdict
3+ from sc2reader .utils import ByteStream , PersonDict
24
5+ class Replay (object ):
6+
7+ def __init__ (self , filename , release , frames = 0 ):
8+ #Split and offset for matching indexes if they pass in the release string
9+ if isinstance (release ,basestring ): release = [None ]+ release .split ('.' )
10+
11+ #Assign all the relevant information to the replay object
12+ self .build = release [4 ]
13+ self .versions = (release [1 ], release [2 ], release [3 ], release [4 ])
14+ self .release_string = "%s.%s.%s.%s" % self .versions
15+ self .frames , self .seconds = (frames , frames / 16 )
16+ self .length = (self .seconds / 60 , self .seconds % 60 )
17+
18+ self .player_names = list ()
19+ self .other_people = set ()
20+ self .filename = filename
21+ self .speed = ""
22+ self .type = ""
23+ self .category = ""
24+ self .is_ladder = False
25+ self .is_private = False
26+ self .map = ""
27+ self .realm = ""
28+ self .events = list ()
29+ self .results = dict ()
30+ self .teams = defaultdict (list )
31+ self .observers = list () #Unordered list of Observer
32+ self .players = list () #Unordered list of Player
33+ self .people = list () #Unordered list of Players+Observers
34+ self .person = PersonDict () #Maps pid to Player/Observer
35+ self .events_by_type = dict ()
36+ self .attributes = list ()
37+ self .messages = list ()
38+ self .recorder = None # Player object
39+ self .winner_known = False
40+
41+ # Set in parsers.DetailParser.load, should we hide this?
42+ self .file_time = None # Probably number milliseconds since EPOCH
43+
44+ # TODO: Test EPOCH differences between MacOsX and Windows
45+ # http://en.wikipedia.org/wiki/Epoch_(reference_date)
46+ # Notice that Windows and Mac have different EPOCHs, I wonder whether
47+ # this is different depending on the OS on which the replay was played.
48+ self .date = None # Date when the game was played in local time
49+ self .utc_date = None # Date when the game was played in UTC
50+
351class Attribute (object ):
452
553 def __init__ (self , data ):
@@ -92,58 +140,11 @@ def __repr__(self):
92140
93141 def __str__ (self ):
94142 return "%s: %s" % (self .name , self .value )
95-
96-
97-
98-
99- class Event (object ):
100- def __init__ (self , elapsed_time , event_type , event_code , global_flag , player_id ,
101- location = None , bytes = "" ):
102- self .time , self .seconds = (elapsed_time , elapsed_time / 16 )
103- self .timestr = "%s:%s" % (self .seconds / 60 , str (self .seconds % 60 ).rjust (2 , "0" ))
104- self .type = event_type
105- self .code = event_code
106- self .is_local = (global_flag == 0x0 )
107- self .player = player_id
108- self .location = location
109- self .bytes = bytes
110- self .abilitystr = ""
111-
112- # Added for convenience
113- self .is_init = (event_type == 0x00 )
114- self .is_player_action = (event_type == 0x01 )
115- self .is_camera_movement = (event_type == 0x03 )
116- self .is_unknown = (event_type == 0x02 or event_type == 0x04 or event_type == 0x05 )
117-
118- def __call__ (self , elapsed_time , event_type , global_flag , player_id , event_code , bytes ):
119- self .time , self .seconds = (elapsed_time , elapsed_time / 16 )
120- self .timestr = "%s:%s" % (self .seconds / 60 , str (self .seconds % 60 ).rjust (2 , "0" ))
121- self .type = event_type
122- self .code = event_code
123- self .is_local = (global_flag == 0x0 )
124- self .player = player_id
125- self .bytes = ""
126- self .abilitystr = ""
127-
128- # Added for convenience
129- self .is_init = (event_type == 0x00 )
130- self .is_player_action = (event_type == 0x01 )
131- self .is_camera_movement = (event_type == 0x03 )
132- self .is_unknown = (event_type == 0x02 or event_type == 0x04 or event_type == 0x05 )
133-
134- self .parse (bytes )
135- return self
136-
137- def __str__ (self ):
138- return "%s - %s - %s" % (self .timestr , self .name , self .abilitystr )
139-
140- def __repr__ (self ):
141- return str (self )
142-
143+
143144class Message (object ):
144145
145- def __init__ (self , time , player , target , text ):
146- self .time , self .sender , self .target , self .text = time , player , target , text
146+ def __init__ (self , time , pid , target , text ):
147+ self .time , self .sender_id , self .target , self .text = time , pid , target , text
147148 self .seconds = time / 16
148149 self .sent_to_all = (self .target == 0 )
149150 self .sent_to_allies = (self .target == 2 )
@@ -156,31 +157,29 @@ def __repr__(self):
156157 return str (self )
157158
158159# Actor is a base class for Observer and Player
159- class Actor (object ):
160- def __init__ (self , is_obs ):
161- self .pid = None
162- self .name = None
163- self .is_obs = is_obs
160+ class Person (object ):
161+ def __init__ (self , pid , name ):
162+ self .pid = pid
163+ self .name = name
164+ self .is_obs = None
164165 self .messages = list ()
165166 self .events = list ()
166- self .recorder = True # Actual recorder will be determined using the replay.message.events file
167+ self .recorder = False # Actual recorder will be determined using the replay.message.events file
167168
168- class Observer (Actor ):
169+ class Observer (Person ):
169170 def __init__ (self , pid , name ):
170- Actor .__init__ (self , True )
171- self .pid = pid
172- self .name = name
171+ super (Observer ,self ).__init__ (pid ,name )
172+ self .is_obs = True
173173
174- class Player (Actor ):
174+ class Player (Person ):
175175
176176 url_template = "http://%s.battle.net/sc2/en/profile/%s/%s/%s/"
177177
178178 def __init__ (self , pid , data , realm = "us" ):
179- Actor .__init__ (self , False )
180179 # TODO: get a map of realm,subregion => region in here
181- self .pid = pid
180+ super (Player ,self ).__init__ (pid ,data [0 ].decode ("hex" ))
181+ self .is_obs = False
182182 self .realm = realm
183- self .name = data [0 ].decode ("hex" )
184183 self .uid = data [1 ][4 ]
185184 self .subregion = data [1 ][2 ]
186185 self .url = self .url_template % (self .realm , self .uid , self .subregion , self .name )
@@ -197,6 +196,8 @@ def __init__(self, pid, data, realm="us"):
197196 ['b' , data [3 ][3 ]],
198197 ['a' , data [3 ][0 ]],
199198 ])
199+
200+ self .result = None
200201 self .color_hex = "%02X%02X%02X" % (data [3 ][1 ], data [3 ][2 ], data [3 ][3 ])
201202 self .color_text = "" # The text of the player color (Red, Blue, etc) to be supplied later
202203 self .handicap = data [6 ]
@@ -211,3 +212,55 @@ def __str__(self):
211212
212213 def __repr__ (self ):
213214 return str (self )
215+
216+
217+
218+ class Event (object ):
219+ def __init__ (self , elapsed_time , event_type , event_code , player_id ):
220+ self .time , self .seconds = (elapsed_time , elapsed_time / 16 )
221+ self .timestr = "%s:%s" % (self .seconds / 60 , str (self .seconds % 60 ).rjust (2 , "0" ))
222+ self .type = event_type
223+ self .code = event_code
224+ self .is_local = (player_id != 16 )
225+ self .player = player_id
226+ self .bytes = bytes
227+ self .abilitystr = ""
228+
229+ # Added for convenience
230+ self .is_init = (event_type == 0x00 )
231+ self .is_player_action = (event_type == 0x01 )
232+ self .is_camera_movement = (event_type == 0x03 )
233+ self .is_unknown = (event_type == 0x02 or event_type == 0x04 or event_type == 0x05 )
234+
235+ def __str__ (self ):
236+ return "%s - %s - %s" % (self .timestr , self .name , self .abilitystr )
237+
238+ def __repr__ (self ):
239+ return str (self )
240+
241+ class UnknownEvent (Event ):
242+ name = 'UnknownEvent'
243+
244+ class PlayerJoinEvent (Event ):
245+ name = 'PlayerJoin'
246+
247+ class GameStartEvent (Event ):
248+ name = 'GameStart'
249+
250+ class PlayerLeaveEvent (Event ):
251+ name = 'PlayerLeave'
252+
253+ class AbilityEvent (Event ):
254+ name = 'AbilityEvent'
255+
256+ class ResourceTransferEvent (Event ):
257+ name = 'ResourceTransfer'
258+
259+ class HotkeyEvent (Event ):
260+ name = 'HotkeyEvent'
261+
262+ class SelectionEvent (Event ):
263+ name = 'SelectionEvent'
264+
265+ class CameraMovementEvent (Event ):
266+ name = 'CameraMovement'
0 commit comments