diff --git a/prisma/migrations/20251112091315_add_board_preview_column/migration.sql b/prisma/migrations/20251112091315_add_board_preview_column/migration.sql new file mode 100644 index 0000000..0de9d26 --- /dev/null +++ b/prisma/migrations/20251112091315_add_board_preview_column/migration.sql @@ -0,0 +1,8 @@ +/* + Warnings: + + - Added the required column `boardPreview` to the `BoardState` table without a default value. This is not possible if the table is not empty. + +*/ +-- AlterTable +ALTER TABLE "BoardState" ADD COLUMN "boardPreview" JSONB NOT NULL; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index ff842dc..4719673 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -20,4 +20,5 @@ model BoardState { createdAt DateTime @default(now()) boardData Json boardName String + boardPreview Json } diff --git a/src/iframe/life-game.html b/src/iframe/life-game.html index 8d75d39..0c4d69c 100644 --- a/src/iframe/life-game.html +++ b/src/iframe/life-game.html @@ -5,6 +5,7 @@ -
+
+
+
diff --git a/src/iframe/life-game.js b/src/iframe/life-game.js index 8ce2604..91f86a4 100644 --- a/src/iframe/life-game.js +++ b/src/iframe/life-game.js @@ -209,6 +209,7 @@ on.save_board = async () => { }; on.apply_board = (newBoard) => { + boardSize = newBoard.length; board = newBoard; renderBoard(); generationChange(0); diff --git a/src/lib/board-preview.ts b/src/lib/board-preview.ts new file mode 100644 index 0000000..79736ab --- /dev/null +++ b/src/lib/board-preview.ts @@ -0,0 +1,38 @@ +const PREVIEW_SIZE = 20; + +/** + * 任意のサイズの盤面データから、中央 20x20 のプレビューを生成します。 + * 20x20 に満たない場合は、中央に配置し、周囲を false (空白) で埋めます。 + */ +export function createPreview(boardData: boolean[][]): boolean[][] { + const boardHeight = boardData.length; + const boardWidth = boardData[0]?.length || 0; + + const finalPreview: boolean[][] = Array.from({ length: PREVIEW_SIZE }, () => + Array(PREVIEW_SIZE).fill(false), + ); + + const sourceStartRow = Math.max(0, Math.floor((boardHeight - PREVIEW_SIZE) / 2)); + const sourceStartCol = Math.max(0, Math.floor((boardWidth - PREVIEW_SIZE) / 2)); + + const destStartRow = Math.max(0, Math.floor((PREVIEW_SIZE - boardHeight) / 2)); + const destStartCol = Math.max(0, Math.floor((PREVIEW_SIZE - boardWidth) / 2)); + + const rowsToCopy = Math.min(PREVIEW_SIZE - destStartRow, boardHeight - sourceStartRow); + const colsToCopy = Math.min(PREVIEW_SIZE - destStartCol, boardWidth - sourceStartCol); + + if (rowsToCopy <= 0 || colsToCopy <= 0) { + return finalPreview; + } + + for (let i = 0; i < rowsToCopy; i++) { + for (let j = 0; j < colsToCopy; j++) { + if (boardData[sourceStartRow + i]?.[sourceStartCol + j] !== undefined) { + finalPreview[destStartRow + i][destStartCol + j] = + boardData[sourceStartRow + i][sourceStartCol + j]; + } + } + } + + return finalPreview; +} diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index f2ec61f..578ef5e 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -6,6 +6,7 @@ import patterns from "$lib/board-templates"; import * as icons from "$lib/icons/index.ts"; import { saveBoard, fetchBoardList, loadBoardById, type BoardListItem } from "./api.ts"; + import { createPreview } from "$lib/board-preview"; let editingCode = $state(lifeGameJS); let appliedCode = $state(lifeGameJS); @@ -23,7 +24,9 @@ let generationFigure = $state(0); let sizeValue = $state(20); - type SaveState = { saving: false } | { saving: true; boardData: boolean[][]; boardName: string }; + type SaveState = + | { saving: false } + | { saving: true; boardData: boolean[][]; boardName: string; boardPreview: boolean[][] }; let saveState: SaveState = $state({ saving: false }); type LoadState = @@ -61,7 +64,9 @@ break; } case "save_board": { - saveState = { saving: true, boardData: event.data.data as boolean[][], boardName: "" }; + const board = event.data.data as boolean[][]; + const preview = createPreview(board); + saveState = { saving: true, boardData: board, boardName: "", boardPreview: preview }; break; } default: { @@ -109,6 +114,7 @@ const board = await loadBoardById(id, isJapanese); if (board) { + sizeValue = board.length; sendEvent("apply_board", board); } } @@ -216,17 +222,35 @@