feat(ctmath): большой батч флешкарт — 8 колод по оставшимся темам ЦТ
ФСУ (8), Иррациональные уравнения (7), Показательные ур./нерав. (7),
Логарифмические ур./нерав. (8), Метод интервалов (6), Вектора на плоскости (10),
Теория вероятностей и комбинаторика (9), Параметры (6) — итого 61 карта.
Канонический материал ЦТ. KaTeX inline $…$. Самопроверка усилена: парность $/{}
+ запрет кириллицы внутри $…$ (math-режим KaTeX). Идемпотентно, запись с --apply.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,188 @@
|
|||||||
|
'use strict';
|
||||||
|
/* ───────────────────────────────────────────────────────────────────────────
|
||||||
|
seed_ctmath_flashcards_p6.js
|
||||||
|
Большой разноплановый батч — 8 колод по оставшимся темам ЦЭ/ЦТ:
|
||||||
|
|
||||||
|
1. «ЦТ · Формулы сокращённого умножения»
|
||||||
|
2. «ЦТ · Иррациональные уравнения»
|
||||||
|
3. «ЦТ · Показательные уравнения и неравенства»
|
||||||
|
4. «ЦТ · Логарифмические уравнения и неравенства»
|
||||||
|
5. «ЦТ · Метод интервалов»
|
||||||
|
6. «ЦТ · Вектора на плоскости»
|
||||||
|
7. «ЦТ · Теория вероятностей и комбинаторика»
|
||||||
|
8. «ЦТ · Параметры»
|
||||||
|
|
||||||
|
Источник: канонический набор ЦТ (фундаментальные темы; материал стандартный).
|
||||||
|
|
||||||
|
Математика — KaTeX inline $…$ (страница флешкарт рендерит \( \), \[ \], $ $; НЕ $$).
|
||||||
|
⚠️ Кириллица ТОЛЬКО вне $…$ — в math-режиме KaTeX нет кириллических глифов.
|
||||||
|
Те же владелец/таблицы/стиль, что seed_ctmath_flashcards.js / _p2 … _p5.
|
||||||
|
|
||||||
|
Идемпотентность: колода ищется по (user_id, title). Если уже есть и наполнена —
|
||||||
|
пропуск (не клобберит SR-прогресс). Пустую/новую — наполняет.
|
||||||
|
|
||||||
|
Запуск:
|
||||||
|
node backend/scripts/seed_ctmath_flashcards_p6.js # DRY-RUN (по умолчанию)
|
||||||
|
node backend/scripts/seed_ctmath_flashcards_p6.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: '#FFBE0B',
|
||||||
|
descr: 'Квадраты и кубы суммы/разности, разность квадратов, сумма и разность кубов.',
|
||||||
|
cards: [
|
||||||
|
['Квадрат суммы', '$(a+b)^2=a^2+2ab+b^2$'],
|
||||||
|
['Квадрат разности', '$(a-b)^2=a^2-2ab+b^2$'],
|
||||||
|
['Разность квадратов', '$a^2-b^2=(a-b)(a+b)$'],
|
||||||
|
['Куб суммы', '$(a+b)^3=a^3+3a^2 b+3ab^2+b^3$'],
|
||||||
|
['Куб разности', '$(a-b)^3=a^3-3a^2 b+3ab^2-b^3$'],
|
||||||
|
['Сумма кубов', '$a^3+b^3=(a+b)(a^2-ab+b^2)$'],
|
||||||
|
['Разность кубов', '$a^3-b^3=(a-b)(a^2+ab+b^2)$'],
|
||||||
|
['Квадрат трёхчлена', '$(a+b+c)^2=a^2+b^2+c^2+2ab+2bc+2ac$'],
|
||||||
|
]},
|
||||||
|
|
||||||
|
{ title: 'ЦТ · Иррациональные уравнения', color: '#2EC4B6',
|
||||||
|
descr: 'Уравнения с корнями: возведение в степень, ОДЗ, обязательная проверка корней, замена.',
|
||||||
|
cards: [
|
||||||
|
['Главная идея решения', 'Изолировать корень и возвести обе части в степень корня, затем ОБЯЗАТЕЛЬНО проверить корни — могут появиться посторонние'],
|
||||||
|
['ОДЗ арифметического корня (чётная степень)', 'Подкоренное выражение $\\ge0$; если корень равен выражению $g$, то нужно ещё $g\\ge0$'],
|
||||||
|
['Уравнение $\\sqrt{f}=g$', 'Равносильно системе: $g\\ge0$ и $f=g^2$'],
|
||||||
|
['Уравнение $\\sqrt{f}=\\sqrt{g}$', 'Равносильно: $f=g$ при $f\\ge0$ (тогда и $g\\ge0$)'],
|
||||||
|
['Почему появляются посторонние корни', 'Возведение в чётную степень не равносильно (теряется знак), поэтому проверка подстановкой обязательна'],
|
||||||
|
['Замена переменной', 'Удобна замена $t=\\sqrt[n]{f}$ при $t\\ge0$ — сводит к рациональному уравнению относительно $t$'],
|
||||||
|
['Корень нечётной степени', '$\\sqrt[3]{f}=g$ равносильно $f=g^3$ без ограничений на знак (ОДЗ — вся ось)'],
|
||||||
|
]},
|
||||||
|
|
||||||
|
{ title: 'ЦТ · Показательные уравнения и неравенства', color: '#FF006E',
|
||||||
|
descr: 'Приведение к равным основаниям, замена t=a^x, направление знака неравенства при a>1 и 0<a<1.',
|
||||||
|
cards: [
|
||||||
|
['Основной приём', '$a^{f}=a^{g}$ (при $a>0$, $a\\neq1$) равносильно $f=g$'],
|
||||||
|
['Свойства степеней (напоминание)', '$a^m\\cdot a^n=a^{m+n}$; $\\dfrac{a^m}{a^n}=a^{m-n}$; $(a^m)^n=a^{mn}$'],
|
||||||
|
['Замена $t=a^x$', 'При наличии $a^{2x}$ и $a^x$ удобна замена $t=a^x>0$ — сводит к квадратному (корни с $t\\le0$ отбрасываем)'],
|
||||||
|
['Неравенство при $a>1$', '$a^{f}>a^{g}$ равносильно $f>g$ — знак сохраняется'],
|
||||||
|
['Неравенство при $0<a<1$', '$a^{f}>a^{g}$ равносильно $f<g$ — знак переворачивается'],
|
||||||
|
['Область значений', '$a^x>0$ всегда, поэтому $a^x=b$ при $b\\le0$ решений не имеет'],
|
||||||
|
['Однородное уравнение', 'Разделить на $b^{2x}$ и свести к квадратному относительно $\\left(\\dfrac{a}{b}\\right)^x$'],
|
||||||
|
]},
|
||||||
|
|
||||||
|
{ title: 'ЦТ · Логарифмические уравнения и неравенства', color: '#8AC926',
|
||||||
|
descr: 'Определение и ОДЗ логарифма, потенцирование, направление знака при a>1 и 0<a<1, замена.',
|
||||||
|
cards: [
|
||||||
|
['Определение логарифма', '$\\log_a b=c$ означает $a^c=b$ (при $a>0$, $a\\neq1$, $b>0$)'],
|
||||||
|
['ОДЗ логарифма', 'Аргумент $>0$, основание $>0$ и $\\neq1$. Записать ДО решения и проверить корни'],
|
||||||
|
['Уравнение $\\log_a f=\\log_a g$', 'Равносильно $f=g$ при $f>0$ и $g>0$'],
|
||||||
|
['Уравнение $\\log_a f=b$', 'Равносильно $f=a^{b}$ с учётом ОДЗ ($f>0$)'],
|
||||||
|
['Неравенство при $a>1$', '$\\log_a f>\\log_a g$ равносильно $f>g>0$ — знак сохраняется'],
|
||||||
|
['Неравенство при $0<a<1$', '$\\log_a f>\\log_a g$ равносильно $0<f<g$ — знак переворачивается'],
|
||||||
|
['Свойства (напоминание)', '$\\log_a(xy)=\\log_a x+\\log_a y$; $\\log_a x^p=p\\log_a x$; $\\log_a x=\\dfrac{\\log_b x}{\\log_b a}$'],
|
||||||
|
['Замена $t=\\log_a x$', 'Сводит уравнение с $\\log^2$ и $\\log$ к квадратному относительно $t$'],
|
||||||
|
]},
|
||||||
|
|
||||||
|
{ title: 'ЦТ · Метод интервалов', color: '#4361EE',
|
||||||
|
descr: 'Решение рациональных неравенств: нули числителя и знаменателя, расстановка знаков, кратность.',
|
||||||
|
cards: [
|
||||||
|
['Когда применяется', 'Для неравенств вида $\\dfrac{P(x)}{Q(x)}>0$ (и $<,\\ge,\\le$), где $P,Q$ разложены на множители'],
|
||||||
|
['Шаг 1 — найти нули', 'Нули числителя (где выражение $=0$) и нули знаменателя (где не определено)'],
|
||||||
|
['Шаг 2 — отметить на оси', 'Нули знаменателя ВСЕГДА выколотые; нули числителя при $\\ge,\\le$ закрашенные, при $>,<$ выколотые'],
|
||||||
|
['Шаг 3 — расставить знаки', 'Определить знак выражения на каждом промежутке (подстановкой пробной точки) и выбрать промежутки с нужным знаком'],
|
||||||
|
['Кратность корня', 'Через корень чётной кратности знак НЕ меняется; через корень нечётной кратности — меняется'],
|
||||||
|
['Типичная ошибка', 'Нельзя умножать неравенство на $Q(x)$ — знак неизвестен. Всё переносим в одну часть и приводим к общему знаменателю'],
|
||||||
|
]},
|
||||||
|
|
||||||
|
{ title: 'ЦТ · Вектора на плоскости', color: '#6A4C93',
|
||||||
|
descr: 'Координаты, длина, операции, скалярное произведение, перпендикулярность и коллинеарность.',
|
||||||
|
cards: [
|
||||||
|
['Координаты вектора по двум точкам', '$\\overrightarrow{AB}=(x_B-x_A;\\ y_B-y_A)$'],
|
||||||
|
['Длина (модуль) вектора', '$|\\vec a|=\\sqrt{a_x^2+a_y^2}$'],
|
||||||
|
['Сумма и разность векторов', '$\\vec a\\pm\\vec b=(a_x\\pm b_x;\\ a_y\\pm b_y)$'],
|
||||||
|
['Умножение вектора на число', '$k\\vec a=(k a_x;\\ k a_y)$'],
|
||||||
|
['Скалярное произведение (координаты)', '$\\vec a\\cdot\\vec b=a_x b_x+a_y b_y$'],
|
||||||
|
['Скалярное произведение (через угол)', '$\\vec a\\cdot\\vec b=|\\vec a|\\,|\\vec b|\\cos\\varphi$'],
|
||||||
|
['Косинус угла между векторами', '$\\cos\\varphi=\\dfrac{\\vec a\\cdot\\vec b}{|\\vec a|\\,|\\vec b|}$'],
|
||||||
|
['Условие перпендикулярности', '$\\vec a\\perp\\vec b$ равносильно $\\vec a\\cdot\\vec b=0$'],
|
||||||
|
['Условие коллинеарности', '$\\vec a\\parallel\\vec b$ равносильно $a_x b_y-a_y b_x=0$'],
|
||||||
|
['Координаты середины отрезка', 'Середина $AB$: $\\left(\\dfrac{x_A+x_B}{2};\\ \\dfrac{y_A+y_B}{2}\\right)$'],
|
||||||
|
]},
|
||||||
|
|
||||||
|
{ title: 'ЦТ · Теория вероятностей и комбинаторика', color: '#F3722C',
|
||||||
|
descr: 'Классическая вероятность, противоположное событие, перестановки, размещения, сочетания.',
|
||||||
|
cards: [
|
||||||
|
['Классическое определение вероятности', '$P=\\dfrac{m}{n}$ — благоприятные исходы делить на все равновозможные'],
|
||||||
|
['Границы вероятности', '$0\\le P\\le1$; $P=0$ — невозможное событие, $P=1$ — достоверное'],
|
||||||
|
['Вероятность противоположного события', '$P(\\bar A)=1-P(A)$'],
|
||||||
|
['Факториал', '$n!=1\\cdot2\\cdot3\\cdots n$; по определению $0!=1$'],
|
||||||
|
['Перестановки из $n$', '$P_n=n!$ — число способов упорядочить $n$ различных элементов'],
|
||||||
|
['Размещения', '$A_n^k=\\dfrac{n!}{(n-k)!}$ — упорядоченные выборки $k$ из $n$'],
|
||||||
|
['Сочетания', '$C_n^k=\\dfrac{n!}{k!\\,(n-k)!}$ — неупорядоченные выборки $k$ из $n$'],
|
||||||
|
['Сложение вероятностей (несовместные)', '$P(A+B)=P(A)+P(B)$ для несовместных событий'],
|
||||||
|
['Умножение вероятностей (независимые)', '$P(A\\cdot B)=P(A)\\cdot P(B)$ для независимых событий'],
|
||||||
|
]},
|
||||||
|
|
||||||
|
{ title: 'ЦТ · Параметры', color: '#277DA1',
|
||||||
|
descr: 'Что значит решить с параметром, разбор по случаям, дискриминант и графический метод.',
|
||||||
|
cards: [
|
||||||
|
['Что значит «решить с параметром»', 'Для КАЖДОГО значения параметра $a$ описать все решения (или их число). Ответ даётся по случаям относительно $a$'],
|
||||||
|
['Линейное уравнение $ax=b$', 'При $a\\neq0$: единственное $x=\\dfrac{b}{a}$. При $a=0,\\ b=0$: любое $x$. При $a=0,\\ b\\neq0$: решений нет'],
|
||||||
|
['Квадратное с параметром — число корней', 'Анализировать знак дискриминанта $D$ и условие $a\\neq0$: $D>0$ — два, $D=0$ — один, $D<0$ — нет'],
|
||||||
|
['Графический метод', 'Выразить параметр: $a=f(x)$, построить график $f(x)$ и пересекать прямой $y=a$ — число пересечений равно числу корней'],
|
||||||
|
['Условие «ровно один корень»', 'Часто $D=0$, либо один корень попадает в ОДЗ, а второй — вне. Граничные случаи проверять отдельно'],
|
||||||
|
['Виета в задачах с параметром', 'Условия на корни ($x_1+x_2$, $x_1 x_2$, их знаки) выразить через параметр, не находя сами корни'],
|
||||||
|
]},
|
||||||
|
];
|
||||||
|
|
||||||
|
/* ── 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;
|
||||||
|
const cyrInMath = (s.match(/\$[^$]*\$/g) || []).some(seg => /[Ѐ-ӿ]/.test(seg));
|
||||||
|
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 (cyrInMath) { 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_p6 (${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_p6.js --apply\n');
|
||||||
|
else console.log('Готово. Колоды добавлены (владелец — admin; раздать классу — через доступ к колоде).\n');
|
||||||
Reference in New Issue
Block a user