'use strict'; /* * Сид недостающих типов биохим-заданий: balance / match / classify / complete. * Контроллер biochemController.js эти типы уже поддерживает, а данных в БД не было * (фильтры в UI были пустыми). Идемпотентно: пропускает уже существующие по title. * * Запуск: node backend/scripts/seed_biochem_challenges.js */ const db = require('../src/db/db'); const getMaxOrder = db.prepare('SELECT MAX(order_n) AS m FROM bio_challenges'); const existsByTitle = db.prepare('SELECT 1 FROM bio_challenges WHERE title = ?'); const insert = db.prepare(`INSERT INTO bio_challenges (title, description, type, target_formula, hint, xp_reward, difficulty, topic_tag, order_n, data_json) VALUES (@title, @description, @type, @target_formula, @hint, @xp_reward, @difficulty, @topic_tag, @order_n, @data_json)`); // data_json-схемы (совпадают с UI biochem.html и контроллером): // balance: { reactants:[...], products:[...], coefficients:[...] } (порядок: реагенты, затем продукты) // match: { pairs:[{left, right}, ...] } // classify: { target, choices:[...], answer } // complete: { equation, choices:[...], answer } const CHALLENGES = [ // ── balance ────────────────────────────────────────────────────────────── { type: 'balance', difficulty: 1, xp: 40, title: 'Баланс: синтез воды', desc: 'Расставь коэффициенты в уравнении образования воды.', data: { reactants: ['H2', 'O2'], products: ['H2O'], coefficients: [2, 1, 2] } }, { type: 'balance', difficulty: 2, xp: 50, title: 'Баланс: горение метана', desc: 'Сбалансируй уравнение полного сгорания метана.', data: { reactants: ['CH4', 'O2'], products: ['CO2', 'H2O'], coefficients: [1, 2, 1, 2] } }, { type: 'balance', difficulty: 2, xp: 50, title: 'Баланс: синтез аммиака', desc: 'Процесс Габера — расставь коэффициенты.', data: { reactants: ['N2', 'H2'], products: ['NH3'], coefficients: [1, 3, 2] } }, { type: 'balance', difficulty: 3, xp: 60, title: 'Баланс: горение этана', desc: 'Сбалансируй сгорание этана (дробные множители убери).', data: { reactants: ['C2H6', 'O2'], products: ['CO2', 'H2O'], coefficients: [2, 7, 4, 6] } }, { type: 'balance', difficulty: 2, xp: 50, title: 'Баланс: ржавление железа', desc: 'Окисление железа кислородом.', data: { reactants: ['Fe', 'O2'], products: ['Fe2O3'], coefficients: [4, 3, 2] } }, // ── match ──────────────────────────────────────────────────────────────── { type: 'match', difficulty: 1, xp: 40, title: 'Сопоставь: простые молекулы', desc: 'Совмести формулу с названием.', data: { pairs: [ { left: 'H2O', right: 'Вода' }, { left: 'CO2', right: 'Углекислый газ' }, { left: 'NH3', right: 'Аммиак' }, { left: 'CH4', right: 'Метан' } ] } }, { type: 'match', difficulty: 2, xp: 50, title: 'Сопоставь: органические вещества', desc: 'Совмести формулу с названием.', data: { pairs: [ { left: 'C2H5OH', right: 'Этанол' }, { left: 'CH3COOH', right: 'Уксусная кислота' }, { left: 'C6H6', right: 'Бензол' }, { left: 'C2H4', right: 'Этилен' } ] } }, { type: 'match', difficulty: 2, xp: 50, title: 'Сопоставь: кислоты и основания', desc: 'Совмести формулу с названием.', data: { pairs: [ { left: 'HCl', right: 'Соляная кислота' }, { left: 'H2SO4', right: 'Серная кислота' }, { left: 'NaOH', right: 'Гидроксид натрия' }, { left: 'HNO3', right: 'Азотная кислота' } ] } }, // ── classify ───────────────────────────────────────────────────────────── { type: 'classify', difficulty: 1, xp: 40, title: 'Класс: метан', target: 'CH4', desc: 'К какому классу относится CH₄?', data: { target: 'CH4', choices: ['Алкан', 'Алкен', 'Алкин', 'Арен'], answer: 'Алкан' } }, { type: 'classify', difficulty: 2, xp: 45, title: 'Класс: этанол', target: 'C2H5OH', desc: 'К какому классу относится C₂H₅OH?', data: { target: 'C2H5OH', choices: ['Спирт', 'Карбоновая кислота', 'Альдегид', 'Кетон'], answer: 'Спирт' } }, { type: 'classify', difficulty: 2, xp: 45, title: 'Класс: уксусная кислота', target: 'CH3COOH', desc: 'К какому классу относится CH₃COOH?', data: { target: 'CH3COOH', choices: ['Карбоновая кислота', 'Спирт', 'Сложный эфир', 'Альдегид'], answer: 'Карбоновая кислота' } }, { type: 'classify', difficulty: 2, xp: 45, title: 'Класс: бензол', target: 'C6H6', desc: 'К какому классу относится C₆H₆?', data: { target: 'C6H6', choices: ['Ароматическое', 'Алкан', 'Алкен', 'Спирт'], answer: 'Ароматическое' } }, // ── complete ───────────────────────────────────────────────────────────── { type: 'complete', difficulty: 1, xp: 40, title: 'Заверши: образование воды', desc: 'Какого реагента не хватает?', data: { equation: '2H₂ + ? → 2H₂O', choices: ['O2', 'CO2', 'N2', 'H2'], answer: 'O2' } }, { type: 'complete', difficulty: 2, xp: 45, title: 'Заверши: горение метана', desc: 'Какого продукта не хватает?', data: { equation: 'CH₄ + 2O₂ → CO₂ + ?', choices: ['H2O', 'H2', 'O2', 'CO'], answer: 'H2O' } }, { type: 'complete', difficulty: 2, xp: 45, title: 'Заверши: синтез аммиака', desc: 'Какой продукт образуется?', data: { equation: 'N₂ + 3H₂ → ?', choices: ['2NH3', 'NH3', 'N2H4', '2NO'], answer: '2NH3' } }, { type: 'complete', difficulty: 1, xp: 40, title: 'Заверши: горение углерода', desc: 'Какой продукт образуется при избытке кислорода?', data: { equation: 'C + O₂ → ?', choices: ['CO2', 'CO', 'C2O', 'O3'], answer: 'CO2' } }, // ── build со структурной проверкой (3D-build, Фаза 5.3) ─────────────────── // target_formula — в Hill-нотации (как считает контроллер); эталон по molecule_id. { type: 'build', difficulty: 1, xp: 45, title: 'Собери: углекислый газ (структура)', target: 'CO2', desc: 'Построй CO₂: углерод с двумя двойными связями к кислороду. Проверяется связность.', hint: 'O=C=O — две двойные связи', data: { requireStructure: true, molecule_id: 2 } }, { type: 'build', difficulty: 2, xp: 55, title: 'Собери: этилен (структура)', target: 'C2H4', desc: 'Построй этилен C₂H₄: двойная связь C=C и по два H на каждом углероде.', hint: 'H₂C=CH₂ — двойная связь между углеродами', data: { requireStructure: true, molecule_id: 12 } }, { type: 'build', difficulty: 2, xp: 60, title: 'Собери: этанол (структура)', target: 'C2H6O', desc: 'Построй этанол: скелет C–C–O, заполни валентности водородами. Важна именно связность (не диметиловый эфир!).', hint: 'CH₃–CH₂–OH: цепочка C–C–O', data: { requireStructure: true, molecule_id: 14 } }, { type: 'build', difficulty: 3, xp: 70, title: 'Собери: уксусную кислоту (структура)', target: 'C2H4O2', desc: 'Построй уксусную кислоту CH₃COOH: метил + карбоксильная группа (C=O и C–O–H).', hint: 'CH₃–COOH: карбоксил −COOH', data: { requireStructure: true, molecule_id: 15 } }, ]; let order = (getMaxOrder.get().m || 0); let added = 0, skipped = 0; db.exec('BEGIN'); try { for (const c of CHALLENGES) { if (existsByTitle.get(c.title)) { skipped++; continue; } order++; insert.run({ title: c.title, description: c.desc || '', type: c.type, target_formula: c.target || '', hint: c.hint || null, xp_reward: c.xp || 40, difficulty: c.difficulty || 1, topic_tag: c.type, order_n: order, data_json: JSON.stringify(c.data), }); added++; } db.exec('COMMIT'); } catch (e) { db.exec('ROLLBACK'); throw e; } console.log(`biochem challenges seed: добавлено ${added}, пропущено ${skipped} (уже были).`); console.log('типы теперь:', db.prepare('SELECT type, COUNT(*) c FROM bio_challenges GROUP BY type ORDER BY type').all() .map(r => `${r.type}:${r.c}`).join(' '));