121 lines
3.7 KiB
Python
121 lines
3.7 KiB
Python
"""General utilities that are useful across runners."""
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import platform
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
from typing import NamedTuple
|
|
|
|
# Configure path to import the environment configuration
|
|
sys.path.insert(0, str(Path(__file__).parents[1]))
|
|
import environment
|
|
|
|
# Reset the path
|
|
del sys.path[0]
|
|
|
|
|
|
class MatchData(NamedTuple):
|
|
"""
|
|
Data about the current match.
|
|
|
|
:param match_number: The current match number
|
|
:param match_duration: The duration of the match in seconds
|
|
:param video_enabled: Whether video recording is enabled
|
|
:param video_resolution: The resolution of the video recording
|
|
"""
|
|
|
|
match_number: int | None = None
|
|
match_duration: int = environment.DEFAULT_MATCH_DURATION
|
|
video_enabled: bool = True
|
|
video_resolution: tuple[int, int] = (1920, 1080)
|
|
|
|
|
|
def get_robot_file(robot_zone: int) -> Path:
|
|
"""
|
|
Get the path to the robot file for the given zone.
|
|
|
|
:param robot_zone: The zone number
|
|
:return: The path to the robot file
|
|
:raises FileNotFoundError: If no robot controller is found for the given zone
|
|
"""
|
|
robot_file = environment.ZONE_ROOT / f'zone_{robot_zone}' / 'robot.py'
|
|
|
|
# Check if the robot file exists
|
|
if not robot_file.exists():
|
|
raise FileNotFoundError(f"No robot code to run for zone {robot_zone}")
|
|
|
|
return robot_file
|
|
|
|
|
|
def get_game_mode() -> str:
|
|
"""
|
|
Get the game mode from the game mode file.
|
|
|
|
Default to 'dev' if the file does not exist.
|
|
|
|
:return: The game mode
|
|
"""
|
|
if environment.GAME_MODE_FILE.exists():
|
|
game_mode = environment.GAME_MODE_FILE.read_text().strip()
|
|
else:
|
|
game_mode = 'dev'
|
|
|
|
assert game_mode in ['dev', 'comp'], f'Invalid game mode: {game_mode}'
|
|
|
|
return game_mode
|
|
|
|
|
|
def print_simulation_version() -> None:
|
|
"""
|
|
Print the version of the simulator that is running.
|
|
|
|
Uses a VERSION file in the root of the simulator to determine the version.
|
|
For development, the version is uses the git describe command.
|
|
|
|
The version is printed to the console.
|
|
"""
|
|
version_file = environment.SIM_ROOT / 'VERSION'
|
|
if version_file.exists():
|
|
version = version_file.read_text().strip()
|
|
else:
|
|
try:
|
|
version = subprocess.check_output(
|
|
['git', 'describe', '--tags', '--always'],
|
|
cwd=str(environment.SIM_ROOT.resolve()),
|
|
).decode().strip()
|
|
except subprocess.CalledProcessError:
|
|
version = 'unknown'
|
|
|
|
print(
|
|
f"Running simulator version: {version} in Python {platform.python_version()} "
|
|
f"({platform.system()}-{platform.machine()})"
|
|
)
|
|
|
|
|
|
def get_match_data() -> MatchData:
|
|
"""Load the match data from the match data file."""
|
|
match_data_file = environment.ARENA_ROOT / 'match.json'
|
|
default_match_data = MatchData()
|
|
|
|
if match_data_file.exists():
|
|
# TODO error handling for invalid json
|
|
raw_data = json.loads(match_data_file.read_text())
|
|
match_data = MatchData(
|
|
match_number=raw_data.get('match_number', default_match_data.match_number),
|
|
match_duration=raw_data.get('duration', default_match_data.match_duration),
|
|
video_enabled=(
|
|
raw_data.get('recording_config', {})
|
|
.get('enabled', default_match_data.video_enabled)
|
|
),
|
|
video_resolution=(
|
|
raw_data.get('recording_config', {})
|
|
.get('video_resolution', default_match_data.video_resolution)
|
|
),
|
|
)
|
|
else:
|
|
match_data = default_match_data
|
|
|
|
return match_data
|