Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/*
Warnings:

- Added the required column `codeData` to the `Board` table without a default value. This is not possible if the table is not empty.
- Added the required column `isEdited` to the `Board` table without a default value. This is not possible if the table is not empty.

*/
-- AlterTable
ALTER TABLE "Board" ADD COLUMN "codeData" JSONB NOT NULL,
ADD COLUMN "isEdited" BOOLEAN NOT NULL;
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
Warnings:

- You are about to drop the column `isEdited` on the `Board` table. All the data in the column will be lost.

*/
-- AlterTable
ALTER TABLE "Board" DROP COLUMN "isEdited";
14 changes: 14 additions & 0 deletions prisma/migrations/20251115105024_rename_columns/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
Warnings:

- You are about to drop the column `codeData` on the `Board` table. All the data in the column will be lost.
- You are about to drop the column `data` on the `Board` table. All the data in the column will be lost.
- Added the required column `board` to the `Board` table without a default value. This is not possible if the table is not empty.
- Added the required column `code` to the `Board` table without a default value. This is not possible if the table is not empty.

*/
-- AlterTable
ALTER TABLE "Board" DROP COLUMN "codeData",
DROP COLUMN "data",
ADD COLUMN "board" JSONB NOT NULL,
ADD COLUMN "code" JSONB NOT NULL;
3 changes: 2 additions & 1 deletion prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ datasource db {
model Board {
id Int @id @default(autoincrement())
createdAt DateTime @default(now())
data Json
board Json
name String
preview Json
code Json
}

model Code {
Expand Down
8 changes: 4 additions & 4 deletions src/iframe/life-game.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
let timer = "stop";
let generationFigure = 0;
let isDragging = false;
let dragMode = false; // true: 黒にする, false: 白にする
let dragMode = 0; // 1: 黒にする, 0: 白にする
let isPlacingTemplate = false;
let patternShape = [];
let patternHeight = 0;
Expand Down Expand Up @@ -70,7 +70,7 @@ function renderBoard() {
for (let c = 0; c < patternWidth; c++) {
const boardRow = i + r;
const boardCol = j + c;
board[boardRow][boardCol] = patternShape[r][c] === 1;
board[boardRow][boardCol] = patternShape[r][c];
}
}
rerender();
Expand Down Expand Up @@ -239,15 +239,15 @@ on.pause = () => {

on.board_reset = () => {
//すべて白にBoardを変更
board = Array.from({ length: boardSize }, () => Array.from({ length: boardSize }, () => false));
board = Array.from({ length: boardSize }, () => Array.from({ length: boardSize }, () => 0));
renderBoard();
generationChange(0);
};

on.board_randomize = () => {
//白黒ランダムにBoardを変更
board = Array.from({ length: boardSize }, () =>
Array.from({ length: boardSize }, () => Math.random() > 0.5),
Array.from({ length: boardSize }, () => (Math.random() > 0.5 ? 1 : 0)),
);
renderBoard();
generationChange(0);
Expand Down
14 changes: 11 additions & 3 deletions src/lib/api/board.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { toast } from "$lib/models/ToastStore.svelte";

export async function saveBoard(data: { board: number[][]; name: string }, isJapanese: boolean) {
export async function saveBoard(
data: { board: number[][]; name: string; code: string },
isJapanese: boolean,
) {
try {
const response = await fetch("/api/board", {
method: "POST",
Expand Down Expand Up @@ -61,10 +64,15 @@ export async function fetchBoardList(isJapanese: boolean): Promise<BoardListItem
}
}

export type LoadedBoardData = {
board: number[][];
code: string;
};

export async function loadBoardById(
id: number,
isJapanese: boolean,
): Promise<number[][] | undefined> {
): Promise<LoadedBoardData | undefined> {
try {
const response = await fetch(`/api/board?id=${id}`);

Expand All @@ -78,7 +86,7 @@ export async function loadBoardById(

const loadedBoard = await response.json();

return loadedBoard as number[][];
return loadedBoard as LoadedBoardData;
} catch (err) {
console.error("Load error", err);
if (isJapanese) {
Expand Down
39 changes: 38 additions & 1 deletion src/lib/components/BoardModals.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,22 @@
isJapanese: boolean;
onSelect: (id: number) => void;
} = $props();

let showConfirmation = $state(false);
let selectedBoardId = $state<number | null>(null);

function handleLoadClick(id: number) {
selectedBoardId = id;
showConfirmation = true;
}

function handleConfirmLoad() {
if (selectedBoardId !== null) {
onSelect(selectedBoardId);
}
showConfirmation = false;
selectedBoardId = null;
}
</script>

<dialog class="modal" open={manager.saveState.saving}>
Expand Down Expand Up @@ -105,7 +121,7 @@
<td class="text-right">
<button
class="btn btn-sm btn-success text-black"
onclick={() => onSelect(item.id)}
onclick={() => handleLoadClick(item.id)}
>
{isJapanese ? "ロード" : "Load"}
</button>
Expand All @@ -125,6 +141,27 @@
</div>
</dialog>

<dialog class="modal modal-middle" open={showConfirmation}>
<div class="modal-box">
<h3 class="font-bold text-lg">
{isJapanese ? "警告" : "Caution"}
</h3>
<p class="py-4">
{isJapanese
? "盤面に加え、コードも上書きされます。よろしいですか?"
: "The current board and **CODE** will be overwritten. Are you sure?"}
</p>
<div class="modal-action">
<button class="btn btn-error" onclick={() => (showConfirmation = false)}>
{isJapanese ? "いいえ" : "No"}
</button>
<button class="btn btn-success text-black" onclick={handleConfirmLoad}>
{isJapanese ? "はい" : "Yes"}
</button>
</div>
</div>
</dialog>

<style>
.board-preview {
display: grid;
Expand Down
37 changes: 31 additions & 6 deletions src/lib/models/BoardManager.svelte.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,21 @@
import { createBoardPreview } from "$lib/board-preview";
import { saveBoard, fetchBoardList, loadBoardById, type BoardListItem } from "$lib/api/board";
import {
saveBoard,
fetchBoardList,
loadBoardById,
type BoardListItem,
type LoadedBoardData,
} from "$lib/api/board";

type SaveState =
| { saving: false }
| { saving: true; data: number[][]; name: string; preview: number[][] };
| {
saving: true;
board: number[][];
name: string;
preview: number[][];
code: string;
};

type LoadState =
| { state: "closed" }
Expand All @@ -16,9 +28,15 @@ export class BoardManager {

constructor() {}

openSaveModal(board: number[][]) {
openSaveModal(board: number[][], code: string) {
const preview = createBoardPreview(board);
this.saveState = { saving: true, data: board, name: "", preview: preview };
this.saveState = {
saving: true,
board: board,
name: "",
preview: preview,
code: code,
};
}

closeSaveModal() {
Expand All @@ -28,7 +46,14 @@ export class BoardManager {
async save(isJapanese: boolean) {
if (!this.saveState.saving) return;
const name = this.saveState.name.trim() === "" ? "Unnamed Board" : this.saveState.name.trim();
await saveBoard({ board: this.saveState.data, name }, isJapanese);
await saveBoard(
{
board: this.saveState.board,
name: name,
code: this.saveState.code,
},
isJapanese,
);
this.closeSaveModal();
}

Expand All @@ -46,7 +71,7 @@ export class BoardManager {
this.loadState = { state: "closed" };
}

async load(id: number, isJapanese: boolean): Promise<number[][] | undefined> {
async load(id: number, isJapanese: boolean): Promise<LoadedBoardData | undefined> {
this.closeLoadModal();
return await loadBoardById(id, isJapanese);
}
Expand Down
10 changes: 6 additions & 4 deletions src/routes/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@
break;
}
case "save_board": {
boardManager.openSaveModal(event.data.data as number[][]);
boardManager.openSaveModal(event.data.data as number[][], appliedCode as string);
break;
}
default: {
Expand All @@ -110,9 +110,11 @@
}

async function onBoardSelect(id: number) {
const board = await boardManager.load(id, isJapanese);
if (board) {
sendEvent("apply_board", board);
const data = await boardManager.load(id, isJapanese);
if (data) {
editingCode = data.code;
appliedCode = data.code;
sendEvent("apply_board", data.board);
}
}

Expand Down
10 changes: 6 additions & 4 deletions src/routes/api/board/+server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import * as v from "valibot";
const BoardSchema = v.object({
board: v.array(v.array(v.number())),
name: v.pipe(v.string(), v.minLength(1, "盤面名は必須です。")),
code: v.string(),
});

export async function POST({ request }) {
Expand All @@ -23,14 +24,15 @@ export async function POST({ request }) {
return json({ message: "無効なリクエストデータです。" }, { status: 400 });
}

const { board, name } = result.output;
const { board, name, code } = result.output;
const preview = createBoardPreview(board);

const newState = await prisma.board.create({
data: {
data: board,
board: board,
name: name,
preview: preview,
code: code,
},
});

Expand All @@ -49,14 +51,14 @@ export async function GET({ url }) {

const state = await prisma.board.findUnique({
where: { id: id },
select: { data: true },
select: { board: true, code: true },
});

if (!state) {
return json({ message: `ID: ${id} の盤面は見つかりません。` }, { status: 404 });
}

return json(state.data);
return json(state);
} else {
//IDが指定されなかった場合、全ての盤面のリストを返す
const allStates = await prisma.board.findMany({
Expand Down