-
Notifications
You must be signed in to change notification settings - Fork 1
/
tournament.py
executable file
·103 lines (78 loc) · 3.16 KB
/
tournament.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#!/usr/bin/env python3
import csv
import os
from argparse import ArgumentParser
from datetime import datetime
from itertools import pairwise
from tempfile import gettempdir
import pandas
import pygame
import tqdm
from racer.constants import framerate, rounds, frames_after_finish
from racer.game_state import GameState
from racer.track import Track
from racer.tracks import all_tracks
def get_laps(car_info):
return car_info.round + (car_info.next_waypoint / len(car_info.track.lines))
def main(track):
pygame.init()
track = Track(next(t for t in all_tracks if t.name == track))
# write to a temporary file so that we have partial scores in case of a crash
filename = f'racer_{datetime.now().strftime("%Y-%m-%d_%H-%M-%S")}'
with open(os.path.join(gettempdir(), filename), 'w+') as f:
print(f'writing game results to {f.name}')
writer = csv.DictWriter(f, fieldnames=['Name', 'Contributor', 'Finish time', 'Frames', 'CPU', 'Track'])
rows = single_game(track)
writer.writeheader()
writer.writerows(rows)
f.seek(0)
df = pandas.read_csv(f)
track = next(Track(t) for t in all_tracks if t.name == df['Track'][0])
track_length = sum((v1 - v0).length() for v0, v1 in pairwise(track.lines + [track.lines[0]]))
df['CPU/t'] = df['CPU'] / df['Frames'] * 1000
df['Speed'] = track_length * rounds / df['Finish time']
# Reorder columns
df = df[['Name', 'Contributor', 'Finish time', 'Speed', 'CPU', 'CPU/t', 'Track']]
df.sort_values(by='Finish time', inplace=True)
print()
print(df.to_string(formatters={'Finish time': '{:.3f}'.format, 'Speed': '{:.2f}'.format, 'CPU': '{:.1f}'.format,
'CPU/t': '{:.1f}'.format}, index=False))
def single_game(track):
min_frames = 6000
game_state = GameState(track)
finishing = False
for _ in tqdm.trange(0, min_frames):
game_state.update(1 / framerate)
for bot, car_info in game_state.bots.items():
if car_info.round >= rounds:
finishing = True
break
if finishing:
break
for _ in tqdm.trange(0, frames_after_finish):
game_state.update(1 / framerate)
finish_index = rounds * len(game_state.track.lines) - 1
rows = []
for bot, car_info in game_state.bots.items():
row = {
'Name': bot.name,
'Contributor': bot.contributor,
'CPU': car_info.cpu,
'Frames': game_state.frames,
'Track': game_state.track.name,
}
if finish_index < len(car_info.waypoint_timing):
finish_time = car_info.waypoint_timing[finish_index]
row['Finish time'] = finish_time
else:
row['Finish time'] = None
rows.append(row)
return rows
if __name__ == '__main__':
parser = ArgumentParser(description='Run a tournament of the coding challenge racer')
parser.add_argument('track', choices=[t.name for t in all_tracks], help='The track to run the tournament on')
args = parser.parse_args()
try:
main(**vars(args))
except KeyboardInterrupt:
pass