Skip to content

Commit

Permalink
refactor: remove checkpoints (#142)
Browse files Browse the repository at this point in the history
  • Loading branch information
exKAZUu authored Sep 25, 2024
1 parent 42f8398 commit 8288f3a
Show file tree
Hide file tree
Showing 23 changed files with 287 additions and 383 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
-- DropTable
PRAGMA foreign_keys=off;
DROP TABLE "ProblemSessionAnswer";
PRAGMA foreign_keys=on;

-- CreateTable
CREATE TABLE "ProblemSubmission" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"sessionId" INTEGER NOT NULL,
"problemType" TEXT NOT NULL,
"traceItemIndex" INTEGER NOT NULL,
"elapsedMilliseconds" INTEGER NOT NULL,
"isCorrect" BOOLEAN NOT NULL,
CONSTRAINT "ProblemSubmission_sessionId_fkey" FOREIGN KEY ("sessionId") REFERENCES "ProblemSession" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
);
4 changes: 2 additions & 2 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,12 @@ model ProblemSession {
elapsedMilliseconds Int @default(0)
completedAt DateTime?
answers ProblemSessionAnswer[]
submissions ProblemSubmission[]
@@index([userId, courseId, lectureId, problemId, completedAt])
}

model ProblemSessionAnswer {
model ProblemSubmission {
id Int @id @default(autoincrement())
createdAt DateTime @default(now())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,12 @@ const LecturePage: NextPage<Props> = async (props) => {
problemId: true,
completedAt: true,
elapsedMilliseconds: true,
answers: { select: { elapsedMilliseconds: true, isCorrect: true } },
submissions: { select: { elapsedMilliseconds: true, isCorrect: true } },
},
where: { userId: session.superTokensUserId, courseId: props.params.courseId, lectureId: props.params.lectureId },
});

return (
<Lecture
currentUserCompletedProblemIdSet={
new Set(currentUserProblemSessions.filter((s) => s.completedAt).map((s) => s.problemId))
}
currentUserProblemSessions={currentUserProblemSessions}
lectureIndex={lectureIndex}
params={props.params}
/>
);
return <Lecture lectureIndex={lectureIndex} params={props.params} problemSessions={currentUserProblemSessions} />;
};

export default LecturePage;
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
'use client';

import type { ProblemSession, ProblemSessionAnswer } from '@prisma/client';
import type { ProblemSession, ProblemSubmission } from '@prisma/client';
import NextLink from 'next/link';
import React from 'react';
import React, { useMemo } from 'react';
import { MdCheckCircle, MdCheckCircleOutline, MdOutlineVerified, MdVerified } from 'react-icons/md';

import {
Expand Down Expand Up @@ -35,18 +35,19 @@ import {
type Props = {
params: { courseId: CourseId; lectureId: string };
lectureIndex: number;
currentUserCompletedProblemIdSet: ReadonlySet<string>;
currentUserProblemSessions: (Pick<ProblemSession, 'problemId' | 'completedAt' | 'elapsedMilliseconds'> & {
answers: Pick<ProblemSessionAnswer, 'elapsedMilliseconds' | 'isCorrect'>[];
problemSessions: (Pick<ProblemSession, 'problemId' | 'completedAt' | 'elapsedMilliseconds'> & {
submissions: Pick<ProblemSubmission, 'elapsedMilliseconds' | 'isCorrect'>[];
})[];
};

export const Lecture: React.FC<Props> = (props) => {
const lectureProblemIds = courseIdToLectureIndexToProblemIds[props.params.courseId][props.lectureIndex];
const completedProblemIdSet = useMemo(
() => new Set(props.problemSessions.filter((s) => s.completedAt).map((s) => s.problemId)),
[props.problemSessions]
);

const completedProblemCount = lectureProblemIds.filter((problemId) =>
props.currentUserCompletedProblemIdSet.has(problemId)
).length;
const lectureProblemIds = courseIdToLectureIndexToProblemIds[props.params.courseId][props.lectureIndex];
const completedProblemCount = lectureProblemIds.filter((problemId) => completedProblemIdSet.has(problemId)).length;
const isLessonCompleted = completedProblemCount >= lectureProblemIds.length;

return (
Expand Down Expand Up @@ -91,23 +92,21 @@ export const Lecture: React.FC<Props> = (props) => {
<Th w="0" />
<Th w="0" />
<Th isNumeric w="0">
初回不正解
初回の不正解
</Th>
<Th isNumeric w="0">
初回所要時間
初回の完了日時
</Th>
</Tr>
</Thead>

<Tbody>
{lectureProblemIds.map((problemId) => {
const firstSession = props.currentUserProblemSessions.find((s) => s.problemId === problemId);

const suspendedSession = props.currentUserProblemSessions.find(
const firstSession = props.problemSessions.find((s) => s.problemId === problemId);
const suspendedSession = props.problemSessions.find(
(s) => s.problemId === problemId && !s.completedAt
);

const isProblemCompleted = props.currentUserCompletedProblemIdSet.has(problemId);
const isProblemCompleted = completedProblemIdSet.has(problemId);

return (
<Tr key={problemId}>
Expand All @@ -132,21 +131,13 @@ export const Lecture: React.FC<Props> = (props) => {
</HStack>
</Td>
<Td isNumeric color="gray.600">
{firstSession?.answers.filter((a) => !a.isCorrect).length ?? 0}
{firstSession?.submissions.filter((a) => !a.isCorrect).length ?? 0}
<Box as="span" fontSize="xs" ms={1}>
</Box>
</Td>
<Td isNumeric color="gray.600">
{/* TODO: なぜ`firstSession?.elapsedMilliseconds`をそのまま表示しない実装になっているのか確認する。 */}
{typeof firstSession?.elapsedMilliseconds === 'number'
? Math.floor(
firstSession.answers.reduce((sum, answer) => sum + answer.elapsedMilliseconds, 0) / 1000
)
: 0}
<Box as="span" fontSize="xs" ms={1}>
</Box>
{firstSession?.completedAt?.toLocaleString() ?? '未完了'}
</Td>
</Tr>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,32 +34,32 @@ interface TurtleGraphicsProps {
isEditable?: boolean;
problem: Problem;
currentTraceItem?: TraceItem;
beforeTraceItem?: TraceItem;
previousTraceItem?: TraceItem;
}

export interface TurtleGraphicsHandle {
initialize(): void;
isPassed(): boolean;
isCorrect(): boolean;
}

export const BoardEditor = forwardRef<TurtleGraphicsHandle, TurtleGraphicsProps>(
({ beforeTraceItem, currentTraceItem, isEditable = false, problem }, ref) => {
({ currentTraceItem, isEditable = false, previousTraceItem, problem }, ref) => {
const [board, setBoard] = useState<ColorChar[][]>([]);
const [characters, setCharacters] = useState<(CharacterTrace & { key: string })[]>([]);
const [selectedCharacter, setSelectedCharacter] = useState<CharacterTrace & { key: string }>();
const [selectedCell, setSelectedCell] = useState<SelectedCell>();

const initialize = useCallback((): void => {
console.log('initialize:', problem, beforeTraceItem);
if (!problem || !beforeTraceItem) return;
console.log('initialize:', problem, previousTraceItem);
if (!problem || !previousTraceItem) return;

const initBoard = beforeTraceItem.board
const initBoard = previousTraceItem.board
.trim()
.split('\n')
.filter((line) => line.trim() !== '')
.map((line) => [...line.trim()]);

const variables = beforeTraceItem.vars;
const variables = previousTraceItem.vars;
const initCharacters = [];
const initOtherVars = [];
for (const key in variables) {
Expand All @@ -75,17 +75,17 @@ export const BoardEditor = forwardRef<TurtleGraphicsHandle, TurtleGraphicsProps>
setCharacters(initCharacters || []);
setSelectedCharacter(undefined);
setSelectedCell(undefined);
}, [beforeTraceItem, problem]);
}, [previousTraceItem, problem]);

useImperativeHandle(ref, () => ({
// 親コンポーネントから関数を呼び出せるようにする
initialize,
isPassed,
isCorrect,
}));

useEffect(() => {
initialize();
}, [beforeTraceItem, initialize, problem]);
}, [previousTraceItem, initialize, problem]);

const updateCharacters = (character: CharacterTrace & { key: string }): void => {
setSelectedCharacter(character);
Expand All @@ -107,7 +107,7 @@ export const BoardEditor = forwardRef<TurtleGraphicsHandle, TurtleGraphicsProps>
});
};

const isPassed = (): boolean => {
const isCorrect = (): boolean => {
if (!currentTraceItem) return false;

const variables = currentTraceItem.vars;
Expand Down Expand Up @@ -336,7 +336,7 @@ export const BoardEditor = forwardRef<TurtleGraphicsHandle, TurtleGraphicsProps>
)}
{!selectedCharacter && selectedPosition && (
<Button colorScheme="brand" size="sm" variant="outline" onClick={() => void handleAddCharacterButton()}>
タートルを追加
タートルを配置
</Button>
)}
</VStack>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
TURTLE_GRAPHICS_BOARD_ROWS as ROWS,
} from '../../../../../../../../constants';
import { Box, Grid, GridItem, Img, keyframes } from '../../../../../../../../infrastructures/useClient/chakra';
import type { CharacterTrace, TraceItemVar } from '../../../../../../../../problems/traceProgram';
import type { CharacterTrace, TraceItemVariable } from '../../../../../../../../problems/traceProgram';
import { charToColor } from '../../../../../../../../problems/traceProgram';

const CHAR_TO_BG_COLOR = {
Expand Down Expand Up @@ -52,7 +52,7 @@ const focusRingKeyframes = keyframes({

type Props = BoxProps & {
board: string | undefined;
vars: TraceItemVar | undefined;
vars: TraceItemVariable | undefined;
focusedCell?: { x: number; y: number };
enableTransitions?: boolean;
onCellClick?: (x: number, y: number) => void;
Expand Down
Loading

0 comments on commit 8288f3a

Please sign in to comment.