| 1 | """What every game's referee shares: where the bots are, how a match is seated, and the files a run leaves. |
| 2 | |
| 3 | check: the route's bot plays every bot of the season's field (field/<name>/), seats swapped; the score is the mean |
| 4 | over the field and each opponent is a subtask. metrics.json is what the site keeps (scienceslack.json names it). |
| 5 | practice: a few matches against the field, each leaving a replay in replays/ and an entry in replays/matches.json. |
| 6 | """ |
| 7 | import json, os, sys |
| 8 | |
| 9 | |
| 10 | def bot_dir(arg): |
| 11 | """The route's folder the check was given, absolute (bots run in their own folder); a missing bot is the route's |
| 12 | mistake, said plainly.""" |
| 13 | if not os.path.isdir(arg): |
| 14 | sys.exit(f'No route folder at {arg}') |
| 15 | return os.path.abspath(arg) |
| 16 | |
| 17 | |
| 18 | def field(root='field'): |
| 19 | return sorted(d for d in os.listdir(root) if os.path.isdir(os.path.join(root, d)) and not d.startswith('.')) |
| 20 | |
| 21 | |
| 22 | def route_name(): |
| 23 | d = os.environ.get('SS_ROUTE_DIR', 'routes').rstrip('/') |
| 24 | return 'main' if d == 'routes' else d.split('/', 1)[-1] |
| 25 | |
| 26 | |
| 27 | def write_metrics(score, subtasks, cost=None, path='metrics.json'): |
| 28 | out = {'score': round(score, 6), 'subtasks': {k: round(v, 6) for k, v in subtasks.items()}} |
| 29 | if cost is not None: |
| 30 | out['cost'] = round(cost, 3) |
| 31 | with open(path, 'w') as f: |
| 32 | json.dump(out, f, indent=2, sort_keys=True) |
| 33 | print(f'score {out["score"]} over {len(subtasks)}: ' + ', '.join(f'{k} {v:.3g}' for k, v in out['subtasks'].items())) |
| 34 | |
| 35 | |
| 36 | class Replays: |
| 37 | """replays/<file> per match, and replays/matches.json saying who sat where and how it ended.""" |
| 38 | |
| 39 | def __init__(self, root='replays'): |
| 40 | self.root, self.index = root, [] |
| 41 | os.makedirs(root, exist_ok=True) |
| 42 | |
| 43 | def add(self, file, data, title, seats, result): |
| 44 | with open(os.path.join(self.root, file), 'w') as f: |
| 45 | f.write(data if isinstance(data, str) else json.dumps(data, separators=(',', ':'))) |
| 46 | self.index.append({'file': file, 'title': title, 'seats': seats, 'result': result}) |
| 47 | with open(os.path.join(self.root, 'matches.json'), 'w') as f: |
| 48 | json.dump(self.index, f, indent=2) |