Files
Learn_System/backend/scripts/seed_ctmath_course.js
T
Maxim Dolgolyov c3816baf99 feat(ct-math): каркас курса ЦЭ/ЦТ на банке questions (темы + draft-курс + секции)
- backend/scripts/seed_ctmath_course.js — идемпотентный аддитивный seed:
  +6 тем (Преобразование выражений/Модуль/Иррациональные ур./Показательные ур./
  Производная/Параметры), DRAFT-курс «ЦЭ/ЦТ — Математика» + 9 секций.
  Применён на живой БД: course id=13 (is_published=0), topics 72-77, sections 27-35.
  Существующие данные не тронуты; повторный запуск ничего не дублирует.
- BUILD_ON_QUESTIONS.md: уточнения инспекции банка (year=2025 = «Экзамен 9»,
  без тем; реальный ЦТ-11 = ~733 размеч., Часть B = fill-blank → гоча mode='ct')
  + блок «Состояние реализации».
- README: статус каркаса.

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

94 lines
4.8 KiB
JavaScript

'use strict';
/*
* Каркас курса «ЦЭ/ЦТ — Математика» на существующем банке questions.
* План: plans/ct-math/ (BUILD_ON_QUESTIONS.md).
* ИДЕМПОТЕНТЕН и АДДИТИВЕН: добавляет недостающие темы (topics),
* создаёт DRAFT-курс (is_published=0) + 9 секций. Существующие данные не трогает.
* Запуск: node backend/scripts/seed_ctmath_course.js (применить)
* node backend/scripts/seed_ctmath_course.js --dry (только показать план)
*/
const db = require('../src/db/db');
const DRY = process.argv.includes('--dry');
const MATH_ID = 3;
// 1) Недостающие темы под модульную карту (см. BUILD_ON_QUESTIONS §3)
const NEW_TOPICS = [
'Преобразование выражений',
'Модуль',
'Иррациональные уравнения',
'Показательные уравнения',
'Производная',
'Параметры',
];
// 2) Секции курса = 9 блоков (PLAN §3)
const SECTIONS = [
'Числа и вычисления',
'Алгебраические преобразования',
'Уравнения и неравенства',
'Функции и производная',
'Тригонометрия',
'Прогрессии и текстовые задачи',
'Планиметрия',
'Стереометрия',
'Продвинутое и комбинированное',
];
const COURSE_TITLE = 'ЦЭ/ЦТ — Математика';
const COURSE_DESC = 'Подготовка к ЦЭ/ЦТ по математике: 30 заданий (часть А — А1–А10, часть В — В1–В20). Теория по темам, тренажёр на банке заданий прошлых лет, карточки формул, пробные варианты.';
function topicExists(name) {
return db.prepare('SELECT id FROM topics WHERE subject_id=? AND LOWER(name)=LOWER(?)').get(MATH_ID, name);
}
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;
}
let addedTopics = 0, skippedTopics = 0;
console.log(DRY ? '[DRY-RUN] план изменений:' : '[APPLY] вношу изменения:');
console.log('\n— Темы (topics) —');
for (const name of NEW_TOPICS) {
const ex = topicExists(name);
if (ex) { console.log(` есть: ${name} (id ${ex.id})`); skippedTopics++; continue; }
if (DRY) { console.log(` + добавить: ${name}`); addedTopics++; continue; }
const id = db.prepare('INSERT INTO topics (subject_id,name) VALUES (?,?)').run(MATH_ID, name).lastInsertRowid;
console.log(` + добавлено: ${name} (id ${id})`);
addedTopics++;
}
console.log('\n— Курс (courses) —');
let course = db.prepare("SELECT id,is_published FROM courses WHERE subject_slug='math' AND title=?").get(COURSE_TITLE);
let courseId;
if (course) {
courseId = course.id;
console.log(` есть курс «${COURSE_TITLE}» (id ${courseId}, ${course.is_published ? 'published' : 'draft'})`);
} else if (DRY) {
console.log(` + создать DRAFT-курс «${COURSE_TITLE}» (created_by=${adminId()})`);
} else {
const by = adminId();
// cover_emoji не указываем — применится дефолт схемы; в коде эмодзи не вводим
courseId = db.prepare(
'INSERT INTO courses (subject_slug,title,description,is_published,created_by) VALUES (?,?,?,0,?)'
).run('math', COURSE_TITLE, COURSE_DESC, by).lastInsertRowid;
console.log(` + создан DRAFT-курс «${COURSE_TITLE}» (id ${courseId}, created_by=${by})`);
}
console.log('\n— Секции (course_sections) —');
if (!courseId && DRY) {
SECTIONS.forEach((t, i) => console.log(` + секция [${i + 1}] ${t}`));
} else if (courseId) {
SECTIONS.forEach((title, i) => {
const ex = db.prepare('SELECT id FROM course_sections WHERE course_id=? AND title=?').get(courseId, title);
if (ex) { console.log(` есть: [${i + 1}] ${title} (id ${ex.id})`); return; }
if (DRY) { console.log(` + секция [${i + 1}] ${title}`); return; }
const id = db.prepare('INSERT INTO course_sections (course_id,title,order_index) VALUES (?,?,?)').run(courseId, title, i + 1).lastInsertRowid;
console.log(` + секция [${i + 1}] ${title} (id ${id})`);
});
}
console.log(`\nИтог: темы +${addedTopics} (есть ${skippedTopics}); курс id=${courseId || '(dry)'}; секций ${SECTIONS.length}.`);
console.log(DRY ? 'DRY-RUN: ничего не записано.' : 'Готово. Курс создан как ЧЕРНОВИК (is_published=0) — ученикам не виден до публикации.');