diff --git a/src/app/(withAuth)/courses/[courseId]/[languageId]/[programId]/Variables.tsx b/src/app/(withAuth)/courses/[courseId]/[languageId]/[programId]/Variables.tsx index 724ef70b..8e56f265 100644 --- a/src/app/(withAuth)/courses/[courseId]/[languageId]/[programId]/Variables.tsx +++ b/src/app/(withAuth)/courses/[courseId]/[languageId]/[programId]/Variables.tsx @@ -25,10 +25,6 @@ export const dirCharToJapanese = { W: '左', }; -const penStateJapanese = (penDown: boolean): string => { - return penDown ? 'おいている' : 'あげている'; -}; - export const Variables: React.FC = ({ traceItemVars }) => { const characterVars = []; const otherVars = []; @@ -51,7 +47,6 @@ export const Variables: React.FC = ({ traceItemVars }) => { 変数名 線の色 向き - ペンの状態 @@ -62,7 +57,6 @@ export const Variables: React.FC = ({ traceItemVars }) => { {dirCharToJapanese[variable.value.dir as keyof typeof dirCharToJapanese]} - {penStateJapanese(variable.value.pen)} ))} diff --git a/src/components/molecules/TurtleGraphicsController.tsx b/src/components/molecules/TurtleGraphicsController.tsx index d017d975..111b9dff 100644 --- a/src/components/molecules/TurtleGraphicsController.tsx +++ b/src/components/molecules/TurtleGraphicsController.tsx @@ -1,8 +1,10 @@ 'use client'; import React from 'react'; +import { FaArrowRotateRight, FaArrowRotateLeft, FaTrashCan } from 'react-icons/fa6'; -import { Box, Button, HStack, VStack } from '../../infrastructures/useClient/chakra'; +import { TURTLE_GRAPHICS_GRID_ROWS as GRID_ROWS, TURTLE_GRAPHICS_GRID_SIZE as GRID_SIZE } from '../../constants'; +import { Box, Button, HStack, IconButton, VStack } from '../../infrastructures/useClient/chakra'; import type { CharacterTrace } from '../../problems/traceProgram'; import type { SelectedCell } from '../../types'; @@ -15,16 +17,12 @@ interface TurtleGraphicsControllerProps { handleClickCharacterTurnRightButton: () => void; handleClickCharacterMoveForwardButton: () => void; handleClickCharacterMoveBackwardButton: () => void; - handleClickCharacterPenUpButton: () => void; - handleClickCharacterPenDownButton: () => void; } export const TurtleGraphicsController: React.FC = ({ handleAddCharacterButton, handleClickCharacterMoveBackwardButton, handleClickCharacterMoveForwardButton, - handleClickCharacterPenDownButton, - handleClickCharacterPenUpButton, handleClickCharacterTurnLeftButton, handleClickCharacterTurnRightButton, handleRemoveCharacterButton, @@ -32,34 +30,50 @@ export const TurtleGraphicsController: React.FC = selectedCharacter, }) => { return ( - + {selectedCharacter && ( - <> + - - + } + onClick={() => handleClickCharacterTurnLeftButton()} + /> + } + onClick={() => handleClickCharacterTurnRightButton()} + /> - - - - - + - + } + onClick={() => handleRemoveCharacterButton(selectedCharacter)} + /> - + )} {selectedCell && ( - + diff --git a/src/components/organisms/TurtleGraphics.tsx b/src/components/organisms/TurtleGraphics.tsx index fdd2fbb1..88995c80 100644 --- a/src/components/organisms/TurtleGraphics.tsx +++ b/src/components/organisms/TurtleGraphics.tsx @@ -1,6 +1,7 @@ 'use client'; import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useState } from 'react'; +import { FaArrowRotateLeft, FaArrowRotateRight, FaTrashCan } from 'react-icons/fa6'; import { TURTLE_GRAPHICS_DEFAULT_COLOR as DEFAULT_COLOR, @@ -8,7 +9,7 @@ import { TURTLE_GRAPHICS_GRID_ROWS as GRID_ROWS, TURTLE_GRAPHICS_GRID_SIZE as GRID_SIZE, } from '../../constants'; -import { Box, Grid, GridItem, Image } from '../../infrastructures/useClient/chakra'; +import { Box, Button, Grid, GridItem, HStack, IconButton, Image, VStack } from '../../infrastructures/useClient/chakra'; import type { Problem } from '../../problems/generateProblem'; import { type CharacterTrace, charToColor, type TraceItem } from '../../problems/traceProgram'; import type { ColorChar, SelectedCell } from '../../types'; @@ -148,9 +149,7 @@ export const TurtleGraphics = forwardRef { - if (!selectedCharacter) return; - - selectedCharacter.pen = false; - updateCharacters(selectedCharacter); - }; - - const handleClickCharacterPenDownButton = (): void => { - if (!selectedCharacter) return; - - selectedCharacter.pen = true; - updateCellColor(selectedCharacter.color as ColorChar, selectedCharacter.x, selectedCharacter.y); - updateCharacters(selectedCharacter); - }; - const handleAddCharacterButton = (): void => { if (!selectedCell) return; @@ -215,7 +197,6 @@ export const TurtleGraphics = forwardRef [...prevCharacters, newTurtle]); @@ -248,67 +229,90 @@ export const TurtleGraphics = forwardRef - - {[...board] - .reverse() - .map((columns, rowIndex) => - columns.map((color, columnIndex) => ( - handleClickCell(columnIndex, GRID_ROWS - rowIndex - 1)} - onContextMenu={(e) => handleContextMenu(e, columnIndex, GRID_ROWS - rowIndex - 1)} - /> - )) - )} - {characters.map((character) => ( - handleClickCharacter(character)} - onContextMenu={(e) => handleContextMenu(e, character.x, character.y)} - > - - {'character' - - - ))} - - {isEnableOperation && ( - + + {selectedCharacter && ( + + } + onClick={() => handleClickCharacterTurnLeftButton()} + /> + } + onClick={() => handleClickCharacterTurnRightButton()} + /> + + + {/* */} + } + onClick={() => handleRemoveCharacterButton(selectedCharacter)} + /> + )} - + + + {[...board] + .reverse() + .map((columns, rowIndex) => + columns.map((color, columnIndex) => ( + handleClickCell(columnIndex, GRID_ROWS - rowIndex - 1)} + onContextMenu={(e) => handleContextMenu(e, columnIndex, GRID_ROWS - rowIndex - 1)} + /> + )) + )} + {characters.map((character) => ( + handleClickCharacter(character)} + onContextMenu={(e) => handleContextMenu(e, character.x, character.y)} + > + + {'character' + + + ))} + {isEnableOperation && ( + + )} + + + ); } ); diff --git a/src/problems/traceProgram.ts b/src/problems/traceProgram.ts index 68e0e703..41136be5 100644 --- a/src/problems/traceProgram.ts +++ b/src/problems/traceProgram.ts @@ -16,8 +16,6 @@ export interface CharacterTrace { color: string; /** 方向を表現する1文字 */ dir: string; - /** ペンが床に触れているか否か */ - pen: boolean; } export interface TraceItem { @@ -61,14 +59,11 @@ export function traceProgram(instrumented: string, rawDisplayProgram: string, la let replaced = false; const newLine = line .replace(/for\s*\(([^;]*);\s*([^;]*);/, (_, init, cond) => `for (${init}; checkForCond(${cond}, ${statementId});`) - .replaceAll( - /\.(set|forward|penDown|penUp|turnRight|turnLeft)\(([^\n;]*)\)(;|\)\s*{)/g, - (_, methodName, args, tail) => { - replaced = true; - const delimiter = args === '' ? '' : ', '; - return `.${methodName}(${args}${delimiter}${statementId})${tail}`; - } - ) + .replaceAll(/\.(set|forward|turnRight|turnLeft)\(([^\n;]*)\)(;|\)\s*{)/g, (_, methodName, args, tail) => { + replaced = true; + const delimiter = args === '' ? '' : ', '; + return `.${methodName}(${args}${delimiter}${statementId})${tail}`; + }) .replace(/\/\/\s*CP.*/, () => { checkpointSids.push(statementId); return ''; @@ -126,7 +121,6 @@ class Character { this.y = y; this.color = color; this.dir = 'N'; - this.pen = true; board[this.y][this.x] = this.color; } forward(sid) { @@ -136,15 +130,7 @@ class Character { if (this.x < 0 || ${GRID_COLUMNS} <= this.x || this.y < 0 || ${GRID_ROWS} <= this.y) { throw new Error('Out of bounds'); } - if (this.pen) board[this.y][this.x] = this.color; - addTrace(sid); - } - penDown(sid) { - this.pen = true; - addTrace(sid); - } - penUp(sid) { - this.pen = false; + board[this.y][this.x] = this.color; addTrace(sid); } turnRight(sid) { diff --git a/tests/traceCode.test.ts b/tests/traceCode.test.ts index 4696e216..ec277c33 100644 --- a/tests/traceCode.test.ts +++ b/tests/traceCode.test.ts @@ -12,7 +12,6 @@ const defaultCharacter: CharacterTrace = { y: cy, color: '#', dir: 'N', - pen: true, }; test.each([