Skip to content

Commit 38aa6cc

Browse files
committed
Enh(viewer): Show completed rounds
1 parent 8d876eb commit 38aa6cc

2 files changed

Lines changed: 50 additions & 14 deletions

File tree

codeclash/viewer/app.py

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -41,17 +41,53 @@ def is_game_folder(log_dir: Path) -> bool:
4141
return metadata_file.exists()
4242

4343

44-
def get_round_count_from_metadata(log_dir: Path) -> int | None:
45-
"""Extract round count from metadata.json if it exists"""
44+
def get_round_count_from_metadata(log_dir: Path) -> tuple[int, int] | None:
45+
"""Extract round count from metadata.json and rounds folder if they exist
46+
47+
Returns:
48+
tuple[int, int] | None: (completed_rounds, total_rounds) or None if not available
49+
"""
4650
metadata_file = log_dir / "metadata.json"
47-
if not metadata_file.exists():
48-
return None
51+
rounds_dir = log_dir / "rounds"
4952

50-
try:
51-
metadata = json.loads(metadata_file.read_text())
52-
return metadata.get("config", {}).get("tournament", {}).get("rounds")
53-
except (json.JSONDecodeError, KeyError):
54-
return None
53+
total_rounds = None
54+
completed_rounds = 0
55+
56+
# First, try to get total rounds from metadata
57+
if metadata_file.exists():
58+
try:
59+
metadata = json.loads(metadata_file.read_text())
60+
total_rounds = metadata.get("config", {}).get("tournament", {}).get("rounds")
61+
62+
# Count completed rounds from round_stats (excluding round 0 which is warmup)
63+
round_stats = metadata.get("round_stats", {})
64+
if round_stats:
65+
# Count rounds > 0 (exclude warmup round 0)
66+
for round_key in round_stats.keys():
67+
if int(round_key) > 0:
68+
completed_rounds += 1
69+
except (json.JSONDecodeError, KeyError, ValueError):
70+
pass
71+
72+
# If we don't have round_stats or metadata, count from rounds folder
73+
if completed_rounds == 0 and rounds_dir.exists():
74+
try:
75+
# Count subdirectories in rounds folder (excluding round 0 if it exists)
76+
round_dirs = [d for d in rounds_dir.iterdir() if d.is_dir()]
77+
for round_dir in round_dirs:
78+
try:
79+
round_num = int(round_dir.name)
80+
if round_num > 0: # Exclude warmup round 0
81+
completed_rounds += 1
82+
except ValueError:
83+
continue
84+
except (OSError, PermissionError):
85+
pass
86+
87+
if total_rounds is not None:
88+
return (completed_rounds, total_rounds)
89+
90+
return None
5591

5692

5793
def get_models_from_metadata(log_dir: Path) -> list[str]:
@@ -159,15 +195,15 @@ def scan_directory(directory: Path, relative_path: str = ""):
159195

160196
# Check if this directory is a game folder
161197
if is_game_folder(item):
162-
round_count = get_round_count_from_metadata(item)
198+
round_info = get_round_count_from_metadata(item)
163199
models = get_models_from_metadata(item)
164200
readme_first_line = get_readme_first_line(item)
165201
game_folders.add(current_relative)
166202
all_folders.append(
167203
{
168204
"name": current_relative,
169205
"full_path": str(item),
170-
"round_count": round_count,
206+
"round_info": round_info, # Now stores (completed, total) tuple or None
171207
"models": models,
172208
"readme_first_line": readme_first_line,
173209
"is_game": True,
@@ -181,7 +217,7 @@ def scan_directory(directory: Path, relative_path: str = ""):
181217
{
182218
"name": current_relative,
183219
"full_path": str(item),
184-
"round_count": None,
220+
"round_info": None,
185221
"models": [],
186222
"readme_first_line": "",
187223
"is_game": False,

codeclash/viewer/templates/picker.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,8 @@ <h3>📁 Base Directory:</h3>
9595

9696
<div class="rounds-cell">
9797
{% if game.is_game %}
98-
{% if game.round_count %}
99-
<span class="rounds-count">{{ game.round_count }}</span>
98+
{% if game.round_info %}
99+
<span class="rounds-count">{{ game.round_info[0] }}/{{ game.round_info[1] }}</span>
100100
{% else %}
101101
<span class="rounds-unknown">?</span>
102102
{% endif %}

0 commit comments

Comments
 (0)