diff --git a/apps/client/src/scenes/result/ResultScene.tsx b/apps/client/src/scenes/result/ResultScene.tsx
index 71772ce..69f90e1 100644
--- a/apps/client/src/scenes/result/ResultScene.tsx
+++ b/apps/client/src/scenes/result/ResultScene.tsx
@@ -8,6 +8,7 @@
import { config } from "../../config";
import { ResultActionBar } from "./components/ResultActionBar";
import { ResultBackground } from "./components/ResultBackground";
+import { ResultPlayerStatsTable } from "./components/ResultPlayerStatsTable";
import { ResultRankingTable } from "./components/ResultRankingTable";
import {
RESULT_BACKGROUND_DARK_OVERLAY_STYLE,
@@ -100,6 +101,10 @@
formatPaintRate={formatPaintRate}
/>
)}
+
+ {isRankingVisible && result.playerStats && result.playerStats.length > 0 && (
+
+ )}
);
diff --git a/apps/client/src/scenes/result/components/ResultPlayerStatsTable.tsx b/apps/client/src/scenes/result/components/ResultPlayerStatsTable.tsx
new file mode 100644
index 0000000..4ef41c3
--- /dev/null
+++ b/apps/client/src/scenes/result/components/ResultPlayerStatsTable.tsx
@@ -0,0 +1,64 @@
+/**
+ * ResultPlayerStatsTable
+ * リザルト画面のプレイヤー個人スタッツ表を表示する
+ * 各プレイヤーの塗り回数と爆弾ヒット回数の一覧描画を担当する
+ */
+import type { PlayerGameStats } from "@repo/shared";
+import { config } from "@client/config";
+import {
+ RESULT_PLAYER_STATS_HEADER_ROW_STYLE,
+ RESULT_PLAYER_STATS_SCROLL_BODY_STYLE,
+ RESULT_TABLE_STYLE,
+ RESULT_RIGHT_ALIGN_STYLE,
+ RESULT_TEAM_CELL_STYLE,
+ getResultPlayerStatsBodyRowStyle,
+ getResultTeamColorDotStyle,
+ RESULT_PLAYER_STATS_SECTION_TITLE_STYLE,
+ RESULT_PLAYER_STATS_VALUE_STYLE,
+} from "../styles/resultStyles";
+
+type Props = {
+ playerStats: PlayerGameStats[];
+};
+
+/** プレイヤー個人スタッツ表を描画するコンポーネント */
+export const ResultPlayerStatsTable = ({ playerStats }: Props) => {
+ const sorted = [...playerStats].sort((a, b) => b.paintCount - a.paintCount);
+
+ return (
+ <>
+
個人スタッツ
+
+
+ プレイヤー
+ 塗り回数
+ ヒット数
+
+
+
+ {sorted.map((player, index) => (
+
+
+
+ {player.playerName}
+
+
+ {player.paintCount.toLocaleString()}
+
+
+ {player.bombHitCount}
+
+
+ ))}
+
+
+ >
+ );
+};
diff --git a/apps/client/src/scenes/result/styles/resultStyles.ts b/apps/client/src/scenes/result/styles/resultStyles.ts
index 8df9dad..7e8d8b8 100644
--- a/apps/client/src/scenes/result/styles/resultStyles.ts
+++ b/apps/client/src/scenes/result/styles/resultStyles.ts
@@ -209,6 +209,49 @@
background: index % 2 === 0 ? "#171717" : "#1d1d1d",
});
+/** プレイヤースタッツ表のグリッド列定義 */
+export const RESULT_PLAYER_STATS_ROW_GRID_TEMPLATE = "1fr 120px 120px";
+
+/** プレイヤースタッツセクションタイトルのスタイル */
+export const RESULT_PLAYER_STATS_SECTION_TITLE_STYLE: CSSProperties = {
+ margin: "24px 0 10px 0",
+ fontSize: "clamp(1rem, 2.6vw, 1.3rem)",
+ fontWeight: 700,
+ letterSpacing: "0.08em",
+ color: "rgba(255, 255, 255, 0.88)",
+ textShadow: "0 2px 8px rgba(0, 0, 0, 0.4)",
+};
+
+/** プレイヤースタッツ表ヘッダー行のスタイル */
+export const RESULT_PLAYER_STATS_HEADER_ROW_STYLE: CSSProperties = {
+ display: "grid",
+ gridTemplateColumns: RESULT_PLAYER_STATS_ROW_GRID_TEMPLATE,
+ background: "#222",
+ padding: "12px 16px",
+ fontWeight: "bold",
+};
+
+/** プレイヤースタッツ表本文スクロール領域のスタイル */
+export const RESULT_PLAYER_STATS_SCROLL_BODY_STYLE: CSSProperties = {
+ maxHeight: "min(36dvh, 320px)",
+ overflowY: "auto",
+};
+
+/** プレイヤースタッツ数値セルのスタイル */
+export const RESULT_PLAYER_STATS_VALUE_STYLE: CSSProperties = {
+ textAlign: "right",
+ fontVariantNumeric: "tabular-nums",
+};
+
+/** プレイヤースタッツ表本文行のスタイルを返す */
+export const getResultPlayerStatsBodyRowStyle = (index: number): CSSProperties => ({
+ display: "grid",
+ gridTemplateColumns: RESULT_PLAYER_STATS_ROW_GRID_TEMPLATE,
+ padding: "12px 16px",
+ borderTop: "1px solid #333",
+ background: index % 2 === 0 ? "#171717" : "#1d1d1d",
+});
+
/** 紙吹雪1片のスタイルを返す */
export const getResultConfettiStyle = (
index: number,