diff options
| author | nsfisis <nsfisis@gmail.com> | 2024-08-10 20:25:59 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2024-08-10 22:55:06 +0900 |
| commit | b4ab693aa438f3f1a335369568aabe7849fc1370 (patch) | |
| tree | 50b2c7cc3716f3f7f33dec16751a00361d317458 /frontend | |
| parent | ec03322292d1063ee113a4ad08cfd823cce87850 (diff) | |
| download | iosdc-japan-2024-albatross-b4ab693aa438f3f1a335369568aabe7849fc1370.tar.gz iosdc-japan-2024-albatross-b4ab693aa438f3f1a335369568aabe7849fc1370.tar.zst iosdc-japan-2024-albatross-b4ab693aa438f3f1a335369568aabe7849fc1370.zip | |
feat: implement watch page
Diffstat (limited to 'frontend')
| -rw-r--r-- | frontend/app/components/GolfWatchApp.client.tsx | 88 | ||||
| -rw-r--r-- | frontend/app/components/GolfWatchApps/GolfWatchAppGaming.tsx | 82 | ||||
| -rw-r--r-- | frontend/app/root.tsx | 2 |
3 files changed, 142 insertions, 30 deletions
diff --git a/frontend/app/components/GolfWatchApp.client.tsx b/frontend/app/components/GolfWatchApp.client.tsx index 355f7e3..a9c9989 100644 --- a/frontend/app/components/GolfWatchApp.client.tsx +++ b/frontend/app/components/GolfWatchApp.client.tsx @@ -116,29 +116,91 @@ export default function GolfWatchApp({ } } else if (lastJsonMessage.type === "watcher:s2c:code") { const { player_id, code } = lastJsonMessage.data; - if (player_id === playerA?.user_id) { - setPlayerInfoA((prev) => ({ ...prev, code })); - } else if (player_id === playerB?.user_id) { - setPlayerInfoB((prev) => ({ ...prev, code })); - } else { - throw new Error("Unknown player_id"); - } + const setter = + player_id === playerA?.user_id ? setPlayerInfoA : setPlayerInfoB; + setter((prev) => ({ ...prev, code })); + } else if (lastJsonMessage.type === "watcher:s2c:submit") { + const { player_id, preliminary_score } = lastJsonMessage.data; + const setter = + player_id === playerA?.user_id ? setPlayerInfoA : setPlayerInfoB; + setter((prev) => ({ + ...prev, + submissionResult: { + status: "running", + preliminaryScore: preliminary_score, + verificationResults: game.verification_steps.map((v) => ({ + testcase_id: v.testcase_id, + status: "running", + label: v.label, + stdout: "", + stderr: "", + })), + }, + })); } else if (lastJsonMessage.type === "watcher:s2c:execresult") { - // const { score } = lastJsonMessage.data; - // if (score !== null && (scoreA === null || score < scoreA)) { - // setScoreA(score); - // } + const { player_id, testcase_id, status, stdout, stderr } = + lastJsonMessage.data; + const setter = + player_id === playerA?.user_id ? setPlayerInfoA : setPlayerInfoB; + setter((prev) => { + const ret = { ...prev }; + if (ret.submissionResult === undefined) { + return ret; + } + ret.submissionResult = { + ...ret.submissionResult, + verificationResults: ret.submissionResult.verificationResults.map( + (v) => + v.testcase_id === testcase_id && v.status === "running" + ? { + ...v, + status, + stdout, + stderr, + } + : v, + ), + }; + return ret; + }); + } else if (lastJsonMessage.type === "watcher:s2c:submitresult") { + const { player_id, status } = lastJsonMessage.data; + const setter = + player_id === playerA?.user_id ? setPlayerInfoA : setPlayerInfoB; + setter((prev) => { + const ret = { ...prev }; + if (ret.submissionResult === undefined) { + return ret; + } + ret.submissionResult = { + ...ret.submissionResult, + status, + }; + if (status === "success") { + if ( + ret.score === null || + ret.submissionResult.preliminaryScore < ret.score + ) { + ret.score = ret.submissionResult.preliminaryScore; + } + } else { + ret.submissionResult.verificationResults = + ret.submissionResult.verificationResults.map((v) => + v.status === "running" ? { ...v, status: "canceled" } : v, + ); + } + return ret; + }); } } else { setGameState("waiting"); } } }, [ + game.verification_steps, lastJsonMessage, readyState, gameState, - playerInfoA, - playerInfoB, playerA?.user_id, playerB?.user_id, ]); diff --git a/frontend/app/components/GolfWatchApps/GolfWatchAppGaming.tsx b/frontend/app/components/GolfWatchApps/GolfWatchAppGaming.tsx index 470a00c..992ce7a 100644 --- a/frontend/app/components/GolfWatchApps/GolfWatchAppGaming.tsx +++ b/frontend/app/components/GolfWatchApps/GolfWatchAppGaming.tsx @@ -14,17 +14,57 @@ export type PlayerInfo = { }; type SubmissionResult = { - status: string; - nextScore: number; - executionResults: ExecutionResult[]; + status: + | "running" + | "success" + | "wrong_answer" + | "timeout" + | "compile_error" + | "runtime_error" + | "internal_error"; + preliminaryScore: number; + verificationResults: VerificationResult[]; }; -type ExecutionResult = { - status: string; +type VerificationResult = { + testcase_id: number | null; + status: + | "running" + | "success" + | "wrong_answer" + | "timeout" + | "compile_error" + | "runtime_error" + | "internal_error" + | "canceled"; label: string; - output: string; + stdout: string; + stderr: string; }; +function submissionResultStatusToLabel( + status: SubmissionResult["status"] | null, +) { + switch (status) { + case null: + return "-"; + case "running": + return "Running..."; + case "success": + return "Accepted"; + case "wrong_answer": + return "Wrong Answer"; + case "timeout": + return "Time Limit Exceeded"; + case "compile_error": + return "Compile Error"; + case "runtime_error": + return "Runtime Error"; + case "internal_error": + return "Internal Error"; + } +} + export default function GolfWatchAppGaming({ problem, playerInfoA, @@ -40,7 +80,7 @@ export default function GolfWatchAppGaming({ const scoreA = playerInfoA.score ?? 0; const scoreB = playerInfoB.score ?? 0; const totalScore = scoreA + scoreB; - return totalScore === 0 ? 50 : (scoreA / totalScore) * 100; + return totalScore === 0 ? 50 : (scoreB / totalScore) * 100; })(); return ( @@ -68,7 +108,7 @@ export default function GolfWatchAppGaming({ {playerInfoB.score ?? "-"} </div> </div> - <div className="grid grid-cols-[2fr_1fr_2fr_1fr] p-2"> + <div className="grid grid-cols-[3fr_2fr_3fr_2fr] p-2"> <div> <pre> <code>{playerInfoA.code}</code> @@ -76,19 +116,24 @@ export default function GolfWatchAppGaming({ </div> <div> <div> - {playerInfoA.submissionResult?.status}( - {playerInfoA.submissionResult?.nextScore}) + {submissionResultStatusToLabel( + playerInfoA.submissionResult?.status ?? null, + )}{" "} + ({playerInfoA.submissionResult?.preliminaryScore}) </div> <div> <ol> - {playerInfoA.submissionResult?.executionResults.map( + {playerInfoA.submissionResult?.verificationResults.map( (result, idx) => ( <li key={idx}> <div> <div> {result.status} {result.label} </div> - <div>{result.output}</div> + <div> + {result.stdout} + {result.stderr} + </div> </div> </li> ), @@ -103,19 +148,24 @@ export default function GolfWatchAppGaming({ </div> <div> <div> - {playerInfoB.submissionResult?.status}( - {playerInfoB.submissionResult?.nextScore}) + {submissionResultStatusToLabel( + playerInfoB.submissionResult?.status ?? null, + )}{" "} + ({playerInfoB.submissionResult?.preliminaryScore ?? "-"}) </div> <div> <ol> - {playerInfoB.submissionResult?.executionResults.map( + {playerInfoB.submissionResult?.verificationResults.map( (result, idx) => ( <li key={idx}> <div> <div> {result.status} {result.label} </div> - <div>{result.output}</div> + <div> + {result.stdout} + {result.stderr} + </div> </div> </li> ), diff --git a/frontend/app/root.tsx b/frontend/app/root.tsx index 054474a..4d7a661 100644 --- a/frontend/app/root.tsx +++ b/frontend/app/root.tsx @@ -21,7 +21,7 @@ export function Layout({ children }: { children: React.ReactNode }) { <Meta /> <Links /> </head> - <body> + <body className="h-screen"> {children} <ScrollRestoration /> <Scripts /> |
