Skip to content
This repository was archived by the owner on Oct 23, 2023. It is now read-only.

Commit a6b978d

Browse files
committed
Implemented JSON FinishUI for IOI-like tasks
1 parent 1a047d9 commit a6b978d

File tree

5 files changed

+170
-26
lines changed

5 files changed

+170
-26
lines changed

python/formats/ioi_format.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from task_maker.uis.ioi import IOIUIInterface, TestcaseGenerationStatus
1919
from task_maker.uis.ioi_curses_ui import IOICursesUI
2020
from task_maker.uis.ioi_finish_ui import IOIFinishUI
21+
from task_maker.uis.ioi_finish_ui_json import IOIFinishUIJSON
2122
from typing import Dict, List, Any, Tuple
2223
from typing import Optional
2324

@@ -342,7 +343,12 @@ def evaluate_task(frontend: Frontend, task: IOITask, solutions: List[Solution],
342343
if config.ui == UIS.CURSES:
343344
curses_ui = IOICursesUI(config, ui_interface)
344345
if config.ui != UIS.SILENT and config.bulk_number is None:
345-
finish_ui = IOIFinishUI(config, ui_interface)
346+
if config.ui == UIS.PRINT:
347+
finish_ui = IOIFinishUI(config, ui_interface)
348+
elif config.ui == UIS.JSON:
349+
finish_ui = IOIFinishUIJSON(config, ui_interface)
350+
else:
351+
raise ValueError("Unsupported UI %s" % str(config.ui))
346352

347353
with ui_interface.run_in_ui(curses_ui, finish_ui):
348354
ins, outs, vals = generate_inputs(frontend, task, ui_interface, config)

python/sanity_checks/ioi.py

Lines changed: 11 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
11
#!/usr/bin/env python3
2-
from distutils.spawn import find_executable
2+
import time
3+
34
import os.path
45
import re
56
import subprocess
6-
import time
7-
from typing import List, Set, Optional, Dict
8-
7+
from distutils.spawn import find_executable
98
from task_maker.args import CacheMode
109
from task_maker.config import Config
11-
from task_maker.formats import IOITask, list_files, VALIDATION_INPUT_NAME, TaskType
10+
from task_maker.formats import IOITask, list_files, VALIDATION_INPUT_NAME, \
11+
TaskType
1212
from task_maker.languages import Language
1313
from task_maker.solution import Solution, get_checker_execution
1414
from task_maker.task_maker_frontend import Frontend, File, Execution, Result, \
1515
ResultStatus
1616
from task_maker.uis.ioi import IOIUIInterface
17+
from typing import List, Set, Optional, Dict
1718

1819

1920
def _get_languages(solutions: List[Solution]):
@@ -117,28 +118,20 @@ def _check_tex_statement(task: IOITask, interface: IOIUIInterface):
117118
def _setup_execution_callback(interface: IOIUIInterface, execution: Execution,
118119
description: str):
119120
log_prefix = "{} ".format(description).ljust(50)
120-
interface.printer.text(log_prefix + "WAITING\n")
121121

122122
def notify_start():
123-
interface.printer.text(log_prefix + "START\n")
124123
interface.running[log_prefix] = time.monotonic()
125124

126125
def get_result(result: Result):
127126
del interface.running[log_prefix]
128-
cached = " [cached]" if result.was_cached else ""
129-
if result.status == ResultStatus.SUCCESS:
130-
interface.printer.green(log_prefix + "SUCCESS" + cached + "\n")
131-
else:
127+
if result.status != ResultStatus.SUCCESS:
132128
interface.add_error("{} failed".format(description))
133-
interface.printer.red(
134-
log_prefix + "FAIL: {} {}\n".format(result.status, cached))
135129

136130
def skipped():
137-
interface.printer.red(log_prefix + "SKIPPED\n")
131+
pass
138132

139133
def get_stderr(stderr):
140-
if stderr:
141-
interface.printer.text(log_prefix + "STDERR\n" + stderr + "\n")
134+
pass
142135

143136
execution.notifyStart(notify_start)
144137
execution.stderr(False).getContentsAsString(get_stderr)
@@ -148,24 +141,17 @@ def get_stderr(stderr):
148141
def _setup_checker_callback(interface: IOIUIInterface, checking: Execution,
149142
description: str, custom_checker: bool):
150143
log_prefix = "{} ".format(description).ljust(50)
151-
interface.printer.text(log_prefix + "WAITING\n")
152144

153145
def notify_start():
154-
interface.printer.text(log_prefix + "START\n")
155146
interface.running[log_prefix] = time.monotonic()
156147

157148
def get_result(result: Result):
158149
del interface.running[log_prefix]
159-
cached = " [cached]" if result.was_cached else ""
160-
if result.status == ResultStatus.SUCCESS:
161-
interface.printer.green(log_prefix + "SUCCESS" + cached + "\n")
162-
else:
150+
if result.status != ResultStatus.SUCCESS:
163151
interface.add_error("{} failed".format(description))
164-
interface.printer.red(
165-
log_prefix + "FAIL: {} {}\n".format(result.status, cached))
166152

167153
def skipped():
168-
interface.printer.red(log_prefix + "SKIPPED\n")
154+
pass
169155

170156
def get_stdout(stdout):
171157
if not custom_checker:

python/source_file.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ def __init__(self, path: str, unit_name: str, exe_name: str,
8484
self.prepared = False
8585
# set only after `prepare`
8686
self.executable = None # type: Optional[File]
87+
self.compilation = None # type: Optional[Execution]
8788
self.compilation_stderr = None # type: Optional[File]
8889
self.compilation_stdout = None # type: Optional[File]
8990

python/uis/ioi_finish_ui_json.py

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
#!/usr/bin/env python3
2+
import json
3+
from task_maker.config import Config
4+
from task_maker.task_maker_frontend import ResultStatus, Result, Resources
5+
from task_maker.uis import FinishUI, SourceFileCompilationResult
6+
from task_maker.uis.ioi import IOIUIInterface, TestcaseGenerationResult, \
7+
SolutionStatus
8+
from typing import Any, Optional, Dict
9+
10+
11+
def _enum_to_str(val: Any) -> Optional[str]:
12+
if val is None:
13+
return None
14+
return str(val).split(".")[-1]
15+
16+
17+
def _resources_to_dict(res: Optional[Resources]) -> Optional[dict]:
18+
if res is None:
19+
return None
20+
return {
21+
"cpu_time": res.cpu_time,
22+
"sys_time": res.sys_time,
23+
"wall_time": res.wall_time,
24+
"memory": res.memory
25+
}
26+
27+
28+
def _result_to_dict(res: Optional[Result]) -> Optional[dict]:
29+
if res is None:
30+
return None
31+
return {
32+
"status":
33+
_enum_to_str(res.status),
34+
"signal":
35+
res.signal if res.status == ResultStatus.SIGNAL else None,
36+
"return_code":
37+
res.return_code if res.status == ResultStatus.RETURN_CODE else None,
38+
"error":
39+
res.error if res.status == ResultStatus.INTERNAL_ERROR else None,
40+
"resources":
41+
_resources_to_dict(res.resources),
42+
"was_cached":
43+
res.was_cached,
44+
"was_killed":
45+
res.was_killed
46+
}
47+
48+
49+
class IOIFinishUIJSON(FinishUI):
50+
"""
51+
FinishUI in JSON for IOI-like tasks
52+
"""
53+
54+
def __init__(self, config: Config, interface: IOIUIInterface):
55+
super().__init__(config, interface)
56+
self.task = interface.task
57+
58+
def print(self):
59+
res = {
60+
"action": "result",
61+
"task": {
62+
"name": self.task.name,
63+
"title": self.task.title
64+
},
65+
"subtasks": self._get_subtasks(),
66+
"solutions": self._get_compilations(self.interface.solutions),
67+
"non_solutions":
68+
self._get_compilations(self.interface.non_solutions),
69+
"testing": self._get_testing(),
70+
"warnings": self.interface.warnings,
71+
"errors": self.interface.errors
72+
}
73+
print(json.dumps(res))
74+
75+
def print_summary(self):
76+
pass
77+
78+
def _get_subtasks(self):
79+
return {
80+
st_num: {
81+
tc_num: self._get_testcase(testcase)
82+
for tc_num, testcase in subtask.items()
83+
}
84+
for st_num, subtask in self.interface.subtasks.items()
85+
}
86+
87+
def _get_testcase(self, testcase: TestcaseGenerationResult):
88+
return {
89+
"status": _enum_to_str(testcase.status),
90+
"generation_result": _result_to_dict(testcase.generation_result),
91+
"generation_stderr": testcase.generation_stderr,
92+
"validation_result": _result_to_dict(testcase.validation_result),
93+
"validation_stderr": testcase.validation_stderr,
94+
"solution_result": _result_to_dict(testcase.solution_result),
95+
"solution_stderr": testcase.solution_stderr
96+
}
97+
98+
def _get_compilations(self, files: Dict[str, SourceFileCompilationResult]):
99+
return {
100+
name: {
101+
"status": _enum_to_str(compilation.status),
102+
"stderr": compilation.stderr,
103+
"result": _result_to_dict(compilation.result)
104+
}
105+
for name, compilation in files.items()
106+
}
107+
108+
def _get_testing(self):
109+
return {
110+
name: self._get_solution(solution)
111+
for name, solution in self.interface.testing.items()
112+
}
113+
114+
def _get_solution(self, solution: SolutionStatus):
115+
return {
116+
"name":
117+
solution.source_file.name,
118+
"path":
119+
solution.source_file.path,
120+
"language":
121+
solution.source_file.language.name,
122+
"score":
123+
solution.score,
124+
"subtask_scores":
125+
solution.subtask_scores,
126+
"subtask_results":
127+
[_enum_to_str(res) for res in solution.subtask_results],
128+
"testcase_results": {
129+
st_num: {
130+
tc_num: {
131+
"status":
132+
_enum_to_str(testcase.status),
133+
"result":
134+
[_result_to_dict(res) for res in testcase.result],
135+
"score":
136+
testcase.score,
137+
"message":
138+
testcase.message,
139+
"checker_outcome":
140+
testcase.checker_outcome,
141+
"checker_result":
142+
_result_to_dict(testcase.checker_result)
143+
}
144+
for tc_num, testcase in subtask.items()
145+
}
146+
for st_num, subtask in solution.testcase_results.items()
147+
}
148+
}

python/uis/ui_printer.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#!/usr/bin/env python3
22
import json
33
from task_maker.printer import Printer
4+
from task_maker.task_maker_frontend import ResultStatus
45

56

67
class UIPrinter:
@@ -271,6 +272,8 @@ def _json(self,
271272
extra: dict,
272273
data: str = None,
273274
cached: bool = False):
275+
if isinstance(data, ResultStatus):
276+
data = str(data).split(".")[-1]
274277
data = {
275278
"action": action,
276279
"state": state,

0 commit comments

Comments
 (0)