diff --git a/package.json b/package.json index 5ccfffec..eb04f512 100644 --- a/package.json +++ b/package.json @@ -50,6 +50,7 @@ "supertokens-auth-react": "0.36.1", "supertokens-node": "16.7.1", "supertokens-web-js": "0.8.0", + "uuid": "9.0.1", "zod": "3.22.4", "zod-form-data": "2.0.2" }, @@ -61,6 +62,7 @@ "@types/node": "20.11.0", "@types/react-dom": "18.2.18", "@types/react-syntax-highlighter": "^15", + "@types/uuid": "^9", "@typescript-eslint/eslint-plugin": "6.18.1", "@typescript-eslint/parser": "6.18.1", "@willbooster/eslint-config-next": "1.1.0", diff --git a/public/character.png b/public/character.png deleted file mode 100644 index b75d3b56..00000000 Binary files a/public/character.png and /dev/null differ diff --git a/public/character/blue.png b/public/character/blue.png new file mode 100644 index 00000000..8e1db312 Binary files /dev/null and b/public/character/blue.png differ diff --git a/public/character/green.png b/public/character/green.png new file mode 100644 index 00000000..a1a0cdf4 Binary files /dev/null and b/public/character/green.png differ diff --git a/public/character/purple.png b/public/character/purple.png new file mode 100644 index 00000000..82917d4c Binary files /dev/null and b/public/character/purple.png differ diff --git a/public/character/red.png b/public/character/red.png new file mode 100644 index 00000000..09f9eaa8 Binary files /dev/null and b/public/character/red.png differ diff --git a/public/character/white.png b/public/character/white.png new file mode 100644 index 00000000..acc0ff54 Binary files /dev/null and b/public/character/white.png differ diff --git a/public/character/yellow.png b/public/character/yellow.png new file mode 100644 index 00000000..c2ddcd68 Binary files /dev/null and b/public/character/yellow.png differ diff --git a/src/app/(withAuth)/problems/[problemId]/page.tsx b/src/app/(withAuth)/problems/[problemId]/page.tsx index 6883f20d..a33c1a40 100644 --- a/src/app/(withAuth)/problems/[problemId]/page.tsx +++ b/src/app/(withAuth)/problems/[problemId]/page.tsx @@ -2,47 +2,59 @@ import { Box, Button, Flex, HStack, Heading, VStack } from '@chakra-ui/react'; import type { NextPage } from 'next'; -import { useEffect, useState } from 'react'; +import { useEffect, useState, useRef } from 'react'; import { SyntaxHighlighter } from '../../../../components/organisms/SyntaxHighlighter'; +import type { TurtleGraphicsHandle } from '../../../../components/organisms/TurtleGraphics'; import { TurtleGraphics } from '../../../../components/organisms/TurtleGraphics'; -import { programIdToName, generateProgram, getDescription } from '../../../../problems/problemData'; +import { programIdToName, generateProgram } from '../../../../problems/problemData'; import { getLanguageIdFromSessionStorage } from '../../../lib/SessionStorage'; -const GRID_COLUMNS = 12; -const GRID_ROWS = 8; -const GRID_SIZE = 40; - const ProblemPage: NextPage<{ params: { problemId: string } }> = ({ params }) => { + const turtleGraphicsRef = useRef(null); const [selectedLanguageId, setSelectedLanguageId] = useState(''); useEffect(() => { setSelectedLanguageId(getLanguageIdFromSessionStorage()); }, []); + const problemProgram = generateProgram(params.problemId, selectedLanguageId); + + const handleClickResetButton = (): void => { + turtleGraphicsRef.current?.reset(); + }; + + const handleClickAnswerButton = (): void => { + const isCorrect = turtleGraphicsRef.current?.isCorrect(); + + // TODO: 一旦アラートで表示 + if (isCorrect) { + alert('正解です'); + } else { + alert('不正解です'); + } + }; + return (
{programIdToName[params.problemId]} - - {getDescription(params.problemId)} + + プログラムの実行後の結果を解答してください。 - + {/* 画面に収まる高さに設定 */} - + - - + + diff --git a/src/app/lib/Board.ts b/src/app/lib/Board.ts index 9ee3a7d1..9041fdb0 100644 --- a/src/app/lib/Board.ts +++ b/src/app/lib/Board.ts @@ -1,15 +1,16 @@ -import type { Cell } from '../../types'; +import { GRID_COLUMNS, GRID_ROWS } from '../../components/organisms/TurtleGraphics'; +import type { Cell, CellColor } from '../../types'; import type { Character } from './Character'; export class Board { grid: Cell[][]; constructor({ - gridSize = [8, 12], + gridSize = [GRID_ROWS, GRID_COLUMNS], }: { gridSize?: [number, number]; } = {}) { - this.grid = this.createGrid(gridSize[1], gridSize[0]); + this.grid = this.createGrid(gridSize[0], gridSize[1]); } createGrid(numRows: number, numColumns: number): Cell[][] { @@ -24,7 +25,15 @@ export class Board { } updateGrid(character: Character): void { - const { cellColor, penDown, x, y } = character; - if (penDown) this.grid[y - 1][x - 1].color = cellColor; + const { color, penDown, x, y } = character; + if (penDown) this.grid[y - 1][x - 1].color = color; + } + + getCellColor(x: number, y: number): CellColor { + return this.grid[y][x].color; + } + + setCellColor(x: number, y: number, color: CellColor): void { + this.grid[y][x].color = color; } } diff --git a/src/app/lib/Character.ts b/src/app/lib/Character.ts index 351af213..012860f1 100644 --- a/src/app/lib/Character.ts +++ b/src/app/lib/Character.ts @@ -1,43 +1,34 @@ -import type { CellColor } from '../../types'; +import { v4 as uuidv4 } from 'uuid'; -export const CharacterColor = { - Red: 'red', - Blue: 'blue', - Green: 'green', - Yellow: 'yellow', - Purple: 'purple', -}; -type Color = (typeof CharacterColor)[keyof typeof CharacterColor]; +import { GRID_COLUMNS, GRID_ROWS } from '../../components/organisms/TurtleGraphics'; +import type { CellColor, CharacterDirection } from '../../types'; export class Character { - id: number; + id: string; name: string; x: number; y: number; - direction: string; - cellColor: CellColor; - color: Color; + direction: CharacterDirection; + color: CellColor; penDown: boolean; path: string[]; constructor({ - cellColor = 'red', color = 'red', direction = 'down', - id = 1, + id = uuidv4(), name = 'Bear', path = ['1,1'], penDown = true, x = 1, y = 1, }: { - id?: number; + id?: string; name?: string; x?: number; y?: number; - direction?: string; - cellColor?: CellColor; - color?: Color; + direction?: CharacterDirection; + color?: CellColor; penDown?: boolean; path?: string[]; } = {}) { @@ -46,35 +37,28 @@ export class Character { this.x = x; this.y = y; this.direction = direction; - this.cellColor = cellColor; this.color = color; this.penDown = penDown; this.path = path; } - moveForward(gridColumns: number, gridRows: number): void { + moveForward(): void { + if (!this.canMoveForward()) return; + switch (this.direction) { case 'up': { - if (this.y <= 1) return; - this.y -= 1; break; } case 'down': { - if (this.y >= gridRows) return; - this.y += 1; break; } case 'left': { - if (this.x <= 1) return; - this.x -= 1; break; } case 'right': { - if (this.x >= gridColumns) return; - this.x += 1; break; } @@ -85,29 +69,23 @@ export class Character { } } - moveBack(gridColumns: number, gridRows: number): void { + moveBack(): void { + if (!this.canMoveBack()) return; + switch (this.direction) { case 'up': { - if (this.y >= gridRows) return; - this.y += 1; break; } case 'down': { - if (this.y <= 1) return; - this.y -= 1; break; } case 'left': { - if (this.x >= gridColumns) return; - this.x += 1; break; } case 'right': { - if (this.x <= 1) return; - this.x -= 1; break; } @@ -160,7 +138,12 @@ export class Character { } } - setColor(color: Color): void { + setPosition(x: number, y: number): void { + this.x = x; + this.y = y; + } + + setColor(color: CellColor): void { this.color = color; } @@ -189,4 +172,40 @@ export class Character { } return ''; } + + canMoveForward(): boolean { + switch (this.direction) { + case 'up': { + return this.y > 1; + } + case 'down': { + return this.y < GRID_ROWS; + } + case 'left': { + return this.x > 1; + } + case 'right': { + return this.x < GRID_COLUMNS; + } + } + return false; + } + + canMoveBack(): boolean { + switch (this.direction) { + case 'up': { + return this.y < GRID_ROWS; + } + case 'down': { + return this.y > 1; + } + case 'left': { + return this.x < GRID_COLUMNS; + } + case 'right': { + return this.x > 1; + } + } + return false; + } } diff --git a/src/app/lib/TurtleGraphicsCell.ts b/src/app/lib/TurtleGraphicsCell.ts deleted file mode 100644 index cff9cbd0..00000000 --- a/src/app/lib/TurtleGraphicsCell.ts +++ /dev/null @@ -1,21 +0,0 @@ -import type { CharacterColor } from './Character'; - -type Color = (typeof CharacterColor)[keyof typeof CharacterColor]; - -export class TurtleGraphicsCell { - id: number; - x: number; - y: number; - backgroundColor: string; - - constructor(id: number, x: number, y: number, backgroundColor: string) { - this.id = id; - this.x = x; - this.y = y; - this.backgroundColor = backgroundColor; - } - - setBackgroundColor(color: Color): void { - this.backgroundColor = color; - } -} diff --git a/src/components/molecules/TurtleGraphicsController.tsx b/src/components/molecules/TurtleGraphicsController.tsx new file mode 100644 index 00000000..bde5a5b5 --- /dev/null +++ b/src/components/molecules/TurtleGraphicsController.tsx @@ -0,0 +1,159 @@ +'use client'; + +import { Box, Button, HStack, VStack } from '@chakra-ui/react'; +import React from 'react'; + +import type { Board } from '../../app/lib/Board'; +import type { Character } from '../../app/lib/Character'; +import type { CellColor, CharacterDirection, SelectedCell } from '../../types'; + +interface TurtleGraphicsControllerProps { + board: Board; + selectedCharacter?: Character; + selectedCell?: SelectedCell; + handleChangeCellColorButton: (color: CellColor) => void; + handleChangeCharacterColorButton: (color: CellColor) => void; + handleAddCharacterButton: () => void; + handleRemoveCharacterButton: (character: Character) => void; + handleClickCharacterMoveButton: () => void; + handleClickChangeCharacterDirectionButton: (direction: CharacterDirection) => void; + handleClickCharacterMoveForwardButton: () => void; + handleClickCharacterMoveBackButton: () => void; + handleClickCharacterPenUpButton: () => void; + handleClickCharacterPenDownButton: () => void; +} + +interface ColorChangeButtonProps { + color: CellColor; + selectedColor?: CellColor; + handleOnClick: (color: CellColor) => void; +} + +export const TurtleGraphicsController: React.FC = ({ + board, + handleAddCharacterButton, + handleChangeCellColorButton, + handleChangeCharacterColorButton, + handleClickChangeCharacterDirectionButton, + handleClickCharacterMoveBackButton, + handleClickCharacterMoveButton, + handleClickCharacterMoveForwardButton, + handleClickCharacterPenDownButton, + handleClickCharacterPenUpButton, + handleRemoveCharacterButton, + selectedCell, + selectedCharacter, +}) => { + const ColorChangeButton: React.FC = ({ color, handleOnClick, selectedColor }) => { + return ( + + ); + }; + + return ( + + {selectedCharacter && ( + <> + + + + + + + + + + + handleChangeCharacterColorButton('red')} + selectedColor={selectedCharacter.color} + /> + handleChangeCharacterColorButton('blue')} + selectedColor={selectedCharacter.color} + /> + handleChangeCharacterColorButton('green')} + selectedColor={selectedCharacter.color} + /> + handleChangeCharacterColorButton('yellow')} + selectedColor={selectedCharacter.color} + /> + handleChangeCharacterColorButton('purple')} + selectedColor={selectedCharacter.color} + /> + handleChangeCharacterColorButton(undefined)} + selectedColor={selectedCharacter.color} + /> + + + + + + + + + + )} + + {selectedCell && ( + <> + + + + + handleChangeCellColorButton('red')} + selectedColor={board.getCellColor(selectedCell.x, selectedCell.y)} + /> + handleChangeCellColorButton('blue')} + selectedColor={board.getCellColor(selectedCell.x, selectedCell.y)} + /> + handleChangeCellColorButton('green')} + selectedColor={board.getCellColor(selectedCell.x, selectedCell.y)} + /> + handleChangeCellColorButton('yellow')} + selectedColor={board.getCellColor(selectedCell.x, selectedCell.y)} + /> + handleChangeCellColorButton('purple')} + selectedColor={board.getCellColor(selectedCell.x, selectedCell.y)} + /> + handleChangeCellColorButton(undefined)} + selectedColor={board.getCellColor(selectedCell.x, selectedCell.y)} + /> + + + )} + + ); +}; diff --git a/src/components/organisms/TurtleGraphics.tsx b/src/components/organisms/TurtleGraphics.tsx index 660cdb37..b9f5a83c 100644 --- a/src/components/organisms/TurtleGraphics.tsx +++ b/src/components/organisms/TurtleGraphics.tsx @@ -2,146 +2,318 @@ import { Box, Grid, GridItem } from '@chakra-ui/react'; import Image from 'next/image'; -import React, { useState } from 'react'; +import React, { useState, forwardRef, useImperativeHandle, useMemo } from 'react'; +import { Board } from '../../app/lib/Board'; import { Character } from '../../app/lib/Character'; -import { TurtleGraphicsCell } from '../../app/lib/TurtleGraphicsCell'; +import { solveProblem } from '../../app/lib/solveProblem'; +import type { CellColor, CharacterDirection, SelectedCell } from '../../types'; +import { TurtleGraphicsController } from '../molecules/TurtleGraphicsController'; // 原点(左上隅)の座標 -const ORIGIN_X = 1; -const ORIGIN_Y = 1; +export const ORIGIN_X = 1; +export const ORIGIN_Y = 1; + +export const GRID_COLUMNS = 12; +export const GRID_ROWS = 8; +export const GRID_SIZE = 40; interface TurtleGraphicsProps { - characters: Character[]; - gridColumns?: number; - gridRows?: number; - gridSize?: number; isEnableOperation?: boolean; + problemProgram: string; +} + +export interface TurtleGraphicsHandle { + reset(): void; + isCorrect(): boolean; } -export const TurtleGraphics: React.FC = ({ - characters: initialCharacters, - gridColumns: gridColumns = 12, - gridRows: gridRows = 8, - gridSize: gridSize = 40, - isEnableOperation: isEnableOperation = false, -}) => { - const [characters, setCharacters] = useState(initialCharacters); - const [cells] = useState( - Array.from({ length: gridColumns * gridRows }).map((_, index) => { - const x = (index % gridColumns) + ORIGIN_X; - const y = Math.floor(index / gridColumns) + ORIGIN_Y; - return new TurtleGraphicsCell(index, x, y, ''); - }) - ); - - const updateCharacter = (character: Character, updater: (char: Character) => void): void => { - setCharacters((prevCharacters) => - prevCharacters.map((prevCharacter) => { - if (prevCharacter.id === character.id) { - const updatedCharacter = new Character({ ...character }); - updater(updatedCharacter); - return updatedCharacter; +export const TurtleGraphics = forwardRef( + ({ isEnableOperation = false, problemProgram }, ref) => { + const [board, setBoard] = useState(new Board()); + const [selectedCharacter, setSelectedCharacter] = useState(); + const [selectedCell, setSelectedCell] = useState(); + const [dragging, setDragging] = useState(false); + + useImperativeHandle(ref, () => ({ + // 親コンポーネントから関数を呼び出せるようにする + reset, + isCorrect, + })); + + // // TODO: プログラムから盤面を生成する処理ができたら置き換える + const getInitialBoard = (): Board => { + return new Board(); + }; + + // TODO: プログラムから盤面を生成する処理ができたら置き換える + const getInitialCharacters = (): Character[] => { + return []; + }; + const getInitialCharactersResult = useMemo(() => getInitialCharacters(), []); + const [characters, setCharacters] = useState(getInitialCharactersResult); + + const updateCharacter = (updater: (char: Character) => void): void => { + if (!selectedCharacter) return; + + const updatedCharacter = new Character({ ...selectedCharacter }); + updater(updatedCharacter); + + setCharacters((prevCharacters) => + prevCharacters.map((prevCharacter) => { + if (prevCharacter.id === selectedCharacter.id) { + return updatedCharacter; + } + return prevCharacter; + }) + ); + setSelectedCharacter(updatedCharacter); + }; + + const reset = (): void => { + setBoard(getInitialBoard()); + setCharacters(getInitialCharacters()); + setSelectedCharacter(undefined); + setSelectedCell(undefined); + }; + + const isCorrect = (): boolean => { + const answer = solveProblem(problemProgram); + + // TODO: 正答を取得する処理ができたら置き換える + const correctCharacters = [answer.character]; + // 順番は関係なく、name, x, y, direction, color、penDownが一致していれば正解 + const isCorrectCharacters = correctCharacters.every((correctCharacter) => { + const character = characters.find((character) => character.name === correctCharacter.name); + + if (!character) return false; + + return ( + character.x === correctCharacter.x && + character.y === correctCharacter.y && + character.direction === correctCharacter.direction && + character.color === correctCharacter.color && + character.penDown === correctCharacter.penDown + ); + }); + + const correctBoard = answer.board; + // すべてのセルの色が一致していれば正解 + const isCorrectBoard = correctBoard.grid.every((rows, rowIndex) => + rows.every((column, columnIndex) => { + const cell = board.grid[rowIndex][columnIndex]; + return cell.color === column.color; + }) + ); + + return isCorrectCharacters && isCorrectBoard; + }; + + const handleClickCharacter = (character: Character): void => { + setSelectedCell(undefined); + setSelectedCharacter(character); + }; + + const handleClickCharacterMoveButton = (): void => { + setDragging(true); + }; + + const finishCharacterDragging = (): void => { + setDragging(false); + }; + + const handleCharacterDragging = (event: React.MouseEvent): void => { + if (selectedCharacter && dragging) { + const rect = event.currentTarget.getBoundingClientRect(); + let x = Math.floor((event.clientX - rect.left) / GRID_SIZE) + 1; + let y = Math.floor((event.clientY - rect.top) / GRID_SIZE) + 1; + + // 移動先の座標がマップ内に収まるように制御 + x = Math.max(ORIGIN_X, Math.min(x, ORIGIN_X + GRID_COLUMNS - 1)); + y = Math.max(ORIGIN_Y, Math.min(y, ORIGIN_Y + GRID_ROWS - 1)); + + setCharacters((prevCharacters) => + prevCharacters.map((prevCharacter) => { + if (prevCharacter.id === selectedCharacter.id) { + selectedCharacter.setPosition(x, y); + return selectedCharacter; + } + return prevCharacter; + }) + ); + } + }; + + const drawCharacterPath = (): void => { + if (!selectedCharacter || !selectedCharacter.penDown) return; + + board.updateGrid(selectedCharacter); + }; + + const handleClickCharacterMoveForwardButton = (): void => { + if (!selectedCharacter) return; + + if (selectedCharacter.canMoveForward()) { + drawCharacterPath(); + } + + updateCharacter((character) => { + character.moveForward(); + }); + }; + + const handleClickCharacterMoveBackButton = (): void => { + if (!selectedCharacter) return; + + if (selectedCharacter.canMoveBack()) { + drawCharacterPath(); + } + + updateCharacter((character) => { + character.moveBack(); + }); + }; + + const handleClickChangeCharacterDirectionButton = (direction: CharacterDirection): void => { + if (!selectedCharacter) return; + + updateCharacter((character) => { + if (direction === 'left') character.turnLeft(); + else if (direction === 'right') character.turnRight(); + }); + }; + + const handleClickChangeCharacterColorButton = (color: CellColor): void => { + if (!selectedCharacter) return; + + updateCharacter((character) => { + character.setColor(color); + }); + }; + + const handleClickCharacterPenUpButton = (): void => { + if (!selectedCharacter) return; + + updateCharacter((character) => { + character.upPen(); + }); + }; + + const handleClickCharacterPenDownButton = (): void => { + if (!selectedCharacter) return; + + updateCharacter((character) => { + character.putPen(); + }); + }; + + const handleAddCharacterButton = (): void => { + if (!selectedCell) return; + + board.setCellColor(selectedCell.x, selectedCell.y, undefined); + + const newCharacter = new Character({ + x: selectedCell.x + ORIGIN_X, + y: selectedCell.y + ORIGIN_Y, + path: [`${selectedCell.x},${selectedCell.y}`], + }); + + setCharacters((prevCharacters) => [...prevCharacters, newCharacter]); + setSelectedCharacter(newCharacter); + setSelectedCell(undefined); + }; + + const handleRemoveCharacterButton = (character: Character): void => { + setCharacters((prevCharacters) => prevCharacters.filter((prevCharacter) => prevCharacter.id !== character.id)); + setSelectedCharacter(undefined); + }; + + const handleClickCell = (x: number, y: number): void => { + setSelectedCharacter(undefined); + setSelectedCell({ x, y }); + }; + + const handleChangeCellColorButton = (color: CellColor): void => { + if (!selectedCell) return; + + setBoard((prevBoard) => { + const newBoard = new Board(); + for (const [y, rows] of prevBoard.grid.entries()) { + for (const [x, column] of rows.entries()) { + newBoard.setCellColor(x, y, column.color); + } } - return prevCharacter; - }) - ); - }; - - const handleMoveForward = (character: Character): void => { - updateCharacter(character, (updatedCharacter) => { - updatedCharacter.moveForward(gridColumns, gridRows); - }); - }; - - const handleMoveBack = (character: Character): void => { - updateCharacter(character, (updatedCharacter) => { - updatedCharacter.moveBack(gridColumns, gridRows); - }); - }; - - const handleTurnleft = (character: Character): void => { - updateCharacter(character, (updatedCharacter) => { - updatedCharacter.turnLeft(); - }); - }; - - const handleTurnRight = (character: Character): void => { - updateCharacter(character, (updatedCharacter) => { - updatedCharacter.turnRight(); - }); - }; - - const handlePutPen = (character: Character): void => { - updateCharacter(character, (updatedCharacter) => { - updatedCharacter.putPen(); - }); - }; - - const handleUpPen = (character: Character): void => { - updateCharacter(character, (updatedCharacter) => { - updatedCharacter.upPen(); - }); - }; - - return ( -
- - {cells.map((cell) => ( - - ))} - {characters.map((character) => ( - - - {character.name} + + {board.grid.map((columns, rowIndex) => + columns.map((g, columnIndex) => ( + handleClickCell(columnIndex, rowIndex)} + /> + )) + )} + {characters.map((character) => ( + handleClickCharacter(character)} + > + + {character.name} + - {character.name} - - ))} - - {isEnableOperation && - characters.map((character) => ( -
-
{character.name}
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
---
-
- ))} -
- ); -}; + ))} + + {isEnableOperation && ( + + )} + + ); + } +); + +TurtleGraphics.displayName = 'TurtleGraphics'; diff --git a/src/problems/problemData.ts b/src/problems/problemData.ts index 87d9a5fc..766e6f83 100644 --- a/src/problems/problemData.ts +++ b/src/problems/problemData.ts @@ -34,10 +34,6 @@ export function generateProgram(programId: ProgramId, languageId: LanguageId): s return programIdToLanguageIdToProgram[programId][languageId]; } -export function getDescription(programId: ProgramId): string { - return programIdToLanguageIdToDescription[programId]; -} - export function getExplanation(programId: ProgramId, languageId: LanguageId): string { return programIdToLanguageIdToExplanation[programId][languageId]; } @@ -77,15 +73,6 @@ public class Curve { }, }; -export const programIdToLanguageIdToDescription: Record = { - straight: ` -直線を描くプログラムです。 -`.trim(), - curve: ` -曲線を描くプログラムです。 -`.trim(), -}; - export const programIdToLanguageIdToExplanation: Record> = { straight: { js: ` diff --git a/src/types.ts b/src/types.ts index 00cd83ef..f573ec13 100644 --- a/src/types.ts +++ b/src/types.ts @@ -9,9 +9,13 @@ export interface LayoutProps { export type LayoutComponent = React.FC; -export type CellColor = 'red' | 'green' | 'blue'; +export type CellColor = 'red' | 'blue' | 'green' | 'yellow' | 'purple' | undefined; export type Cell = { - color: CellColor | undefined; + color: CellColor; +}; +export type SelectedCell = { + x: number; + y: number; }; export type History = { @@ -25,3 +29,5 @@ export type SolveProblemResult = { board: Board; histories: History[] | undefined; }; + +export type CharacterDirection = 'up' | 'down' | 'left' | 'right'; diff --git a/tests/solveProblem.test.ts b/tests/solveProblem.test.ts index 450ff170..f021d31f 100644 --- a/tests/solveProblem.test.ts +++ b/tests/solveProblem.test.ts @@ -44,18 +44,14 @@ test('Solve a problem', () => { // prettier-ignore expect(answer.board.grid).toEqual([ - [{ color: 'red' }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }], - [{ color: 'red' }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }], - [{ color: 'red' }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }], - [{ color: 'red' }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }], - [{ color: 'red' }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }], - [{ color: 'red' }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }], - [{ color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }], - [{ color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }], - [{ color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }], - [{ color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }], - [{ color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }], - [{ color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }], + [{ color: 'red' }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }], + [{ color: 'red' }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }], + [{ color: 'red' }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }], + [{ color: 'red' }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }], + [{ color: 'red' }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }], + [{ color: 'red' }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }], + [{ color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }], + [{ color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }, { color: undefined }], ]); expect(answer.histories).not.toBeFalsy(); expect(answer.histories?.at(-1)?.character.x).toEqual(1); diff --git a/yarn.lock b/yarn.lock index 7d0128ab..41df205e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4262,6 +4262,13 @@ __metadata: languageName: node linkType: hard +"@types/uuid@npm:^9": + version: 9.0.7 + resolution: "@types/uuid@npm:9.0.7" + checksum: b329ebd4f9d1d8e08d4f2cc211be4922d70d1149f73d5772630e4a3acfb5170c6d37b3d7a39a0412f1a56e86e8a844c7f297c798b082f90380608bf766688787 + languageName: node + linkType: hard + "@typescript-eslint/eslint-plugin@npm:6.18.1": version: 6.18.1 resolution: "@typescript-eslint/eslint-plugin@npm:6.18.1" @@ -11509,6 +11516,7 @@ __metadata: "@types/node": "npm:20.11.0" "@types/react-dom": "npm:18.2.18" "@types/react-syntax-highlighter": "npm:^15" + "@types/uuid": "npm:^9" "@typescript-eslint/eslint-plugin": "npm:6.18.1" "@typescript-eslint/parser": "npm:6.18.1" "@willbooster/eslint-config-next": "npm:1.1.0" @@ -11547,6 +11555,7 @@ __metadata: supertokens-node: "npm:16.7.1" supertokens-web-js: "npm:0.8.0" typescript: "npm:5.3.3" + uuid: "npm:9.0.1" vitest: "npm:1.2.0" zod: "npm:3.22.4" zod-form-data: "npm:2.0.2" @@ -11949,6 +11958,15 @@ __metadata: languageName: node linkType: hard +"uuid@npm:9.0.1": + version: 9.0.1 + resolution: "uuid@npm:9.0.1" + bin: + uuid: dist/bin/uuid + checksum: 1607dd32ac7fc22f2d8f77051e6a64845c9bce5cd3dd8aa0070c074ec73e666a1f63c7b4e0f4bf2bc8b9d59dc85a15e17807446d9d2b17c8485fbc2147b27f9b + languageName: node + linkType: hard + "uuid@npm:^3.2.1": version: 3.4.0 resolution: "uuid@npm:3.4.0"