Skip to content

Commit 955199b

Browse files
authored
Add support for subtasked tasks (#53)
* added subtask possibility * fix for subtask support * added basic frontend for subtasks * fixed bug * added table for subtask view * bugfix * added documentation for subtasks * refactored result view
1 parent 7d59c04 commit 955199b

File tree

7 files changed

+75
-10
lines changed

7 files changed

+75
-10
lines changed

backend/terry/handlers/info_handler.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,10 @@ def patch_submission(submission):
203203

204204
del result["output"]
205205
result = BaseHandler.format_dates(result)
206+
206207
result["output"] = temp
208+
if "subtasks" in feedback:
209+
result["subtasks"] = feedback["subtasks"]
207210

208211
return result
209212

format-specs.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,4 +125,12 @@ The checker should print to its standard output a JSON value with _at least_ the
125125
- `severity`: a string with one of the following values: `"warning"`
126126
- `message`: the message to show to the contestant.
127127

128+
The following field must be present if and only if the problem is scored with subtasks:
129+
- `subtasks`: the subtasks of the task. It is an array with an entry for each subtask. Each entry is an object with _at least_ the following fields:
130+
- `score`: a number indicating the score of the contestant on the subtask.
131+
- `max_score`: a number indicating the maximum score on the subtask.
132+
- `testcases`: an array of numbers, containing the testcases belonging to the subtask.
133+
134+
Note that is the checker's responsibility to make sure that the information contained in `subtasks` is accurate.
135+
128136
The checker should be very resilient to invalid output files submitted by the contestant. To avoid writing every time the parsing code a Python library is available [here](https://github.com/algorithm-ninja/territoriali-cli/blob/master/terry_cli/parser.py). Note that it's useful only for the `Case #1: ...` output format.

frontend/src/contest/submission/FeedbackView.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ export function FeedbackView({ submission, task }: Props) {
5959
<ResultView
6060
cases={submission.feedback.cases}
6161
alerts={submission.feedback.alerts}
62+
subtasks={submission.subtasks}
6263
renderCase={renderCase}
6364
renderCaseSummary={renderCaseSummary}
6465
/>

frontend/src/contest/submission/GridList.css

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,9 @@ dl.terry-grid-list > dd {
1717
-ms-flex: 1 1 100%;
1818
flex: 1 1 100%;
1919
}
20+
21+
dl.terry-grid-list > dd > table {
22+
border-spacing: 10px 0;
23+
border-collapse: separate;
24+
margin-left: -10px;
25+
}

frontend/src/contest/submission/ResultView.tsx

Lines changed: 49 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,63 @@
11
import React from "react";
22
import { Trans } from "@lingui/macro";
3-
import { Alert } from "src/types/contest";
3+
import { Alert, Subtask } from "src/types/contest";
44

55
type Props<T> = {
66
cases: T[];
77
alerts: Alert[];
8+
subtasks?: Subtask[];
89
renderCase: (c: T, i: number) => React.ReactNode;
910
renderCaseSummary: (c: T, i: number) => React.ReactNode;
1011
};
1112

1213
export function ResultView<T>({
13-
cases, alerts, renderCase, renderCaseSummary,
14+
cases, alerts, subtasks, renderCase, renderCaseSummary,
1415
}: Props<T>) {
16+
const renderGridWithSubtasks = (subtasks: Subtask[], cases: T[]) => {
17+
return (
18+
<>
19+
<table>
20+
<tbody>
21+
{subtasks.map((s: Subtask, i: number) => (
22+
<tr>
23+
<td>
24+
Subtask {i + 1} ({s.score}/{s.max_score})
25+
</td>
26+
<td>
27+
<ul className="list-inline mb-0">
28+
{s.testcases.map((i: number, _: number) => (
29+
// eslint-disable-next-line react/no-array-index-key
30+
<li className="list-inline-item" key={i}>
31+
{renderCaseSummary(cases[i], i + 1)}
32+
</li>
33+
))}
34+
</ul>
35+
</td>
36+
</tr>
37+
))}
38+
</tbody>
39+
</table>
40+
</>
41+
)
42+
};
43+
44+
const renderGridWithoutSubtasks = (cases: T[]) => {
45+
return (
46+
<>
47+
<ul className="list-inline mb-0">
48+
{cases.map((c: T, i: number) => (
49+
// eslint-disable-next-line react/no-array-index-key
50+
<li className="list-inline-item" key={i}>
51+
{renderCaseSummary(c, i + 1)}
52+
</li>
53+
))}
54+
</ul>
55+
</>
56+
);
57+
}
58+
59+
const summary = subtasks ? renderGridWithSubtasks(subtasks, cases) : renderGridWithoutSubtasks(cases);
60+
1561
return (
1662
<>
1763
<ul className="list-unstyled">
@@ -34,14 +80,7 @@ export function ResultView<T>({
3480
:
3581
</dt>
3682
<dd>
37-
<ul className="list-inline mb-0">
38-
{cases.map((c: T, i: number) => (
39-
// eslint-disable-next-line react/no-array-index-key
40-
<li className="list-inline-item" key={i}>
41-
{renderCaseSummary(c, i + 1)}
42-
</li>
43-
))}
44-
</ul>
83+
{summary}
4584
</dd>
4685
</dl>
4786
<div className="result-detail">

frontend/src/contest/submission/ValidationView.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ export function ValidationView({ output }: Props) {
4545
<ResultView
4646
alerts={output.validation.alerts}
4747
cases={output.validation.cases}
48+
subtasks={undefined}
4849
renderCase={renderCase}
4950
renderCaseSummary={renderCaseSummary}
5051
/>

frontend/src/types/contest.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ type FeedbackData = {
1717
cases: FeedbackCaseInfo[];
1818
};
1919

20+
export type Subtask = {
21+
max_score: number;
22+
score: number;
23+
testcases: number[];
24+
};
25+
2026
export type Submission = {
2127
id: string;
2228
date: string;
@@ -26,6 +32,7 @@ export type Submission = {
2632
input: InputData;
2733
output: UploadedOutput;
2834
source: UploadedSource;
35+
subtasks: Subtask[];
2936
feedback: FeedbackData;
3037
};
3138

0 commit comments

Comments
 (0)