Files
Learn_System/backend/src/db/migrations/022_exam_prep.sql
T

126 lines
6.0 KiB
SQL

-- ═══════════════════════════════════════════════════════════════
-- 022: Exam Preparation Module
--
-- Generic exam preparation infrastructure parameterized by exam_key.
-- Supports multiple exams (math9, phys9, chem9, math11ce, etc.) sharing
-- the same task bank, attempts tracking, mock sessions, and study plans.
--
-- See docs/exam-prep-plan.md for full architecture.
-- ═══════════════════════════════════════════════════════════════
-- ── Exam tracks registry ────────────────────────────────────────
CREATE TABLE exam_tracks (
exam_key TEXT PRIMARY KEY,
title TEXT NOT NULL,
subject_slug TEXT NOT NULL,
grade INTEGER NOT NULL,
duration_min INTEGER NOT NULL,
tasks_per_variant INTEGER NOT NULL,
variants_count INTEGER NOT NULL,
scoring_json TEXT,
intro_html TEXT,
enabled INTEGER NOT NULL DEFAULT 1,
sort_order INTEGER NOT NULL DEFAULT 0
);
-- ── Task bank (one row per task across all variants) ────────────
CREATE TABLE exam_tasks (
id INTEGER PRIMARY KEY,
exam_key TEXT NOT NULL REFERENCES exam_tracks(exam_key) ON DELETE CASCADE,
variant INTEGER NOT NULL,
task_idx INTEGER NOT NULL,
task_type TEXT NOT NULL CHECK (task_type IN ('mc','open','long')),
text_html TEXT NOT NULL,
figure_html TEXT,
opts_json TEXT,
answer TEXT,
solution_html TEXT NOT NULL,
topic TEXT,
subtopic TEXT,
difficulty INTEGER,
UNIQUE(exam_key, variant, task_idx)
);
CREATE INDEX idx_exam_tasks_topic ON exam_tasks(exam_key, topic);
CREATE INDEX idx_exam_tasks_variant ON exam_tasks(exam_key, variant);
CREATE INDEX idx_exam_tasks_type ON exam_tasks(exam_key, task_type);
-- ── User attempts ───────────────────────────────────────────────
CREATE TABLE exam_attempts (
id INTEGER PRIMARY KEY,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
exam_task_id INTEGER NOT NULL REFERENCES exam_tasks(id) ON DELETE CASCADE,
user_answer TEXT,
is_correct INTEGER,
time_ms INTEGER,
mode TEXT NOT NULL CHECK (mode IN ('practice','variant','topic','mock')),
session_id INTEGER,
hint_used INTEGER NOT NULL DEFAULT 0,
solution_viewed INTEGER NOT NULL DEFAULT 0,
created_at INTEGER NOT NULL
);
CREATE INDEX idx_exam_attempts_user_time ON exam_attempts(user_id, created_at DESC);
CREATE INDEX idx_exam_attempts_task ON exam_attempts(exam_task_id);
CREATE INDEX idx_exam_attempts_session ON exam_attempts(session_id);
CREATE INDEX idx_exam_attempts_user_task ON exam_attempts(user_id, exam_task_id, created_at DESC);
-- ── Mock exam sessions ──────────────────────────────────────────
CREATE TABLE exam_mock_sessions (
id INTEGER PRIMARY KEY,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
exam_key TEXT NOT NULL,
variant INTEGER,
source TEXT NOT NULL CHECK (source IN ('variant','random','weak-topics')),
task_ids_json TEXT NOT NULL,
started_at INTEGER NOT NULL,
finished_at INTEGER,
duration_planned_min INTEGER NOT NULL,
score INTEGER,
total_correct INTEGER,
total_tasks INTEGER,
status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('active','finished','abandoned'))
);
CREATE INDEX idx_mock_user ON exam_mock_sessions(user_id, started_at DESC);
-- ── User preparation plan ───────────────────────────────────────
CREATE TABLE exam_user_plan (
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
exam_key TEXT NOT NULL,
exam_date TEXT NOT NULL,
daily_target INTEGER NOT NULL DEFAULT 10,
weak_focus INTEGER NOT NULL DEFAULT 1,
created_at INTEGER NOT NULL,
updated_at INTEGER NOT NULL,
PRIMARY KEY (user_id, exam_key)
);
-- ── Topic dictionary (populated in F6) ──────────────────────────
CREATE TABLE exam_topics (
slug TEXT PRIMARY KEY,
exam_key TEXT NOT NULL,
parent_slug TEXT,
title TEXT NOT NULL,
description TEXT,
sort_order INTEGER NOT NULL DEFAULT 0
);
CREATE INDEX idx_topics_exam ON exam_topics(exam_key, parent_slug);
-- ── Seed: math9 track ───────────────────────────────────────────
-- Placeholder scoring grid (simple proportional). Replace with the actual
-- Belarus 9th-grade math exam grid once published per academic year.
INSERT INTO exam_tracks (
exam_key, title, subject_slug, grade, duration_min,
tasks_per_variant, variants_count, scoring_json, intro_html, enabled, sort_order
) VALUES (
'math9',
'Экзамен 9 класс — Математика',
'math',
9,
180,
10,
80,
'[{"correct":30,"score":10},{"correct":27,"score":9},{"correct":24,"score":8},{"correct":21,"score":7},{"correct":18,"score":6},{"correct":15,"score":5},{"correct":12,"score":4},{"correct":9,"score":3},{"correct":6,"score":2},{"correct":3,"score":1},{"correct":0,"score":0}]',
'<p>Полная подготовка к выпускному экзамену по математике за 9 класс. 80 реальных вариантов, разбор каждого задания, тренажёр по темам, пробные экзамены с таймером.</p>',
1,
10
);