feat(ctmath): seed-скрипт ещё двух колод флешкарт (Планиметрия, Свойства функций)
Источники — бесплатные материалы Кедр: «Свойства четырёхугольников», «Уравнение окружности», «Шпора по свойствам функций» + базовый набор формул треугольника. 50 карт (31 + 19), KaTeX inline $…$. Идемпотентно, DRY-RUN по умолчанию, запись только с --apply. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,147 @@
|
||||
'use strict';
|
||||
/* ───────────────────────────────────────────────────────────────────────────
|
||||
seed_ctmath_flashcards_p2.js
|
||||
Ещё две колоды карточек для подготовки к ЦЭ/ЦТ (интервальное повторение):
|
||||
|
||||
1. «ЦТ · Планиметрия — формулы» — треугольники, четырёхугольники, окружность
|
||||
2. «ЦТ · Свойства функций» — чтение графика: D(y), E(y), нули,
|
||||
монотонность, экстремумы, f'(x), чётность, сдвиги
|
||||
|
||||
Источники (бесплатные материалы Кедр от Егора):
|
||||
• Свойства четырехугольников.pdf (параллелограмм/прямоугольник/ромб/квадрат)
|
||||
• Уравнение окружности _ Материал.pdf (уравнение, радиус, расстояние, прямая)
|
||||
• Шпора_по_свойствам_функций_ct_matem.pdf (графический разбор свойств)
|
||||
Формулы треугольника и площадей — базовый набор ЦТ (в шпорах Кедр их нет).
|
||||
|
||||
Математика — KaTeX inline $…$ (страница флешкарт рендерит \( \), \[ \], $ $; НЕ $$).
|
||||
Те же владелец/таблицы/стиль, что seed_ctmath_flashcards.js (Тригонометрия и т.д.).
|
||||
|
||||
Идемпотентность: колода ищется по (user_id, title). Если уже есть и наполнена —
|
||||
пропуск (не клобберит SR-прогресс). Пустую/новую — наполняет.
|
||||
|
||||
Запуск:
|
||||
node backend/scripts/seed_ctmath_flashcards_p2.js # DRY-RUN (по умолчанию)
|
||||
node backend/scripts/seed_ctmath_flashcards_p2.js --apply # запись в БД
|
||||
|
||||
⚠️ Массовую запись в БД запускает ПОЛЬЗОВАТЕЛЬ вручную (авто-режим Claude Code
|
||||
блокирует продакшн-записи). Без --apply ничего не пишется — только сводка.
|
||||
─────────────────────────────────────────────────────────────────────────── */
|
||||
|
||||
const db = require('../src/db/db');
|
||||
const APPLY = process.argv.includes('--apply');
|
||||
|
||||
const owner = (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()).id;
|
||||
|
||||
const DECKS = [
|
||||
{ title: 'ЦТ · Планиметрия — формулы', color: '#FB5607',
|
||||
descr: 'Треугольники, четырёхугольники, окружность. Формулы для планиметрических задач ЦЭ/ЦТ.',
|
||||
cards: [
|
||||
// ── Треугольник ──────────────────────────────────────────────────────
|
||||
['Сумма углов треугольника', '$\\angle A+\\angle B+\\angle C=180^\\circ$'],
|
||||
['Площадь треугольника через основание и высоту', '$S=\\dfrac12\\,a\\,h_a$'],
|
||||
['Площадь треугольника через две стороны и угол', '$S=\\dfrac12\\,ab\\sin C$'],
|
||||
['Теорема Пифагора (прямоугольный $\\triangle$)', '$c^2=a^2+b^2$, где $c$ — гипотенуза'],
|
||||
['Теорема косинусов', '$c^2=a^2+b^2-2ab\\cos C$'],
|
||||
['Теорема синусов', '$\\dfrac{a}{\\sin A}=\\dfrac{b}{\\sin B}=\\dfrac{c}{\\sin C}=2R$'],
|
||||
['Формула Герона', '$S=\\sqrt{p(p-a)(p-b)(p-c)}$, где $p=\\dfrac{a+b+c}{2}$'],
|
||||
['Радиус вписанной окружности ($\\triangle$)', '$r=\\dfrac{S}{p}$ ($p$ — полупериметр)'],
|
||||
['Радиус описанной окружности ($\\triangle$)', '$R=\\dfrac{abc}{4S}$'],
|
||||
['Площадь равностороннего треугольника', '$S=\\dfrac{a^2\\sqrt3}{4}$'],
|
||||
['Средняя линия треугольника', 'Параллельна стороне и равна её половине: $m=\\dfrac{a}{2}$'],
|
||||
['Медиана к гипотенузе (прямоугольный $\\triangle$)', 'Равна половине гипотенузы: $m_c=\\dfrac{c}{2}$'],
|
||||
// ── Четырёхугольники ─────────────────────────────────────────────────
|
||||
['Параллелограмм — определение', 'Четырёхугольник, у которого противоположные стороны попарно параллельны'],
|
||||
['Свойства параллелограмма', 'Противолежащие стороны и углы равны; сумма углов при одной стороне $180^\\circ$; диагонали точкой пересечения делятся пополам'],
|
||||
['Сумма квадратов диагоналей параллелограмма', '$d_1^2+d_2^2=2(a^2+b^2)$'],
|
||||
['Площадь параллелограмма', '$S=a\\,h_a=ab\\sin\\alpha$'],
|
||||
['Прямоугольник — отличие и диагонали', 'Параллелограмм со всеми прямыми углами; диагонали равны: $AC=BD$'],
|
||||
['Площадь прямоугольника', '$S=ab$'],
|
||||
['Ромб — отличие и диагонали', 'Параллелограмм со всеми равными сторонами; диагонали $\\perp$ и являются биссектрисами углов'],
|
||||
['Площадь ромба', '$S=\\dfrac12\\,d_1 d_2=a^2\\sin\\alpha$'],
|
||||
['Квадрат — диагональ и площадь', '$d=a\\sqrt2$; $S=a^2=\\dfrac12\\,d^2$'],
|
||||
['Средняя линия трапеции', '$m=\\dfrac{a+b}{2}$ — полусумма оснований'],
|
||||
['Площадь трапеции', '$S=\\dfrac{a+b}{2}\\cdot h$'],
|
||||
// ── Окружность ───────────────────────────────────────────────────────
|
||||
['Длина окружности', '$C=2\\pi R=\\pi D$'],
|
||||
['Площадь круга', '$S=\\pi R^2$'],
|
||||
['Длина дуги в $n^\\circ$', '$l=\\dfrac{\\pi R n}{180}$'],
|
||||
['Площадь сектора в $n^\\circ$', '$S=\\dfrac{\\pi R^2 n}{360}$'],
|
||||
['Вписанный угол', 'Равен половине центрального, опирающегося на ту же дугу'],
|
||||
['Угол, опирающийся на диаметр', 'Прямой: $90^\\circ$'],
|
||||
['Уравнение окружности', '$(x-x_0)^2+(y-y_0)^2=R^2$ — центр $(x_0;y_0)$, радиус $R$'],
|
||||
['Расстояние между точками', '$d=\\sqrt{(x_2-x_1)^2+(y_2-y_1)^2}$'],
|
||||
]},
|
||||
|
||||
{ title: 'ЦТ · Свойства функций', color: '#3A86FF',
|
||||
descr: 'Чтение графика функции: область определения и значений, нули, монотонность, экстремумы, производная, чётность, сдвиги.',
|
||||
cards: [
|
||||
["Область определения $D(y)$", "Множество всех значений $x$, при которых функция существует (проекция графика на ось $Ox$)"],
|
||||
["Множество значений $E(y)$", "Множество всех значений $y$, которые принимает функция (проекция графика на ось $Oy$)"],
|
||||
["Нули функции", "Значения $x$, при которых $f(x)=0$ — точки пересечения графика с осью $Ox$"],
|
||||
["Пересечение графика с осью $Oy$", "Точка $(0;\\,f(0))$ — подставляем $x=0$"],
|
||||
["Наибольшее и наименьшее значения функции", "Ордината $y$ самой высокой и самой низкой точек графика"],
|
||||
["Функция возрастает на промежутке", "Большему $x$ соответствует большее $y$ (график идёт вверх); признак: $f'(x)>0$"],
|
||||
["Функция убывает на промежутке", "Большему $x$ соответствует меньшее $y$ (график идёт вниз); признак: $f'(x)<0$"],
|
||||
["Промежутки знакопостоянства", "$y>0$ — где график выше оси $Ox$; $y<0$ — где ниже оси $Ox$"],
|
||||
["Точка максимума $x_{\\max}$", "Точка, в которой функция меняет возрастание на убывание ($f'$ меняет знак с $+$ на $-$)"],
|
||||
["Точка минимума $x_{\\min}$", "Точка, в которой функция меняет убывание на возрастание ($f'$ меняет знак с $-$ на $+$)"],
|
||||
["Экстремум функции", "Значение $y=f(x)$ в точке максимума или минимума (сама точка $x$ — точка экстремума)"],
|
||||
["Знак $f'(x)$ и монотонность", "$f'(x)>0$ → функция возрастает; $f'(x)<0$ → функция убывает"],
|
||||
["Условие $f'(x)=0$", "Точка, подозрительная на экстремум: экстремум есть, если $f'$ при переходе меняет знак"],
|
||||
["Чётная функция", "$f(-x)=f(x)$; график симметричен относительно оси $Oy$"],
|
||||
["Нечётная функция", "$f(-x)=-f(x)$; график симметричен относительно начала координат"],
|
||||
["Сдвиг $y=f(x)+a$ (при $a>0$)", "График сдвигается вверх на $a$"],
|
||||
["Сдвиг $y=f(x)-a$ (при $a>0$)", "График сдвигается вниз на $a$"],
|
||||
["Сдвиг $y=f(x+a)$ (при $a>0$)", "График сдвигается влево на $a$"],
|
||||
["Сдвиг $y=f(x-a)$ (при $a>0$)", "График сдвигается вправо на $a$"],
|
||||
]},
|
||||
];
|
||||
|
||||
/* ── self-check: чаще всего KaTeX ломают непарные $ или {} ─────────────────── */
|
||||
let bad = 0;
|
||||
for (const d of DECKS) {
|
||||
d.cards.forEach(([f, b], i) => {
|
||||
[['front', f], ['back', b]].forEach(([side, s]) => {
|
||||
const dollars = (s.match(/\$/g) || []).length;
|
||||
const braces = (s.match(/\{/g) || []).length - (s.match(/\}/g) || []).length;
|
||||
if (dollars % 2 !== 0) { console.error(`✗ непарный $ — «${d.title}» #${i + 1} (${side}): ${s}`); bad++; }
|
||||
if (braces !== 0) { console.error(`✗ непарные {} — «${d.title}» #${i + 1} (${side}): ${s}`); bad++; }
|
||||
});
|
||||
});
|
||||
}
|
||||
if (bad) { console.error(`\nСамопроверка: ${bad} проблем — исправь до записи.\n`); process.exit(1); }
|
||||
|
||||
const findDeck = db.prepare('SELECT id FROM flashcard_decks WHERE user_id=? AND title=?');
|
||||
const countCard = db.prepare('SELECT COUNT(*) c FROM flashcard_cards WHERE deck_id=?');
|
||||
const insDeck = db.prepare('INSERT INTO flashcard_decks (user_id,title,description,color) VALUES (?,?,?,?)');
|
||||
const insCard = db.prepare('INSERT INTO flashcard_cards (deck_id,front,back,order_idx) VALUES (?,?,?,?)');
|
||||
|
||||
console.log(`\n=== seed_ctmath_flashcards_p2 (${APPLY ? 'APPLY' : 'DRY-RUN'}) ===`);
|
||||
console.log('владелец user_id =', owner, '\n');
|
||||
|
||||
let plannedDecks = 0, plannedCards = 0;
|
||||
|
||||
for (const d of DECKS) {
|
||||
const ex = findDeck.get(owner, d.title);
|
||||
if (ex) {
|
||||
const have = countCard.get(ex.id).c;
|
||||
if (have > 0) { console.log(`• «${d.title}» (id ${ex.id}) — уже наполнена (${have} карт), пропуск`); continue; }
|
||||
// колода есть, но пустая → дольём карты
|
||||
plannedDecks++; plannedCards += d.cards.length;
|
||||
console.log(`+ «${d.title}» (id ${ex.id}) — пустая, долить ${d.cards.length} карт`);
|
||||
if (APPLY) d.cards.forEach(([f, b], i) => insCard.run(ex.id, f, b, i));
|
||||
continue;
|
||||
}
|
||||
plannedDecks++; plannedCards += d.cards.length;
|
||||
console.log(`+ «${d.title}» — новая колода, ${d.cards.length} карт`);
|
||||
if (APPLY) {
|
||||
const did = insDeck.run(owner, d.title, d.descr, d.color).lastInsertRowid;
|
||||
d.cards.forEach(([f, b], i) => insCard.run(did, f, b, i));
|
||||
console.log(` создана id ${did}`);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`\nИтого к ${APPLY ? 'записи' : 'добавлению'}: колод ${plannedDecks}, карт ${plannedCards}.`);
|
||||
if (!APPLY) console.log('DRY-RUN: ничего не записано. Для записи: node backend/scripts/seed_ctmath_flashcards_p2.js --apply\n');
|
||||
else console.log('Готово. Колоды добавлены (владелец — admin; раздать классу — через доступ к колоде).\n');
|
||||
Reference in New Issue
Block a user