Skip to content

Commit 47bbe58

Browse files
finish UI for new online judge
1 parent b08a916 commit 47bbe58

File tree

8 files changed

+148
-127
lines changed

8 files changed

+148
-127
lines changed

src/components/Groups/OnlineJudgeSubmission/OnlineJudgeSubmission.tsx

+48-37
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,58 @@
11
import React from 'react';
2+
import { ProblemSubmissionResult } from '../../../models/groups/problem';
3+
import TestCaseResult from './TestCaseResult';
24

35
const OnlineJudgeSubmission = ({
46
submission,
57
}: {
6-
submission: any;
8+
submission: ProblemSubmissionResult;
79
}): JSX.Element => {
810
return (
9-
<pre>{JSON.stringify(submission, null, 2)}</pre>
10-
// <div>
11-
// <div>
12-
// {submission.gradingStatus === 'waiting' &&
13-
// 'Waiting for an available grading server...'}
14-
// {submission.gradingStatus === 'in_progress' && 'Grading in progress'}
15-
// {submission.gradingStatus === 'done' &&
16-
// (submission.compilationError ? 'Compilation Error' : 'Done')}
17-
// {submission.gradingStatus === 'error' &&
18-
// (submission.errorMessage
19-
// ? 'Error: ' + submission.errorMessage
20-
// : 'Error')}
21-
// </div>
22-
// {submission.gradingStatus === 'done' &&
23-
// submission.status !== ExecutionStatus.AC && (
24-
// <p>
25-
// Common issues: Java users should name their class Main. Remember to
26-
// use standard input/output instead of file input/output. Finally, our
27-
// grader currently has an issue that requires you to output an endline
28-
// (ex. \n or endl) at the end of the output. This is a bug (it works
29-
// on USACO without the endline) that we're working on fixing.
30-
// </p>
31-
// )}
32-
// {submission.compilationError === true && (
33-
// <pre className="text-red-800 dark:text-red-200 overflow-auto">
34-
// {submission.compilationErrorMessage}
35-
// </pre>
36-
// )}
37-
// {submission.compilationError === false && (
38-
// <div>
39-
// {submission.testCases.map(tc => (
40-
// <TestCaseResult data={tc} key={tc.caseId} />
41-
// ))}
42-
// </div>
43-
// )}
44-
// </div>
11+
<div>
12+
<div>
13+
{submission.status === 'compiling' && 'Compiling in progress...'}
14+
{submission.status === 'executing' && 'Grading in progress...'}
15+
{submission.status === 'done' &&
16+
(submission.verdict === 'CE'
17+
? 'Compilation Error'
18+
: submission.verdict === 'IE'
19+
? 'Internal Error: ' +
20+
submission.message +
21+
' ' +
22+
submission.debugData
23+
: 'Done')}
24+
</div>
25+
{submission.verdict !== 'IE' && (
26+
<>
27+
{submission.status === 'done' && submission.verdict !== 'AC' && (
28+
<p>
29+
Common issues: Java users should name their class Main. Remember
30+
to use standard input/output instead of file input/output.
31+
Finally, our grader currently has an issue that requires you to
32+
output an endline (ex. \n or endl) at the end of the output. This
33+
is a bug (it works on USACO without the endline) that we're
34+
working on fixing.
35+
</p>
36+
)}
37+
{submission.verdict === 'CE' && (
38+
<pre className="text-red-800 dark:text-red-200 overflow-auto">
39+
{submission.message}
40+
</pre>
41+
)}
42+
{submission.verdict !== 'CE' && (
43+
<div>
44+
{submission.testCases.map((tc, i) => (
45+
<TestCaseResult
46+
data={tc}
47+
tcNum={i + 1}
48+
key={submission.submissionID + '_' + i}
49+
/>
50+
))}
51+
</div>
52+
)}
53+
</>
54+
)}
55+
</div>
4556
);
4657
};
4758

src/components/Groups/OnlineJudgeSubmission/TestCaseResult.tsx

+22-16
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,48 @@
11
import React from 'react';
22
import {
3-
getTestCaseSymbol,
4-
TestCaseResult as TestCaseResultType,
3+
ProblemSubmissionTestCaseResult,
4+
verdictToSymbol,
55
} from '../../../models/groups/problem';
66

77
const TestCaseResult = ({
88
data,
9+
tcNum,
910
}: {
10-
data: TestCaseResultType;
11+
data: ProblemSubmissionTestCaseResult | null;
12+
tcNum: number;
1113
}): JSX.Element => {
12-
const containerClasses = data.pass
13-
? 'bg-green-100 border-green-200 dark:bg-green-700 dark:border-green-700'
14-
: 'bg-red-100 border-red-200 dark:bg-red-700 dark:border-red-700';
15-
const textColor = data.pass
16-
? 'text-green-800 dark:text-green-100'
17-
: 'text-red-800 dark:text-red-100';
14+
const containerClasses = data
15+
? data.verdict === 'AC'
16+
? 'bg-green-100 border-green-200 dark:bg-green-700 dark:border-green-700'
17+
: 'bg-red-100 border-red-200 dark:bg-red-700 dark:border-red-700'
18+
: 'bg-gray-100 border-gray-200 dark:bg-gray-700 dark:border-gray-700';
19+
const textColor = data
20+
? data.verdict === 'AC'
21+
? 'text-green-800 dark:text-green-100'
22+
: 'text-red-800 dark:text-red-100'
23+
: 'text-transparent';
1824
return (
1925
<div
2026
className={`m-1 inline-block w-[70px] h-[60px] dark:bg-opacity-50 border ${containerClasses} relative`}
21-
title={data.pass === true ? 'Correct answer' : data.error}
27+
title={data ? data.verdict : 'Loading...'}
2228
>
2329
<div
2430
className={`font-bold text-center text-[2.5rem] ${textColor} leading-10`}
2531
>
26-
{getTestCaseSymbol(data)}
32+
{data ? verdictToSymbol[data.verdict] : '.'}
2733
</div>
2834
<span
2935
className={`absolute bottom-0 left-[4px] ${textColor} text-[0.8125rem] font-bold`}
3036
>
31-
{data.caseId + 1}
37+
{tcNum}
3238
</span>
33-
{data.pass && (
39+
{data?.verdict === 'AC' && (
3440
<span
3541
className={`absolute bottom-0 right-0 text-right ${textColor} leading-3 p-[2px] text-[0.625rem]`}
3642
>
37-
{/* {data.memory}kb
38-
<br /> */}
39-
{data.time}ms
43+
{data.memory}kb
44+
<br />
45+
{data.time}s
4046
</span>
4147
)}
4248
</div>

src/components/Groups/ProblemPage/ProblemSidebar.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ export default function ProblemSidebar({
8686
Source: {problem.source}
8787
</span>
8888
</div>
89-
{problem.usacoGuideId && (
89+
{/* {problem.usacoGuideId && (
9090
<div className="flex items-center space-x-2">
9191
<LinkIcon className="h-5 w-5 text-gray-400 dark:text-gray-400" />
9292
<span className="text-gray-900 dark:text-gray-300 text-sm font-medium">
@@ -99,7 +99,7 @@ export default function ProblemSidebar({
9999
</TextTooltip>
100100
</span>
101101
</div>
102-
)}
102+
)} */}
103103
<SidebarDueDate post={post} />
104104
</div>
105105
<div className="mt-6 border-t border-gray-200 dark:border-gray-700 py-6 space-y-8">

src/components/Groups/ProblemPage/ProblemSubmissionInterface.tsx

+26-48
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import {
1010
ExecutionStatus,
1111
GroupProblemData,
1212
Submission,
13-
SubmissionType,
1413
} from '../../../models/groups/problem';
1514
import ButtonGroup from '../../ButtonGroup';
1615
import TabIndentableTextarea from '../../elements/TabIndentableTextarea';
@@ -35,11 +34,6 @@ export default function ProblemSubmissionInterface({
3534
problem: GroupProblemData;
3635
}) {
3736
const { lang, firebaseUser } = React.useContext(UserDataContext);
38-
if (problem.submissionType !== SubmissionType.SELF_GRADED) {
39-
throw new Error(
40-
"Problem submission interface doesn't support CCC problems yet"
41-
);
42-
}
4337
const emptySubmission: Partial<Submission> = {
4438
problemId: problem.id,
4539
type: problem.submissionType,
@@ -87,18 +81,11 @@ export default function ProblemSubmissionInterface({
8781
);
8882
}
8983

90-
// todo remove
91-
const isCPIClass =
92-
'2i0ZZTfYhlxGi9OEIjy2' === activeGroup.activeGroupId ||
93-
'd7eYGfddXq3m2trXG2xt' === activeGroup.activeGroupId;
94-
// 'UyefpawGOgGFh14ptihn' === activeGroup.activeGroupId; // todo remove (mvcpc club)
9584
// todo add ys?
96-
const cannotSubmit =
97-
isCPIClass &&
98-
!(
99-
problem.usacoGuideId?.startsWith('usaco') ||
100-
problem.usacoGuideId?.startsWith('cses')
101-
);
85+
const cannotSubmit = !(
86+
problem.usacoGuideId?.startsWith('usaco') ||
87+
problem.usacoGuideId?.startsWith('cses')
88+
);
10289

10390
if (cannotSubmit) {
10491
return (
@@ -143,37 +130,28 @@ export default function ProblemSubmissionInterface({
143130
</h2>
144131
</div>
145132
<div className="text-sm mt-1 text-gray-900 dark:text-gray-300">
146-
{isCPIClass ? (
147-
<>
148-
All problems submitted through this website use standard
149-
input/output. When using Java, make sure to name your class Main.
150-
You can use{' '}
151-
<a
152-
href="https://ide.usaco.guide/"
153-
target="_blank"
154-
rel="noreferrer"
155-
className="underline"
156-
>
157-
ide.usaco.guide
158-
</a>{' '}
159-
to test your code online. Report any issues to{' '}
160-
<a
161-
href="mailto:classes@joincpi.org"
162-
target="_blank"
163-
rel="noreferrer"
164-
className="underline"
165-
>
166-
classes@joincpi.org
167-
</a>
168-
.
169-
</>
170-
) : (
171-
<>
172-
<b>Self-graded problem:</b> Use the Problem Statement link above to
173-
test your code. Submit your <i>working</i> code below. Group admins
174-
will manually verify your code to ensure that your code works.
175-
</>
176-
)}
133+
<>
134+
All problems submitted through this website use standard input/output.
135+
When using Java, make sure to name your class Main. You can use{' '}
136+
<a
137+
href="https://ide.usaco.guide/"
138+
target="_blank"
139+
rel="noreferrer"
140+
className="underline"
141+
>
142+
ide.usaco.guide
143+
</a>{' '}
144+
to test your code online. Report any issues to{' '}
145+
<a
146+
href="mailto:classes@joincpi.org"
147+
target="_blank"
148+
rel="noreferrer"
149+
className="underline"
150+
>
151+
classes@joincpi.org
152+
</a>
153+
.
154+
</>
177155
</div>
178156
{submissionResult && (
179157
<div className="mt-4">

src/context/UserDataContext/UserDataContext.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ export const UserDataProvider = ({
261261
// If the user is signed in, sync remote data with local data
262262
React.useEffect(() => {
263263
if (firebaseUser) {
264-
firebaseUser.getIdToken(true).then(token => console.log(token));
264+
// firebaseUser.getIdToken(true).then(token => console.log(token));
265265

266266
const userDoc = doc(getFirestore(firebaseApp), 'users', firebaseUser.uid);
267267
return onSnapshot(userDoc, {

src/hooks/groups/usePostActions.ts

+2-3
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,8 @@ export interface ProblemSubmissionRequestData {
3131

3232
export function usePostActions(groupId: string) {
3333
const firebaseApp = useFirebaseApp();
34-
const { firebaseUser, setUserProgressOnProblems } = useContext(
35-
UserDataContext
36-
);
34+
const { firebaseUser, setUserProgressOnProblems } =
35+
useContext(UserDataContext);
3736

3837
const updatePost = async (postId: string, updatedData: Partial<PostData>) => {
3938
await updateDoc(

src/hooks/useProblemSubmissionResult.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,13 @@ export default function useProblemSubmissionResult() {
1616

1717
setResult(data);
1818

19-
if (res.ok && data.status === 'executing') {
19+
if (res.ok && data.status !== 'done') {
2020
setTimeout(() => queryResult(curSubmission, submissionID), 1000);
2121
}
2222
};
2323

2424
if (submissionID) {
25+
setResult(null);
2526
queryResult(++currentSubmission.current, submissionID);
2627
}
2728
}, [submissionID]);

src/models/groups/problem.ts

+45-19
Original file line numberDiff line numberDiff line change
@@ -119,25 +119,51 @@ export type TestCaseResult = { caseId: number } & (
119119
}
120120
);
121121

122-
export const getTestCaseSymbol = (testCase: TestCaseResult): string => {
123-
if (testCase.pass === true) {
124-
return '*';
125-
}
126-
switch (testCase.error) {
127-
case TestResultError.COMPILE_TIMEOUT:
128-
case TestResultError.COMPILE_ERROR:
129-
return 'c';
130-
case TestResultError.RUNTIME_ERROR:
131-
return '!';
132-
case TestResultError.TIME_LIMIT_EXCEEDED:
133-
return 't';
134-
case TestResultError.EMPTY_MISSING_OUTPUT:
135-
return 'e';
136-
case TestResultError.WRONG_ANSWER:
137-
return 'x';
138-
case TestResultError.INTERNAL_ERROR:
139-
return '?';
140-
}
122+
123+
// Temporarily taken from online-judge repo
124+
export interface ProblemSubmissionResult {
125+
submissionID: string;
126+
status: "compiling" | "executing" | "done";
127+
verdict?: ExecutionVerdict;
128+
testCases: (ProblemSubmissionTestCaseResult | null)[];
129+
130+
problemID: string;
131+
language: string;
132+
filename: string;
133+
sourceCode: string; // gzipped in dynamodb
134+
message?: string; // gzipped in dynamodb. used either for compiling or internal error.
135+
debugData?: string; // gzipped in dynamodb. optionally provided for internal_error
136+
}
137+
138+
export interface ProblemSubmissionTestCaseResult {
139+
verdict: ExecutionVerdict;
140+
time: string;
141+
memory: string;
142+
143+
// each of these is truncated to 4kb then gzipped in dynamodb
144+
input: string;
145+
expectedOutput: string;
146+
stdout: string;
147+
stderr: string;
148+
}
149+
150+
export type ExecutionVerdict =
151+
| "AC"
152+
| "WA"
153+
| "RTE"
154+
| "MLE"
155+
| "TLE"
156+
| "CE"
157+
| "IE"; // IE is internal error
158+
159+
export const verdictToSymbol: {[key in ExecutionVerdict]: string} = {
160+
"AC": "*",
161+
"WA": "x",
162+
"RTE": "!",
163+
"MLE": "m",
164+
"TLE": "t",
165+
"CE": "c",
166+
"IE": "?",
141167
};
142168

143169
export const submissionTextColor: { [key in ExecutionStatus]: string } = {

0 commit comments

Comments
 (0)