Files
hyungi_document_server/migrations/222_study_question_progress.sql
T
Hyungi Ahn e5982ebde4 feat(study): Phase 1 학습 루프 데이터 계층 — progress 캐시 + finalize + review API
vision (풀이 → 확인 → 학습 → 복습 → 다음 풀이 가중치) 의 데이터 계층.

데이터 모델 (migrations 222~225):
- study_question_progress 테이블 — user × topic × question 단위 현재 상태 캐시
  - 마지막 시도: last_outcome, last_attempted_at, last_attempt_id
  - 검토 상태: last_reviewed_at
  - 복습 큐: due_at, review_stage
  - 패턴 분류 (derived): pattern_state, pattern_updated_at, pattern_window_attempts
- 3 partial idx (due / topic_pattern / pending_review) — 탭별 빠른 조회

패턴 분류 (services/study/learning_pattern.py):
- 7 분류: unattempted/unsure/chronic_wrong/regressed/recovered/stable/unstable
- 윈도우 = 최근 3회 + 과거 correct/wrong 존재 여부
- chronic_wrong > regressed > recovered 우선순위 (보수적 학습)
- 가드: wrong 1회만으로 regressed 안 됨 (이전 correct 이력 필요)
- stable 은 3 연속 correct 부터

세션 종료 집계 (services/study/session_finalize.py):
- attempts append-only 원본 보존, progress upsert 만
- 마지막 attempt 직후 finalize hook 자동 발동
- finalize 는 last_* + pattern_state 만 갱신, due_at 미진입 문제는 NULL 유지
- 이미 due_at 박힌 문제는 finalize 가 stage 갱신 (correct → +1 / wrong → 리셋)

API (api/study_question_progress.py):
- POST /study-topics/{tid}/questions/{qid}/review-complete
  → last_reviewed_at + (wrong/unsure 인 경우만) due_at 최초 부여
- GET /study-topics/{tid}/review-queue?tab=due_today|pending_review|chronic|regressed|mastered
  → 5 탭 paginated 조회
  → pending_review 는 last_reviewed_at < last_attempted_at 까지 포함 (이전 확인완료 후 다시 wrong 잡힘)

Phase 1-E (풀이 선별 알고리즘) 은 후속 commit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 09:28:46 +09:00

43 lines
1.9 KiB
SQL
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- 222_study_question_progress.sql
-- Phase 1: 학습 루프 데이터 계층 — 사용자 × 토픽 × 문제 단위 현재 상태 캐시.
--
-- 책임 분리:
-- attempts (append-only 원본 로그) → progress (현재 상태 캐시) → pattern derived
--
-- 컬럼 분류:
-- 마지막 시도: last_outcome / last_attempted_at / last_attempt_id
-- 사용자 검토: last_reviewed_at
-- 복습 큐: due_at / review_stage
-- 패턴 분류 (derived): pattern_state / pattern_updated_at / pattern_window_attempts
--
-- finalize 가 last_* + pattern_state 만 갱신. due_at 최초 부여는 review-complete 단계.
-- 이미 due_at 박힌 문제 다시 풀면 finalize 가 stage 갱신.
--
-- study_question_id 는 현재 단일 topic 소속 전제. 향후 N:M 도입되어도 user×topic×question
-- 3 키 unique 가 안전 → 처음부터 3 키.
CREATE TABLE IF NOT EXISTS study_question_progress (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
study_topic_id BIGINT NOT NULL REFERENCES study_topics(id) ON DELETE CASCADE,
study_question_id BIGINT NOT NULL REFERENCES study_questions(id) ON DELETE RESTRICT,
last_outcome VARCHAR(20),
last_attempted_at TIMESTAMPTZ,
last_attempt_id BIGINT REFERENCES study_question_attempts(id) ON DELETE SET NULL,
last_reviewed_at TIMESTAMPTZ,
due_at TIMESTAMPTZ,
review_stage SMALLINT,
pattern_state VARCHAR(30),
pattern_updated_at TIMESTAMPTZ,
pattern_window_attempts SMALLINT,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
CONSTRAINT uq_progress_user_topic_question UNIQUE (user_id, study_topic_id, study_question_id)
);