From cca0f63e50684d6806697589b620ee4b4c1b21b5 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Thu, 20 Mar 2025 22:18:14 +0900 Subject: feat(frontend): improve watch page layout --- frontend/app/components/Gaming/Problem.tsx | 56 -------------------- frontend/app/components/Gaming/ProblemColumn.tsx | 60 ++++++++++++++++++++++ frontend/app/components/Gaming/SubmitResult.tsx | 18 ------- .../components/GolfPlayApps/GolfPlayAppGaming.tsx | 26 +++------- .../GolfWatchApps/GolfWatchAppGaming1v1.tsx | 48 +++++++++++------ .../GolfWatchAppGamingMultiplayer.tsx | 12 ++--- frontend/app/components/TitledColumn.tsx | 15 ++++++ frontend/app/states/play.ts | 10 ++++ frontend/app/states/watch.ts | 10 ++++ 9 files changed, 140 insertions(+), 115 deletions(-) delete mode 100644 frontend/app/components/Gaming/Problem.tsx create mode 100644 frontend/app/components/Gaming/ProblemColumn.tsx delete mode 100644 frontend/app/components/Gaming/SubmitResult.tsx create mode 100644 frontend/app/components/TitledColumn.tsx (limited to 'frontend') diff --git a/frontend/app/components/Gaming/Problem.tsx b/frontend/app/components/Gaming/Problem.tsx deleted file mode 100644 index e2f1487..0000000 --- a/frontend/app/components/Gaming/Problem.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import BorderedContainerWithCaption from "../BorderedContainerWithCaption"; -import CodeBlock from "./CodeBlock"; -import InlineCode from "./InlineCode"; - -type Props = { - title: string; - description: string; - sampleCode: string; -}; - -export default function Problem({ title, description, sampleCode }: Props) { - return ( -
-
{title}
- -
-					{description}
-				
-
- - - - -
-

- スコアはコード中の全 ASCII - 空白文字を除去した後のバイト数です。また、先頭や末尾に置かれた PHP - タグ (、 - ) はカウントされません。 -

-

- 同じスコアを出した場合、より提出が早かったプレイヤーの勝ちとなります。 -

-

- この環境の PHP バージョンは{" "} - 8.4.4 です。 mbstring - を除くほとんどの拡張は無効化されています。 - また、ファイルやネットワークアクセスはできません。 -

-

- テストの成否は、標準出力へ出力された文字列を比較して判定されます。 - 末尾の改行はあってもなくても構いません。 - 標準エラー出力の内容は無視されますが、fatal error - 等で実行が中断された場合は失敗扱いとなります。 -

-

- なお、 - は{" "} - {" "} - に設定されています。 -

-
-
-
- ); -} diff --git a/frontend/app/components/Gaming/ProblemColumn.tsx b/frontend/app/components/Gaming/ProblemColumn.tsx new file mode 100644 index 0000000..2a57afd --- /dev/null +++ b/frontend/app/components/Gaming/ProblemColumn.tsx @@ -0,0 +1,60 @@ +import BorderedContainerWithCaption from "../BorderedContainerWithCaption"; +import TitledColumn from "../TitledColumn"; +import CodeBlock from "./CodeBlock"; +import InlineCode from "./InlineCode"; + +type Props = { + title: string; + description: string; + sampleCode: string; +}; + +export default function ProblemColumn({ + title, + description, + sampleCode, +}: Props) { + return ( + + +
+					{description}
+				
+
+ + + + +
+

+ スコアはコード中の全 ASCII + 空白文字を除去した後のバイト数です。また、先頭や末尾に置かれた PHP + タグ (、 + ) はカウントされません。 +

+

+ 同じスコアを出した場合、より提出が早かったプレイヤーの勝ちとなります。 +

+

+ この環境の PHP バージョンは{" "} + 8.4.4 です。 mbstring + を除くほとんどの拡張は無効化されています。 + また、ファイルやネットワークアクセスはできません。 +

+

+ テストの成否は、標準出力へ出力された文字列を比較して判定されます。 + 末尾の改行はあってもなくても構いません。 + 標準エラー出力の内容は無視されますが、fatal error + 等で実行が中断された場合は失敗扱いとなります。 +

+

+ なお、 + は{" "} + {" "} + に設定されています。 +

+
+
+
+ ); +} diff --git a/frontend/app/components/Gaming/SubmitResult.tsx b/frontend/app/components/Gaming/SubmitResult.tsx deleted file mode 100644 index ea75b6b..0000000 --- a/frontend/app/components/Gaming/SubmitResult.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import type { components } from "../../api/schema"; -import SubmitStatusLabel from "../SubmitStatusLabel"; - -type Props = { - status: components["schemas"]["ExecutionStatus"]; -}; - -export default function SubmitResult({ status }: Props) { - return ( -
-
-
- -
-
-
- ); -} diff --git a/frontend/app/components/GolfPlayApps/GolfPlayAppGaming.tsx b/frontend/app/components/GolfPlayApps/GolfPlayAppGaming.tsx index 0931f73..c4bd772 100644 --- a/frontend/app/components/GolfPlayApps/GolfPlayAppGaming.tsx +++ b/frontend/app/components/GolfPlayApps/GolfPlayAppGaming.tsx @@ -5,26 +5,18 @@ import { gamingLeftTimeSecondsAtom, scoreAtom, statusAtom, + calcCodeSize, } from "../../states/play"; import type { PlayerProfile } from "../../types/PlayerProfile"; import BorderedContainer from "../BorderedContainer"; import LeftTime from "../Gaming/LeftTime"; -import Problem from "../Gaming/Problem"; +import ProblemColumn from "../Gaming/ProblemColumn"; import SubmitButton from "../SubmitButton"; import SubmitStatusLabel from "../SubmitStatusLabel"; import ThreeColumnLayout from "../ThreeColumnLayout"; +import TitledColumn from "../TitledColumn"; import UserIcon from "../UserIcon"; -function calcCodeSize(code: string): number { - const trimmed = code - .replace(/\s+/g, "") - .replace(/^<\?php/, "") - .replace(/^<\?/, "") - .replace(/\?>$/, ""); - const utf8Encoded = new TextEncoder().encode(trimmed); - return utf8Encoded.length; -} - type Props = { gameDisplayName: string; playerProfile: PlayerProfile; @@ -86,13 +78,12 @@ export default function GolfPlayAppGaming({ - -
-
ソースコード
+
@@ -109,9 +100,8 @@ export default function GolfPlayAppGaming({ className="grow resize-none h-full w-full p-2 bg-gray-50 rounded-lg border border-gray-300 focus:outline-hidden focus:ring-2 focus:ring-gray-400 transition duration-300" /> -
-
-
提出結果
+ +
@@ -139,7 +129,7 @@ export default function GolfPlayAppGaming({ NOTE: 過去の提出結果を閲覧する機能は現在実装中です。それまでは提出コードをお手元に保管しておいてください。

- + ); diff --git a/frontend/app/components/GolfWatchApps/GolfWatchAppGaming1v1.tsx b/frontend/app/components/GolfWatchApps/GolfWatchAppGaming1v1.tsx index f72397d..4a7fe8a 100644 --- a/frontend/app/components/GolfWatchApps/GolfWatchAppGaming1v1.tsx +++ b/frontend/app/components/GolfWatchApps/GolfWatchAppGaming1v1.tsx @@ -2,15 +2,18 @@ import { useAtomValue } from "jotai"; import { gamingLeftTimeSecondsAtom, latestGameStatesAtom, + calcCodeSize, } from "../../states/watch"; import type { PlayerProfile } from "../../types/PlayerProfile"; +import BorderedContainer from "../BorderedContainer"; +import SubmitStatusLabel from "../SubmitStatusLabel"; +import ThreeColumnLayout from "../ThreeColumnLayout"; +import TitledColumn from "../TitledColumn"; +import UserIcon from "../UserIcon"; import CodeBlock from "../Gaming/CodeBlock"; import LeftTime from "../Gaming/LeftTime"; -import Problem from "../Gaming/Problem"; +import ProblemColumn from "../Gaming/ProblemColumn"; import ScoreBar from "../Gaming/ScoreBar"; -import SubmitResult from "../Gaming/SubmitResult"; -import ThreeColumnLayout from "../ThreeColumnLayout"; -import UserIcon from "../UserIcon"; type Props = { gameDisplayName: string; @@ -43,6 +46,9 @@ export default function GolfWatchAppGaming1v1({ const scoreB = stateB?.score ?? null; const statusB = stateB?.status ?? "none"; + const codeSizeA = calcCodeSize(codeA); + const codeSizeB = calcCodeSize(codeB); + const topBg = gameResult ? gameResult === "winA" ? "bg-orange-400" @@ -102,19 +108,27 @@ export default function GolfWatchAppGaming1v1({ bgB="bg-purple-400" /> - -
-
- - -
- -
- + }> + +
+ コードサイズ: {codeSizeA} +
+ +
+
+ + }> + +
+ コードサイズ: {codeSizeB} +
+ +
+
); diff --git a/frontend/app/components/GolfWatchApps/GolfWatchAppGamingMultiplayer.tsx b/frontend/app/components/GolfWatchApps/GolfWatchAppGamingMultiplayer.tsx index 06a2376..a6b9464 100644 --- a/frontend/app/components/GolfWatchApps/GolfWatchAppGamingMultiplayer.tsx +++ b/frontend/app/components/GolfWatchApps/GolfWatchAppGamingMultiplayer.tsx @@ -2,8 +2,9 @@ import { useAtomValue } from "jotai"; import type { components } from "../../api/schema"; import { gamingLeftTimeSecondsAtom } from "../../states/watch"; import LeftTime from "../Gaming/LeftTime"; -import Problem from "../Gaming/Problem"; +import ProblemColumn from "../Gaming/ProblemColumn"; import RankingTable from "../Gaming/RankingTable"; +import TitledColumn from "../TitledColumn"; import TwoColumnLayout from "../TwoColumnLayout"; type RankingEntry = components["schemas"]["RankingEntry"]; @@ -27,7 +28,7 @@ export default function GolfWatchAppGamingMultiplayer({ return (
-
+
{gameDisplayName}
@@ -36,15 +37,14 @@ export default function GolfWatchAppGamingMultiplayer({
- -
-
順位表
+ -
+
); diff --git a/frontend/app/components/TitledColumn.tsx b/frontend/app/components/TitledColumn.tsx new file mode 100644 index 0000000..4272ad4 --- /dev/null +++ b/frontend/app/components/TitledColumn.tsx @@ -0,0 +1,15 @@ +import React from "react"; + +type Props = { + children: React.ReactNode; + title: React.ReactNode; +}; + +export default function TitledColumn({ children, title }: Props) { + return ( +
+
{title}
+ {children} +
+ ); +} diff --git a/frontend/app/states/play.ts b/frontend/app/states/play.ts index 7bf4b4e..79b25c7 100644 --- a/frontend/app/states/play.ts +++ b/frontend/app/states/play.ts @@ -100,3 +100,13 @@ export const setLatestGameStateAtom = atom( set(rawScoreAtom, value.score); }, ); + +export function calcCodeSize(code: string): number { + const trimmed = code + .replace(/\s+/g, "") + .replace(/^<\?php/, "") + .replace(/^<\?/, "") + .replace(/\?>$/, ""); + const utf8Encoded = new TextEncoder().encode(trimmed); + return utf8Encoded.length; +} diff --git a/frontend/app/states/watch.ts b/frontend/app/states/watch.ts index 14a70b4..8c7faa7 100644 --- a/frontend/app/states/watch.ts +++ b/frontend/app/states/watch.ts @@ -83,3 +83,13 @@ export const setLatestGameStatesAtom = atom( set(rawLatestGameStatesAtom, value); }, ); + +export function calcCodeSize(code: string): number { + const trimmed = code + .replace(/\s+/g, "") + .replace(/^<\?php/, "") + .replace(/^<\?/, "") + .replace(/\?>$/, ""); + const utf8Encoded = new TextEncoder().encode(trimmed); + return utf8Encoded.length; +} -- cgit v1.2.3-70-g09d2