From 0dc14384503c67e84b290de9f022ea88470e1380 Mon Sep 17 00:00:00 2001 From: Hikaru Ishiwata <145771843+hishiwat@users.noreply.github.com> Date: Thu, 26 Sep 2024 14:53:05 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A4=89=E6=95=B0=E6=83=85=E5=A0=B1?= =?UTF-8?q?=E3=82=92=E6=93=8D=E4=BD=9C=E7=9B=A4=E9=9D=A2=E3=81=AE=E4=B8=8B?= =?UTF-8?q?=E3=81=AB=E7=A7=BB=E5=8B=95=E3=81=99=E3=82=8B=20(#157)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Sakamoto, Kazunori Co-authored-by: Sakamoto, Kazunori --- .../problems/[problemId]/BoardEditor.tsx | 43 +++++- .../problems/[problemId]/ProblmBody.tsx | 134 ++++++++---------- .../problems/[problemId]/Variables.tsx | 6 +- .../problems/[problemId]/pageOnClient.tsx | 18 ++- 4 files changed, 109 insertions(+), 92 deletions(-) diff --git a/src/app/(withAuth)/courses/[courseId]/lectures/[lectureId]/problems/[problemId]/BoardEditor.tsx b/src/app/(withAuth)/courses/[courseId]/lectures/[lectureId]/problems/[problemId]/BoardEditor.tsx index 25676647..e4020bf9 100644 --- a/src/app/(withAuth)/courses/[courseId]/lectures/[lectureId]/problems/[problemId]/BoardEditor.tsx +++ b/src/app/(withAuth)/courses/[courseId]/lectures/[lectureId]/problems/[problemId]/BoardEditor.tsx @@ -17,6 +17,7 @@ import { HStack, Icon, IconButton, + Spacer, VStack, } from '../../../../../../../../infrastructures/useClient/chakra'; import type { Problem } from '../../../../../../../../problems/generateProblem'; @@ -33,15 +34,15 @@ interface TurtleGraphicsProps { problem: Problem; currentTraceItemIndex: number; previousTraceItemIndex: number; + handleClickSubmitButton: () => Promise; } export interface TurtleGraphicsHandle { - initialize(): void; isCorrect(): boolean; } export const BoardEditor = forwardRef( - ({ currentTraceItemIndex, previousTraceItemIndex, problem }, ref) => { + ({ currentTraceItemIndex, handleClickSubmitButton, previousTraceItemIndex, problem }, ref) => { const [board, updateBoard] = useImmer([]); const [turtles, updateTurtles] = useImmer([]); const [selectedCell, setSelectedCell] = useState(); @@ -51,7 +52,6 @@ export const BoardEditor = forwardRef const initialize = useCallback( (keepSelectedCell = false): void => { - console.log('initialize:', problem, previousTraceItem); const initialBoard = parseBoard(previousTraceItem.board); updateBoard(initialBoard); updateTurtles(Object.values(previousTraceItem.vars ?? {}).filter(isTurtleTrace)); @@ -61,7 +61,6 @@ export const BoardEditor = forwardRef ); useImperativeHandle(ref, () => ({ - initialize, isCorrect, })); @@ -158,9 +157,11 @@ export const BoardEditor = forwardRef const selectedPosition = selectedCell ? { x: selectedCell.x, y: selectedCell.y } : undefined; + useShortcutKeys(handleClickSubmitButton); + return ( -
+
cells.join('')).join('\n')} @@ -263,12 +264,30 @@ export const BoardEditor = forwardRef )} + + + + ); } ); +BoardEditor.displayName = 'BoardEditor'; + function canPutTurtle(turtlesTraces: TurtleTrace[], x: number, y: number): boolean { return 0 <= x && x < COLUMNS && 0 <= y && y < ROWS && !turtlesTraces.some((t) => t.x === x && t.y === y); } @@ -281,4 +300,16 @@ function parseBoard(boardString: string): ColorChar[][] { .map((line) => [...line.trim()]) as ColorChar[][]; } -BoardEditor.displayName = 'BoardEditor'; +function useShortcutKeys(handleClickAnswerButton: () => Promise): void { + useEffect(() => { + const handleKeyDown = (event: KeyboardEvent): void => { + if (event.key === 'Enter') { + event.preventDefault(); + void handleClickAnswerButton(); + } + }; + window.addEventListener('keydown', handleKeyDown); + return () => window.removeEventListener('keydown', handleKeyDown); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); +} diff --git a/src/app/(withAuth)/courses/[courseId]/lectures/[lectureId]/problems/[problemId]/ProblmBody.tsx b/src/app/(withAuth)/courses/[courseId]/lectures/[lectureId]/problems/[problemId]/ProblmBody.tsx index ba3b51a3..539254c1 100644 --- a/src/app/(withAuth)/courses/[courseId]/lectures/[lectureId]/problems/[problemId]/ProblmBody.tsx +++ b/src/app/(withAuth)/courses/[courseId]/lectures/[lectureId]/problems/[problemId]/ProblmBody.tsx @@ -14,6 +14,7 @@ import { Box, Button, Card, + Flex, Heading, HStack, Tag, @@ -131,46 +132,48 @@ export const ProblemBody: React.FC = (props) => { return ( <> - - - - - 問題 - {problemType === 'step' && ( - - ステップ実行モード - - )} - {problemType === 'executionResult' && ( - - - - )} - - - - - {problemType === 'executionResult' ? ( - 'プログラムを実行した後' - ) : ( - <> - - {props.problem.sidToLineIndex.get(props.problem.traceItems[currentTraceItemIndex].sid)}行目 - - を実行した後 - + + + + + + 問題 + {problemType === 'step' && ( + + ステップ実行モード + + )} + {problemType === 'executionResult' && ( + + + )} + + + + + {problemType === 'executionResult' ? ( + 'プログラムを実行した後' + ) : ( + <> + + {props.problem.sidToLineIndex.get(props.problem.traceItems[currentTraceItemIndex].sid)}行目 + + を実行した後 + + )} + + の盤面を作成し、提出ボタンを押してください。 - の盤面を作成し、提出ボタンを押してください。 - + = (props) => { /> - {problemType !== 'executionResult' && - props.problem.sidToLineIndex.get(props.problem.traceItems[previousTraceItemIndex].sid) && ( - + + + + + + {problemType !== 'executionResult' && + props.problem.sidToLineIndex.get(props.problem.traceItems[previousTraceItemIndex].sid) && ( + + - 参考: {props.problem.sidToLineIndex.get(props.problem.traceItems[previousTraceItemIndex].sid)}行目 @@ -213,38 +227,12 @@ export const ProblemBody: React.FC = (props) => { isTurtleTrace )} /> - - - )} - - - - - - - - - - - + + + + + )} = ({ traceItemVars }) => { return ( } mx={-5}> - + - + {characterVars?.map((variable) => ( + - ))} diff --git a/src/app/(withAuth)/courses/[courseId]/lectures/[lectureId]/problems/[problemId]/pageOnClient.tsx b/src/app/(withAuth)/courses/[courseId]/lectures/[lectureId]/problems/[problemId]/pageOnClient.tsx index 06b6e027..bb861535 100644 --- a/src/app/(withAuth)/courses/[courseId]/lectures/[lectureId]/problems/[problemId]/pageOnClient.tsx +++ b/src/app/(withAuth)/courses/[courseId]/lectures/[lectureId]/problems/[problemId]/pageOnClient.tsx @@ -10,7 +10,7 @@ import { MIN_INTERVAL_MS_OF_ACTIVE_EVENTS, } from '../../../../../../../../constants'; import { backendTrpcReact } from '../../../../../../../../infrastructures/trpcBackend/client'; -import { Flex, Heading, HStack, Link, Text, VStack } from '../../../../../../../../infrastructures/useClient/chakra'; +import { Heading, HStack, Link, Text, VStack } from '../../../../../../../../infrastructures/useClient/chakra'; import type { Problem } from '../../../../../../../../problems/generateProblem'; import type { CourseId, ProblemId } from '../../../../../../../../problems/problemData'; import { courseIdToLectureIds, courseIdToName, problemIdToName } from '../../../../../../../../problems/problemData'; @@ -79,15 +79,13 @@ export const ProblemPageOnClient: React.FC = (props) => { {problemIdToName[props.params.problemId]} - - - + ); };
タートルの変数名線の色 向き線の色
{variable.key}{dirCharToJapanese[variable.value.dir as keyof typeof dirCharToJapanese]} = ({ traceItemVars }) => { w="1.5em" /> {dirCharToJapanese[variable.value.dir as keyof typeof dirCharToJapanese]}