Files
Learn_System/backend/scripts/seed_ctmath_flashcards_p6.js
T
Maxim Dolgolyov 824ca369bb 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>
2026-06-19 09:33:39 +03:00

189 lines
17 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'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');