Skip to content

Commit 5b33ad8

Browse files
committed
Simplify log copying
1 parent 1c343ad commit 5b33ad8

8 files changed

Lines changed: 44 additions & 94 deletions

File tree

codeclash/games/battlecode/battlecode.py

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,8 @@
55

66
from codeclash.constants import DIR_WORK, RESULT_TIE
77
from codeclash.games.game import CodeGame, RoundStats
8-
from codeclash.utils.environment import copy_from_container
98

10-
BATTLECODE_LOG = "sim.log"
9+
BC_LOG = "sim.log"
1110

1211

1312
class BattleCodeGame(CodeGame):
@@ -24,17 +23,9 @@ def __init__(self, config, *, tournament_id: str, local_output_dir: Path):
2423
else:
2524
self.run_cmd_round += f" --{arg} {val}"
2625

27-
def copy_logs_from_env(self, round_num):
28-
super().copy_logs_from_env(round_num)
29-
copy_from_container(
30-
container=self.environment,
31-
src_path="/testbed/sim.log",
32-
dest_path=self.log_round(round_num) / f"sim_{round_num}.log",
33-
)
34-
35-
def get_stats(self, agents: list[Any], round_num: int) -> RoundStats:
26+
def get_results(self, agents: list[Any], round_num: int) -> RoundStats:
3627
winners = []
37-
with open(self.log_round(round_num) / f"sim_{round_num}.log") as f:
28+
with open(self.log_round(round_num) / BC_LOG) as f:
3829
lines = f.read().strip().split("\n")
3930
# Get the third-to-last line which contains the winner info
4031
winner_line = lines[-3] if len(lines) >= 3 else ""
@@ -62,5 +53,5 @@ def execute_round(self, agents: list[Any]):
6253
cmd = f"{self.run_cmd_round} {' '.join(args)}"
6354
self.logger.info(f"Running game: {cmd}")
6455

65-
response = self.environment.execute(cmd + f" > {BATTLECODE_LOG}")
56+
response = self.environment.execute(cmd + f" > {self.log_env / BC_LOG}")
6657
assert response["returncode"] == 0, response

codeclash/games/battlesnake/battlesnake.py

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from codeclash.agents.player import Player
99
from codeclash.constants import RESULT_TIE
1010
from codeclash.games.game import CodeGame, RoundStats
11-
from codeclash.utils.environment import assert_zero_exit_code, copy_from_container
11+
from codeclash.utils.environment import assert_zero_exit_code
1212

1313

1414
class BattleSnakeGame(CodeGame):
@@ -38,18 +38,10 @@ def _wait_for_ports(self, ports: list[int], timeout: float = 3.0) -> None:
3838

3939
time.sleep(0.1)
4040

41-
def copy_logs_from_env(self, round_num):
42-
super().copy_logs_from_env(round_num)
43-
copy_from_container(
44-
container=self.environment,
45-
src_path=f"{self.environment.config.cwd}/game/logs",
46-
dest_path=self.log_round(round_num),
47-
)
48-
49-
def get_stats(self, agents: list[Player], round_num: int) -> RoundStats:
41+
def get_results(self, agents: list[Player], round_num: int) -> RoundStats:
5042
scores = {}
5143
for idx in range(self.game_config["sims_per_round"]):
52-
with open(self.log_round(round_num) / f"logs/sim_{idx}.jsonl") as f:
44+
with open(self.log_round(round_num) / f"sim_{idx}.jsonl") as f:
5345
lines = f.read().strip().split("\n")
5446
results = json.loads(lines[-1]) # Get the last line which contains the game result
5547
winner = RESULT_TIE if results["isDraw"] else results["winnerName"]
@@ -78,7 +70,6 @@ def execute_round(self, agents: list[Player]):
7870
try:
7971
cmd = self.run_cmd_round + " " + " ".join(cmd)
8072
self.logger.info(f"Running game: {cmd}")
81-
self.environment.execute("rm -rf logs; mkdir logs", cwd=f"{self.environment.config.cwd}/game")
8273

8374
# Use ThreadPoolExecutor for parallel execution
8475
with ThreadPoolExecutor(20) as executor:
@@ -99,7 +90,7 @@ def _run_single_simulation(self, cmd: str, idx: int) -> tuple[str, str]:
9990
"""Run a single battlesnake simulation and return log and result outputs."""
10091
assert_zero_exit_code(
10192
self.environment.execute(
102-
cmd + f" -o logs/sim_{idx}.jsonl",
93+
cmd + f" -o {self.log_env / f'sim_{idx}.jsonl'}",
10394
cwd=f"{self.environment.config.cwd}/game",
10495
)
10596
)

codeclash/games/corewar/corewar.py

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
from codeclash.agents.player import Player
66
from codeclash.games.game import CodeGame, RoundStats
7-
from codeclash.utils.environment import copy_from_container
87

98
COREWAR_LOG = "sim.log"
109

@@ -22,15 +21,7 @@ def __init__(self, config, *, tournament_id: str, local_output_dir: Path):
2221
else:
2322
self.run_cmd_round += f" -{arg} {val}"
2423

25-
def copy_logs_from_env(self, round_num: int) -> None:
26-
super().copy_logs_from_env(round_num)
27-
copy_from_container(
28-
container=self.environment,
29-
src_path=f"/testbed/{COREWAR_LOG}",
30-
dest_path=self.log_round(round_num) / COREWAR_LOG,
31-
)
32-
33-
def get_stats(self, agents: list[Player], round_num: int) -> RoundStats:
24+
def get_results(self, agents: list[Player], round_num: int) -> RoundStats:
3425
with open(self.log_round(round_num) / COREWAR_LOG) as f:
3526
result_output = f.read()
3627
self.logger.debug(f"Determining winner from result output: {result_output}")
@@ -64,7 +55,11 @@ def get_stats(self, agents: list[Player], round_num: int) -> RoundStats:
6455

6556
def execute_round(self, agents: list[Player]):
6657
args = [f"/{agent.name}/warriors/warrior.red" for agent in agents]
67-
cmd = f"{self.run_cmd_round} {shlex.join(args)} -r {self.game_config['sims_per_round']} > {COREWAR_LOG};"
58+
cmd = (
59+
f"{self.run_cmd_round} {shlex.join(args)} "
60+
f"-r {self.game_config['sims_per_round']} "
61+
f"> {self.log_env / COREWAR_LOG};"
62+
)
6863
self.logger.info(f"Running game: {cmd}")
6964
response = self.environment.execute(cmd)
7065
assert response["returncode"] == 0, response

codeclash/games/dummy/dummy_game.py

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,16 @@
22

33
from codeclash.agents.player import Player
44
from codeclash.games.game import CodeGame, RoundStats
5-
from codeclash.utils.environment import assert_zero_exit_code, copy_from_container
5+
from codeclash.utils.environment import assert_zero_exit_code
6+
7+
DUMMY_LOG = "result.log"
68

79

810
class DummyGame(CodeGame):
911
name: str = "DummyGame"
1012

11-
def copy_logs_from_env(self, round_num):
12-
super().copy_logs_from_env(round_num)
13-
copy_from_container(
14-
container=self.environment,
15-
src_path="/testbed/result.log",
16-
dest_path=self.log_round(round_num) / "result.log",
17-
)
18-
19-
def get_stats(self, agents: list[Player], round_num: int) -> RoundStats:
20-
with open(self.log_round(round_num) / "result.log") as f:
13+
def get_results(self, agents: list[Player], round_num: int) -> RoundStats:
14+
with open(self.log_round(round_num) / DUMMY_LOG) as f:
2115
round_log = f.read()
2216
lines = round_log.split("FINAL_RESULTS")[-1].splitlines()
2317

@@ -37,6 +31,6 @@ def get_stats(self, agents: list[Player], round_num: int) -> RoundStats:
3731

3832
def execute_round(self, agents: list[Player]) -> None:
3933
args = [f"/{agent.name}/main.py" for agent in agents]
40-
cmd = f"python engine.py {' '.join(args)} -r {self.game_config['sims_per_round']} > result.log;"
34+
cmd = f"python engine.py {' '.join(args)} -r {self.game_config['sims_per_round']} > {self.log_env / DUMMY_LOG};"
4135
self.logger.info(f"Running game: {cmd}")
4236
assert_zero_exit_code(self.environment.execute(cmd))

codeclash/games/game.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
from codeclash.agents.player import Player
1212
from codeclash.constants import DIR_LOGS, DIR_WORK, GH_ORG
13-
from codeclash.utils.environment import assert_zero_exit_code, copy_between_containers
13+
from codeclash.utils.environment import assert_zero_exit_code, copy_between_containers, copy_from_container
1414
from codeclash.utils.log import get_logger
1515

1616

@@ -102,6 +102,11 @@ def build_image(self):
102102
def copy_logs_from_env(self, round_num: int) -> None:
103103
"""Copy logs from the game's environment to the local machine."""
104104
(self.log_local / "rounds" / str(round_num)).mkdir(parents=True, exist_ok=True)
105+
copy_from_container(
106+
container=self.environment,
107+
src_path=str(self.log_env) + "/.",
108+
dest_path=self.log_round(round_num),
109+
)
105110

106111
def end(self, cleanup: bool = False):
107112
if cleanup:
@@ -175,10 +180,10 @@ def run_round(self, agents: list[Player], round_num: int) -> RoundStats:
175180
self._pre_round_setup(agents)
176181
self.execute_round(agents)
177182
self.copy_logs_from_env(round_num)
178-
return self.get_stats(agents, round_num)
183+
return self.get_results(agents, round_num)
179184

180185
@abstractmethod
181-
def get_stats(self, agents: list[Player], round_num: int) -> RoundStats:
186+
def get_results(self, agents: list[Player], round_num: int) -> RoundStats:
182187
"""Determine the winner of the game based on the result output.
183188
184189
Args:

codeclash/games/huskybench/huskybench.py

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,8 @@
33

44
from codeclash.agents.player import Player
55
from codeclash.games.game import CodeGame, RoundStats
6-
from codeclash.utils.environment import copy_from_container
76

8-
HB_LOG_DIR = Path("/testbed/engine/logs/")
7+
HB_LOG_ENGINE = "engine.log"
98
HB_REGEX_SCORE = re.compile(r"Player\s(\d+)\sdelta\supdated\:[\d\s\-\+\=]+,\smoney\:\s\d+\s\-\>\s(\d+)")
109

1110

@@ -26,26 +25,17 @@ def __init__(self, config, *, tournament_id: str, local_output_dir: Path):
2625
else:
2726
self.run_cmd_round += f" --{arg} {val}"
2827

29-
def copy_logs_from_env(self, round_num):
30-
super().copy_logs_from_env(round_num)
31-
log_path = self.log_round(round_num)
32-
copy_from_container(
33-
container=self.environment,
34-
src_path=HB_LOG_DIR,
35-
dest_path=log_path,
36-
)
37-
38-
def get_stats(self, agents: list[Player], round_num: int) -> RoundStats:
28+
def get_results(self, agents: list[Player], round_num: int) -> RoundStats:
3929
map_id_to_agent = {}
4030
for agent in agents:
41-
with open(self.log_round(round_num) / f"logs/{agent.name}.log") as f:
31+
with open(self.log_round(round_num) / f"{agent.name}.log") as f:
4232
for line in f:
4333
if line.startswith("My id:"):
4434
agent_id = line.strip().split()[-1]
4535
map_id_to_agent[agent_id] = agent.name
4636
self.logger.info("Agent IDs: " + str(map_id_to_agent))
4737

48-
with open(self.log_round(round_num) / "logs/engine.log") as f:
38+
with open(self.log_round(round_num) / HB_LOG_ENGINE) as f:
4939
score_updates = [
5040
(match.group(1), int(match.group(2))) for l in f.readlines() if (match := HB_REGEX_SCORE.search(l))
5141
]
@@ -55,13 +45,12 @@ def get_stats(self, agents: list[Player], round_num: int) -> RoundStats:
5545
return RoundStats(winner=max(agent_to_score, key=agent_to_score.get), scores=agent_to_score)
5646

5747
def execute_round(self, agents: list[Player]):
58-
self.environment.execute(f"rm -rf {HB_LOG_DIR}; mkdir -p {HB_LOG_DIR}")
5948
try:
60-
cmd = f"{self.run_cmd_round} > {HB_LOG_DIR / 'engine.log'} &"
49+
cmd = f"{self.run_cmd_round} > {self.log_env / HB_LOG_ENGINE} &"
6150
self.logger.debug(f"Starting game engine with command: {cmd}")
6251
self.environment.execute(cmd)
6352
for agent in agents:
64-
cmd = f"python client/main.py --port 8000 > {HB_LOG_DIR / f'{agent.name}.log'} &"
53+
cmd = f"python client/main.py --port 8000 > {self.log_env / f'{agent.name}.log'} &"
6554
self.logger.debug(f"Adding agent with command: {cmd}")
6655
self.environment.execute(cmd, cwd=f"/{agent.name}")
6756
finally:

codeclash/games/robocode/robocode.py

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44

55
from codeclash.agents.player import Player
66
from codeclash.games.game import CodeGame, RoundStats
7-
from codeclash.utils.environment import assert_zero_exit_code, copy_from_container, create_file_in_container
7+
from codeclash.utils.environment import assert_zero_exit_code, create_file_in_container
8+
9+
RC_LOG = "scoreboard.txt"
810

911

1012
class RoboCodeGame(CodeGame):
@@ -53,16 +55,8 @@ def dict_to_lines(d, prefix=""):
5355
dict_to_lines(default_battle_config)
5456
return "\n".join(battle_lines)
5557

56-
def copy_logs_from_env(self, round_num: int) -> None:
57-
super().copy_logs_from_env(round_num)
58-
copy_from_container(
59-
container=self.environment,
60-
src_path="/testbed/logs",
61-
dest_path=self.log_round(round_num),
62-
)
63-
64-
def get_stats(self, agents: list[Player], round_num: int) -> RoundStats:
65-
with open(self.log_round(round_num) / "logs/results.txt") as f:
58+
def get_results(self, agents: list[Player], round_num: int) -> RoundStats:
59+
with open(self.log_round(round_num) / RC_LOG) as f:
6660
result_output = f.read()
6761
print(result_output)
6862
lines = result_output.strip().split("\n")
@@ -104,6 +98,6 @@ def execute_round(self, agents: list[Player]):
10498
create_file_in_container(self.environment, content=battle_content, dest_path=f"battles/{battle_file}")
10599

106100
# Run battle with results output to file
107-
cmd = f"mkdir -p logs; {self.run_cmd_round} -battle {battle_file} -results logs/results.txt"
101+
cmd = f"{self.run_cmd_round} -battle {battle_file} -results {self.log_env / RC_LOG}"
108102
self.logger.info(f"Running game: {cmd}")
109103
assert_zero_exit_code(self.environment.execute(cmd))

codeclash/games/robotrumble/robotrumble.py

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from codeclash.agents.player import Player
66
from codeclash.constants import RESULT_TIE
77
from codeclash.games.game import CodeGame, RoundStats
8-
from codeclash.utils.environment import assert_zero_exit_code, copy_from_container
8+
from codeclash.utils.environment import assert_zero_exit_code
99

1010

1111
class RobotRumbleGame(CodeGame):
@@ -16,18 +16,10 @@ def __init__(self, config, *, tournament_id: str, local_output_dir: Path):
1616
assert len(config["players"]) == 2, "RobotRumble is a two-player game"
1717
self.run_cmd_round: str = "./rumblebot run term"
1818

19-
def copy_logs_from_env(self, round_num: int) -> None:
20-
super().copy_logs_from_env(round_num)
21-
copy_from_container(
22-
container=self.environment,
23-
src_path="/testbed/logs",
24-
dest_path=self.log_round(round_num),
25-
)
26-
27-
def get_stats(self, agents: list[Player], round_num: int) -> RoundStats:
19+
def get_results(self, agents: list[Player], round_num: int) -> RoundStats:
2820
winners = []
2921
for idx in range(self.game_config.get("sims_per_round", 100)):
30-
with open(self.log_round(round_num) / f"logs/sim_{idx}.txt") as f:
22+
with open(self.log_round(round_num) / f"sim_{idx}.txt") as f:
3123
lines = f.read().strip().split("\n")
3224

3325
# Get the last 2 lines which contain the game result (same as original)
@@ -58,9 +50,8 @@ def get_stats(self, agents: list[Player], round_num: int) -> RoundStats:
5850
return RoundStats(winner=final_winner, scores=dict(counts))
5951

6052
def execute_round(self, agents: list[Player]):
61-
self.environment.execute("rm -rf logs; mkdir -p logs")
6253
args = [f"/{agent.name}/robot.py" for agent in agents]
6354
cmd = f"{self.run_cmd_round} {shlex.join(args)}"
6455
self.logger.info(f"Running game: {cmd}")
6556
for idx in range(self.game_config.get("sims_per_round", 100)):
66-
assert_zero_exit_code(self.environment.execute(cmd + f" > logs/sim_{idx}.txt"))
57+
assert_zero_exit_code(self.environment.execute(cmd + f" > {self.log_env / f'sim_{idx}.txt'}"))

0 commit comments

Comments
 (0)