c3816baf99
- 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>
94 lines
4.8 KiB
JavaScript
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) — ученикам не виден до публикации.');
|