'use strict'; /* * Входная диагностика для курса «ЦЭ/ЦТ — Математика». * Собирает ОДИН test из РЕАЛЬНЫХ размеченных вопросов ЦТ-11 (banks 2011–2024): * по 1 заданию на ключевую тему, смесь уровней (single 🟢 → fill-blank 🔴). * Новых вопросов НЕ авторит — только группирует существующие. * ИДЕМПОТЕНТЕН: если test с таким title есть — не дублирует. * Запуск: node backend/scripts/seed_ctmath_diagnostic.js (применить) * node backend/scripts/seed_ctmath_diagnostic.js --dry (показать выбор) */ const db = require('../src/db/db'); const DRY = process.argv.includes('--dry'); const MATH_ID = 3; const TITLE = 'Диагностика ЦЭ/ЦТ — Математика'; const DESC = 'Входная диагностика: задания по ключевым темам (от базовых до сложных) для определения уровня и приоритетных тем подготовки к ЦЭ/ЦТ.'; // Слоты: тема (по имени) + предпочтительный тип + уровень-зонд. // Исключаем набор year=2025 («Экзамен 9»): берём только размеченные ЦТ-11 (year<=2024). const SLOTS = [ ['Теория чисел', 'single', 'base'], ['Арифметика и степени', 'single', 'base'], ['Квадратные уравнения', 'single', 'base'], ['Тригонометрия', 'single', 'base'], ['Числовые промежутки', 'single', 'base'], ['Словесные задачи', 'fill-blank', 'mid'], ['Прогрессии', 'fill-blank', 'mid'], ['Функции', 'fill-blank', 'mid'], ['Геометрия', 'fill-blank', 'mid'], ['Окружность и круг', 'single', 'mid'], ['Стереометрия', 'fill-blank', 'mid'], ['Логарифмы', 'fill-blank', 'hard'], ['Неравенства', 'fill-blank', 'hard'], ['Уравнения', 'fill-blank', 'hard'], ['Показательные неравенства','fill-blank', 'hard'], ]; function topicId(name) { const r = db.prepare('SELECT id FROM topics WHERE subject_id=? AND LOWER(name)=LOWER(?)').get(MATH_ID, name); return r && r.id; } function adminId() { const u = db.prepare("SELECT id FROM users WHERE role='admin' ORDER BY id LIMIT 1").get() || db.prepare('SELECT id FROM users ORDER BY id LIMIT 1').get(); return u && u.id; } // Кандидаты по теме: сперва предпочт. тип, потом любой; только размеченные ЦТ-11 (year<=2024 или not null), // исключая набор «Экзамен 9» (source_type='экзамен 9'); 2024 в приоритете, затем свежие. function candidates(tid, type) { const order = "ORDER BY (year=2024) DESC, year DESC, id"; const base = `SELECT id, type, year, substr(text,1,70) AS t FROM questions WHERE subject_id=${MATH_ID} AND topic_id=${tid} AND (source_type IS NULL OR source_type <> 'экзамен 9')`; const pref = db.prepare(`${base} AND type=? ${order} LIMIT 8`).all(type); const any = db.prepare(`${base} ${order} LIMIT 8`).all(); // предпочт. тип впереди, затем остальные (для фолбэка) const seen = new Set(pref.map(r => r.id)); return [...pref, ...any.filter(r => !seen.has(r.id))]; } const used = new Set(); const picks = []; for (const [name, type, level] of SLOTS) { const tid = topicId(name); if (!tid) { console.log(` [skip] нет темы: ${name}`); continue; } const cand = candidates(tid, type).find(r => !used.has(r.id)); if (!cand) { console.log(` [skip] нет вопросов: ${name}`); continue; } used.add(cand.id); picks.push({ name, level, ...cand }); } console.log(DRY ? '[DRY-RUN] выбранные вопросы диагностики:' : '[APPLY] диагностика:'); const mark = { base: 'базовый', mid: 'средний', hard: 'сложный' }; picks.forEach((p, i) => console.log( ` ${String(i + 1).padStart(2)}. [${mark[p.level]}] ${p.name} | qid ${p.id} (${p.type}, ${p.year || '—'}) — ${p.t.replace(/\s+/g, ' ')}…` )); console.log(`\nВсего отобрано: ${picks.length} заданий.`); const existing = db.prepare("SELECT id FROM tests WHERE subject_slug='math' AND title=?").get(TITLE); if (existing) { console.log(`\nТест «${TITLE}» уже существует (id ${existing.id}) — не дублирую.`); } else if (DRY) { console.log(`\nDRY-RUN: тест НЕ создан. Будет создан с ${picks.length} вопросами.`); } else { const by = adminId(); const testId = db.prepare( 'INSERT INTO tests (title, subject_slug, description, show_answers, time_limit, created_by) VALUES (?,?,?,?,?,?)' ).run(TITLE, 'math', DESC, 1, 40, by).lastInsertRowid; const ins = db.prepare('INSERT INTO test_questions (test_id, question_id, order_index) VALUES (?,?,?)'); picks.forEach((p, i) => ins.run(testId, p.id, i)); console.log(`\nСоздан тест «${TITLE}» (id ${testId}, ${picks.length} вопросов, лимит 40 мин).`); console.log('Выдать классу/ученику: assignment с test_id=' + testId + ' (mode неважен, test_id перекрывает выбор).'); }