Skip to content

Commit cc57dd1

Browse files
committed
Clean up logging, configs
1 parent 151cd04 commit cc57dd1

16 files changed

Lines changed: 87 additions & 19 deletions

README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,11 @@ Make sure you have `GITHUB_TOKEN` (w/ access permissions for this organization)
1717

1818
To run `n` rounds of 2+ models competing against one another on a game, run the following:
1919
```bash
20-
python main.py configs/battlesnake.yaml
21-
python main.py configs/robocode.yaml
22-
python main.py configs/robotrumble.yaml
23-
python main.py configs/corewar.yaml
20+
python main.py configs/pvp/battlecode.yaml
21+
python main.py configs/pvp/battlesnake.yaml
22+
python main.py configs/pvp/robocode.yaml
23+
python main.py configs/pvp/robotrumble.yaml
24+
python main.py configs/pvp/corewar.yaml
2425
```
2526

2627
For storing `logs/`, we're maintaining an AWS S3 bucket (`s3://codeclash`).

codeclash/agents/abstract.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ def __init__(
3030
self.game_context = game_context
3131
self.logger = get_logger(
3232
self.name,
33-
log_path=self.game_context.log_local / f"{self.name}.log",
33+
log_path=self.game_context.log_local / "players" / self.name / "player.log",
3434
emoji="👤",
3535
)
3636
self._metadata = {

codeclash/agents/dummy.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,3 @@ class Dummy(Player):
66

77
def run(self):
88
pass
9-
# self.commit() # now called in post_round_hook

codeclash/agents/minisweagent.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,12 @@ def run(self):
9393
result = exc_message
9494
print(exc_message)
9595
finally:
96-
traj_path = self.game_context.log_local / f"{self.name}_r{self.game_context.round}.traj.json"
96+
traj_path = (
97+
self.game_context.log_local
98+
/ "players"
99+
/ self.name
100+
/ f"{self.name}_r{self.game_context.round}.traj.json"
101+
)
97102
save_traj(
98103
self.agent, # type: ignore
99104
traj_path,
@@ -104,6 +109,5 @@ def run(self):
104109
copy_to_container(
105110
self.environment,
106111
traj_path,
107-
self.game_context.log_env / traj_path.name,
112+
self.game_context.log_env / "past_edits" / traj_path.name,
108113
)
109-
# self.commit() # now called in post_round_hook

codeclash/games/abstract.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ def __init__(self, config: dict, *, tournament_id: str, local_output_dir: Path):
6060
"game_id": tournament_id,
6161
"created_timestamp": int(time.time()),
6262
}
63-
self.log_env: Path = (DIR_WORK / DIR_LOGS / self.game_id).resolve()
63+
self.log_env: Path = (DIR_WORK / DIR_LOGS).resolve()
6464
self.log_local: Path = local_output_dir
6565
self.logger = get_logger(self.name, log_path=self.log_local / "game.log", emoji="🏓")
6666
self.environment: DockerEnvironment = self.get_environment()

codeclash/ratings/win_rate.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import argparse
2+
import json
3+
from dataclasses import dataclass
4+
from pathlib import Path
5+
6+
from codeclash.constants import RESULT_TIE
7+
8+
9+
@dataclass
10+
class PlayerGameProfile:
11+
player_id: str
12+
game_id: str
13+
wins: int = 0
14+
count: int = 0
15+
16+
@property
17+
def win_rate(self) -> float:
18+
return self.wins / self.count if self.count > 0 else 0.0
19+
20+
21+
def main(log_dir: Path):
22+
player_profiles = {}
23+
for game_log_folder in log_dir.iterdir():
24+
if game_log_folder.is_dir():
25+
print(f"Processing game log folder: {game_log_folder}")
26+
27+
game_id = game_log_folder.name.split(".")[1]
28+
player_ids = [x.name for x in (game_log_folder / "players").iterdir() if x.is_dir()]
29+
num_rounds = len(list((game_log_folder / "rounds").iterdir()))
30+
31+
for player in player_ids:
32+
if f"{game_id}.{player}" in player_profiles:
33+
player_profiles[f"{game_id}.{player}"].count += num_rounds
34+
else:
35+
player_profiles[f"{game_id}.{player}"] = PlayerGameProfile(
36+
player_id=player, game_id=game_id, count=num_rounds
37+
)
38+
39+
for round_folder in (game_log_folder / "rounds").iterdir():
40+
round_results = json.load(open(round_folder / "results.json"))
41+
winner = round_results.get("winner")
42+
if winner != RESULT_TIE:
43+
player_profiles[f"{game_id}.{winner}"].wins += 1
44+
45+
print("Player profiles:")
46+
for profile in player_profiles.values():
47+
print(
48+
f" - {profile.player_id} (Game: {profile.game_id}) - Win Rate: {profile.win_rate:.2%} ({profile.wins}/{profile.count})"
49+
)
50+
51+
52+
if __name__ == "__main__":
53+
parser = argparse.ArgumentParser()
54+
parser.add_argument("log_dir", type=Path, help="Path to `logs/<user>` folder containing game logs")
55+
args = parser.parse_args()
56+
main(args.log_dir)

codeclash/tournaments/pvp.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -83,20 +83,23 @@ def run_training_round(self, round_num: int) -> None:
8383
self.logger.info(f"Round {round_num}:\n{record.stats}")
8484

8585
# Create directory for round logs
86-
(self.game.log_local / f"round_{round_num}").mkdir(parents=True, exist_ok=True)
86+
(self.game.log_local / "rounds" / str(round_num)).mkdir(parents=True, exist_ok=True)
8787

88-
# Write log to file
88+
# Write logs to file
8989
for idx, lo in enumerate(record.data.logs):
90-
round_log_path = self.game.log_local / f"round_{round_num}" / f"sim_{idx}.log"
90+
round_log_path = self.game.log_local / "rounds" / str(round_num) / f"sim_{idx}.log"
9191
round_log_path.write_text(lo)
92+
results_file = self.game.log_local / "rounds" / str(round_num) / "results.json"
93+
with open(results_file, "w") as f:
94+
json.dump(record.stats.model_dump(), fp=f, indent=2)
9295

9396
# Copy log to agent environments
9497
for agent in self.agents:
9598
self.logger.info(f"Copying round {round_num} log(s) to {agent.name}'s container...")
9699
copy_to_container(
97100
agent.environment,
98-
self.game.log_local / f"round_{round_num}",
99-
f"logs/round_{round_num}/",
101+
self.game.log_local / "rounds" / str(round_num),
102+
f"logs/rounds/{round_num}/",
100103
)
101104

102105
for agent in self.agents:
@@ -112,7 +115,8 @@ def run_agent(self, agent: Player, round_num: int) -> None:
112115

113116
def end(self) -> None:
114117
"""Save output files, clean up game resources and push agents if requested."""
115-
(self.local_output_dir / "metadata.json").write_text(json.dumps(self.game.get_metadata()))
118+
with open(self.local_output_dir / "metadata.json", "w") as f:
119+
json.dump(self.game.get_metadata(), fp=f, indent=2)
116120
self.game.end(self.cleanup_on_end)
117121
if self.push_agent:
118122
for agent in self.agents:

codeclash/tournaments/single_player.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"""
44

55
import copy
6+
import json
67

78
from codeclash.agents import get_agent
89
from codeclash.agents.abstract import Player
@@ -95,16 +96,19 @@ def run_training_round(self, round_num: int) -> None:
9596

9697
# Write log to file
9798
for idx, lo in enumerate(record.data.logs):
98-
round_log_path = self.game.log_local / f"round_{round_num}" / f"sim_{idx}.log"
99+
round_log_path = self.game.log_local / "rounds" / str(round_num) / f"sim_{idx}.log"
99100
round_log_path.parent.mkdir(parents=True, exist_ok=True)
100101
round_log_path.write_text(lo)
102+
results_file = self.game.log_local / "rounds" / str(round_num) / "results.json"
103+
with open(results_file, "w") as f:
104+
json.dump(record.stats.model_dump(), fp=f, indent=2)
101105

102106
# Copy log to main agent environment only
103107
self.logger.info(f"Copying round {round_num} log(s) to {self.agent.name}'s container...")
104108
copy_to_container(
105109
self.agent.environment,
106-
self.game.log_local / f"round_{round_num}",
107-
f"logs/round_{round_num}/",
110+
self.game.log_local / "rounds" / str(round_num),
111+
f"logs/rounds/{round_num}/",
108112
)
109113

110114
self.run_main_agent(round_num)

0 commit comments

Comments
 (0)