미지수 괄호 문제 풀이 추가
This commit is contained in:
@@ -32,32 +32,39 @@ AI 에이전트(Claude Code 등)가 이 프로젝트에서 작업할 때 따라
|
||||
## 디렉토리 구조 및 파일 위치 규칙
|
||||
|
||||
```
|
||||
app/ # Next.js App Router 루트
|
||||
(game)/ # 게임 화면 라우트 그룹
|
||||
number-parentheses/ # 숫자 괄호 준비 화면
|
||||
select-type/ # 문제 유형 선택
|
||||
select-mode/ # 게임 모드 선택
|
||||
play/ # 문제 풀이
|
||||
app/ # Next.js App Router 루트
|
||||
(game)/ # 게임 화면 라우트 그룹
|
||||
number-parentheses/ # 숫자 괄호 준비 화면
|
||||
variable-parentheses/ # 미지수 괄호 준비 화면
|
||||
play/ # 미지수 괄호 풀이 화면
|
||||
select-mode/ # 게임 모드 선택 (미구현)
|
||||
play/ # 숫자 괄호 풀이 화면
|
||||
api/
|
||||
auth/ # NextAuth.js 핸들러
|
||||
problem/ # 문제 생성 API
|
||||
record/ # 풀이 기록 저장 API
|
||||
auth/ # NextAuth.js 핸들러
|
||||
problem/ # 문제 생성 API
|
||||
record/ # 풀이 기록 저장 API
|
||||
layout.tsx
|
||||
page.tsx # 시작 화면
|
||||
page.tsx # 시작 화면 (학습 내용 선택)
|
||||
components/
|
||||
math/ # KaTeX 수식 컴포넌트
|
||||
game/ # 게임 UI 컴포넌트
|
||||
math/ # KaTeX 수식 컴포넌트
|
||||
game/ # 게임 UI 컴포넌트
|
||||
lib/
|
||||
engine/ # 문제 생성 알고리즘 엔진
|
||||
prisma.ts # Prisma Client 싱글턴
|
||||
redis.ts # Redis Client 싱글턴
|
||||
engine/ # 문제 생성 알고리즘 엔진
|
||||
parenthesis-sign.ts # 숫자 괄호 엔진
|
||||
variable-parenthesis.ts # 미지수 괄호 엔진
|
||||
types.ts # 숫자 괄호 타입
|
||||
variable-types.ts # 미지수 괄호 타입
|
||||
input-device.ts # 입력 장치 감지 미디어 쿼리 상수
|
||||
prisma.ts # Prisma Client 싱글턴
|
||||
redis.ts # Redis Client 싱글턴
|
||||
store/
|
||||
gameStore.ts # Zustand 전역 게임 상태
|
||||
gameStore.ts # 숫자 괄호 Zustand 전역 상태
|
||||
variableGameStore.ts # 미지수 괄호 Zustand 전역 상태
|
||||
types/
|
||||
*.d.ts # 타입 선언이 없는 서드파티 모듈 보강
|
||||
*.d.ts # 타입 선언이 없는 서드파티 모듈 보강
|
||||
prisma/
|
||||
schema.prisma # MariaDB 모델 정의
|
||||
.gitea/workflows/deploy.yml # CI/CD 워크플로우
|
||||
schema.prisma # MariaDB 모델 정의
|
||||
.gitea/workflows/deploy.yml # CI/CD 워크플로우
|
||||
```
|
||||
|
||||
---
|
||||
@@ -78,7 +85,7 @@ prisma/
|
||||
|
||||
### 상태 관리
|
||||
|
||||
- 전역 게임 상태(점수, 진행도, 선택한 모드·유형)는 `store/gameStore.ts`의 Zustand store로 관리한다.
|
||||
- 숫자 괄호 전역 게임 상태는 `store/gameStore.ts`, 미지수 괄호 전역 게임 상태는 `store/variableGameStore.ts`의 Zustand store로 관리한다. 학습 유형별로 store를 분리한다.
|
||||
- 컴포넌트 내부의 로컬 상태는 `useState`를 사용한다.
|
||||
- Zustand selector 안에서 매번 새 객체·배열을 반환하는 함수(`score()` 등)를 호출하지 않는다. 필요한 파생값은 구독한 state를 기준으로 컴포넌트 내부에서 계산하거나 안정적인 selector로 분리한다.
|
||||
- store에는 세션 원본 상태와 상태 변경 action을 우선 두고, 렌더링 전용 파생값은 컴포넌트 또는 별도 순수 유틸에서 계산한다.
|
||||
@@ -93,18 +100,28 @@ prisma/
|
||||
### 접근성 / 키보드 조작
|
||||
|
||||
- 문제 풀이 화면은 키보드만으로 진행할 수 있어야 한다.
|
||||
- 문제 풀이 화면은 모든 항을 하나의 공유 input으로 입력한다.
|
||||
- 정답·오답 피드백이 표시되면 다음 진행 버튼에 focus를 둔다.
|
||||
- 최종 결과 화면이 표시되면 다시 시작 버튼에 focus를 둔다.
|
||||
- 아이콘이나 기호만으로 상태를 표시할 때는 `aria-label`, `sr-only` 텍스트 등으로 의미를 함께 제공한다.
|
||||
|
||||
#### 숫자 괄호 풀이 화면 (`/play`)
|
||||
|
||||
- 모든 항을 하나의 공유 input으로 입력한다.
|
||||
- input 아래에는 각 항의 입력값 버튼을 버튼 그룹으로 표시한다. 현재 입력 중인 항은 `aria-pressed`로 표시하고, 비어 있는 항은 `?`로 표시한다.
|
||||
- 첫째 항에서 Enter를 누르면 같은 input이 둘째 항 입력으로 전환된다.
|
||||
- 둘째 항에서 Enter를 누르면 제출 동작을 실행한다. 별도 제출 버튼이 없어도 form submit 흐름이 유지되어야 한다.
|
||||
- 터치 기반 입력 환경에서는 input focus 시 커스텀 숫자 키패드를 표시한다. 키패드는 숫자, `+/-`, `.`, `⌫`, `↵` 버튼을 제공한다.
|
||||
- 마우스/트랙패드처럼 hover 가능한 정밀 포인터가 있는 환경은 물리 키보드 사용 환경으로 간주하고 커스텀 숫자 키패드를 숨긴다. 웹 표준 API로 물리 키보드 연결 여부 자체를 안정적으로 판별할 수 없으므로 해상도 기준으로 분기하지 않는다.
|
||||
- 마우스/트랙패드처럼 hover 가능한 정밀 포인터가 있는 환경은 물리 키보드 사용 환경으로 간주하고 커스텀 숫자 키패드를 숨긴다. 웹 표준 API로 물리 키보드 연결 여부 자체를 안정적으로 판별할 수 없으므로 해상도 기준으로 분기하지 않는다. (`lib/input-device.ts`의 `DESKTOP_INPUT_DEVICE_QUERY` 사용)
|
||||
- 입력 중에는 `-`, `1.` 같은 임시 값을 허용할 수 있지만 제출 시에는 정상적인 양의 실수 또는 음의 실수 표현만 통과시킨다.
|
||||
- 문제 풀이 화면 최초 진입 시 모바일 키보드를 강제로 열지 않는다. 사용자가 input을 직접 focus하거나 피드백 후 다음 문제로 넘어갈 때 input에 focus를 둔다.
|
||||
- 터치 기반 입력 환경에서 input focus 시 `span.katex` 상단이 브라우저 화면 상단에 오도록 조정한다.
|
||||
- 정답·오답 피드백이 표시되면 다음 진행 버튼에 focus를 둔다.
|
||||
- 최종 결과 화면이 표시되면 다시 시작 버튼에 focus를 둔다.
|
||||
- 아이콘이나 기호만으로 상태를 표시할 때는 `aria-label`, `sr-only` 텍스트 등으로 의미를 함께 제공한다.
|
||||
|
||||
#### 미지수 괄호 풀이 화면 (`/variable-parentheses/play`)
|
||||
|
||||
- 답을 직접 입력하지 않는다. 각 항의 보기 버튼 중에서 선택한다.
|
||||
- 첫째 항 선택 후 자동으로 둘째 항 보기로 focus가 이동한다.
|
||||
- 두 항을 모두 선택하면 `정답 확인` 버튼에 focus가 이동하고 버튼이 활성화된다.
|
||||
- 선택된 보기 버튼은 `aria-pressed`로 표시한다.
|
||||
|
||||
### API / 백엔드
|
||||
|
||||
@@ -117,9 +134,14 @@ prisma/
|
||||
|
||||
- 문제 생성 로직은 `lib/engine/` 하위에 위치한다.
|
||||
- 문제는 AI 호출 없이 알고리즘으로 생성한다. 외부 AI API를 문제 생성에 사용하지 않는다.
|
||||
- 미지수의 계수는 항상 정수이어야 한다.
|
||||
- 생성 파라미터: 숫자 자릿수, 괄호 깊이(`()` / `(){}` / `(){}[]`), 괄호 개수(1–3), 미지수(없음/x/x,y/x,y,z).
|
||||
- 계수는 항상 정수이어야 한다.
|
||||
- 문제 세션에서 중복을 방지할 때는 랜덤 id가 아니라 수학적 문제 조건을 나타내는 안정적인 key를 기준으로 한다.
|
||||
- 모든 엔진은 전체 가능한 시드 목록을 모듈 로드 시 한 번 생성(`createAllProblemSeeds`)하고, 세션 생성 시 셔플 후 슬라이스하는 방식으로 중복 없이 출제한다.
|
||||
- 숫자 괄호 엔진: `lib/engine/parenthesis-sign.ts` / 타입: `lib/engine/types.ts`
|
||||
- 미지수 괄호 엔진: `lib/engine/variable-parenthesis.ts` / 타입: `lib/engine/variable-types.ts`
|
||||
- 괄호 안 두 항 중 정확히 하나가 `정수 × x` 항이다.
|
||||
- 각 항의 보기는 정답 계수의 절대값 기준 음수/양수 두 개를 셔플해 제공한다.
|
||||
- 채점은 choice id 기반으로 수행한다.
|
||||
|
||||
---
|
||||
|
||||
@@ -147,33 +169,34 @@ NEXTAUTH_SECRET=your-secret
|
||||
|
||||
## 게임 도메인 컨텍스트
|
||||
|
||||
### 문제 유형
|
||||
### 학습 유형
|
||||
|
||||
1. **괄호 음수 분배**: 괄호 앞 음수 곱셈 시 괄호 내 부호 변경 (예: `-2 × (3 - 6)`)
|
||||
2. **이항 부호 변경**: 등식의 항을 이항할 때 부호 반전 (예: `3x - 5y + 8 = -2x + 2y - 2`)
|
||||
| 유형 | 상태 | 라우트 | 답변 방식 |
|
||||
|---|---|---|---|
|
||||
| 숫자 괄호 풀기 | 구현 완료 | `/number-parentheses` → `/play` | 직접 입력 |
|
||||
| 미지수 괄호 풀기 | 구현 완료 | `/variable-parentheses` → `/variable-parentheses/play` | 보기 선택 |
|
||||
| 분수 괄호 풀기 | 미구현 | — | — |
|
||||
| 실수 괄호 풀기 | 미구현 | — | — |
|
||||
|
||||
### 게임 모드
|
||||
|
||||
| 모드 | 설명 |
|
||||
|---|---|
|
||||
| 스피드 퀴즈 | 제한 시간 내 최대 문제 풀기, Redis Sorted Set 기반 실시간 점수판 |
|
||||
| 일반 풀이 | 시간 제한 없음, 틀린 유형 반복 출제 |
|
||||
| 스피드 퀴즈 | 제한 시간 내 최대 문제 풀기, Redis Sorted Set 기반 실시간 점수판 (미구현) |
|
||||
| 일반 풀이 | 시간 제한 없음, 틀린 유형 반복 출제 (미구현) |
|
||||
|
||||
### 화면 흐름
|
||||
|
||||
```
|
||||
학습 내용 선택 → 숫자 괄호 준비 → 문제 풀이 → 결과 및 기록
|
||||
학습 내용 선택(/) → 준비 화면 → 문제 풀이 → 결과
|
||||
```
|
||||
|
||||
- 시작 화면(`/`)은 학습 내용 선택 화면이다.
|
||||
- 현재 활성 학습 내용은 `숫자 괄호 풀기`이며 `/number-parentheses`로 이동한다.
|
||||
- `분수 괄호 풀기`, `실수 괄호 풀기`, `미지수 괄호 풀기`는 준비 중 항목으로 disabled 상태로 표시한다.
|
||||
- 숫자 괄호 준비 화면(`/number-parentheses`)은 문제 수 `[5] [10]` 선택 버튼 그룹을 제공하고 기본값은 `10`이다.
|
||||
- 숫자 괄호 준비 화면은 괄호 종류 `()`, `{}`, `[]` 버튼 그룹을 제공한다. 현재는 `()`만 선택 가능하고 `{}`, `[]`는 disabled 상태로 표시한다.
|
||||
- 준비 화면의 `연습 시작`은 Zustand 세션을 초기화하고 `/play?count=N`으로 이동한다.
|
||||
- 문제 풀이 화면은 URL의 `count` 쿼리와 Zustand의 선택 문제 수를 동기화한다. 허용 문제 수는 `5`, `10`이며 유효하지 않은 값은 `10`으로 처리한다.
|
||||
- 정답·오답 피드백은 `계산식 = 내가 입력한 답` 형식으로 표시한다. 정답은 `○`, 오답은 붉은색 입력값과 `×`, 굵은 정답값을 함께 보여준다.
|
||||
- 최종 결과 화면은 지금까지 푼 문제를 `문제 = 내가 입력한 답` 형식으로 나열하고, 피드백 화면과 같은 정답·오답 색상 및 기호 규칙을 사용한다.
|
||||
- 시작 화면(`/`)은 학습 내용 선택 화면이다. `숫자 괄호 풀기`, `미지수 괄호 풀기`가 활성화되어 있고 분수/실수 괄호는 disabled 상태다.
|
||||
- 준비 화면은 문제 수 `[5] [10]` 버튼 그룹과 괄호 종류 버튼 그룹을 제공한다. 기본값은 `10`이며, 현재는 `()`만 선택 가능하다.
|
||||
- 준비 화면의 `연습 시작`은 Zustand 세션을 초기화하고 풀이 화면으로 이동한다.
|
||||
- 풀이 화면은 URL의 `count` 쿼리와 Zustand의 선택 문제 수를 동기화한다. 허용 문제 수는 `5`, `10`이며 유효하지 않은 값은 `10`으로 처리한다.
|
||||
- 정답·오답 피드백은 `계산식 = 내가 입력한(고른) 답` 형식으로 표시한다. 정답은 `○`, 오답은 붉은색 답과 `×`, 굵은 정답값을 함께 보여준다.
|
||||
- 최종 결과 화면은 지금까지 푼 문제를 `문제 = 내가 입력한(고른) 답` 형식으로 나열하고, 피드백 화면과 같은 정답·오답 색상 및 기호 규칙을 사용한다.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user