1313from sc2reader import utils
1414from sc2reader import log_utils
1515from sc2reader .objects import Player , Observer , Team , PlayerSummary , Graph
16- from sc2reader .constants import REGIONS , LOCALIZED_RACES , GAME_SPEED_FACTOR , GAME_SPEED_CODES , RACE_CODES
16+ from sc2reader .constants import REGIONS , LOCALIZED_RACES , GAME_SPEED_FACTOR , GAME_SPEED_CODES , RACE_CODES , PLAYER_TYPE_CODES , TEAM_COLOR_CODES , GAME_FORMAT_CODES , GAME_TYPE_CODES , DIFFICULTY_CODES
1717
1818
1919class Resource (object ):
@@ -416,6 +416,24 @@ class GameSummary(Resource):
416416 'SB' ,
417417 'SRC' ,
418418 ]
419+ lobby_keys = {
420+ 3000 : ('game_speed' , GAME_SPEED_CODES ),
421+ 2001 : ('game_type' , GAME_FORMAT_CODES ), #1v1/2v2/3v3/4v4/5v5/6v6/FFA
422+ 3010 : ('unknown1' , {'sey' :'yes' , 'on' :'no' } ), #yes/no
423+ 3006 : ('unknown2' , {'3' :'3' ,'5' :'5' ,'7' :'7' ,'01' :'10' ,'51' :'15' ,'02' :'20' ,'52' :'25' ,'03' :'30' }), #3',5/7/10/15/20/25/30
424+ 1001 : ('unknown3' , {'sey' :'yes' , 'on' :'no' }), #yes/no
425+ 1000 : ('unknown4' , {'tlfD' :'Default' }), #Dflt
426+ 2000 : ('unknown5' , {'2t' :'t2' , '3t' :'t3' , 'AFF' :'FFA' , 'tsuC' :'Custom' }), #t2/t3/FFA/Cust
427+ 3009 : ('lobby_type' , GAME_TYPE_CODES ) #Priv/Pub/Amm (Auto MatchMaking)
428+ }
429+ lobby_player_keys = {
430+ 500 : ('slot_state' , PLAYER_TYPE_CODES ), #Clsd/Open/Humn/Comp
431+ 3001 : ('race' , RACE_CODES ),
432+ 3003 : ('energy' , {'05' :'50' ,'06' :'60' ,'07' :'70' ,'08' :'80' ,'09' :'90' ,'001' :'100' }),
433+ 3002 : ('color' , TEAM_COLOR_CODES ),
434+ 3004 : ('difficulty' , DIFFICULTY_CODES ),
435+ 3008 : ('nonplayer_mode' , {'sbO' :'Observer' ,'feR' :'Ref' }) #Obs/Ref
436+ }
419437
420438 #: Game speed
421439 game_speed = str ()
@@ -426,11 +444,17 @@ class GameSummary(Resource):
426444 #: Game length (in-game)
427445 game_length_ingame = int ()
428446
447+ #: Lobby properties
448+ lobby_properties = dict ()
449+
429450 #: Game completion time
430451 time = int ()
431452
432- #: Players, a list of :class`PlayerSummary` from the game
433- players = list ()
453+ #: Players, a dict of :class`PlayerSummary` from the game
454+ players = dict ()
455+
456+ #: Teams, a dict of pids
457+ teams = dict ()
434458
435459 #: Build orders, a dict of build orders indexed by player id
436460 build_orders = dict ()
@@ -444,10 +468,12 @@ class GameSummary(Resource):
444468 def __init__ (self , summary_file , filename = None , ** options ):
445469 super (GameSummary , self ).__init__ (summary_file , filename ,** options )
446470
447- self .players = list ()
471+ self .players = dict ()
448472 self .build_orders = dict ()
449473 self .image_urls = list ()
450474 self .localization_urls = dict ()
475+ self .lobby_properties = dict ()
476+ self .teams = dict ()
451477
452478 self .data = zlib .decompress (summary_file .read ()[16 :])
453479 self .parts = list ()
@@ -470,12 +496,32 @@ def __init__(self, summary_file, filename=None, **options):
470496 self .game_length_ingame = self .parts [0 ][7 ]
471497 self .game_length = self .game_length_ingame / GAME_SPEED_FACTOR [self .game_speed ]
472498
499+ # parse lobby properties
500+ lobby_template = dict ()
501+ for prop in self .parts [0 ][5 ]:
502+ if not prop [0 ][1 ] in self .lobby_keys :
503+ continue
504+ lobby_template [prop [0 ][1 ]] = [o [0 ].strip ('\x00 ' ) for o in prop [1 ]]
505+ for prop in self .parts [0 ][6 ][6 ]:
506+ if not prop [0 ][1 ] in lobby_template :
507+ continue
508+ key = self .lobby_keys [prop [0 ][1 ]][0 ]
509+ val = lobby_template [prop [0 ][1 ]][prop [1 ][0 ]]
510+ self .lobby_properties [key ] = self .lobby_keys [prop [0 ][1 ]][1 ][utils .reverse_str (val )]
511+
512+ # Prepare player lobby properties
513+ lobby_player_template = dict ()
514+ for prop in self .parts [0 ][5 ]:
515+ if not prop [0 ][1 ] in self .lobby_player_keys :
516+ continue
517+ lobby_player_template [prop [0 ][1 ]] = [o [0 ].strip ().strip ('\x00 ' ) for o in prop [1 ]]
518+
473519 # Parse player structs, 16 is the maximum amount of players
474520 for i in range (16 ):
475521 player = None
476- # Check if player, break if not
522+ # Check if player, skip if not
477523 if self .parts [0 ][3 ][i ][2 ] == '\x00 \x00 \x00 \x00 ' :
478- break
524+ continue
479525 player_struct = self .parts [0 ][3 ][i ]
480526
481527 player = PlayerSummary (player_struct [0 ][0 ])
@@ -498,11 +544,24 @@ def __init__(self, summary_file, filename=None, **options):
498544 # { 0: 3405691582L, 1: 11402158793782460416L}
499545 player .unknown2 = player_struct [0 ][1 ][1 ]
500546
501- self .players .append (player )
547+ # Parse lobby properties
548+ player .lobby_properties = dict ()
549+ for prop in self .parts [0 ][6 ][6 ]:
550+ if not prop [0 ][1 ] in lobby_player_template :
551+ continue
552+ key = self .lobby_player_keys [prop [0 ][1 ]][0 ]
553+ val = lobby_player_template [prop [0 ][1 ]][prop [1 ][player .pid ][0 ]]
554+ player .lobby_properties [key ] = self .lobby_player_keys [prop [0 ][1 ]][1 ][utils .reverse_str (val )]
555+
556+ self .players [player .pid ] = player
557+ if not player .teamid in self .teams :
558+ self .teams [player .teamid ] = list ()
559+ self .teams [player .teamid ].append (player .pid )
560+
502561
503562 # Parse graph and stats stucts, for each player
504- for p in self .players :
505-
563+ for pid in self .players :
564+ p = self . players [ pid ]
506565 # Graph stuff
507566 xy = [(o [2 ], o [0 ]) for o in self .parts [4 ][0 ][2 ][1 ][p .pid ]]
508567 p .army_graph = Graph ([], [], xy_list = xy )
@@ -542,7 +601,8 @@ def __init__(self, summary_file, filename=None, **options):
542601 bo_structs .append (self .parts [4 ][0 ][3 :])
543602
544603 # This might not be the most effective way, but it works
545- for p in self .players :
604+ for pid in self .players :
605+ p = self .players [pid ]
546606 bo = list ()
547607 for bo_struct in bo_structs :
548608 for order in bo_struct :
@@ -571,7 +631,7 @@ def __str__(self):
571631 int (self .game_length )/ 3600 ,
572632 (int (self .game_length )% 3600 )/ 60 ,
573633 (int (self .game_length )% 3600 )% 60 ,
574- '' .join (p .race [0 ] for p in self .players ))
634+ '' .join (self . players [ p ] .race [0 ] for p in self .players ))
575635
576636class MapInfo (Resource ):
577637 url_template = 'http://{0}.depot.battle.net:1119/{1}.s2mi'
0 commit comments