@@ -72,36 +72,55 @@ def __init__(self, log_dir: Path):
7272
7373 def parse_game_metadata (self ) -> GameMetadata :
7474 """Parse overall game metadata"""
75- # Look for results.json or metadata.json
76- results_file = self .log_dir / "results.json"
77- if not results_file .exists ():
78- # Check for metadata.json as fallback
79- metadata_file = self .log_dir / "metadata.json"
80- if metadata_file .exists ():
81- results = json .loads (metadata_file .read_text ())
82- else :
83- results = {"status" : "No results file found" }
75+ # Look for metadata.json
76+ metadata_file = self .log_dir / "metadata.json"
77+ if metadata_file .exists ():
78+ results = json .loads (metadata_file .read_text ())
8479 else :
85- results = json . loads ( results_file . read_text ())
80+ results = { "status" : "No metadata file found" }
8681
87- # Parse main .log if it exists
88- main_log_file = self .log_dir / "game .log"
89- main_log = main_log_file .read_text () if main_log_file .exists () else "No main log found"
82+ # Parse tournament .log if it exists
83+ main_log_file = self .log_dir / "tournament .log"
84+ main_log = main_log_file .read_text () if main_log_file .exists () else "No tournament log found"
9085
91- # Parse round logs
86+ # Parse round directories and their sim logs
9287 rounds = []
93- round_files = sorted (self .log_dir .glob ("round_*.log" ))
94- for round_file in round_files :
95- round_content = round_file .read_text ()
96- rounds .append ({"filename" : round_file .name , "content" : round_content })
88+ rounds_dir = self .log_dir / "rounds"
89+ if rounds_dir .exists ():
90+ # Get all round directories (sorted numerically)
91+ round_dirs = sorted ([d for d in rounds_dir .iterdir () if d .is_dir ()], key = lambda x : int (x .name ))
92+
93+ for round_dir in round_dirs :
94+ round_num = int (round_dir .name )
95+
96+ # Collect all sim logs for this round
97+ sim_logs = []
98+ sim_files = sorted (round_dir .glob ("sim_*.log" ), key = lambda x : int (x .stem .split ("_" )[1 ]))
99+
100+ for sim_file in sim_files :
101+ sim_content = sim_file .read_text ()
102+ sim_logs .append ({"filename" : sim_file .name , "content" : sim_content })
103+
104+ # Check for round results
105+ results_file = round_dir / "results.json"
106+ round_results = None
107+ if results_file .exists ():
108+ round_results = json .loads (results_file .read_text ())
109+
110+ rounds .append ({"round_num" : round_num , "sim_logs" : sim_logs , "results" : round_results })
97111
98112 return GameMetadata (results = results , main_log = main_log , rounds = rounds )
99113
100114 def parse_trajectory (self , player_id : int , round_num : int ) -> TrajectoryInfo | None :
101115 """Parse a specific trajectory file"""
116+ # Look in players/$player_id/ directory
117+ player_dir = self .log_dir / "players" / f"p{ player_id } "
118+ if not player_dir .exists ():
119+ return None
120+
102121 # Try both .json and .log extensions
103122 for ext in [".json" , ".log" ]:
104- traj_file = self . log_dir / f"p{ player_id } _r{ round_num } .traj{ ext } "
123+ traj_file = player_dir / f"p{ player_id } _r{ round_num } .traj{ ext } "
105124 if traj_file .exists ():
106125 try :
107126 data = json .loads (traj_file .read_text ())
@@ -127,18 +146,34 @@ def parse_trajectory(self, player_id: int, round_num: int) -> TrajectoryInfo | N
127146 def get_available_trajectories (self ) -> list [tuple ]:
128147 """Get list of available trajectory files as (player_id, round_num) tuples"""
129148 trajectories = []
130- for traj_file in self .log_dir .glob ("p*_r*.traj.*" ):
131- # Extract player and round from filename like p1_r2.traj.json
132- parts = traj_file .stem .split ("." ) # Remove extension
133- if parts :
134- name_part = parts [0 ] # p1_r2
135- try :
136- player_part , round_part = name_part .split ("_" )
137- player_id = int (player_part [1 :]) # Remove 'p' prefix
138- round_num = int (round_part [1 :]) # Remove 'r' prefix
139- trajectories .append ((player_id , round_num ))
140- except (ValueError , IndexError ):
141- continue
149+ players_dir = self .log_dir / "players"
150+
151+ if not players_dir .exists ():
152+ return trajectories
153+
154+ # Iterate through player directories
155+ for player_dir in players_dir .iterdir ():
156+ if not player_dir .is_dir ():
157+ continue
158+
159+ try :
160+ # Extract player_id from directory name (e.g., "p1" -> 1)
161+ player_id = int (player_dir .name [1 :]) # Remove 'p' prefix
162+ except (ValueError , IndexError ):
163+ continue
164+
165+ # Find trajectory files in this player's directory
166+ for traj_file in player_dir .glob ("p*_r*.traj.*" ):
167+ # Extract round from filename like p1_r2.traj.json
168+ parts = traj_file .stem .split ("." ) # Remove extension
169+ if parts :
170+ name_part = parts [0 ] # p1_r2
171+ try :
172+ _ , round_part = name_part .split ("_" )
173+ round_num = int (round_part [1 :]) # Remove 'r' prefix
174+ trajectories .append ((player_id , round_num ))
175+ except (ValueError , IndexError ):
176+ continue
142177
143178 return sorted (trajectories )
144179
0 commit comments