3
3
import zlib
4
4
import pprint
5
5
import hashlib
6
+ import collections
6
7
from datetime import datetime
7
8
import time
8
9
from StringIO import StringIO
@@ -332,37 +333,17 @@ def load_players(self):
332
333
return
333
334
if 'replay.attributes.events' not in self .raw_data :
334
335
return
336
+ if 'replay.initData' not in self .raw_data :
337
+ return
335
338
336
- # Create and add the players based on attribute and details information
337
- player_index , obs_index , default_region = 0 , 0 , ''
338
- player_data = self .raw_data ['replay.details' ].players
339
- for pid , attributes in sorted (self .attributes .iteritems ()):
340
-
341
- # We've already processed the global attributes
342
- if pid == 16 : continue
343
-
344
- # Open Slots are skipped because it doesn't seem useful to store
345
- # an "Open" player to fill a spot that would otherwise be empty.
346
- if attributes ['Player Type' ] == 'Open' : continue
347
-
348
- # Get the player data from the details file, increment the index to
349
- # Keep track of which player we are processing
350
- pdata = player_data [player_index ]
351
- player_index += 1
352
-
353
- # If this is a human player, push back the initial observer index in
354
- # the list of all human players we gathered from the initdata file.
355
- if attributes ['Player Type' ] == 'Human' :
356
- obs_index += 1
357
-
358
- # Create the player using the current pid and the player name from
359
- # The details file. This works because players are stored in order
360
- # of pid inside of the details file. Attributes and Details must be
361
- # processed together because Details doesn't index players by or
362
- # store their player ids; Attributes can provide that information
363
- # and allow for accurate pid mapping even with computers, observers,
364
- # and open open slots.
365
- #
339
+ # 1. pids are in lobby join order, use initData.player_names
340
+ # 2. use the name to get the player_data index
341
+ # 2a. if observer, save pid+name for later
342
+ # 3. use the player_data index as the attrib_data index...?
343
+ # 4. use the player_data and attribute_data to load the player
344
+ # 5. after loop, load the computer players and (optionally) their attributes
345
+ # 6. then load the observer pid,name using attributes if available
346
+ def createPlayer (pid , pdata , attributes ):
366
347
# General information re: each player comes from the following files
367
348
# * replay.initData
368
349
# * replay.details
@@ -373,7 +354,9 @@ def load_players(self):
373
354
player = Player (pid ,pdata .name )
374
355
375
356
# Cross reference the player and team lookups
376
- team_number = attributes ['Teams' + self .type ]
357
+ # TODO: Players without attribute events, where do we get the team info?
358
+ # print pdata.name, attributes, pdata
359
+ team_number = attributes .get ('Teams' + self .type ,0 )
377
360
if not team_number in self .team :
378
361
self .team [team_number ] = Team (team_number )
379
362
self .teams .append (self .team [team_number ])
@@ -387,20 +370,19 @@ def load_players(self):
387
370
elif pdata .result == 2 :
388
371
player .team .result = "Loss"
389
372
390
- player .pick_race = attributes [ 'Race' ]
373
+ player .pick_race = attributes . get ( 'Race' , 'Unknown' )
391
374
player .play_race = LOCALIZED_RACES .get (pdata .race , pdata .race )
392
- player .difficulty = attributes [ 'Difficulty' ]
393
- player .is_human = (attributes [ 'Player Type' ] == 'Human' )
375
+ player .difficulty = attributes . get ( 'Difficulty' , 'Unknown' )
376
+ player .is_human = (attributes . get ( 'Player Type' , 'Computer' ) == 'Human' )
394
377
player .uid = pdata .bnet .uid
395
378
player .subregion = pdata .bnet .subregion
396
379
player .handicap = pdata .handicap
397
380
398
381
# We need initData for the gateway portion of the url!
399
- if 'replay.initData' in self . raw_data and self .gateway :
382
+ if self .gateway :
400
383
player .gateway = self .gateway
401
384
if player .is_human and player .subregion :
402
385
player .region = REGIONS [self .gateway ].get (player .subregion , 'Unknown' )
403
- default_region = player .region
404
386
405
387
# Conversion instructions to the new color object:
406
388
# color_rgba is the color object itself
@@ -415,35 +397,58 @@ def load_players(self):
415
397
self .player [pid ] = player
416
398
self .person [pid ] = player
417
399
400
+ def createObserver (pid , name , attributes ):
401
+ observer = Observer (pid ,name )
402
+ self .observers .append (observer )
403
+ self .people .append (observer )
404
+ self .person [pid ] = observer
405
+
406
+ observer_data = list ()
407
+ unassigned_player_data = collections .OrderedDict ((p .name , (idx ,p )) for idx , p in enumerate (self .raw_data ['replay.details' ].players ))
408
+ try :
409
+ for pid , name in enumerate (self .raw_data ['replay.initData' ].player_names ):
410
+ if name in unassigned_player_data :
411
+ idx , pdata = unassigned_player_data [name ]
412
+ attributes = self .attributes .get (idx ,dict ())
413
+ createPlayer (pid , pdata , attributes )
414
+ del unassigned_player_data [name ]
415
+ else :
416
+ observer_data .append ((pid ,name ))
417
+
418
+ comp_start_id = len (self .raw_data ['replay.initData' ].player_names )
419
+ for name , (idx ,pdata ) in unassigned_player_data .items ():
420
+ attributes = self .attributes .get (idx ,dict ())
421
+ createPlayer (comp_start_id , pdata , attributes )
422
+ comp_start_id += 1
423
+
424
+ obs_start_idx = len (self .raw_data ['replay.details' ].players )
425
+ for pid , name in observer_data :
426
+ attributes = self .attributes .get (obs_start_idx ,dict ())
427
+ createObserver (pid , name , attributes )
428
+ obs_start_idx += 1
429
+ except :
430
+ print unassigned_player_data
431
+ print self .raw_data ['replay.initData' ].player_names
432
+ raise
433
+
434
+
435
+ self .humans = filter (lambda p : p .is_human , self .people )
436
+
418
437
#Create an store an ordered lineup string
419
438
for team in self .teams :
420
439
team .lineup = '' .join (sorted (player .play_race [0 ].upper () for player in team ))
421
440
422
441
self .real_type = real_type (self .teams )
423
442
424
- if 'replay.initData' in self .raw_data :
425
- # Assign the default region to computer players for consistency
426
- # We know there will be a default region because there must be
427
- # at least 1 human player or we wouldn't have a self.
428
- for player in self .players :
429
- if not player .is_human :
430
- player .region = default_region
431
-
432
- # Create observers out of the leftover names gathered from initData
433
- all_players = [p .name for p in self .players ]
434
- all_people = self .raw_data ['replay.initData' ].player_names
435
- for obs_name in all_people :
436
- if obs_name in all_players : continue
437
-
438
- observer = Observer (obs_index ,obs_name )
439
- observer .region = default_region
440
- self .observers .append (observer )
441
- self .people .append (observer )
442
- self .person [obs_index ] = observer
443
- obs_index += 1
444
-
445
- # Miscellaneous people processing
446
- self .humans = filter (lambda p : p .is_human , self .people )
443
+ # Assign the default region to computer players for consistency
444
+ # We know there will be a default region because there must be
445
+ # at least 1 human player or we wouldn't have a self.
446
+ default_region = self .humans [0 ].region
447
+ for player in self .players :
448
+ if not player .is_human :
449
+ player .region = default_region
450
+ for obs in self .observers :
451
+ obs .region = default_region
447
452
448
453
if 'replay.message.events' in self .raw_data :
449
454
# Figure out recorder
0 commit comments