-- ═══════════════════════════════════════════════════════════════ -- 081: Practice progress (ИИ-тренажёр, Фаза 0). -- -- Прогресс ученика по НАВЫКАМ тренажёра. Навык = skill генератора -- (напр. 'linear-basic'); задачи генерируются на клиенте детерминированно -- и проверяются подстановкой — сервер хранит лишь агрегаты результата. -- -- На каждую попытку клиент шлёт { skill, correct }. Сервер делает upsert: -- solved — всего верных ответов -- attempts — всего попыток (верных и нет) -- cur_streak — текущая серия верных подряд (обнуляется ошибкой) -- best_streak — лучшая серия -- mastered — 1, как только cur_streak достиг порога (липкое) -- UNIQUE(user_id, skill) — одна строка на пару ученик-навык. -- user_id ON DELETE CASCADE — прогресс удаляется вместе с учеником. -- ═══════════════════════════════════════════════════════════════ CREATE TABLE IF NOT EXISTS practice_progress ( id INTEGER PRIMARY KEY AUTOINCREMENT, user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE, skill TEXT NOT NULL, -- идентификатор навыка генератора solved INTEGER NOT NULL DEFAULT 0, -- всего верных ответов attempts INTEGER NOT NULL DEFAULT 0, -- всего попыток cur_streak INTEGER NOT NULL DEFAULT 0, -- текущая серия верных подряд best_streak INTEGER NOT NULL DEFAULT 0, -- лучшая серия mastered INTEGER NOT NULL DEFAULT 0, -- 1, когда серия достигала порога updated_at TEXT DEFAULT (datetime('now')), UNIQUE (user_id, skill) ); CREATE INDEX IF NOT EXISTS idx_practice_progress_user ON practice_progress (user_id);