Files
Learn_System/backend/scripts/cleanup_ctmath_bank.js
T
Maxim Dolgolyov 68817cc612 fix(ctmath): чистка банка — год-пачки убраны из пикера пробников
- exam-prep.js: MOCK_VARIANT_RANGE — для ctmath показываем как пробники
  только чистые 30-задачные варианты [101;1999]; год-пачки (variant=год
  2011-2024 и 0, до 114 задач) остаются пулом для тренажёра по темам,
  но скрыты из пикера/mock-start/просмотра вариантов. math9 (1..80) не затронут
  (диапазон только для ctmath).
- mock.js: пикер «По варианту» — выпадающий список реальных вариантов
  (через listVariants) вместо number-input 1..N; раньше для ctmath он
  предлагал 1..18 и не доходил до 101 → пробник по варианту не запускался.
- cleanup_ctmath_bank.js: идемпотентный скрипт — ретайр битого id=1419
  (mc с противоречивым ответом → long), variants_count → 3 (чистых вариантов).
- seed_*: variants_count считается по диапазону [101;1999] (консистентно с роутом).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 22:22:32 +03:00

89 lines
5.3 KiB
JavaScript
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.
'use strict';
/* ───────────────────────────────────────────────────────────────────────────
cleanup_ctmath_bank.js — точечная чистка банка exam-prep ctmath.
Что делает (идемпотентно):
1. id=1248 (вычисление 5^lg2·2^lg5): дефектная задача (варианты «а» и «д»
одинаковы, верного ответа нет) — уже переведена в 'long'; чистим
литеральное answer="null" → NULL.
2. id=1419 (var 2024, «укажите номера пар»): битый mc — сохранённый ответ «а»
(«3 и 4») противоречит решению («4 и 5»), причём «4 и 5» вообще нет среди
вариантов; единственная подходящая пара — №4, ни один mc-вариант не верен.
Ретайрим в 'long' (self-check): убирается из авто-проверки тренажёра/пробника
(там берутся только mc/open), но текст и разбор сохраняются.
3. variants_count трека ctmath → число «чистых» вариантов-пробников (variant≥101),
чтобы шапка («N вариантов») соответствовала пикеру (год-пачки скрыты роутом).
Год-пачки (variant=год) НЕ удаляются — они остаются пулом задач для тренажёра
по темам (он отбирает по subtopic). «Указательные» opts (["1","1"]…) НЕ трогаем —
они рабочие (ученик выбирает номер).
Запуск: node backend/scripts/cleanup_ctmath_bank.js [--apply]
─────────────────────────────────────────────────────────────────────────── */
const { DatabaseSync } = require('node:sqlite');
const path = require('path');
const APPLY = process.argv.includes('--apply');
const EXAM = 'ctmath';
// Чистые варианты-пробники: 3-значные [101;1999]; год-пачки — 4-значные годы
// (≥2011) и 0 — исключены. Совпадает с MOCK_VARIANT_RANGE.ctmath в routes/exam-prep.js.
const MOCK_LO = 101, MOCK_HI = 1999;
const db = new DatabaseSync(path.join(__dirname, '..', 'data', 'learnspace.db'));
const get = (sql, ...a) => db.prepare(sql).get(...a);
console.log(`\n=== cleanup_ctmath_bank (${APPLY ? 'APPLY' : 'DRY-RUN'}) ===\n`);
const actions = [];
// 1. id=1248 answer="null" → NULL
const t1248 = get(`SELECT id, task_type, answer FROM exam_tasks WHERE id=1248 AND exam_key=?`, EXAM);
if (t1248 && t1248.answer === 'null') {
actions.push({ desc: `id=1248: answer "null" → NULL (тип ${t1248.task_type})`,
run: () => db.prepare(`UPDATE exam_tasks SET answer=NULL WHERE id=1248`).run() });
} else {
console.log(`• id=1248: пропуск (answer=${t1248 ? JSON.stringify(t1248.answer) : 'нет строки'})`);
}
// 2. id=1419 битый mc → long, answer/opts NULL
const t1419 = get(`SELECT id, task_type FROM exam_tasks WHERE id=1419 AND exam_key=?`, EXAM);
if (t1419 && t1419.task_type === 'mc') {
actions.push({ desc: `id=1419: битый mc → 'long' (answer/opts → NULL, текст и разбор сохраняются)`,
run: () => db.prepare(`UPDATE exam_tasks SET task_type='long', answer=NULL, opts_json=NULL WHERE id=1419`).run() });
} else {
console.log(`• id=1419: пропуск (тип ${t1419 ? t1419.task_type : 'нет строки'})`);
}
// 3. variants_count = число чистых вариантов (≥101)
const cleanCnt = get(`SELECT COUNT(DISTINCT variant) c FROM exam_tasks WHERE exam_key=? AND variant BETWEEN ? AND ?`, EXAM, MOCK_LO, MOCK_HI).c;
const curCnt = get(`SELECT variants_count vc FROM exam_tracks WHERE exam_key=?`, EXAM).vc;
if (curCnt !== cleanCnt) {
actions.push({ desc: `exam_tracks.variants_count: ${curCnt}${cleanCnt} (чистых вариантов [${MOCK_LO};${MOCK_HI}])`,
run: () => db.prepare(`UPDATE exam_tracks SET variants_count=? WHERE exam_key=?`).run(cleanCnt, EXAM) });
} else {
console.log(`• variants_count: пропуск (уже ${curCnt})`);
}
console.log(`\nК применению (${actions.length}):`);
actions.forEach(a => console.log(' - ' + a.desc));
if (!actions.length) { console.log('\nНечего менять — всё уже в нужном состоянии.\n'); db.close(); process.exit(0); }
if (!APPLY) {
console.log('\nDRY-RUN: ничего не записано. Для записи: node backend/scripts/cleanup_ctmath_bank.js --apply\n');
db.close(); process.exit(0);
}
db.exec('BEGIN');
try {
for (const a of actions) a.run();
db.exec('COMMIT');
console.log(`\n✓ Применено изменений: ${actions.length}.\n`);
} catch (e) {
db.exec('ROLLBACK');
console.error('\n✗ Ошибка, откат:', e.message);
process.exitCode = 1;
}
db.close();