Skip to content

Commit 1b40824

Browse files
committed
Add contest-export script
1 parent 0309f2b commit 1b40824

File tree

2 files changed

+92
-1
lines changed

2 files changed

+92
-1
lines changed

misc-tools/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ include $(TOPDIR)/Makefile.global
99
TARGETS =
1010
OBJECTS =
1111

12-
SUBST_DOMSERVER = fix_permissions configure-domjudge import-contest force-passwords
12+
SUBST_DOMSERVER = fix_permissions configure-domjudge import-contest \
13+
export-contest force-passwords
1314

1415
SUBST_JUDGEHOST = dj_make_chroot dj_run_chroot dj_make_chroot_docker \
1516
dj_judgehost_cleanup

misc-tools/export-contest.in

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
#!/usr/bin/env python3
2+
3+
'''
4+
export-contest -- Convenience script to export a contest (including metadata,
5+
teams and problems) from the command line. Defaults to using the CLI interface;
6+
Specify a DOMjudge API URL as to use that.
7+
8+
Reads credentials from ~/.netrc when using the API.
9+
10+
Part of the DOMjudge Programming Contest Jury System and licensed
11+
under the GNU GPL. See README and COPYING for details.
12+
'''
13+
14+
import json
15+
import sys
16+
from concurrent.futures import ThreadPoolExecutor
17+
from pathlib import Path
18+
19+
sys.path.append('@domserver_libdir@')
20+
import dj_utils
21+
22+
cid = None
23+
webappdir = '@domserver_webappdir@'
24+
25+
26+
def usage():
27+
print(f'Usage: {sys.argv[0]} [<domjudge-api-url>]')
28+
exit(1)
29+
30+
31+
def api_to_file(endpoint: str, filename: str):
32+
print(f"Fetching '{endpoint}' to '{filename}'")
33+
data = dj_utils.do_api_request(endpoint, decode=False)
34+
with open(filename, 'wb') as f:
35+
f.write(data)
36+
37+
return data
38+
39+
40+
def download_submission(submission):
41+
d = f'submissions/{submission["id"]}'
42+
Path(d).mkdir(parents=True, exist_ok=True)
43+
for f in submission['files']:
44+
if f['mime'] == 'application/zip':
45+
print(f"Downloading '{f['href']}'")
46+
data = dj_utils.do_api_request(f['href'], decode=False)
47+
with open(f'{d}/files.zip', 'wb') as f:
48+
f.write(data)
49+
50+
51+
if len(sys.argv) == 1:
52+
dj_utils.domjudge_webapp_folder_or_api_url = webappdir
53+
elif len(sys.argv) == 2:
54+
dj_utils.domjudge_webapp_folder_or_api_url = sys.argv[1]
55+
else:
56+
usage()
57+
58+
59+
user_data = dj_utils.do_api_request('user')
60+
if 'admin' not in user_data['roles']:
61+
print('Your user does not have the \'admin\' role, can not export.')
62+
exit(1)
63+
64+
65+
contest_id = 'wf48_finals'
66+
67+
for endpoint in [
68+
'accounts',
69+
'awards',
70+
'balloons',
71+
'clarifications',
72+
'groups',
73+
'judgements',
74+
'languages',
75+
'organizations',
76+
'problems',
77+
# 'runs',
78+
'scoreboard',
79+
'submissions',
80+
'teams',
81+
]:
82+
data = api_to_file(f'contests/{contest_id}/{endpoint}', f'{endpoint}.json')
83+
if endpoint == 'submissions':
84+
submissions = json.loads(data)
85+
86+
api_to_file(f'contests/{contest_id}/event-feed?stream=false', 'event-feed.ndjson')
87+
88+
with ThreadPoolExecutor(20) as executor:
89+
for submission in submissions[:10]:
90+
executor.submit(download_submission, submission)

0 commit comments

Comments
 (0)