feat(cefr): CEFR level testing and automated gap ingestion engine (Task 15)

This commit is contained in:
2026-10-06 15:24:33 +03:00
parent 1c3f03a64c
commit 3fae321322
11 changed files with 2926 additions and 10 deletions
+44
View File
@@ -202,6 +202,43 @@ def _migrate(conn: sqlite3.Connection):
""")
conn.execute("CREATE INDEX IF NOT EXISTS idx_sentence_trans_hash ON sentence_translations(sentence_hash);")
# Ensure cefr_questions and cefr_progress tables exist
conn.execute("""
CREATE TABLE IF NOT EXISTS cefr_questions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
level TEXT NOT NULL,
term TEXT NOT NULL COLLATE NOCASE,
translation TEXT NOT NULL,
pos TEXT DEFAULT '',
phonetic TEXT DEFAULT '',
sentence TEXT NOT NULL,
options_json TEXT NOT NULL,
explanation TEXT DEFAULT '',
frequency_rank INTEGER DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE(level, term COLLATE NOCASE)
);
""")
conn.execute("CREATE INDEX IF NOT EXISTS idx_cefr_q_level ON cefr_questions(level);")
conn.execute("CREATE INDEX IF NOT EXISTS idx_cefr_q_term ON cefr_questions(term COLLATE NOCASE);")
conn.execute("""
CREATE TABLE IF NOT EXISTS cefr_progress (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL,
question_id INTEGER NOT NULL,
level TEXT NOT NULL,
is_mastered INTEGER DEFAULT 0,
attempts INTEGER DEFAULT 0,
mistakes INTEGER DEFAULT 0,
last_tested_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
FOREIGN KEY (question_id) REFERENCES cefr_questions(id) ON DELETE CASCADE,
UNIQUE(user_id, question_id)
);
""")
conn.execute("CREATE INDEX IF NOT EXISTS idx_cefr_prog_user_lvl ON cefr_progress(user_id, level);")
# Auto-seed offline dictionary if empty
_seed_offline_dictionary(conn)
@@ -212,6 +249,13 @@ def _migrate(conn: sqlite3.Connection):
except Exception:
pass
# Seed curated CEFR questions
try:
from app.cefr import seed_cefr_questions
seed_cefr_questions(conn)
except Exception:
pass
def _seed_offline_dictionary(conn: sqlite3.Connection):
"""Seeds the offline dictionary from data/offline_dict.tsv.gz if the table is empty."""