diff options
| author | nsfisis <nsfisis@gmail.com> | 2025-03-21 09:23:01 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2025-03-21 09:50:56 +0900 |
| commit | 80ee46c81dda5331f66aa401435447f22ff187cd (patch) | |
| tree | 10830e1e882808b0ecbebd2164fd805160558ca2 /frontend | |
| parent | d379ce3309e5241359b9849fd0170909a140169c (diff) | |
| download | phperkaigi-2025-albatross-80ee46c81dda5331f66aa401435447f22ff187cd.tar.gz phperkaigi-2025-albatross-80ee46c81dda5331f66aa401435447f22ff187cd.tar.zst phperkaigi-2025-albatross-80ee46c81dda5331f66aa401435447f22ff187cd.zip | |
feat(frontend): show game result in 1v1 watch
Diffstat (limited to 'frontend')
| -rw-r--r-- | frontend/app/api/schema.d.ts | 2 | ||||
| -rw-r--r-- | frontend/app/components/GolfWatchApp.tsx | 1 | ||||
| -rw-r--r-- | frontend/app/components/GolfWatchApps/GolfWatchAppGaming1v1.tsx | 23 | ||||
| -rw-r--r-- | frontend/app/states/watch.ts | 32 |
4 files changed, 47 insertions, 11 deletions
diff --git a/frontend/app/api/schema.d.ts b/frontend/app/api/schema.d.ts index 0cace21..6f69292 100644 --- a/frontend/app/api/schema.d.ts +++ b/frontend/app/api/schema.d.ts @@ -201,6 +201,8 @@ export interface components { code: string; /** @example 100 */ score: number | null; + /** @example 946684800 */ + best_score_submitted_at: number | null; status: components["schemas"]["ExecutionStatus"]; }; RankingEntry: { diff --git a/frontend/app/components/GolfWatchApp.tsx b/frontend/app/components/GolfWatchApp.tsx index cfd5e74..492d555 100644 --- a/frontend/app/components/GolfWatchApp.tsx +++ b/frontend/app/components/GolfWatchApp.tsx @@ -138,7 +138,6 @@ export default function GolfWatchApp({ problemTitle={game.problem.title} problemDescription={game.problem.description} sampleCode={game.problem.sample_code} - gameResult={null /* TODO */} /> ) : ( <GolfWatchAppGamingMultiplayer diff --git a/frontend/app/components/GolfWatchApps/GolfWatchAppGaming1v1.tsx b/frontend/app/components/GolfWatchApps/GolfWatchAppGaming1v1.tsx index 63ad5f3..168f5d9 100644 --- a/frontend/app/components/GolfWatchApps/GolfWatchAppGaming1v1.tsx +++ b/frontend/app/components/GolfWatchApps/GolfWatchAppGaming1v1.tsx @@ -1,6 +1,8 @@ import { useAtomValue } from "jotai"; import { calcCodeSize, + checkGameResultKind, + gameStateKindAtom, gamingLeftTimeSecondsAtom, latestGameStatesAtom, } from "../../states/watch"; @@ -23,7 +25,6 @@ type Props = { problemTitle: string; problemDescription: string; sampleCode: string; - gameResult: "winA" | "winB" | "draw" | null; }; export default function GolfWatchAppGaming1v1({ @@ -33,16 +34,16 @@ export default function GolfWatchAppGaming1v1({ problemTitle, problemDescription, sampleCode, - gameResult, }: Props) { + const gameStateKind = useAtomValue(gameStateKindAtom); const leftTimeSeconds = useAtomValue(gamingLeftTimeSecondsAtom)!; const latestGameStates = useAtomValue(latestGameStatesAtom); - const stateA = latestGameStates[`${playerProfileA.id}`]; + const stateA = latestGameStates[`${playerProfileA.id}`] ?? null; const codeA = stateA?.code ?? ""; const scoreA = stateA?.score ?? null; const statusA = stateA?.status ?? "none"; - const stateB = latestGameStates[`${playerProfileB.id}`]; + const stateB = latestGameStates[`${playerProfileB.id}`] ?? null; const codeB = stateB?.code ?? ""; const scoreB = stateB?.score ?? null; const statusB = stateB?.status ?? "none"; @@ -50,10 +51,12 @@ export default function GolfWatchAppGaming1v1({ const codeSizeA = calcCodeSize(codeA); const codeSizeB = calcCodeSize(codeB); - const topBg = gameResult - ? gameResult === "winA" + const gameResultKind = checkGameResultKind(gameStateKind, stateA, stateB); + + const topBg = gameResultKind + ? gameResultKind === "winA" ? "bg-orange-400" - : gameResult === "winB" + : gameResultKind === "winB" ? "bg-purple-400" : "bg-sky-600" : "bg-sky-600"; @@ -76,11 +79,11 @@ export default function GolfWatchAppGaming1v1({ </div> <div className="font-bold text-center"> <div className="text-gray-100">{gameDisplayName}</div> - {gameResult ? ( + {gameResultKind ? ( <div className="text-3xl"> - {gameResult === "winA" + {gameResultKind === "winA" ? `勝者 ${playerProfileA.displayName}` - : gameResult === "winB" + : gameResultKind === "winB" ? `勝者 ${playerProfileB.displayName}` : "引き分け"} </div> diff --git a/frontend/app/states/watch.ts b/frontend/app/states/watch.ts index 8c7faa7..2c255f4 100644 --- a/frontend/app/states/watch.ts +++ b/frontend/app/states/watch.ts @@ -93,3 +93,35 @@ export function calcCodeSize(code: string): number { const utf8Encoded = new TextEncoder().encode(trimmed); return utf8Encoded.length; } + +export type GameResultKind = "winA" | "winB" | "draw"; + +export function checkGameResultKind( + gameStateKind: GameStateKind, + stateA: LatestGameState | null, + stateB: LatestGameState | null, +): GameResultKind | null { + if (gameStateKind !== "finished") { + return null; + } + + const scoreA = stateA?.score; + const scoreB = stateB?.score; + if (scoreA == null && scoreB == null) { + return "draw"; + } + if (scoreA == null) { + return "winB"; + } + if (scoreB == null) { + return "winA"; + } + if (scoreA === scoreB) { + // If score is non-null, state and best_score_submitted_at should also be non-null. + const submittedAtA = stateA!.best_score_submitted_at!; + const submittedAtB = stateB!.best_score_submitted_at!; + return submittedAtA < submittedAtB ? "winA" : "winB"; + } else { + return scoreA < scoreB ? "winA" : "winB"; + } +} |
