Files
Learn_System/frontend/js/trainer/generators.js
T
Maxim Dolgolyov 3201d65f50 feat(trainer): V4.1 группа 4 — 20 генераторов (квадратные + прогрессии)
Четвёртая волна плана v4. «Корень-вперёд»: roots проверяет каждый корень,
simplify — эквивалентность, compute — целое.

Квадратные (quadratic): quad-incomplete-bx (ax²+bx=0), quad-incomplete-c (ax²=c),
quad-disc-clean (через дискриминант, чистый D), quad-trinomial-factor (разложить
трёхчлен), quad-find-b (найти b по корню), quad-count-roots (сколько корней по
знаку D), quad-vertex-x (абсцисса вершины), quad-complete-square (полный квадрат);
формулировки по Виета: quad-roots-sum, quad-roots-prod, quad-build-eq (составить
уравнение по корням), quad-double-root (кратный корень, D=0).

Прогрессии (progressions): prog-arith-sum (сумма арифм.), prog-arith-find-d
(найти разность), prog-arith-find-n (номер члена), prog-arith-mean (среднее
арифм.), prog-geom-find-q (знаменатель), prog-geom-mean (геом. среднее √(ac)),
prog-geom-sum (сумма геом.), prog-arith-word (ряды кресел).

Итого 136 генераторов. Смоук 36748 проверок (roots: переменное число корней, вкл.
кратный; simplify: приём канон.+отказ off-by-one; compute: целое; все шаги→LaTeX);
геометрия не задета (6968/0).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 13:38:59 +03:00

2290 lines
136 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';
/* ════════════════════════════════════════════════════════════════════════
Генераторы задач тренажёра — ДАННЫЕ, не код. Таксономия: тема → навык.
Приём «корень-вперёд»: выбираем целый корень/множители и коэффициенты, затем
ВЫВОДИМ остальное так, чтобы ответ был целым, а задача — решаемой. Поэтому
самопроверка движка (verifyRoot) всегда проходит. Шаг решения —
{ note(подробный текст), tex(одно равенство) }; tex рендерится в KaTeX
(exprToLatex). Последний шаг «Проверка» подставляет корень — это и педагогика,
и наглядная демонстрация того, как движок проверяет ответ.
Виды задач:
• solve (деф.) — уравнение lhs = rhs, ученик находит x. Показывается уравнение.
• compute (kind:'compute') — вычислительная задача (проценты): на сцене —
текстовый prompt из display, а lhs:'x' / rhs:<значение> служат ТОЛЬКО для
проверки ответа подстановкой (latex уравнения не показывается).
Темы (7 класс, алгебра): Уравнения → Пропорции → Проценты. Дальше (Уровень 1):
текстовые задачи через LLM с той же подстановочной верификацией.
════════════════════════════════════════════════════════════════════════ */
(function (global) {
// Классы по программе наших учебников (Алгебра/Геометрия 7–9).
var TOPICS = [
{ key: 'linear-eq', label: 'Уравнения', subject: 'algebra', grade: 7, order: 1 },
{ key: 'proportions', label: 'Пропорции', subject: 'algebra', grade: 6, order: 2 },
{ key: 'percents', label: 'Проценты', subject: 'algebra', grade: 6, order: 3 },
{ key: 'simplify', label: 'Упрощение', subject: 'algebra', grade: 7, order: 4 },
{ key: 'powers', label: 'Степени', subject: 'algebra', grade: 7, order: 5 },
{ key: 'formulas', label: 'Формулы', subject: 'algebra', grade: 7, order: 6 },
{ key: 'inequalities', label: 'Неравенства', subject: 'algebra', grade: 7, order: 7 },
{ key: 'systems', label: 'Системы', subject: 'algebra', grade: 7, order: 8 },
{ key: 'quadratic', label: 'Квадратные', subject: 'algebra', grade: 8, order: 9 },
{ key: 'progressions', label: 'Прогрессии', subject: 'algebra', grade: 9, order: 10 },
{ key: 'gcd-lcm', label: 'НОД и НОК', subject: 'algebra', grade: 5, order: 1.4 },
{ key: 'fractions', label: 'Дроби', subject: 'algebra', grade: 5, order: 1.5 },
{ key: 'decimals', label: 'Десятичные', subject: 'algebra', grade: 5, order: 1.6 },
{ key: 'negatives', label: 'Отрицательные', subject: 'algebra', grade: 6, order: 1.7 },
{ key: 'applied', label: 'Задачи', subject: 'algebra', grade: 7, order: 11 },
{ key: 'g-angles', label: 'Углы', subject: 'geometry', grade: 7, order: 12 },
{ key: 'g-pyth', label: 'Пифагор', subject: 'geometry', grade: 8, order: 13 },
{ key: 'g-area', label: 'Площади', subject: 'geometry', grade: 8, order: 14 },
{ key: 'g-poly', label: 'Многоугольники', subject: 'geometry', grade: 8, order: 15 },
{ key: 'g-sim', label: 'Подобие', subject: 'geometry', grade: 8, order: 16 },
{ key: 'g-circle', label: 'Окружность', subject: 'geometry', grade: 9, order: 17 }
];
var GENERATORS = [
/* ═══ Тема: Уравнения ═══ */
/* ax + b = c */
{
id: 'lin-basic', topic: 'linear-eq', order: 1, subject: 'algebra', grade: 7,
title: 'ax + b = c',
pick: { a: [2, 9], b: [1, 20], root: [-9, 9] },
require: 'root != 0',
derive: { c: 'a*root + b', cmb: 'a*root' },
lhs: '{a}*x + {b}', rhs: '{c}', display: '{a}x + {b} = {c}',
answerVar: 'x', answer: 'root', integerAnswer: true,
solution: [
{ note: 'Перед нами линейное уравнение. Наша цель — оставить x одного в левой части. Сначала уберём свободное число {b}: перенесём его вправо, поменяв знак.', tex: '{a}x = {c} - {b}' },
{ note: 'Выполняем вычитание в правой части.', tex: '{a}x = {cmb}' },
{ note: 'Осталось избавиться от множителя при x — делим обе части уравнения на {a}.', tex: 'x = {cmb} / {a}' },
{ note: 'Получаем корень уравнения.', tex: 'x = {ans}' },
{ note: 'Проверка: подставим найденное значение в исходное уравнение — левая часть должна совпасть с правой.', tex: '{a}*({ans}) + {b} = {c}' }
]
},
/* a(x + b) = c */
{
id: 'lin-paren', topic: 'linear-eq', order: 2, subject: 'algebra', grade: 7,
title: 'a(x + b) = c',
pick: { a: [2, 8], b: [1, 12], root: [-9, 9] },
require: 'root != 0',
derive: { c: 'a*(root + b)', ca: 'root + b' },
lhs: '{a}*(x + {b})', rhs: '{c}', display: '{a}(x + {b}) = {c}',
answerVar: 'x', answer: 'root', integerAnswer: true,
solution: [
{ note: 'Слева число {a} умножается на скобку. Самый короткий путь — разделить обе части уравнения на {a}, чтобы убрать этот множитель.', tex: 'x + {b} = {ca}' },
{ note: 'Справа получилось целое число. Теперь переносим {b} вправо со сменой знака.', tex: 'x = {ca} - {b}' },
{ note: 'Получаем корень уравнения.', tex: 'x = {ans}' },
{ note: 'Проверка: подставляем корень в скобку исходного уравнения.', tex: '{a}*({ans} + {b}) = {c}' }
]
},
/* ax + b = cx + d */
{
id: 'lin-both-sides', topic: 'linear-eq', order: 3, subject: 'algebra', grade: 7,
title: 'ax + b = cx + d',
pick: { a: [3, 9], c: [1, 8], b: [1, 20], root: [-9, 9] },
constraint: 'c < a', require: 'root != 0',
derive: { d: '(a - c)*root + b', amc: 'a - c', dmb: '(a - c)*root' },
lhs: '{a}*x + {b}', rhs: '{c}*x + {d}', display: '{a}x + {b} = {c}x + {d}',
answerVar: 'x', answer: 'root', integerAnswer: true,
solution: [
{ note: 'Здесь x есть в обеих частях. Соберём все слагаемые с x слева, а числа — справа. Переносимые слагаемые меняют знак.', tex: '({a} - {c})x = {d} - {b}' },
{ note: 'Приводим подобные: вычитаем коэффициенты при x и отдельно числа.', tex: '{amc}x = {dmb}' },
{ note: 'Делим обе части на коэффициент при x, то есть на {amc}.', tex: 'x = {dmb} / {amc}' },
{ note: 'Получаем корень уравнения.', tex: 'x = {ans}' },
{ note: 'Проверка: подставим корень — обе части дадут одно и то же число.', tex: '{a}*({ans}) + {b} = {c}*({ans}) + {d}' }
]
},
/* a(x + b) = c(x + d) */
{
id: 'lin-paren-both', topic: 'linear-eq', order: 4, subject: 'algebra', grade: 7,
title: 'a(x+b) = c(x+d)',
pick: { a: [2, 6], c: [2, 6], b: [1, 10], root: [-6, 6] },
constraint: 'a != c',
derive: { V: 'a*(root + b)', d: 'V/c - root', ab: 'a*b', cd: 'c*(V/c - root)', amc: 'a - c', diff: 'c*(V/c - root) - a*b' },
require: 'mod(V, c) == 0 && root != 0',
lhs: '{a}*(x + {b})', rhs: '{c}*(x + {d})', display: '{a}(x + {b}) = {c}(x + {d})',
answerVar: 'x', answer: 'root', integerAnswer: true,
solution: [
{ note: 'Скобки с двух сторон. Раскрываем их: умножаем множитель перед скобкой на каждое слагаемое внутри.', tex: '{a}x + {ab} = {c}x + {cd}' },
{ note: 'Переносим слагаемые с x влево, числа — вправо, и приводим подобные.', tex: '{amc}x = {diff}' },
{ note: 'Делим обе части на {amc}.', tex: 'x = {diff} / {amc}' },
{ note: 'Получаем корень уравнения.', tex: 'x = {ans}' },
{ note: 'Проверка: подставляем корень в обе скобки.', tex: '{a}*({ans} + {b}) = {c}*({ans} + {d})' }
]
},
/* x/a + b = c */
{
id: 'lin-frac-denom', topic: 'linear-eq', order: 5, subject: 'algebra', grade: 7,
title: 'x/a + b = c',
pick: { a: [2, 6], k: [-6, 6], b: [1, 12] },
require: 'k != 0',
derive: { root: 'a*k', c: 'k + b', cmb: 'k' },
lhs: 'x/{a} + {b}', rhs: '{c}', display: 'x/{a} + {b} = {c}',
answerVar: 'x', answer: 'root', integerAnswer: true,
solution: [
{ note: 'Слева — дробь x/{a} и число {b}. Сначала уберём свободное число: вычтем {b} из обеих частей.', tex: 'x/{a} = {cmb}' },
{ note: 'Чтобы избавиться от знаменателя {a}, умножаем обе части уравнения на {a}.', tex: 'x = {cmb} * {a}' },
{ note: 'Получаем корень уравнения.', tex: 'x = {ans}' },
{ note: 'Проверка: подставляем корень в исходное уравнение.', tex: '{ans}/{a} + {b} = {c}' }
]
},
/* (a·x)/b = c */
{
id: 'lin-coef-frac', topic: 'linear-eq', order: 6, subject: 'algebra', grade: 7,
title: 'ax/b = c',
pick: { a: [2, 5], b: [2, 5], m: [-5, 5] },
require: 'm != 0',
derive: { root: 'b*m', c: 'a*m', cb: 'a*m*b' },
lhs: '{a}*x/{b}', rhs: '{c}', display: '{a}x/{b} = {c}',
answerVar: 'x', answer: 'root', integerAnswer: true,
solution: [
{ note: 'Слева дробь, в числителе — {a}x. Умножаем обе части уравнения на знаменатель {b}, чтобы избавиться от дроби.', tex: '{a}x = {cb}' },
{ note: 'Теперь делим обе части на коэффициент {a}.', tex: 'x = {cb} / {a}' },
{ note: 'Получаем корень уравнения.', tex: 'x = {ans}' },
{ note: 'Проверка: подставляем корень в исходную дробь.', tex: '{a}*({ans})/{b} = {c}' }
]
},
/* (ax + b)/c = d */
{
id: 'lin-frac-eq', topic: 'linear-eq', order: 7, subject: 'algebra', grade: 7,
title: '(ax + b)/c = d',
pick: { a: [2, 6], b: [1, 12], c: [2, 6], root: [-6, 6] },
derive: { prod: 'a*root + b', d: '(a*root + b)/c', cd: 'a*root + b', cdmb: 'a*root' },
require: 'mod(a*root + b, c) == 0 && root != 0',
lhs: '({a}*x + {b})/{c}', rhs: '{d}', display: '({a}x + {b})/{c} = {d}',
answerVar: 'x', answer: 'root', integerAnswer: true,
solution: [
{ note: 'Вся левая часть делится на {c}. Умножаем обе части уравнения на {c}, чтобы убрать знаменатель.', tex: '{a}x + {b} = {cd}' },
{ note: 'Переносим число {b} в правую часть со сменой знака.', tex: '{a}x = {cdmb}' },
{ note: 'Делим обе части на {a}.', tex: 'x = {cdmb} / {a}' },
{ note: 'Получаем корень уравнения.', tex: 'x = {ans}' },
{ note: 'Проверка: подставляем корень в исходную дробь.', tex: '({a}*({ans}) + {b})/{c} = {d}' }
]
},
/* ═══ Тема: Пропорции ═══ */
/* a/b = c/x */
{
id: 'prop-x-right', topic: 'proportions', order: 1, subject: 'algebra', grade: 7,
title: 'a/b = c/x',
pick: { a: [2, 9], b: [2, 9], t: [2, 9] },
derive: { c: 'a*t', root: 'b*t', bc: 'b*a*t' },
lhs: '{a}/{b}', rhs: '{c}/x', display: '{a}/{b} = {c}/x',
answerVar: 'x', answer: 'root', integerAnswer: true,
solution: [
{ note: 'Это пропорция — равенство двух отношений. По основному свойству пропорции произведение крайних членов равно произведению средних (умножаем «крест-накрест»).', tex: '{a}*x = {b} * {c}' },
{ note: 'Считаем произведение в правой части.', tex: '{a}x = {bc}' },
{ note: 'Делим обе части на {a}, чтобы найти x.', tex: 'x = {bc} / {a}' },
{ note: 'Получаем корень.', tex: 'x = {ans}' },
{ note: 'Проверка: при найденном x обе дроби равны.', tex: '{a}/{b} = {c}/{ans}' }
]
},
/* x/a = b/c */
{
id: 'prop-x-left', topic: 'proportions', order: 2, subject: 'algebra', grade: 7,
title: 'x/a = b/c',
pick: { a: [2, 9], c: [2, 9], s: [2, 9] },
derive: { b: 'c*s', root: 'a*s', ab: 'a*c*s' },
lhs: 'x/{a}', rhs: '{b}/{c}', display: 'x/{a} = {b}/{c}',
answerVar: 'x', answer: 'root', integerAnswer: true,
solution: [
{ note: 'Перед нами пропорция. Перемножаем её члены крест-накрест: числитель левой дроби на знаменатель правой и наоборот.', tex: '{c}*x = {a} * {b}' },
{ note: 'Считаем произведение в правой части.', tex: '{c}x = {ab}' },
{ note: 'Делим обе части на {c}.', tex: 'x = {ab} / {c}' },
{ note: 'Получаем корень.', tex: 'x = {ans}' },
{ note: 'Проверка: обе дроби равны.', tex: '{ans}/{a} = {b}/{c}' }
]
},
/* a/x = b/c */
{
id: 'prop-x-denom', topic: 'proportions', order: 3, subject: 'algebra', grade: 7,
title: 'a/x = b/c',
pick: { b: [2, 9], c: [2, 9], s: [2, 9] },
derive: { a: 'b*s', root: 'c*s', ac: 'b*s*c' },
lhs: '{a}/x', rhs: '{b}/{c}', display: '{a}/x = {b}/{c}',
answerVar: 'x', answer: 'root', integerAnswer: true,
solution: [
{ note: 'Пропорция, где неизвестное стоит в знаменателе. Перемножаем крест-накрест.', tex: '{b}*x = {a} * {c}' },
{ note: 'Считаем произведение в правой части.', tex: '{b}x = {ac}' },
{ note: 'Делим обе части на {b}.', tex: 'x = {ac} / {b}' },
{ note: 'Получаем корень.', tex: 'x = {ans}' },
{ note: 'Проверка: обе дроби равны.', tex: '{a}/{ans} = {b}/{c}' }
]
},
/* ═══ Тема: Проценты (вычислительные задачи) ═══ */
/* p% от числа a */
{
id: 'pct-of', topic: 'percents', order: 1, subject: 'algebra', grade: 7, kind: 'compute',
title: 'p% от числа',
pick: { pidx: [2, 10], abase: [1, 15] },
derive: { p: 'pidx*5', a: 'abase*20', val: 'pidx*abase' },
lhs: 'x', rhs: '{p}*{a}/100', display: 'Найдите {p}% от числа {a}',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'Процент — это сотая доля числа. Чтобы найти {p}% от {a}, нужно умножить число на {p} и разделить на 100.', tex: 'x = {a}*{p}/100' },
{ note: 'Выполняем умножение и деление — получаем ответ.', tex: 'x = {ans}' }
]
},
/* сколько % составляет a от b */
{
id: 'pct-what', topic: 'percents', order: 2, subject: 'algebra', grade: 7, kind: 'compute',
title: 'Сколько процентов',
pick: { pidx: [2, 10], bbase: [1, 8] },
derive: { p: 'pidx*5', b: 'bbase*20', a: 'pidx*bbase' },
lhs: 'x', rhs: '100*{a}/{b}', display: 'Сколько процентов составляет {a} от {b}?',
answerVar: 'x', answer: 'p', integerAnswer: true,
solution: [
{ note: 'Чтобы узнать, какую часть {a} составляет от {b}, делим {a} на {b}. А чтобы перевести эту часть в проценты — умножаем результат на 100.', tex: 'x = {a}/{b}*100' },
{ note: 'Считаем — ответ получается в процентах.', tex: 'x = {ans}' }
]
},
/* p% числа равны a — найти число */
{
id: 'pct-whole', topic: 'percents', order: 3, subject: 'algebra', grade: 7, kind: 'compute',
title: 'Число по проценту',
pick: { pidx: [2, 10], wbase: [1, 12] },
derive: { p: 'pidx*5', whole: 'wbase*20', a: 'pidx*wbase' },
lhs: 'x', rhs: '100*{a}/{p}', display: '{p}% числа равны {a}. Найдите это число.',
answerVar: 'x', answer: 'whole', integerAnswer: true,
solution: [
{ note: 'Известно, что {p}% некоторого числа равны {a}. Значит само число во столько раз больше: умножаем {a} на 100 и делим на {p}.', tex: 'x = {a}*100/{p}' },
{ note: 'Считаем — получаем искомое число.', tex: 'x = {ans}' }
]
},
/* ═══ Тема: Упрощение выражений (проверка эквивалентностью) ═══ */
/* a·x + b·x → (a+b)x */
{
id: 'simp-like', topic: 'simplify', order: 1, subject: 'algebra', grade: 7, kind: 'simplify',
title: 'Привести подобные',
pick: { a: [2, 9], b: [2, 9] },
derive: { s: 'a + b' },
srcExpr: '{a}*x + {b}*x', answerExpr: '{s}*x', answerVars: ['x'],
display: 'Упростите: {a}x + {b}x',
solution: [
{ note: 'Слагаемые {a}x и {b}x подобны (одинаковая буквенная часть x). Складываем коэффициенты: {a} + {b} = {s}.', tex: '{a}x + {b}x' },
{ note: 'Получаем:', tex: '{s}x' }
]
},
/* a(x + b) → ax + ab */
{
id: 'simp-expand', topic: 'simplify', order: 2, subject: 'algebra', grade: 7, kind: 'simplify',
title: 'Раскрыть скобки',
pick: { a: [2, 9], b: [1, 9] },
derive: { ab: 'a*b' },
srcExpr: '{a}*(x + {b})', answerExpr: '{a}*x + {ab}', answerVars: ['x'],
display: 'Раскройте скобки: {a}(x + {b})',
solution: [
{ note: 'Умножаем множитель {a} на каждое слагаемое в скобке: {a}·x и {a}·{b}.', tex: '{a}(x + {b})' },
{ note: 'Получаем:', tex: '{a}x + {ab}' }
]
},
/* ═══ Тема: Квадратные уравнения (несколько корней) ═══ */
/* x² + bx + c = 0 — разложение по Виета (два корня r1, r2) */
{
id: 'quad-factored', topic: 'quadratic', order: 1, subject: 'algebra', grade: 8, kind: 'roots',
title: 'x² + bx + c = 0',
pick: { r1: [-7, 7], r2: [-7, 7] },
constraint: 'r1 != r2',
derive: { b: '-(r1 + r2)', c: 'r1*r2' },
lhs: 'x^2 + {b}*x + {c}', rhs: '0',
answerVar: 'x', answers: ['r1', 'r2'], integerAnswer: true,
solution: [
{ note: 'Квадратное уравнение приравнено к нулю. По теореме Виета ищем два числа: их сумма равна {r1}+{r2}, произведение — {c}. Это и есть корни. Раскладываем на множители:', tex: '(x - {r1})(x - {r2}) = 0' },
{ note: 'Произведение равно нулю, когда обнуляется множитель. Первый корень:', tex: 'x = {r1}' },
{ note: 'Второй корень:', tex: 'x = {r2}' }
]
},
/* x² − a² = 0 — разность квадратов (корни ±a) */
{
id: 'quad-diff', topic: 'quadratic', order: 2, subject: 'algebra', grade: 8, kind: 'roots',
title: 'x² a² = 0',
pick: { a: [2, 9] },
derive: { a2: 'a*a' },
lhs: 'x^2 - {a2}', rhs: '0',
answerVar: 'x', answers: ['a', '-a'], integerAnswer: true,
solution: [
{ note: 'Слева — разность квадратов: x² − {a2} = (x {a})(x + {a}). Раскладываем:', tex: '(x - {a})(x + {a}) = 0' },
{ note: 'Первый корень:', tex: 'x = {a}' },
{ note: 'Второй корень:', tex: 'x = -{a}' }
]
},
/* ═══ Тема: Степени ═══ */
/* вычислить aⁿ */
{
id: 'pow-eval', topic: 'powers', order: 1, subject: 'algebra', grade: 8, kind: 'compute',
title: 'Вычислить степень',
pick: { a: [2, 6], n: [2, 3] },
derive: { val: 'a^n' },
lhs: 'x', rhs: '{a}^{n}', display: 'Вычислите {a} в степени {n}',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'Степень — это повторное умножение основания на себя.', tex: 'x = {a}^{n}' },
{ note: 'Считаем:', tex: 'x = {ans}' }
]
},
/* xᵃ · xᵇ = xᵃ⁺ᵇ */
{
id: 'pow-mult', topic: 'powers', order: 2, subject: 'algebra', grade: 8, kind: 'simplify',
title: 'Произведение степеней',
pick: { a: [2, 5], b: [2, 5] },
derive: { s: 'a + b' },
srcExpr: 'x^{a}*x^{b}', answerExpr: 'x^{s}', answerVars: ['x'],
display: 'Упростите: x^{a}·x^{b}',
solution: [
{ note: 'Основание одинаковое (x) — при умножении степеней показатели складываются: {a} + {b} = {s}.', tex: 'x^{a} * x^{b}' },
{ note: 'Получаем:', tex: 'x^{s}' }
]
},
/* (xᵃ)ᵇ = xᵃᵇ */
{
id: 'pow-pow', topic: 'powers', order: 3, subject: 'algebra', grade: 8, kind: 'simplify',
title: 'Степень степени',
pick: { a: [2, 4], b: [2, 3] },
derive: { ab: 'a*b' },
srcExpr: '(x^{a})^{b}', answerExpr: 'x^{ab}', answerVars: ['x'],
display: 'Упростите: (x^{a})^{b}',
solution: [
{ note: 'При возведении степени в степень показатели перемножаются: {a}·{b} = {ab}.', tex: '(x^{a})^{b}' },
{ note: 'Получаем:', tex: 'x^{ab}' }
]
},
/* ═══ Тема: Формулы сокращённого умножения ═══ */
/* (x + a)² */
{
id: 'sq-sum', topic: 'formulas', order: 1, subject: 'algebra', grade: 8, kind: 'simplify',
title: 'Квадрат суммы',
pick: { a: [1, 9] },
derive: { a2: 'a*a', a2x: '2*a' },
srcExpr: '(x + {a})^2', answerExpr: 'x^2 + {a2x}*x + {a2}', answerVars: ['x'],
display: 'Раскройте: (x + {a})²',
solution: [
{ note: 'Это квадрат суммы. Формула: (a + b)² = a² + 2ab + b² (здесь a = x, b = {a}).', tex: '(x + {a})^2' },
{ note: 'Раскрываем и приводим к стандартному виду:', tex: 'x^2 + {a2x}*x + {a2}' }
]
},
/* (x a)² */
{
id: 'sq-diff', topic: 'formulas', order: 2, subject: 'algebra', grade: 8, kind: 'simplify',
title: 'Квадрат разности',
pick: { a: [1, 9] },
derive: { a2: 'a*a', a2x: '2*a' },
srcExpr: '(x - {a})^2', answerExpr: 'x^2 - {a2x}*x + {a2}', answerVars: ['x'],
display: 'Раскройте: (x {a})²',
solution: [
{ note: 'Это квадрат разности. Формула: (a − b)² = a² − 2ab + b² (здесь a = x, b = {a}).', tex: '(x - {a})^2' },
{ note: 'Раскрываем и приводим к стандартному виду:', tex: 'x^2 - {a2x}*x + {a2}' }
]
},
/* (x a)(x + a) = x² a² */
{
id: 'diff-sq', topic: 'formulas', order: 3, subject: 'algebra', grade: 8, kind: 'simplify',
title: 'Разность квадратов',
pick: { a: [2, 9] },
derive: { a2: 'a*a' },
srcExpr: '(x - {a})*(x + {a})', answerExpr: 'x^2 - {a2}', answerVars: ['x'],
display: 'Раскройте: (x {a})(x + {a})',
solution: [
{ note: 'Произведение разности и суммы — формула разности квадратов: (a − b)(a + b) = a² b².', tex: '(x - {a})*(x + {a})' },
{ note: 'Получаем:', tex: 'x^2 - {a2}' }
]
},
/* ═══ Тема: Линейные неравенства ═══ */
/* ax + b < c (a>0, знак сохраняется) */
{
id: 'ineq-lt', topic: 'inequalities', order: 1, subject: 'algebra', grade: 8, kind: 'inequality',
title: 'ax + b < c',
pick: { a: [2, 6], b: [1, 15], root: [-8, 8] },
derive: { c: 'a*root + b', cmb: 'a*root' },
lhs: '{a}*x + {b}', rhs: '{c}', dispOp: '<', relOp: '<', bound: 'root',
answerVar: 'x',
solution: [
{ note: 'Переносим свободный член {b} вправо:', tex: '{a}x < {cmb}' },
{ note: 'Делим обе части на {a} — число положительное, знак неравенства не меняется:', tex: 'x < {root}' }
]
},
/* ax + b ≥ c (a>0) */
{
id: 'ineq-ge', topic: 'inequalities', order: 2, subject: 'algebra', grade: 8, kind: 'inequality',
title: 'ax + b ≥ c',
pick: { a: [2, 6], b: [1, 15], root: [-8, 8] },
derive: { c: 'a*root + b', cmb: 'a*root' },
lhs: '{a}*x + {b}', rhs: '{c}', dispOp: '>=', relOp: '>=', bound: 'root',
answerVar: 'x',
solution: [
{ note: 'Переносим {b} вправо:', tex: '{a}x >= {cmb}' },
{ note: 'Делим на {a} (положительное) — знак сохраняется:', tex: 'x >= {root}' }
]
},
/* ax + b < c (коэффициент отрицательный → знак МЕНЯЕТСЯ) */
{
id: 'ineq-flip', topic: 'inequalities', order: 3, subject: 'algebra', grade: 8, kind: 'inequality',
title: 'ax + b < c (смена знака)',
pick: { a: [2, 6], b: [1, 15], root: [-8, 8] },
derive: { c: 'b - a*root', cmb: '-a*root' },
lhs: '-{a}*x + {b}', rhs: '{c}', dispOp: '<', relOp: '>', bound: 'root',
answerVar: 'x',
solution: [
{ note: 'Переносим {b} вправо:', tex: '-{a}x < {cmb}' },
{ note: 'Делим на отрицательное число (−{a}) — знак неравенства МЕНЯЕТСЯ на противоположный:', tex: 'x > {root}' }
]
},
/* ═══ Тема: Прогрессии (9 класс) ═══ */
/* n-й член арифметической прогрессии */
{
id: 'prog-arith-term', topic: 'progressions', order: 1, subject: 'algebra', grade: 9, kind: 'compute',
title: 'n-й член арифм. прогрессии',
pick: { a: [-10, 20], d: [-8, 8], n: [3, 12] }, require: 'd != 0',
derive: { val: 'a + (n - 1)*d' },
lhs: 'x', rhs: '{a} + ({n} - 1)*{d}', display: 'Арифметическая прогрессия: a₁ = {a}, d = {d}. Найдите {n}-й член.',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'Формула n-го члена арифметической прогрессии: aₙ = a₁ + (n − 1)·d. Подставляем:', tex: 'x = {a} + ({n} - 1)*{d}' },
{ note: 'Считаем:', tex: 'x = {ans}' }
]
},
/* n-й член геометрической прогрессии */
{
id: 'prog-geom-term', topic: 'progressions', order: 2, subject: 'algebra', grade: 9, kind: 'compute',
title: 'n-й член геом. прогрессии',
pick: { b: [1, 5], q: [2, 3], n: [2, 4] },
derive: { val: 'b * q^(n - 1)' },
lhs: 'x', rhs: '{b} * {q}^({n} - 1)', display: 'Геометрическая прогрессия: b₁ = {b}, q = {q}. Найдите {n}-й член.',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'Формула n-го члена геометрической прогрессии: bₙ = b₁·q^(n−1). Подставляем:', tex: 'x = {b} * {q}^({n} - 1)' },
{ note: 'Считаем:', tex: 'x = {ans}' }
]
},
/* ═══ Тема: Углы (геометрия, 7 класс) ═══ */
/* третий угол треугольника */
{
id: 'ang-triangle', topic: 'g-angles', order: 1, subject: 'geometry', grade: 7, kind: 'compute',
title: 'Третий угол треугольника',
figure: { type: 'triangle-angles', angA: 'a', angB: 'b' },
figurePrompt: 'Найдите неизвестный угол треугольника (в градусах).',
pick: { a: [20, 80], b: [20, 80] }, derive: { val: '180 - a - b' }, require: 'val >= 15 && val <= 150',
lhs: 'x', rhs: '180 - {a} - {b}', display: 'В треугольнике два угла равны {a}° и {b}°. Найдите третий угол (в градусах).',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'Сумма углов треугольника равна 180°. Значит третий угол:', tex: 'x = 180 - {a} - {b}' },
{ note: 'Считаем:', tex: 'x = {ans}' }
]
},
/* смежный угол */
{
id: 'ang-adjacent', topic: 'g-angles', order: 2, subject: 'geometry', grade: 7, kind: 'compute',
title: 'Смежный угол',
figure: { type: 'adjacent-angles', ang: 'a' },
figurePrompt: 'Найдите неизвестный угол (в градусах).',
pick: { a: [25, 155] }, derive: { val: '180 - a' },
lhs: 'x', rhs: '180 - {a}', display: 'Один из смежных углов равен {a}°. Найдите другой смежный с ним угол.',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'Сумма смежных углов равна 180°. Значит:', tex: 'x = 180 - {a}' },
{ note: 'Считаем:', tex: 'x = {ans}' }
]
},
/* внешний угол треугольника */
{
id: 'ang-exterior', topic: 'g-angles', order: 3, subject: 'geometry', grade: 7, kind: 'compute',
title: 'Внешний угол треугольника',
figure: { type: 'triangle-angles', angA: 'a', angB: 'b', ext: true },
figurePrompt: 'Найдите внешний угол треугольника (в градусах).',
pick: { a: [20, 80], b: [20, 80] }, derive: { val: 'a + b' }, require: 'val <= 160',
lhs: 'x', rhs: '{a} + {b}', display: 'Внешний угол треугольника равен сумме двух не смежных с ним внутренних углов. Эти углы равны {a}° и {b}°. Найдите внешний угол.',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'Внешний угол треугольника равен сумме двух не смежных с ним внутренних углов:', tex: 'x = {a} + {b}' },
{ note: 'Считаем:', tex: 'x = {ans}' }
]
},
/* ═══ Тема: Теорема Пифагора (геометрия, 8 класс) ═══ */
/* гипотенуза по катетам (пифагорова тройка m,n) */
{
id: 'pyth-hyp', topic: 'g-pyth', order: 1, subject: 'geometry', grade: 8, kind: 'compute',
title: 'Гипотенуза (Пифагор)',
figure: { type: 'right-triangle', a: 'a', b: 'b', c: 'c', unknown: 'c' },
figurePrompt: 'Найдите гипотенузу прямоугольного треугольника (отмечена «?»).',
pick: { m: [2, 5], n: [1, 4] }, constraint: 'm > n',
derive: { a: 'm*m - n*n', b: '2*m*n', c: 'm*m + n*n' },
lhs: 'x', rhs: 'sqrt({a}^2 + {b}^2)', display: 'Катеты прямоугольного треугольника равны {a} и {b}. Найдите гипотенузу.',
answerVar: 'x', answer: 'c', integerAnswer: true,
solution: [
{ note: 'По теореме Пифагора c² = a² + b², значит c = √(a² + b²):', tex: 'x = sqrt({a}^2 + {b}^2)' },
{ note: 'Считаем (выходит целое — это пифагорова тройка):', tex: 'x = {ans}' }
]
},
/* катет по гипотенузе и катету */
{
id: 'pyth-leg', topic: 'g-pyth', order: 2, subject: 'geometry', grade: 8, kind: 'compute',
title: 'Катет (Пифагор)',
figure: { type: 'right-triangle', a: 'a', b: 'b', c: 'c', unknown: 'b' },
figurePrompt: 'Найдите неизвестный катет (отмечен «?»).',
pick: { m: [2, 5], n: [1, 4] }, constraint: 'm > n',
derive: { a: 'm*m - n*n', b: '2*m*n', c: 'm*m + n*n' },
lhs: 'x', rhs: 'sqrt({c}^2 - {a}^2)', display: 'Гипотенуза прямоугольного треугольника {c}, один катет {a}. Найдите второй катет.',
answerVar: 'x', answer: 'b', integerAnswer: true,
solution: [
{ note: 'По теореме Пифагора b² = c² − a², значит b = √(c² a²):', tex: 'x = sqrt({c}^2 - {a}^2)' },
{ note: 'Считаем:', tex: 'x = {ans}' }
]
},
/* ═══ Тема: Площади (геометрия, 8 класс) ═══ */
/* площадь прямоугольника */
{
id: 'area-rect', topic: 'g-area', order: 1, subject: 'geometry', grade: 8, kind: 'compute',
title: 'Площадь прямоугольника',
figure: { type: 'rectangle', w: 'a', h: 'b' },
figurePrompt: 'Найдите площадь прямоугольника.',
pick: { a: [2, 16], b: [2, 16] }, derive: { val: 'a*b' },
lhs: 'x', rhs: '{a}*{b}', display: 'Стороны прямоугольника {a} и {b}. Найдите его площадь.',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'Площадь прямоугольника — произведение его сторон:', tex: 'x = {a}*{b}' },
{ note: 'Считаем:', tex: 'x = {ans}' }
]
},
/* площадь треугольника */
{
id: 'area-triangle', topic: 'g-area', order: 2, subject: 'geometry', grade: 8, kind: 'compute',
title: 'Площадь треугольника',
figure: { type: 'triangle-base-height', base: 'a', height: 'h' },
figurePrompt: 'Найдите площадь треугольника.',
pick: { a: [2, 16], h: [2, 16] }, require: 'mod(a*h, 2) == 0',
derive: { val: 'a*h/2' },
lhs: 'x', rhs: '{a}*{h}/2', display: 'Основание треугольника {a}, высота к нему {h}. Найдите площадь.',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'Площадь треугольника — половина произведения основания на высоту:', tex: 'x = {a}*{h}/2' },
{ note: 'Считаем:', tex: 'x = {ans}' }
]
},
/* площадь квадрата */
{
id: 'area-square', topic: 'g-area', order: 3, subject: 'geometry', grade: 8, kind: 'compute',
title: 'Площадь квадрата',
figure: { type: 'square', a: 'a' },
figurePrompt: 'Найдите площадь квадрата.',
pick: { a: [2, 20] }, derive: { val: 'a*a' },
lhs: 'x', rhs: '{a}^2', display: 'Сторона квадрата {a}. Найдите его площадь.',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'Площадь квадрата — сторона, возведённая в квадрат:', tex: 'x = {a}^2' },
{ note: 'Считаем:', tex: 'x = {ans}' }
]
},
/* ═══ Тема: Системы 2 линейных уравнений (7 класс) ═══
kind:'system' — ответ ПАРА (x; y). «Корень-вперёд»: берём решение (sx, sy) и
коэффициенты, выводим правые части c1/c2 так, что система имеет ровно это
решение (определитель ≠ 0). Движок рисует \begin{cases}, проверяет подстановкой. */
/* система с положительными коэффициентами */
{
id: 'sys-2x2', topic: 'systems', order: 1, subject: 'algebra', grade: 7, kind: 'system',
title: 'Система 2×2',
pick: { a1: [2, 4], b1: [2, 4], a2: [2, 4], b2: [2, 4], sx: [-6, 6], sy: [-6, 6] },
constraint: 'a1*b2 - a2*b1 != 0',
derive: { c1: 'a1*sx + b1*sy', c2: 'a2*sx + b2*sy', coefY: 'b1*a2 - b2*a1', rhsY: 'c1*a2 - c2*a1' },
eqs: [{ lhs: '{a1}*x + {b1}*y', rhs: '{c1}' }, { lhs: '{a2}*x + {b2}*y', rhs: '{c2}' }],
answers: { x: 'sx', y: 'sy' }, answerVars: ['x', 'y'], integerAnswer: true,
solution: [
{ note: 'Решаем методом сложения. Уравняем коэффициенты при x: умножим первое уравнение на {a2}, а второе — на {a1}.', tex: '' },
{ note: 'Вычтем из первого уравнения второе — слагаемые с x сократятся, останется только y:', tex: '{coefY}*y = {rhsY}' },
{ note: 'Разделим обе части на коэффициент при y:', tex: 'y = {sy}' },
{ note: 'Подставим y = {sy} в первое уравнение системы:', tex: '{a1}*x + {b1}*{sy} = {c1}' },
{ note: 'Решим его относительно x:', tex: 'x = {sx}' },
{ note: 'Ответ: x = {sx}, y = {sy}.', tex: '' }
]
},
/* система с отрицательными коэффициентами (сложнее) */
{
id: 'sys-2x2-neg', topic: 'systems', order: 2, subject: 'algebra', grade: 8, kind: 'system',
title: 'Система (с отрицательными)',
pick: { a1: [-4, 4], b1: [-4, 4], a2: [-4, 4], b2: [-4, 4], sx: [-7, 7], sy: [-7, 7] },
constraint: 'abs(a1) >= 2 && abs(b1) >= 2 && abs(a2) >= 2 && abs(b2) >= 2 && a1*b2 - a2*b1 != 0',
derive: { c1: 'a1*sx + b1*sy', c2: 'a2*sx + b2*sy', coefY: 'b1*a2 - b2*a1', rhsY: 'c1*a2 - c2*a1' },
eqs: [{ lhs: '{a1}*x + {b1}*y', rhs: '{c1}' }, { lhs: '{a2}*x + {b2}*y', rhs: '{c2}' }],
answers: { x: 'sx', y: 'sy' }, answerVars: ['x', 'y'], integerAnswer: true,
solution: [
{ note: 'Метод сложения (внимательно со знаками). Уравняем коэффициенты при x: умножим первое уравнение на {a2}, второе — на {a1}.', tex: '' },
{ note: 'Вычтем из первого уравнения второе — переменная x исключается:', tex: '{coefY}*y = {rhsY}' },
{ note: 'Разделим обе части на коэффициент при y:', tex: 'y = {sy}' },
{ note: 'Подставим y = {sy} в первое уравнение системы:', tex: '{a1}*x + {b1}*{sy} = {c1}' },
{ note: 'Найдём x:', tex: 'x = {sx}' },
{ note: 'Ответ: x = {sx}, y = {sy}.', tex: '' }
]
},
/* ═══ Тема: Задачи (текстовые, параметрические — 7 класс) ═══
kind:'compute' — условие в display, lhs:'x'/rhs:<формула> для проверки. */
/* путь = скорость × время */
{
id: 'app-move-dist', topic: 'applied', order: 1, subject: 'algebra', grade: 7, kind: 'compute',
title: 'Путь (движение)',
pick: { v: [10, 90], t: [2, 9] }, derive: { val: 'v*t' },
lhs: 'x', rhs: '{v}*{t}', display: 'Автомобиль ехал {t} ч со скоростью {v} км/ч. Какой путь он проехал (в км)?',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'Путь равен произведению скорости на время:', tex: 'x = {v}*{t}' },
{ note: 'Считаем:', tex: 'x = {ans}' }
]
},
/* время = путь / скорость */
{
id: 'app-move-time', topic: 'applied', order: 2, subject: 'algebra', grade: 7, kind: 'compute',
title: 'Время (движение)',
pick: { v: [10, 90], t: [2, 9] }, derive: { S: 'v*t', val: 't' },
lhs: 'x', rhs: '{S}/{v}', display: 'Расстояние между городами {S} км. Автомобиль едет со скоростью {v} км/ч. За сколько часов он доедет?',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'Время равно пути, делённому на скорость:', tex: 'x = {S}/{v}' },
{ note: 'Считаем:', tex: 'x = {ans}' }
]
},
/* скорость = путь / время */
{
id: 'app-move-speed', topic: 'applied', order: 3, subject: 'algebra', grade: 7, kind: 'compute',
title: 'Скорость (движение)',
pick: { v: [10, 90], t: [2, 9] }, derive: { S: 'v*t', val: 'v' },
lhs: 'x', rhs: '{S}/{t}', display: 'Поезд прошёл {S} км за {t} ч. Найдите его среднюю скорость (км/ч).',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'Скорость равна пути, делённому на время:', tex: 'x = {S}/{t}' },
{ note: 'Считаем:', tex: 'x = {ans}' }
]
},
/* содержание вещества в сплаве (проценты) */
{
id: 'app-alloy', topic: 'applied', order: 4, subject: 'algebra', grade: 7, kind: 'compute',
title: 'Сплав (проценты)',
pick: { mfac: [1, 9], pidx: [1, 9] }, derive: { m: 'mfac*10', p: 'pidx*10', val: 'mfac*pidx' },
lhs: 'x', rhs: '{m}*{p}/100', display: 'Сплав массой {m} кг содержит {p}% меди. Сколько килограммов меди в сплаве?',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'Масса меди = масса сплава × процент ÷ 100:', tex: 'x = {m}*{p}/100' },
{ note: 'Считаем:', tex: 'x = {ans}' }
]
},
/* цена со скидкой */
{
id: 'app-discount', topic: 'applied', order: 5, subject: 'algebra', grade: 7, kind: 'compute',
title: 'Цена со скидкой',
pick: { pbase: [5, 30], didx: [1, 5] }, derive: { price: 'pbase*10', d: 'didx*10', val: 'pbase*(10 - didx)' },
lhs: 'x', rhs: '{price}*(100 - {d})/100', display: 'Товар стоил {price} руб. Скидка {d}%. Сколько он стоит после скидки (в рублях)?',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'Новая цена = старая × (100 − скидка) ÷ 100:', tex: 'x = {price}*(100 - {d})/100' },
{ note: 'Считаем:', tex: 'x = {ans}' }
]
},
/* ═══ Площади (дополнение к g-area): трапеция, параллелограмм, ромб ═══ */
/* площадь трапеции */
{
id: 'area-trapezoid', topic: 'g-area', order: 4, subject: 'geometry', grade: 8, kind: 'compute',
title: 'Площадь трапеции',
figure: { type: 'trapezoid', bottom: 'a', top: 'b', height: 'h' },
figurePrompt: 'Найдите площадь трапеции.',
pick: { a: [2, 14], b: [2, 14], h: [2, 12] }, require: 'mod((a + b)*h, 2) == 0',
derive: { val: '(a + b)*h/2' },
lhs: 'x', rhs: '({a} + {b})*{h}/2', display: 'Основания трапеции {a} и {b}, высота {h}. Найдите площадь.',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'Площадь трапеции — полусумма оснований на высоту:', tex: 'x = ({a} + {b})*{h}/2' },
{ note: 'Считаем:', tex: 'x = {ans}' }
]
},
/* площадь параллелограмма */
{
id: 'area-parallelogram', topic: 'g-area', order: 5, subject: 'geometry', grade: 8, kind: 'compute',
title: 'Площадь параллелограмма',
figure: { type: 'parallelogram', base: 'a', height: 'h' },
figurePrompt: 'Найдите площадь параллелограмма.',
pick: { a: [2, 16], h: [2, 14] }, derive: { val: 'a*h' },
lhs: 'x', rhs: '{a}*{h}', display: 'Сторона параллелограмма {a}, высота к ней {h}. Найдите площадь.',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'Площадь параллелограмма — сторона на высоту к ней:', tex: 'x = {a}*{h}' },
{ note: 'Считаем:', tex: 'x = {ans}' }
]
},
/* площадь ромба по диагоналям */
{
id: 'area-rhombus', topic: 'g-area', order: 6, subject: 'geometry', grade: 8, kind: 'compute',
title: 'Площадь ромба',
figure: { type: 'rhombus', d1: 'd1', d2: 'd2' },
figurePrompt: 'Найдите площадь ромба.',
pick: { d1: [2, 16], d2: [2, 16] }, require: 'mod(d1*d2, 2) == 0',
derive: { val: 'd1*d2/2' },
lhs: 'x', rhs: '{d1}*{d2}/2', display: 'Диагонали ромба {d1} и {d2}. Найдите площадь.',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'Площадь ромба — половина произведения диагоналей:', tex: 'x = {d1}*{d2}/2' },
{ note: 'Считаем:', tex: 'x = {ans}' }
]
},
/* ═══ Тема: Многоугольники (геометрия, 8 класс) ═══ */
/* сумма углов выпуклого n-угольника */
{
id: 'poly-angles-sum', topic: 'g-poly', order: 1, subject: 'geometry', grade: 8, kind: 'compute',
title: 'Сумма углов многоугольника',
figure: { type: 'regular-polygon', n: 'n' },
figurePrompt: 'Найдите сумму углов многоугольника на чертеже (в градусах).',
pick: { n: [3, 12] }, derive: { val: '180*(n - 2)' },
lhs: 'x', rhs: '180*({n} - 2)', display: 'Найдите сумму углов выпуклого {n}-угольника (в градусах).',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'Сумма углов выпуклого n-угольника равна 180°·(n − 2):', tex: 'x = 180*({n} - 2)' },
{ note: 'Считаем:', tex: 'x = {ans}' }
]
},
/* угол правильного n-угольника */
{
id: 'poly-regular-angle', topic: 'g-poly', order: 2, subject: 'geometry', grade: 8, kind: 'compute',
title: 'Угол правильного многоугольника',
figure: { type: 'regular-polygon', n: 'n', markAngle: true },
figurePrompt: 'Найдите угол правильного многоугольника на чертеже (в градусах).',
pick: { n: [3, 20] }, require: 'mod(180*(n - 2), n) == 0',
derive: { val: '180*(n - 2)/n' },
lhs: 'x', rhs: '180*({n} - 2)/{n}', display: 'Найдите величину угла правильного {n}-угольника (в градусах).',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'Угол правильного n-угольника = 180°·(n 2) ÷ n:', tex: 'x = 180*({n} - 2)/{n}' },
{ note: 'Считаем:', tex: 'x = {ans}' }
]
},
/* ═══ Тема: Подобие (геометрия, 8 класс) ═══ */
/* сходственная сторона по коэффициенту подобия */
{
id: 'sim-side', topic: 'g-sim', order: 1, subject: 'geometry', grade: 8, kind: 'compute',
title: 'Сторона по коэффициенту',
figure: { type: 'two-similar', side: 'a', k: 'k', mode: 'side' },
figurePrompt: 'Найдите сходственную сторону подобного треугольника (отмечена «?»).',
pick: { a: [2, 15], k: [2, 5] }, derive: { val: 'a*k' },
lhs: 'x', rhs: '{a}*{k}', display: 'Треугольники подобны с коэффициентом {k}. Сторона первого равна {a}. Найдите сходственную сторону второго.',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'Сходственные стороны подобных фигур пропорциональны коэффициенту подобия:', tex: 'x = {a}*{k}' },
{ note: 'Считаем:', tex: 'x = {ans}' }
]
},
/* периметр подобной фигуры */
{
id: 'sim-perimeter', topic: 'g-sim', order: 2, subject: 'geometry', grade: 8, kind: 'compute',
title: 'Периметр подобной фигуры',
figure: { type: 'two-similar', perim: 'p', k: 'k', mode: 'perimeter' },
figurePrompt: 'Найдите периметр подобной фигуры (отмечена «?»).',
pick: { p: [5, 30], k: [2, 5] }, derive: { val: 'p*k' },
lhs: 'x', rhs: '{p}*{k}', display: 'Фигуры подобны с коэффициентом {k}. Периметр первой равен {p}. Найдите периметр второй.',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'Периметры подобных фигур относятся как коэффициент подобия:', tex: 'x = {p}*{k}' },
{ note: 'Считаем:', tex: 'x = {ans}' }
]
},
/* ═══ Тема: Дроби (5–6 класс) ═══
kind:'compute'; ответ может быть дробным — ученик вводит «3/4» (SimExpr посчитает). */
/* часть от числа (целый ответ: число кратно знаменателю) */
{
id: 'frac-of-number', topic: 'fractions', order: 1, subject: 'algebra', grade: 5, kind: 'compute',
title: 'Часть от числа',
pick: { n: [2, 6], a: [1, 5], mfac: [2, 9] }, require: 'a < n',
derive: { m: 'n*mfac', val: 'mfac*a' },
lhs: 'x', rhs: '{m}*{a}/{n}', display: 'Найдите {a}/{n} от числа {m}.',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'Чтобы найти часть от числа, умножаем число на числитель и делим на знаменатель:', tex: 'x = {m}*{a}/{n}' },
{ note: 'Считаем:', tex: 'x = {ans}' }
]
},
/* сложение дробей с одинаковым знаменателем (ответ — дробь) */
{
id: 'frac-add-same', topic: 'fractions', order: 2, subject: 'algebra', grade: 5, kind: 'compute',
title: 'Сложение дробей',
pick: { n: [3, 9], a: [1, 6], b: [1, 6] }, require: 'a + b < 2*n',
derive: { val: '(a + b)/n' },
lhs: 'x', rhs: '({a} + {b})/{n}', display: 'Вычислите {a}/{n} + {b}/{n}. Ответ запишите дробью (например 3/4) или числом.',
answerVar: 'x', answer: 'val',
solution: [
{ note: 'При одинаковом знаменателе складываем числители, знаменатель оставляем:', tex: 'x = ({a} + {b})/{n}' },
{ note: 'Получаем значение:', tex: 'x = {ans}' }
]
},
/* ═══ Тема: НОД и НОК (5–6 класс) ═══
Оба числа строим из ДВУХ простых множителей p<q (из {2,3,5,7}) с показателями
1..2: a = p^e1·q^f1, b = p^e2·q^f2. Тогда разложение известно из параметров →
решение показывает СТАНДАРТНЫЙ школьный метод (разложение на простые множители):
НОД = общие множители в НАИМЕНЬШИХ степенях (min показателей),
НОК = все множители в НАИБОЛЬШИХ степенях (max показателей).
gcd/lcm — функции SimExpr, дают эталон для проверки; min/max — показатели для шагов.
(exprToLatex убирает ^1 → разложение печатается красиво: 2^2·3, а не 2^2·3^1.) */
/* наибольший общий делитель — через разложение на простые множители */
{
id: 'gcd-pair', topic: 'gcd-lcm', order: 1, subject: 'algebra', grade: 5, kind: 'compute',
title: 'НОД двух чисел',
pick: { g: [2, 9], m: [2, 8], n: [2, 8] }, constraint: 'm != n',
derive: { a: 'g*m', b: 'g*n', val: 'gcd(a, b)' },
require: 'a <= 90 && b <= 90',
factorize: [{ name: 'aFac', of: 'a' }, { name: 'bFac', of: 'b' }, { name: 'dFac', of: 'gcd(a, b)' }],
lhs: 'x', rhs: 'gcd({a}, {b})', display: 'Найдите наибольший общий делитель (НОД) чисел {a} и {b}.',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'Разложим {a} на простые множители:', tex: '{a} = {aFac}' },
{ note: 'Разложим {b} на простые множители:', tex: '{b} = {bFac}' },
{ note: 'НОД — произведение ОБЩИХ множителей (повторяющиеся берём в наименьшем количестве):', tex: 'x = {dFac}' },
{ note: 'Перемножаем:', tex: 'x = {ans}' }
]
},
/* наименьшее общее кратное — через разложение на простые множители */
{
id: 'lcm-pair', topic: 'gcd-lcm', order: 2, subject: 'algebra', grade: 6, kind: 'compute',
title: 'НОК двух чисел',
pick: { g: [2, 9], m: [2, 8], n: [2, 8] }, constraint: 'm != n',
derive: { a: 'g*m', b: 'g*n', val: 'lcm(a, b)' },
require: 'a <= 60 && b <= 60 && lcm(a, b) <= 240',
factorize: [{ name: 'aFac', of: 'a' }, { name: 'bFac', of: 'b' }, { name: 'kFac', of: 'lcm(a, b)' }],
lhs: 'x', rhs: 'lcm({a}, {b})', display: 'Найдите наименьшее общее кратное (НОК) чисел {a} и {b}.',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'Разложим {a} на простые множители:', tex: '{a} = {aFac}' },
{ note: 'Разложим {b} на простые множители:', tex: '{b} = {bFac}' },
{ note: 'НОК — произведение ВСЕХ множителей (общие берём в наибольшем количестве):', tex: 'x = {kFac}' },
{ note: 'Перемножаем:', tex: 'x = {ans}' }
]
},
/* ═══ Тема: Десятичные дроби (5 класс) ═══
Строим через десятые/сотые (целые ÷10, ÷100) → ответ печатается чисто. */
/* сложение десятичных */
{
id: 'dec-add', topic: 'decimals', order: 1, subject: 'algebra', grade: 5, kind: 'compute',
title: 'Сложение десятичных',
pick: { a: [1, 9], b: [1, 9] }, derive: { da: 'a/10', db: 'b/10', val: '(a + b)/10' },
lhs: 'x', rhs: '({a} + {b})/10', display: 'Вычислите {da} + {db}.',
answerVar: 'x', answer: 'val',
solution: [
{ note: 'Складываем десятичные дроби поразрядно (запятая под запятой):', tex: 'x = {da} + {db}' },
{ note: 'Получаем:', tex: 'x = {ans}' }
]
},
/* вычитание десятичных */
{
id: 'dec-sub', topic: 'decimals', order: 2, subject: 'algebra', grade: 5, kind: 'compute',
title: 'Вычитание десятичных',
pick: { a: [2, 9], b: [1, 8] }, constraint: 'a > b', derive: { da: 'a/10', db: 'b/10', val: '(a - b)/10' },
lhs: 'x', rhs: '({a} - {b})/10', display: 'Вычислите {da} {db}.',
answerVar: 'x', answer: 'val',
solution: [
{ note: 'Вычитаем десятичные дроби поразрядно:', tex: 'x = {da} - {db}' },
{ note: 'Получаем:', tex: 'x = {ans}' }
]
},
/* умножение десятичных */
{
id: 'dec-mult', topic: 'decimals', order: 3, subject: 'algebra', grade: 5, kind: 'compute',
title: 'Умножение десятичных',
pick: { a: [1, 9], b: [1, 9] }, derive: { da: 'a/10', db: 'b/10', val: '(a*b)/100' },
lhs: 'x', rhs: '({a}*{b})/100', display: 'Вычислите {da} · {db}.',
answerVar: 'x', answer: 'val',
solution: [
{ note: 'Перемножаем без запятых как целые, затем отделяем 2 знака после запятой (по сумме знаков у множителей):', tex: 'x = {da} * {db}' },
{ note: 'Получаем:', tex: 'x = {ans}' }
]
},
/* ═══ Тема: Отрицательные числа (6 класс) ═══
Словесные формулировки — без двусмысленных операторов в условии. */
/* сумма с отрицательными */
{
id: 'neg-add', topic: 'negatives', order: 1, subject: 'algebra', grade: 6, kind: 'compute',
title: 'Сумма (отрицательные)',
pick: { a: [-12, 12], b: [-12, 12] }, constraint: 'a != 0 && b != 0 && (a < 0 || b < 0)', derive: { val: 'a + b' },
lhs: 'x', rhs: '{a} + {b}', display: 'Найдите сумму чисел {a} и {b}.',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'Складываем с учётом знаков: при одинаковых знаках складываем модули; при разных — из большего модуля вычитаем меньший и ставим знак большего:', tex: 'x = {a} + {b}' },
{ note: 'Получаем:', tex: 'x = {ans}' }
]
},
/* разность с отрицательными */
{
id: 'neg-sub', topic: 'negatives', order: 2, subject: 'algebra', grade: 6, kind: 'compute',
title: 'Разность (отрицательные)',
pick: { a: [-12, 12], b: [-12, 12] }, constraint: 'a != 0 && b != 0 && (a < 0 || b < 0)', derive: { val: 'a - b' },
lhs: 'x', rhs: '{a} - ({b})', display: 'Из числа {a} вычтите {b}.',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'Вычесть число — значит прибавить ему противоположное:', tex: 'x = {a} - ({b})' },
{ note: 'Получаем:', tex: 'x = {ans}' }
]
},
/* произведение с отрицательными */
{
id: 'neg-mult', topic: 'negatives', order: 3, subject: 'algebra', grade: 6, kind: 'compute',
title: 'Произведение (отрицательные)',
pick: { a: [-9, 9], b: [-9, 9] }, constraint: 'a != 0 && b != 0 && (a < 0 || b < 0)', derive: { val: 'a*b' },
lhs: 'x', rhs: '{a}*{b}', display: 'Найдите произведение чисел {a} и {b}.',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'Перемножаем модули; знак минус — если множители разных знаков, плюс — если одинаковых:', tex: 'x = {a}*{b}' },
{ note: 'Получаем:', tex: 'x = {ans}' }
]
},
/* ═══ Тема: Окружность (геометрия, 9 класс) ═══
Считаем с π ≈ 3,14 (как в учебниках) → ответ — КОНЕЧНАЯ десятичная дробь,
ученик вводит её (SimExpr принимает «31.4»). Чертёж показывает радиус/диаметр/угол. */
/* длина окружности по радиусу: C = 2πr */
{
id: 'circ-length', topic: 'g-circle', order: 1, subject: 'geometry', grade: 9, kind: 'compute',
title: 'Длина окружности',
figure: { type: 'circle', r: 'r', show: 'radius' },
figurePrompt: 'Найдите длину окружности (π ≈ 3,14).',
pick: { r: [1, 20] }, derive: { val: '2*3.14*r' },
lhs: 'x', rhs: '2*3.14*{r}', display: 'Радиус окружности равен {r}. Найдите длину окружности (π ≈ 3,14).',
answerVar: 'x', answer: 'val',
solution: [
{ note: 'Длина окружности вычисляется по формуле C = 2πr. Подставляем r = {r} и π ≈ 3,14:', tex: 'x = 2*3.14*{r}' },
{ note: 'Считаем:', tex: 'x = {ans}' }
]
},
/* длина окружности по диаметру: C = πd */
{
id: 'circ-diam', topic: 'g-circle', order: 2, subject: 'geometry', grade: 9, kind: 'compute',
title: 'Длина по диаметру',
figure: { type: 'circle', d: 'd', show: 'diameter' },
figurePrompt: 'Найдите длину окружности (π ≈ 3,14).',
pick: { d: [2, 30] }, derive: { val: '3.14*d' },
lhs: 'x', rhs: '3.14*{d}', display: 'Диаметр окружности равен {d}. Найдите длину окружности (π ≈ 3,14).',
answerVar: 'x', answer: 'val',
solution: [
{ note: 'Длину окружности можно найти через диаметр: C = πd. Подставляем d = {d} и π ≈ 3,14:', tex: 'x = 3.14*{d}' },
{ note: 'Считаем:', tex: 'x = {ans}' }
]
},
/* площадь круга: S = πr² */
{
id: 'circ-area', topic: 'g-circle', order: 3, subject: 'geometry', grade: 9, kind: 'compute',
title: 'Площадь круга',
figure: { type: 'circle', r: 'r', show: 'area' },
figurePrompt: 'Найдите площадь круга (π ≈ 3,14).',
pick: { r: [1, 15] }, derive: { val: '3.14*r^2' },
lhs: 'x', rhs: '3.14*{r}^2', display: 'Радиус круга равен {r}. Найдите его площадь (π ≈ 3,14).',
answerVar: 'x', answer: 'val',
solution: [
{ note: 'Площадь круга вычисляется по формуле S = πr². Подставляем r = {r} и π ≈ 3,14:', tex: 'x = 3.14*{r}^2' },
{ note: 'Считаем:', tex: 'x = {ans}' }
]
},
/* длина дуги: L = (n/360)·2πr; n = 45·k, требуем конечную дробь (r·k чётно) */
{
id: 'circ-arc', topic: 'g-circle', order: 4, subject: 'geometry', grade: 9, kind: 'compute',
title: 'Длина дуги',
figure: { type: 'circle-arc', r: 'r', angle: 'n' },
figurePrompt: 'Найдите длину дуги (π ≈ 3,14).',
pick: { r: [3, 12], k: [1, 7] }, require: 'mod(r*k, 2) == 0',
derive: { n: '45*k', val: '45*k/360*2*3.14*r' },
lhs: 'x', rhs: '{n}/360*2*3.14*{r}', display: 'Дуга окружности радиуса {r} опирается на центральный угол {n}°. Найдите длину дуги (π ≈ 3,14).',
answerVar: 'x', answer: 'val',
solution: [
{ note: 'Длина дуги — это часть длины окружности: L = (n/360)·2πr. Здесь n = {n}°, r = {r}, π ≈ 3,14:', tex: 'x = {n}/360*2*3.14*{r}' },
{ note: 'Считаем:', tex: 'x = {ans}' }
]
},
/* ═══════════════════════════════════════════════════════════════════════
V4.1 — Группа 1 (линейные): новые формы и формулировки. Все «корень-вперёд».
═══════════════════════════════════════════════════════════════════════ */
/* ── Уравнения ── */
/* ax + b = cx + d с гарантированным делением на (a−c)≥2 */
{
id: 'lin-both-frac', topic: 'linear-eq', order: 8, subject: 'algebra', grade: 7,
title: 'ax + b = cx + d (с делением)',
pick: { a: [5, 9], c: [1, 4], b: [1, 12], root: [-7, 7] },
constraint: 'a - c >= 2', require: 'root != 0',
derive: { d: '(a - c)*root + b', amc: 'a - c', dmb: '(a - c)*root' },
lhs: '{a}*x + {b}', rhs: '{c}*x + {d}', display: '{a}x + {b} = {c}x + {d}',
answerVar: 'x', answer: 'root', integerAnswer: true,
solution: [
{ note: 'x есть в обеих частях. Соберём слагаемые с x слева, числа — справа (со сменой знака).', tex: '({a} - {c})x = {d} - {b}' },
{ note: 'Приводим подобные.', tex: '{amc}x = {dmb}' },
{ note: 'Делим обе части на коэффициент при x — на {amc}.', tex: 'x = {dmb} / {amc}' },
{ note: 'Получаем корень.', tex: 'x = {ans}' },
{ note: 'Проверка: подставляем корень — обе части совпадут.', tex: '{a}*({ans}) + {b} = {c}*({ans}) + {d}' }
]
},
/* a/(x + b) = c — x в знаменателе */
{
id: 'lin-x-denom', topic: 'linear-eq', order: 9, subject: 'algebra', grade: 8,
title: 'a/(x + b) = c',
pick: { c: [2, 6], b: [-5, 8], root: [-7, 9] },
require: 'root + b != 0 && root != 0',
derive: { a: 'c*(root + b)', rb: 'root + b' },
lhs: '{a}/(x + {b})', rhs: '{c}', display: '{a}/(x + {b}) = {c}',
answerVar: 'x', answer: 'root', integerAnswer: true,
solution: [
{ note: 'Знаменатель x + {b} не равен нулю. Умножим обе части на него.', tex: '{a} = {c}*(x + {b})' },
{ note: 'Разделим обе части на {c}.', tex: 'x + {b} = {rb}' },
{ note: 'Перенесём {b} вправо со сменой знака.', tex: 'x = {ans}' },
{ note: 'Проверка: подставляем корень в исходную дробь.', tex: '{a}/({ans} + {b}) = {c}' }
]
},
/* k/x = c — обратная пропорция */
{
id: 'lin-k-over-x', topic: 'linear-eq', order: 10, subject: 'algebra', grade: 8,
title: 'k/x = c',
pick: { c: [2, 9], root: [-9, 9] },
require: 'root != 0',
derive: { k: 'c*root' },
lhs: '{k}/x', rhs: '{c}', display: '{k}/x = {c}',
answerVar: 'x', answer: 'root', integerAnswer: true,
solution: [
{ note: 'Умножим обе части на x, чтобы убрать дробь.', tex: '{k} = {c}*x' },
{ note: 'Разделим обе части на {c}.', tex: 'x = {k} / {c}' },
{ note: 'Получаем корень.', tex: 'x = {ans}' },
{ note: 'Проверка: подставляем корень.', tex: '{k}/({ans}) = {c}' }
]
},
/* |ax + b| = c — два корня */
{
id: 'lin-abs', topic: 'linear-eq', order: 11, subject: 'algebra', grade: 8, kind: 'roots',
title: '|ax + b| = c',
pick: { a: [1, 5], r1: [-7, 3], r2: [-2, 8] },
constraint: 'r2 > r1',
derive: { b: '-a*(r1 + r2)/2', c: 'a*(r2 - r1)/2' },
require: 'mod(a*(r1 + r2), 2) == 0 && c > 0',
lhs: 'abs({a}*x + {b})', rhs: '{c}', display: '|{a}x + {b}| = {c}',
answerVar: 'x', answers: ['r1', 'r2'], integerAnswer: true,
solution: [
{ note: 'Модуль равен {c}, значит выражение под модулем равно {c} или −{c}. Рассмотрим два случая.', tex: '' },
{ note: 'Первый случай — выражение равно {c}:', tex: '{a}*x + {b} = {c}' },
{ note: 'Решаем и получаем корень:', tex: 'x = {r2}' },
{ note: 'Второй случай — выражение равно −{c}:', tex: '{a}*x + {b} = -{c}' },
{ note: 'Решаем и получаем второй корень:', tex: 'x = {r1}' }
]
},
/* (ax + b)/c = (dx + g)/f — дробь = дробь (крест-накрест) */
{
id: 'lin-frac-eq-frac', topic: 'linear-eq', order: 12, subject: 'algebra', grade: 8,
title: '(ax + b)/c = (dx + g)/f',
pick: { a: [2, 5], c: [2, 4], d: [1, 4], f: [2, 4], b: [1, 9], root: [-5, 6] },
constraint: 'a*f != c*d',
require: 'mod(f*(a*root + b) - c*d*root, c) == 0 && root != 0',
derive: { g: '(f*(a*root + b) - c*d*root)/c', fa: 'f*a', fb: 'f*b', cd: 'c*d', cg: 'c*g', cross: 'f*a - c*d', rc: '(f*a - c*d)*root' },
lhs: '({a}*x + {b})/{c}', rhs: '({d}*x + {g})/{f}', display: '({a}x + {b})/{c} = ({d}x + {g})/{f}',
answerVar: 'x', answer: 'root', integerAnswer: true,
solution: [
{ note: 'Перед нами равенство двух дробей. Умножаем крест-накрест: числитель левой на знаменатель правой и наоборот.', tex: '{f}*({a}*x + {b}) = {c}*({d}*x + {g})' },
{ note: 'Раскрываем скобки.', tex: '{fa}*x + {fb} = {cd}*x + {cg}' },
{ note: 'Собираем x слева, числа справа.', tex: '{cross}*x = {rc}' },
{ note: 'Делим на коэффициент при x.', tex: 'x = {ans}' },
{ note: 'Проверка: при найденном x обе дроби равны.', tex: '({a}*({ans}) + {b})/{c} = ({d}*({ans}) + {g})/{f}' }
]
},
/* a(b(x + c) + d) = e — вложенные скобки */
{
id: 'lin-nested-paren', topic: 'linear-eq', order: 13, subject: 'algebra', grade: 8,
title: 'a(b(x + c) + d) = e',
pick: { a: [2, 4], b: [2, 4], c: [-4, 6], d: [1, 8], root: [-5, 6] },
require: 'root != 0',
derive: { ev: 'a*(b*(root + c) + d)', inner: 'b*(root + c) + d', inner2: 'b*(root + c)', rootc: 'root + c' },
lhs: '{a}*({b}*(x + {c}) + {d})', rhs: '{ev}', display: '{a}({b}(x + {c}) + {d}) = {ev}',
answerVar: 'x', answer: 'root', integerAnswer: true,
solution: [
{ note: 'Снимаем внешний множитель {a}: делим обе части на {a}.', tex: '{b}*(x + {c}) + {d} = {inner}' },
{ note: 'Переносим {d} вправо.', tex: '{b}*(x + {c}) = {inner2}' },
{ note: 'Делим на {b}.', tex: 'x + {c} = {rootc}' },
{ note: 'Переносим {c} и получаем корень.', tex: 'x = {ans}' },
{ note: 'Проверка: подставляем корень во вложенные скобки.', tex: '{a}*({b}*({ans} + {c}) + {d}) = {ev}' }
]
},
/* ax + b = mx — «выразите x» (буквенный коэффициент как параметр) */
{
id: 'lin-literal', topic: 'linear-eq', order: 14, subject: 'algebra', grade: 8,
title: 'ax + b = mx (выразите x)',
pick: { a: [2, 5], gap: [2, 6], root: [2, 8] },
derive: { m: 'a + gap', b: 'gap*root', mma: 'gap' },
lhs: '{a}*x + {b}', rhs: '{m}*x', display: '{a}x + {b} = {m}x',
answerVar: 'x', answer: 'root', integerAnswer: true,
solution: [
{ note: 'Соберём слагаемые с x в одной части: перенесём {a}x вправо, число оставим слева.', tex: '{b} = ({m} - {a})*x' },
{ note: 'Приводим подобные (коэффициент при x).', tex: '{b} = {mma}*x' },
{ note: 'Делим обе части на {mma}.', tex: 'x = {b} / {mma}' },
{ note: 'Получаем корень.', tex: 'x = {ans}' },
{ note: 'Проверка: подставляем корень.', tex: '{a}*({ans}) + {b} = {m}*({ans})' }
]
},
/* ── Неравенства ── */
/* ax + b < cx + d, a>c — знак сохраняется */
{
id: 'ineq-both-sides', topic: 'inequalities', order: 4, subject: 'algebra', grade: 8, kind: 'inequality',
title: 'ax + b < cx + d',
pick: { a: [3, 7], c: [1, 4], b: [1, 12], root: [-6, 8] },
constraint: 'a - c >= 2',
derive: { d: '(a - c)*root + b', amc: 'a - c', dmb: '(a - c)*root' },
lhs: '{a}*x + {b}', rhs: '{c}*x + {d}', dispOp: '<', relOp: '<', bound: 'root',
answerVar: 'x',
solution: [
{ note: 'Собираем x слева, числа справа (со сменой знака при переносе).', tex: '({a} - {c})x < {d} - {b}' },
{ note: 'Приводим подобные.', tex: '{amc}x < {dmb}' },
{ note: 'Делим на {amc} — число положительное, знак неравенства сохраняется.', tex: 'x < {root}' }
]
},
/* ax + b ≥ cx + d, c>a — смена знака */
{
id: 'ineq-both-flip', topic: 'inequalities', order: 5, subject: 'algebra', grade: 8, kind: 'inequality',
title: 'ax + b ≥ cx + d (смена знака)',
pick: { a: [1, 4], c: [3, 7], b: [1, 12], root: [-6, 8] },
constraint: 'c - a >= 2',
derive: { d: '(a - c)*root + b', amc: 'a - c', dmb: '(a - c)*root' },
lhs: '{a}*x + {b}', rhs: '{c}*x + {d}', dispOp: '>=', relOp: '<=', bound: 'root',
answerVar: 'x',
solution: [
{ note: 'Собираем x слева, числа справа.', tex: '({a} - {c})x >= {d} - {b}' },
{ note: 'Приводим подобные — коэффициент при x отрицательный.', tex: '{amc}*x >= {dmb}' },
{ note: 'Делим на отрицательное число {amc} — знак неравенства МЕНЯЕТСЯ.', tex: 'x <= {root}' }
]
},
/* a(x + b) > c — скобка в неравенстве */
{
id: 'ineq-paren', topic: 'inequalities', order: 6, subject: 'algebra', grade: 8, kind: 'inequality',
title: 'a(x + b) > c',
pick: { a: [2, 6], b: [1, 8], root: [-5, 8] },
derive: { c: 'a*(root + b)', rootb: 'root + b' },
lhs: '{a}*(x + {b})', rhs: '{c}', dispOp: '>', relOp: '>', bound: 'root',
answerVar: 'x',
solution: [
{ note: 'Делим обе части на {a} (положительное) — знак сохраняется.', tex: 'x + {b} > {rootb}' },
{ note: 'Переносим {b} вправо.', tex: 'x > {root}' }
]
},
/* Сколько целых решений у lo < x ≤ hi (двойное неравенство через compute) */
{
id: 'ineq-count-int', topic: 'inequalities', order: 7, subject: 'algebra', grade: 8, kind: 'compute',
title: 'Число целых решений',
pick: { lo: [-6, 3], span: [2, 8] },
derive: { hi: 'lo + span', val: 'span' },
lhs: 'x', rhs: '{hi} - {lo}', display: 'Сколько целых чисел x удовлетворяют условию {lo} < x ≤ {hi}?',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'Целые решения — это {lo}+1, {lo}+2, …, {hi}. Их количество равно {hi} − {lo}.', tex: 'x = {hi} - {lo}' },
{ note: 'Считаем.', tex: 'x = {ans}' }
]
},
/* ── Системы ── */
/* x + y = S, x y = D — сумма и разность */
{
id: 'sys-sum-diff', topic: 'systems', order: 3, subject: 'algebra', grade: 7, kind: 'system',
title: 'Система x + y = S, x y = D',
pick: { sx: [-7, 8], sy: [-7, 8] },
derive: { S: 'sx + sy', D: 'sx - sy', twoX: '2*sx', twoY: '2*sy' },
eqs: [{ lhs: 'x + y', rhs: '{S}' }, { lhs: 'x - y', rhs: '{D}' }],
answers: { x: 'sx', y: 'sy' }, answerVars: ['x', 'y'], integerAnswer: true,
solution: [
{ note: 'Сложим уравнения почленно — переменная y исключается.', tex: '2*x = {twoX}' },
{ note: 'Находим x.', tex: 'x = {sx}' },
{ note: 'Вычтем из первого уравнения второе — исключается x.', tex: '2*y = {twoY}' },
{ note: 'Находим y.', tex: 'y = {sy}' },
{ note: 'Ответ: x = {sx}, y = {sy}.', tex: '' }
]
},
/* y = mx + k, a2·x + b2·y = c2 — метод подстановки */
{
id: 'sys-subst', topic: 'systems', order: 4, subject: 'algebra', grade: 7, kind: 'system',
title: 'Система (подстановка)',
pick: { sx: [-5, 6], sy: [-6, 7], m: [-3, 4], a2: [1, 5], b2: [1, 4] },
constraint: 'a2 + b2*m != 0',
derive: { k: 'sy - m*sx', c2: 'a2*sx + b2*sy', detc: 'a2 + b2*m', rhsx: 'c2 - b2*k' },
eqs: [{ lhs: 'y', rhs: '{m}*x + {k}' }, { lhs: '{a2}*x + {b2}*y', rhs: '{c2}' }],
answers: { x: 'sx', y: 'sy' }, answerVars: ['x', 'y'], integerAnswer: true,
solution: [
{ note: 'Первое уравнение уже выражает y. Подставим его во второе.', tex: '{a2}*x + {b2}*({m}*x + {k}) = {c2}' },
{ note: 'Раскрываем скобки и приводим подобные при x.', tex: '{detc}*x = {rhsx}' },
{ note: 'Находим x.', tex: 'x = {sx}' },
{ note: 'Подставляем x в первое уравнение.', tex: 'y = {m}*({sx}) + {k}' },
{ note: 'Находим y.', tex: 'y = {sy}' },
{ note: 'Ответ: x = {sx}, y = {sy}.', tex: '' }
]
},
/* Текстовая задача на систему (мальчики/девочки) */
{
id: 'sys-word', topic: 'systems', order: 5, subject: 'algebra', grade: 7, kind: 'system',
title: 'Текстовая задача (система)',
pick: { sx: [5, 16], sy: [6, 18] },
constraint: 'sy > sx',
derive: { N: 'sx + sy', D: 'sy - sx', twoY: '2*sy' },
eqs: [{ lhs: 'x + y', rhs: '{N}' }, { lhs: 'y - x', rhs: '{D}' }],
display: 'В классе всего {N} учеников, причём девочек на {D} больше, чем мальчиков. Сколько мальчиков (x) и девочек (y)?',
answers: { x: 'sx', y: 'sy' }, answerVars: ['x', 'y'], integerAnswer: true,
solution: [
{ note: 'Обозначим мальчиков за x, девочек за y. Всего учеников:', tex: 'x + y = {N}' },
{ note: 'Девочек на {D} больше, чем мальчиков:', tex: 'y - x = {D}' },
{ note: 'Сложим уравнения — найдём удвоенное число девочек.', tex: '2*y = {twoY}' },
{ note: 'Находим число девочек y.', tex: 'y = {sy}' },
{ note: 'Тогда мальчиков:', tex: 'x = {N} - {sy}' },
{ note: 'Ответ: мальчиков {sx}, девочек {sy}.', tex: '' }
]
},
/* Система 3×3 (вводный тизер) */
{
id: 'sys-3x3', topic: 'systems', order: 6, subject: 'algebra', grade: 9, kind: 'system',
title: 'Система 3×3',
pick: { sx: [-4, 5], sy: [-4, 5], sz: [-4, 5] },
derive: { S: 'sx + sy + sz', Sxy: 'sx + sy', Syz: 'sy + sz' },
eqs: [{ lhs: 'x + y + z', rhs: '{S}' }, { lhs: 'x + y', rhs: '{Sxy}' }, { lhs: 'y + z', rhs: '{Syz}' }],
answers: { x: 'sx', y: 'sy', z: 'sz' }, answerVars: ['x', 'y', 'z'], integerAnswer: true,
solution: [
{ note: 'Вычтем из первого уравнения второе — найдём z.', tex: 'z = {S} - {Sxy}' },
{ note: 'Получаем z.', tex: 'z = {sz}' },
{ note: 'Вычтем из первого уравнения третье — найдём x.', tex: 'x = {S} - {Syz}' },
{ note: 'Получаем x.', tex: 'x = {sx}' },
{ note: 'Из второго уравнения найдём y.', tex: 'y = {Sxy} - {sx}' },
{ note: 'Ответ: x = {sx}, y = {sy}, z = {sz}.', tex: '' }
]
},
/* ═══════════════════════════════════════════════════════════════════════
V4.1 — Группа 2: пропорции, проценты, текстовые задачи. Все compute,
«корень-вперёд» → ответ — чистое целое. (t как имя param в тренажёре допустим.)
═══════════════════════════════════════════════════════════════════════ */
/* ── Пропорции (сюжетные) ── */
/* прямая пропорция: цена/количество */
{
id: 'prop-direct-word', topic: 'proportions', order: 4, subject: 'algebra', grade: 6, kind: 'compute',
title: 'Прямая пропорция',
pick: { u: [2, 9], n: [2, 6], m: [2, 9] }, constraint: 'm != n',
derive: { S: 'u*n', val: 'u*m' },
lhs: 'x', rhs: '{S}*{m}/{n}', display: 'За {n} тетрадей заплатили {S} руб. Сколько рублей стоят {m} таких тетрадей?',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'Сначала найдём цену одной тетради: делим стоимость на количество.', tex: '{S} / {n} = {u}' },
{ note: 'Тогда {m} тетрадей стоят:', tex: 'x = {u} * {m}' },
{ note: 'Считаем.', tex: 'x = {ans}' }
]
},
/* обратная пропорция: рабочие/дни */
{
id: 'prop-inverse-word', topic: 'proportions', order: 5, subject: 'algebra', grade: 6, kind: 'compute',
title: 'Обратная пропорция',
pick: { n: [2, 9], m: [2, 9], d2: [2, 9] }, constraint: 'n != m',
derive: { W: 'm*d2', d: 'm*d2/n', val: 'd2' },
require: 'mod(m*d2, n) == 0 && d >= 2',
lhs: 'x', rhs: '{n}*{d}/{m}', display: '{n} рабочих выполнили заказ за {d} дней. За сколько дней выполнят тот же заказ {m} рабочих?',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'Это обратная пропорция: общий объём работы постоянен. Считаем «рабочие-дни»: {n} · {d}.', tex: '{n} * {d} = {W}' },
{ note: 'Делим общий объём на новое число рабочих {m}.', tex: 'x = {W} / {m}' },
{ note: 'Считаем.', tex: 'x = {ans}' }
]
},
/* масштаб карты */
{
id: 'prop-scale-map', topic: 'proportions', order: 6, subject: 'algebra', grade: 6, kind: 'compute',
title: 'Масштаб карты',
pick: { kbase: [1, 9], a: [2, 12] },
derive: { k: 'kbase*100', val: 'a*kbase' },
lhs: 'x', rhs: '{a}*{k}/100', display: 'Масштаб карты 1 : {k}. Отрезок на карте равен {a} см. Какому расстоянию на местности это соответствует (в метрах)?',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'Масштаб 1 : {k} значит, что 1 см карты — это {k} см на местности. Отрезок {a} см — это {a}·{k} см.', tex: '{a} * {k}' },
{ note: 'Переводим сантиметры в метры — делим на 100.', tex: 'x = {a} * {k} / 100' },
{ note: 'Считаем.', tex: 'x = {ans}' }
]
},
/* сложная (тройная) пропорция */
{
id: 'prop-compound', topic: 'proportions', order: 7, subject: 'algebra', grade: 7, kind: 'compute',
title: 'Тройная пропорция',
pick: { r: [1, 4], n: [2, 6], d: [2, 6], m: [2, 6], e2: [2, 6] },
derive: { W: 'r*n*d', val: 'r*m*e2' },
lhs: 'x', rhs: '{W}*{m}*{e2}/({n}*{d})', display: '{n} рабочих за {d} дней изготовили {W} деталей. Сколько деталей изготовят {m} рабочих за {e2} дней при той же производительности?',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'Найдём, сколько деталей делает один рабочий за один день: {W} ÷ ({n}·{d}).', tex: '{W} / ({n} * {d})' },
{ note: 'Тогда {m} рабочих за {e2} дней изготовят:', tex: 'x = {W} * {m} * {e2} / ({n} * {d})' },
{ note: 'Считаем.', tex: 'x = {ans}' }
]
},
/* деление в отношении a:b */
{
id: 'prop-share-ratio', topic: 'proportions', order: 8, subject: 'algebra', grade: 6, kind: 'compute',
title: 'Деление в отношении',
pick: { a: [1, 7], b: [1, 7], u: [2, 20] },
derive: { S: 'u*(a + b)', val: 'u*a' },
lhs: 'x', rhs: '{S}*{a}/({a}+{b})', display: 'Сумму {S} руб разделили в отношении {a} : {b}. Сколько рублей получил первый?',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'Всего долей {a} + {b}. Одна доля равна {S} ÷ ({a}+{b}).', tex: '{S} / ({a} + {b}) = {u}' },
{ note: 'Первому достаётся {a} долей:', tex: 'x = {u} * {a}' },
{ note: 'Считаем.', tex: 'x = {ans}' }
]
},
/* ── Проценты ── */
/* увеличение на p% */
{
id: 'pct-increase', topic: 'percents', order: 4, subject: 'algebra', grade: 6, kind: 'compute',
title: 'Увеличение на p%',
pick: { abase: [1, 9], pidx: [1, 8] },
derive: { a: 'abase*100', p: 'pidx*5', val: 'abase*(100 + pidx*5)' },
lhs: 'x', rhs: '{a}*(100 + {p})/100', display: 'Цену {a} руб повысили на {p}%. Сколько рублей стала стоить вещь?',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'Повышение на {p}% — это умножение на (100 + {p})/100.', tex: 'x = {a} * (100 + {p}) / 100' },
{ note: 'Считаем.', tex: 'x = {ans}' }
]
},
/* уменьшение на p% */
{
id: 'pct-decrease', topic: 'percents', order: 5, subject: 'algebra', grade: 6, kind: 'compute',
title: 'Уменьшение на p%',
pick: { abase: [1, 9], pidx: [1, 18] },
derive: { a: 'abase*100', p: 'pidx*5', val: 'abase*(100 - pidx*5)' },
lhs: 'x', rhs: '{a}*(100 - {p})/100', display: 'Число {a} уменьшили на {p}%. Какое число получилось?',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'Уменьшение на {p}% — это умножение на (100 {p})/100.', tex: 'x = {a} * (100 - {p}) / 100' },
{ note: 'Считаем.', tex: 'x = {ans}' }
]
},
/* на сколько процентов изменилось */
{
id: 'pct-change', topic: 'percents', order: 6, subject: 'algebra', grade: 7, kind: 'compute',
title: 'На сколько процентов выросло',
pick: { abase: [2, 12], pidx: [1, 10] },
derive: { a: 'abase*20', p: 'pidx*5', b: 'abase*(100 + pidx*5)/5', val: 'pidx*5' },
lhs: 'x', rhs: '100*({b} - {a})/{a}', display: 'Цена выросла с {a} руб до {b} руб. На сколько процентов выросла цена?',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'Рост в рублях: {b} {a}.', tex: '{b} - {a}' },
{ note: 'Какую долю это составляет от исходной цены — делим на {a} и умножаем на 100.', tex: 'x = 100 * ({b} - {a}) / {a}' },
{ note: 'Считаем (в процентах).', tex: 'x = {ans}' }
]
},
/* простые проценты (вклад) */
{
id: 'pct-simple-interest', topic: 'percents', order: 7, subject: 'algebra', grade: 8, kind: 'compute',
title: 'Простые проценты',
pick: { sbase: [1, 9], pidx: [1, 6], n: [1, 4] },
derive: { S: 'sbase*100', p: 'pidx*5', val: 'S*(100 + p*n)/100' },
lhs: 'x', rhs: '{S}*(100 + {p}*{n})/100', display: 'В банк положили {S} руб под {p}% годовых (простые проценты). Какая сумма будет на счёте через {n} г.?',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'За {n} г. простыми процентами начислят {p}·{n}% от вклада.', tex: '{p} * {n}' },
{ note: 'Итог — вклад плюс проценты:', tex: 'x = {S} * (100 + {p} * {n}) / 100' },
{ note: 'Считаем.', tex: 'x = {ans}' }
]
},
/* сложные проценты (2 года) */
{
id: 'pct-compound-2y', topic: 'percents', order: 8, subject: 'algebra', grade: 9, kind: 'compute',
title: 'Сложные проценты (2 года)',
pick: { sbase: [1, 3], pidx: [1, 4] },
derive: { S: 'sbase*10000', p: 'pidx*10', val: 'S*(100 + p)^2/10000' },
lhs: 'x', rhs: '{S}*(100 + {p})^2/10000', display: 'Вклад {S} руб под {p}% годовых с ежегодной капитализацией. Какая сумма будет через 2 года?',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'Капитализация: каждый год сумма умножается на (100+{p})/100. За 2 года — дважды.', tex: 'x = {S} * (100 + {p}) / 100 * (100 + {p}) / 100' },
{ note: 'Это умножение на квадрат множителя:', tex: 'x = {S} * (100 + {p})^2 / 10000' },
{ note: 'Считаем.', tex: 'x = {ans}' }
]
},
/* найти исходное до повышения */
{
id: 'pct-restore-before', topic: 'percents', order: 9, subject: 'algebra', grade: 8, kind: 'compute',
title: 'Цена до повышения',
pick: { abase: [1, 9], pidx: [1, 8] },
derive: { a: 'abase*100', p: 'pidx*5', b: 'abase*(100 + pidx*5)', val: 'abase*100' },
lhs: 'x', rhs: '{b}*100/(100 + {p})', display: 'После повышения на {p}% цена стала {b} руб. Какой была цена до повышения (в рублях)?',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'Новая цена — это (100 + {p})% от старой, то есть старая × (100 + {p})/100 = {b}.', tex: '{b} = x * (100 + {p}) / 100' },
{ note: 'Выражаем старую цену:', tex: 'x = {b} * 100 / (100 + {p})' },
{ note: 'Считаем.', tex: 'x = {ans}' }
]
},
/* ── Текстовые: движение, работа, смеси, прибыль ── */
/* встречное движение */
{
id: 'app-meet', topic: 'applied', order: 6, subject: 'algebra', grade: 7, kind: 'compute',
title: 'Встречное движение',
pick: { u: [20, 70], v: [20, 70], t: [2, 6] },
derive: { S: '(u + v)*t', val: 't' },
lhs: 'x', rhs: '{S}/({u}+{v})', display: 'Из двух городов навстречу выехали машины со скоростями {u} и {v} км/ч. Расстояние между городами {S} км. Через сколько часов они встретятся?',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'При встречном движении скорости складываются — машины сближаются на ({u}+{v}) км/ч.', tex: '{u} + {v}' },
{ note: 'Время до встречи — расстояние ÷ скорость сближения.', tex: 'x = {S} / ({u} + {v})' },
{ note: 'Считаем.', tex: 'x = {ans}' }
]
},
/* движение вдогонку */
{
id: 'app-overtake', topic: 'applied', order: 7, subject: 'algebra', grade: 8, kind: 'compute',
title: 'Движение вдогонку',
pick: { u: [10, 40], g: [5, 30], t: [2, 6] },
derive: { v: 'u + g', d: 'g*t', val: 't' },
lhs: 'x', rhs: '{d}/({v}-{u})', display: 'Велосипедист едет со скоростью {u} км/ч, мотоциклист — со скоростью {v} км/ч, отставая на {d} км. Через сколько часов мотоциклист догонит велосипедиста?',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'При движении вдогонку скорость сближения — разность скоростей: {v} − {u}.', tex: '{v} - {u}' },
{ note: 'Время — отставание ÷ скорость сближения.', tex: 'x = {d} / ({v} - {u})' },
{ note: 'Считаем.', tex: 'x = {ans}' }
]
},
/* движение по реке (против течения) */
{
id: 'app-upstream', topic: 'applied', order: 8, subject: 'algebra', grade: 7, kind: 'compute',
title: 'Скорость против течения',
pick: { v: [8, 25], c: [1, 6] }, constraint: 'c < v',
derive: { val: 'v - c' },
lhs: 'x', rhs: '{v}-{c}', display: 'Собственная скорость лодки {v} км/ч, скорость течения {c} км/ч. С какой скоростью лодка идёт против течения (км/ч)?',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'Против течения скорость лодки уменьшается на скорость течения.', tex: 'x = {v} - {c}' },
{ note: 'Считаем.', tex: 'x = {ans}' }
]
},
/* совместная работа */
{
id: 'app-work-joint', topic: 'applied', order: 9, subject: 'algebra', grade: 8, kind: 'compute',
title: 'Совместная работа',
pick: { t: [2, 6], a: [3, 14] }, constraint: 'a > t',
derive: { b: 'a*t/(a - t)', val: 't' },
require: 'mod(a*t, a - t) == 0 && b >= 2 && b <= 60',
lhs: 'x', rhs: '{a}*{b}/({a}+{b})', display: 'Первый рабочий выполнит работу за {a} ч, второй — за {b} ч. За сколько часов они выполнят её, работая вместе?',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'За час первый делает 1/{a} работы, второй 1/{b}. Вместе их производительности складываются.', tex: '1/{a} + 1/{b}' },
{ note: 'Время совместной работы — это произведение, делённое на сумму:', tex: 'x = {a} * {b} / ({a} + {b})' },
{ note: 'Считаем.', tex: 'x = {ans}' }
]
},
/* смешивание двух растворов */
{
id: 'app-mix-blend', topic: 'applied', order: 10, subject: 'algebra', grade: 9, kind: 'compute',
title: 'Концентрация смеси',
pick: { m1: [1, 6], m2: [1, 6], p1: [10, 40], p2: [50, 90] },
derive: { val: '(m1*p1 + m2*p2)/(m1 + m2)' },
require: 'mod(m1*p1 + m2*p2, m1 + m2) == 0',
lhs: 'x', rhs: '({m1}*{p1} + {m2}*{p2})/({m1}+{m2})', display: 'Смешали {m1} кг раствора {p1}% и {m2} кг раствора {p2}%. Какова концентрация (в процентах) полученной смеси?',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'Вещества в первом растворе: {m1}·{p1}/100, во втором: {m2}·{p2}/100.', tex: '{m1} * {p1} / 100 + {m2} * {p2} / 100' },
{ note: 'Концентрация смеси — всё вещество ÷ общую массу, в процентах:', tex: 'x = ({m1} * {p1} + {m2} * {p2}) / ({m1} + {m2})' },
{ note: 'Считаем.', tex: 'x = {ans}' }
]
},
/* прибыль в процентах */
{
id: 'app-profit-pct', topic: 'applied', order: 11, subject: 'algebra', grade: 8, kind: 'compute',
title: 'Прибыль в процентах',
pick: { cbase: [1, 9], pidx: [1, 10] },
derive: { c: 'cbase*100', p: 'pidx*5', s: 'cbase*(100 + pidx*5)', val: 'pidx*5' },
lhs: 'x', rhs: '100*({s} - {c})/{c}', display: 'Товар купили за {c} руб, а продали за {s} руб. Сколько процентов прибыли получили?',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'Прибыль в рублях: {s} − {c}.', tex: '{s} - {c}' },
{ note: 'Сколько это процентов от закупочной цены — делим на {c} и умножаем на 100.', tex: 'x = 100 * ({s} - {c}) / {c}' },
{ note: 'Считаем.', tex: 'x = {ans}' }
]
},
/* ═══════════════════════════════════════════════════════════════════════
V4.1 — Группа 3: выражения (упрощение/формулы/степени) + новые формулировки
(вставь-пропуск, найди-ошибку, какой закон, упрости-и-вычисли). simplify —
проверка эквивалентностью (любая равная форма принимается); compute — целое.
═══════════════════════════════════════════════════════════════════════ */
/* ── Упрощение ── */
/* привести подобные с двумя переменными */
{
id: 'simp-like-multivar', topic: 'simplify', order: 3, subject: 'algebra', grade: 7, kind: 'simplify',
title: 'Подобные (две буквы)',
pick: { a: [2, 7], b: [2, 7], c: [1, 6], d: [1, 6] },
derive: { sx: 'a + c', sy: 'b + d' },
srcExpr: '{a}*x + {b}*y + {c}*x + {d}*y', answerExpr: '{sx}*x + {sy}*y', answerVars: ['x', 'y'],
display: 'Упростите: {a}x + {b}y + {c}x + {d}y',
solution: [
{ note: 'Группируем подобные: слагаемые с x и слагаемые с y отдельно.', tex: '({a} + {c})x + ({b} + {d})y' },
{ note: 'Складываем коэффициенты.', tex: '{sx}x + {sy}y' }
]
},
/* привести подобные со свободным членом */
{
id: 'simp-like-const', topic: 'simplify', order: 4, subject: 'algebra', grade: 7, kind: 'simplify',
title: 'Подобные с числом',
pick: { a: [2, 8], c: [1, 7], b: [1, 9], d: [1, 9] },
derive: { sx: 'a + c', sc: 'b + d' },
srcExpr: '{a}*x + {b} + {c}*x + {d}', answerExpr: '{sx}*x + {sc}', answerVars: ['x'],
display: 'Упростите: {a}x + {b} + {c}x + {d}',
solution: [
{ note: 'Складываем отдельно слагаемые с x и отдельно числа.', tex: '({a} + {c})x + ({b} + {d})' },
{ note: 'Получаем.', tex: '{sx}x + {sc}' }
]
},
/* вычесть скобку (знаки) */
{
id: 'simp-sub-bracket', topic: 'simplify', order: 5, subject: 'algebra', grade: 7, kind: 'simplify',
title: 'Вычесть скобку',
pick: { a: [4, 9], c: [1, 3], b: [5, 12], d: [1, 4] },
constraint: 'c < a && d < b',
derive: { sx: 'a - c', sc: 'b - d' },
srcExpr: '{a}*x + {b} - ({c}*x + {d})', answerExpr: '{sx}*x + {sc}', answerVars: ['x'],
display: 'Упростите: {a}x + {b} ({c}x + {d})',
solution: [
{ note: 'Раскрываем скобку: знак «минус» перед ней меняет знаки ВСЕХ слагаемых внутри.', tex: '{a}x + {b} - {c}x - {d}' },
{ note: 'Приводим подобные.', tex: '{sx}x + {sc}' }
]
},
/* раскрыть и привести */
{
id: 'simp-distribute-combine', topic: 'simplify', order: 6, subject: 'algebra', grade: 7, kind: 'simplify',
title: 'Раскрыть и привести',
pick: { a: [2, 6], b: [1, 8], c: [1, 7] },
derive: { ab: 'a*b', sx: 'a + c' },
srcExpr: '{a}*(x + {b}) + {c}*x', answerExpr: '{sx}*x + {ab}', answerVars: ['x'],
display: 'Упростите: {a}(x + {b}) + {c}x',
solution: [
{ note: 'Раскрываем скобку — умножаем {a} на каждое слагаемое.', tex: '{a}x + {ab} + {c}x' },
{ note: 'Приводим подобные при x.', tex: '{sx}x + {ab}' }
]
},
/* вынести общий множитель */
{
id: 'simp-factor-common', topic: 'simplify', order: 7, subject: 'algebra', grade: 7, kind: 'simplify',
title: 'Вынести множитель',
pick: { a: [2, 6], c: [2, 7], d: [1, 8] },
derive: { ac: 'a*c', ad: 'a*d' },
srcExpr: '{ac}*x + {ad}', answerExpr: '{a}*({c}*x + {d})', answerVars: ['x'],
display: 'Вынесите общий множитель: {ac}x + {ad}',
solution: [
{ note: 'Оба слагаемых делятся на {a} — это общий множитель.', tex: '{ac}x + {ad}' },
{ note: 'Выносим {a} за скобку.', tex: '{a}*({c}x + {d})' }
]
},
/* группировка */
{
id: 'simp-factor-group', topic: 'simplify', order: 8, subject: 'algebra', grade: 8, kind: 'simplify',
title: 'Группировка',
pick: { a: [1, 7], b: [1, 7] },
srcExpr: 'x*(x + {a}) + {b}*(x + {a})', answerExpr: '(x + {a})*(x + {b})', answerVars: ['x'],
display: 'Разложите на множители: x(x + {a}) + {b}(x + {a})',
solution: [
{ note: 'В обоих слагаемых есть общая скобка (x + {a}). Выносим её.', tex: '(x + {a})*(x + {b})' },
{ note: 'Это и есть разложение на множители.', tex: '(x + {a})(x + {b})' }
]
},
/* упростить и вычислить при x = x0 */
{
id: 'simp-eval-at', topic: 'simplify', order: 9, subject: 'algebra', grade: 7, kind: 'compute',
title: 'Упростить и вычислить',
pick: { a: [2, 7], b: [2, 7], x0: [1, 5] },
derive: { s: 'a + b', val: '(a + b)*x0' },
lhs: 'x', rhs: '({a} + {b})*{x0}', display: 'Упростите {a}x + {b}x и найдите значение при x = {x0}.',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'Приводим подобные: {a}x + {b}x = {s}x.', tex: '{a}x + {b}x = {s}x' },
{ note: 'Подставляем x = {x0}.', tex: 'x = {s} * {x0}' },
{ note: 'Считаем.', tex: 'x = {ans}' }
]
},
/* ── Формулы сокращённого умножения (обратные + расширенные) ── */
/* разложить разность квадратов (обратно) */
{
id: 'diff-sq-factor', topic: 'formulas', order: 4, subject: 'algebra', grade: 8, kind: 'simplify',
title: 'Разложить разность квадратов',
pick: { a: [2, 9] },
derive: { a2: 'a*a' },
srcExpr: 'x^2 - {a2}', answerExpr: '(x - {a})*(x + {a})', answerVars: ['x'],
display: 'Разложите на множители: x² − {a2}',
solution: [
{ note: 'Это разность квадратов: x² − {a2} = x² − {a}². Применяем формулу a² − b² = (a b)(a + b).', tex: 'x^2 - {a}^2' },
{ note: 'Получаем произведение.', tex: '(x - {a})*(x + {a})' }
]
},
/* свернуть полный квадрат (обратно) */
{
id: 'sq-trinom-factor', topic: 'formulas', order: 5, subject: 'algebra', grade: 8, kind: 'simplify',
title: 'Свернуть в квадрат',
pick: { a: [1, 9] },
derive: { a2: 'a*a', a2x: '2*a' },
srcExpr: 'x^2 + {a2x}*x + {a2}', answerExpr: '(x + {a})^2', answerVars: ['x'],
display: 'Разложите на множители: x² + {a2x}x + {a2}',
solution: [
{ note: 'Это полный квадрат: средний член {a2x}x = 2·{a}·x, свободный {a2} = {a}².', tex: 'x^2 + 2*{a}*x + {a}^2' },
{ note: 'Сворачиваем по формуле (x + {a})².', tex: '(x + {a})^2' }
]
},
/* квадрат суммы с коэффициентом */
{
id: 'sq-sum-coef', topic: 'formulas', order: 6, subject: 'algebra', grade: 8, kind: 'simplify',
title: 'Квадрат суммы (с коэф.)',
pick: { a: [1, 6], b: [2, 4] },
derive: { b2: 'b*b', a2: 'a*a', mid: '2*a*b' },
srcExpr: '({b}*x + {a})^2', answerExpr: '{b2}*x^2 + {mid}*x + {a2}', answerVars: ['x'],
display: 'Раскройте: ({b}x + {a})²',
solution: [
{ note: 'Формула квадрата суммы: (bx + a)² = (bx)² + 2·bx·a + a².', tex: '({b}x)^2 + 2*{b}*{a}*x + {a}^2' },
{ note: 'Считаем коэффициенты.', tex: '{b2}*x^2 + {mid}*x + {a2}' }
]
},
/* куб суммы */
{
id: 'cube-sum', topic: 'formulas', order: 7, subject: 'algebra', grade: 9, kind: 'simplify',
title: 'Куб суммы',
pick: { a: [1, 5] },
derive: { c1: '3*a', c2: '3*a*a', c3: 'a*a*a' },
srcExpr: '(x + {a})^3', answerExpr: 'x^3 + {c1}*x^2 + {c2}*x + {c3}', answerVars: ['x'],
display: 'Раскройте: (x + {a})³',
solution: [
{ note: 'Куб суммы: (x + a)³ = x³ + 3a·x² + 3a²·x + a³.', tex: 'x^3 + 3*{a}*x^2 + 3*{a}^2*x + {a}^3' },
{ note: 'Считаем коэффициенты.', tex: 'x^3 + {c1}*x^2 + {c2}*x + {c3}' }
]
},
/* сумма кубов (разложение) */
{
id: 'sum-cubes-factor', topic: 'formulas', order: 8, subject: 'algebra', grade: 9, kind: 'simplify',
title: 'Сумма кубов',
pick: { a: [2, 5] },
derive: { a3: 'a*a*a', a2: 'a*a' },
srcExpr: 'x^3 + {a3}', answerExpr: '(x + {a})*(x^2 - {a}*x + {a2})', answerVars: ['x'],
display: 'Разложите на множители: x³ + {a3}',
solution: [
{ note: 'Это сумма кубов: x³ + {a3} = x³ + {a}³. Формула a³ + b³ = (a + b)(a² ab + b²).', tex: 'x^3 + {a}^3' },
{ note: 'Получаем произведение.', tex: '(x + {a})*(x^2 - {a}*x + {a2})' }
]
},
/* вставь пропущенное число в тождестве */
{
id: 'fmt-blank-square', topic: 'formulas', order: 9, subject: 'algebra', grade: 8, kind: 'compute',
title: 'Вставь число (тождество)',
pick: { a: [1, 9] },
derive: { a2x: '2*a', val: 'a*a' },
lhs: 'x', rhs: '{val}', display: 'Вставьте пропущенное число: (x + {a})² = x² + {a2x}x + ▢',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'Квадрат суммы: (x + {a})² = x² + 2·{a}·x + {a}². Пропущен свободный член {a}².', tex: 'x = {a}^2' },
{ note: 'Считаем.', tex: 'x = {ans}' }
]
},
/* найди ошибку: пропущенный средний член */
{
id: 'fmt-fix-square', topic: 'formulas', order: 10, subject: 'algebra', grade: 8, kind: 'compute',
title: 'Найди ошибку',
pick: { a: [2, 9] },
derive: { a2: 'a*a', val: '2*a' },
lhs: 'x', rhs: '{val}', display: 'Ученик записал (x + {a})² = x² + {a2}. Это неверно: пропущен средний член. Чему равен коэффициент при x?',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'В формуле (x + {a})² есть средний член 2·{a}·x. Ученик его потерял.', tex: 'x = 2 * {a}' },
{ note: 'Считаем коэффициент.', tex: 'x = {ans}' }
]
},
/* ── Степени ── */
/* частное степеней */
{
id: 'pow-div', topic: 'powers', order: 4, subject: 'algebra', grade: 8, kind: 'simplify',
title: 'Частное степеней',
pick: { a: [5, 9], b: [1, 4] }, constraint: 'a > b',
derive: { d: 'a - b' },
srcExpr: 'x^{a}/x^{b}', answerExpr: 'x^{d}', answerVars: ['x'],
display: 'Упростите: x^{a} / x^{b}',
solution: [
{ note: 'При делении степеней с одинаковым основанием показатели вычитаются: {a} − {b}.', tex: 'x^{a} / x^{b}' },
{ note: 'Получаем.', tex: 'x^{d}' }
]
},
/* степень произведения */
{
id: 'pow-product-base', topic: 'powers', order: 5, subject: 'algebra', grade: 8, kind: 'simplify',
title: 'Степень произведения',
pick: { a: [2, 4], n: [2, 3] },
derive: { an: 'a^n' },
srcExpr: '({a}*x)^{n}', answerExpr: '{an}*x^{n}', answerVars: ['x'],
display: 'Раскройте степень: ({a}x)^{n}',
solution: [
{ note: 'В степень возводится каждый множитель: ({a}x)^{n} = {a}^{n}·x^{n}.', tex: '{a}^{n}*x^{n}' },
{ note: 'Считаем {a}^{n}.', tex: '{an}*x^{n}' }
]
},
/* дробь степеней (объединить и сократить) */
{
id: 'pow-frac-combine', topic: 'powers', order: 6, subject: 'algebra', grade: 8, kind: 'simplify',
title: 'Дробь степеней',
pick: { a: [2, 5], b: [2, 5], c: [1, 4] }, require: 'a + b - c >= 1',
derive: { d: 'a + b - c' },
srcExpr: '(x^{a}*x^{b})/x^{c}', answerExpr: 'x^{d}', answerVars: ['x'],
display: 'Упростите: (x^{a} · x^{b}) / x^{c}',
solution: [
{ note: 'В числителе складываем показатели: {a} + {b}.', tex: 'x^({a} + {b}) / x^{c}' },
{ note: 'При делении вычитаем показатель знаменателя: ({a} + {b}) {c}.', tex: 'x^{d}' }
]
},
/* степени одного основания — число */
{
id: 'pow-numeric-laws', topic: 'powers', order: 7, subject: 'algebra', grade: 8, kind: 'compute',
title: 'Произведение степеней (число)',
pick: { b: [2, 3], a: [2, 3], c: [1, 2] },
derive: { val: 'b^(a + c)' },
lhs: 'x', rhs: '{b}^{a}*{b}^{c}', display: 'Вычислите {b}^{a} · {b}^{c} (запишите числом).',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'У одинакового основания показатели складываются: {a} + {c}.', tex: 'x = {b}^({a} + {c})' },
{ note: 'Считаем.', tex: 'x = {ans}' }
]
},
/* стандартный вид числа */
{
id: 'pow-standard-form', topic: 'powers', order: 8, subject: 'algebra', grade: 8, kind: 'compute',
title: 'Стандартный вид числа',
pick: { a: [2, 9], n: [2, 4] },
derive: { val: 'a*10^n' },
lhs: 'x', rhs: '{a}*10^{n}', display: 'Запишите число {a}·10^{n} в обычном виде.',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: '{a}·10^{n} — это {a} с {n} нулями.', tex: 'x = {a} * 10^{n}' },
{ note: 'Считаем.', tex: 'x = {ans}' }
]
},
/* какой показатель (закон степеней) */
{
id: 'pow-which-law', topic: 'powers', order: 9, subject: 'algebra', grade: 8, kind: 'compute',
title: 'Какой показатель',
pick: { a: [2, 6], b: [2, 6] },
derive: { val: 'a + b' },
lhs: 'x', rhs: '{a} + {b}', display: 'В какую степень нужно возвести x, чтобы x^{a} · x^{b} = x^▢ ?',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'При умножении степеней с одинаковым основанием показатели складываются.', tex: 'x = {a} + {b}' },
{ note: 'Считаем.', tex: 'x = {ans}' }
]
},
/* ═══════════════════════════════════════════════════════════════════════
V4.1 — Группа 4: квадратные уравнения и прогрессии. «Корень-вперёд» →
целые корни/ответы; roots проверяет каждый корень, simplify — эквивалентность.
═══════════════════════════════════════════════════════════════════════ */
/* ── Квадратные ── */
/* ax² + bx = 0 — вынесение x */
{
id: 'quad-incomplete-bx', topic: 'quadratic', order: 3, subject: 'algebra', grade: 8, kind: 'roots',
title: 'ax² + bx = 0',
pick: { a: [2, 5], r: [-6, 6] }, constraint: 'r != 0',
derive: { b: '-a*r' },
lhs: '{a}*x^2 + {b}*x', rhs: '0', display: '{a}x² + {b}x = 0',
answerVar: 'x', answers: ['0', 'r'], integerAnswer: true,
solution: [
{ note: 'Выносим общий множитель x за скобку.', tex: 'x*({a}*x + {b}) = 0' },
{ note: 'Произведение равно нулю — первый корень:', tex: 'x = 0' },
{ note: 'Из второго множителя {a}x + {b} = 0:', tex: 'x = {r}' }
]
},
/* ax² = c — извлечение корня */
{
id: 'quad-incomplete-c', topic: 'quadratic', order: 4, subject: 'algebra', grade: 8, kind: 'roots',
title: 'ax² = c',
pick: { a: [1, 4], r: [2, 9] },
derive: { c: 'a*r*r', r2: 'r*r' },
lhs: '{a}*x^2 - {c}', rhs: '0', display: '{a}x² {c} = 0',
answerVar: 'x', answers: ['r', '-r'], integerAnswer: true,
solution: [
{ note: 'Переносим {c} вправо и делим на {a}.', tex: 'x^2 = {r2}' },
{ note: 'Извлекаем квадратный корень — первый корень:', tex: 'x = {r}' },
{ note: 'Второй корень — со знаком минус:', tex: 'x = -{r}' }
]
},
/* ax² + bx + c = 0 — через дискриминант (чистый D) */
{
id: 'quad-disc-clean', topic: 'quadratic', order: 5, subject: 'algebra', grade: 8, kind: 'roots',
title: 'Через дискриминант',
pick: { a: [2, 3], r1: [-4, 4], r2: [-4, 4] }, constraint: 'r1 != r2',
derive: { b: '-a*(r1 + r2)', c: 'a*r1*r2', disc: 'a*a*(r1 - r2)*(r1 - r2)', sqd: 'a*abs(r1 - r2)' },
lhs: '{a}*x^2 + {b}*x + {c}', rhs: '0', display: '{a}x² + {b}x + {c} = 0',
answerVar: 'x', answers: ['r1', 'r2'], integerAnswer: true,
solution: [
{ note: 'Дискриминант D = b² − 4ac.', tex: 'D = {b}^2 - 4*{a}*{c}' },
{ note: 'Считаем дискриминант.', tex: 'D = {disc}' },
{ note: 'Корни x = (b ± √D)/(2a), где √D = {sqd}. Первый корень:', tex: 'x = {r1}' },
{ note: 'Второй корень:', tex: 'x = {r2}' }
]
},
/* разложить трёхчлен на множители */
{
id: 'quad-trinomial-factor', topic: 'quadratic', order: 6, subject: 'algebra', grade: 8, kind: 'simplify',
title: 'Разложить трёхчлен',
pick: { r1: [-6, 6], r2: [-6, 6] }, constraint: 'r1 != r2',
derive: { b: '-(r1 + r2)', c: 'r1*r2' },
srcExpr: 'x^2 + {b}*x + {c}', answerExpr: '(x - {r1})*(x - {r2})', answerVars: ['x'],
display: 'Разложите на множители: x² + {b}x + {c}',
solution: [
{ note: 'По теореме Виета ищем два числа с суммой −({b}) и произведением {c}: это {r1} и {r2}.', tex: '' },
{ note: 'Разложение на множители:', tex: '(x - {r1})*(x - {r2})' }
]
},
/* найти b по одному корню */
{
id: 'quad-find-b', topic: 'quadratic', order: 7, subject: 'algebra', grade: 8, kind: 'compute',
title: 'Найти b по корню',
pick: { r: [-6, 6], k: [-6, 6] }, constraint: 'r != 0 && k != 0 && k != r',
derive: { c: 'r*k', b: '-(r + k)' },
lhs: 'x', rhs: '{b}', display: 'Один из корней уравнения x² + bx + {c} = 0 равен {r}. Найдите b.',
answerVar: 'x', answer: 'b', integerAnswer: true,
solution: [
{ note: 'Подставляем корень x = {r} в уравнение.', tex: '{r}^2 + b*{r} + {c} = 0' },
{ note: 'Выражаем b.', tex: 'b = -({r}^2 + {c}) / {r}' },
{ note: 'Считаем.', tex: 'b = {ans}' }
]
},
/* сколько корней (знак дискриминанта) */
{
id: 'quad-count-roots', topic: 'quadratic', order: 8, subject: 'algebra', grade: 8, kind: 'compute',
title: 'Сколько корней',
pick: { a: [1, 3], b: [-8, 8], c: [-6, 9] },
derive: { disc: 'b*b - 4*a*c', nroots: 'disc > 0 ? 2 : (disc == 0 ? 1 : 0)' },
lhs: 'x', rhs: '{nroots}', display: 'Сколько действительных корней у уравнения {a}x² + {b}x + {c} = 0? (введите 0, 1 или 2)',
answerVar: 'x', answer: 'nroots', integerAnswer: true,
solution: [
{ note: 'Считаем дискриминант D = b² − 4ac.', tex: 'D = {b}^2 - 4*{a}*{c}' },
{ note: 'D = {disc}. Если D > 0 — два корня, D = 0 — один, D < 0 — корней нет.', tex: 'D = {disc}' },
{ note: 'Ответ.', tex: 'x = {ans}' }
]
},
/* абсцисса вершины параболы */
{
id: 'quad-vertex-x', topic: 'quadratic', order: 9, subject: 'algebra', grade: 8, kind: 'compute',
title: 'Вершина параболы',
pick: { a: [1, 4], xv: [-6, 6], c: [-5, 9] }, constraint: 'xv != 0',
derive: { b: '-2*a*xv' },
lhs: 'x', rhs: '{xv}', display: 'Найдите абсциссу вершины параболы y = {a}x² + {b}x + {c} (ось симметрии x₀).',
answerVar: 'x', answer: 'xv', integerAnswer: true,
solution: [
{ note: 'Абсцисса вершины: x₀ = b/(2a).', tex: 'x = -{b} / (2*{a})' },
{ note: 'Считаем.', tex: 'x = {ans}' }
]
},
/* выделить полный квадрат */
{
id: 'quad-complete-square', topic: 'quadratic', order: 10, subject: 'algebra', grade: 9, kind: 'simplify',
title: 'Выделить полный квадрат',
pick: { p: [-6, 6], k: [-5, 9] }, constraint: 'p != 0',
derive: { b: '2*p', c: 'p*p + k' },
srcExpr: 'x^2 + {b}*x + {c}', answerExpr: '(x + {p})^2 + {k}', answerVars: ['x'],
display: 'Выделите полный квадрат: x² + {b}x + {c}',
solution: [
{ note: 'Берём половину коэффициента при x: {b}/2 = {p}. Прибавляем и вычитаем {p}².', tex: 'x^2 + {b}*x + {p}^2 - {p}^2 + {c}' },
{ note: 'Сворачиваем полный квадрат.', tex: '(x + {p})^2 + {k}' }
]
},
/* сумма корней (Виета) */
{
id: 'quad-roots-sum', topic: 'quadratic', order: 11, subject: 'algebra', grade: 8, kind: 'compute',
title: 'Сумма корней (Виета)',
pick: { r1: [-7, 7], r2: [-7, 7] }, constraint: 'r1 != r2',
derive: { b: '-(r1 + r2)', c: 'r1*r2', sum: 'r1 + r2' },
lhs: 'x', rhs: '{r1} + {r2}', display: 'Найдите сумму корней уравнения x² + {b}x + {c} = 0.',
answerVar: 'x', answer: 'sum', integerAnswer: true,
solution: [
{ note: 'По теореме Виета сумма корней приведённого уравнения равна −b.', tex: 'x = -({b})' },
{ note: 'Считаем.', tex: 'x = {ans}' }
]
},
/* произведение корней (Виета) */
{
id: 'quad-roots-prod', topic: 'quadratic', order: 12, subject: 'algebra', grade: 8, kind: 'compute',
title: 'Произведение корней (Виета)',
pick: { r1: [-7, 7], r2: [-7, 7] }, constraint: 'r1 != r2 && r1 != 0 && r2 != 0',
derive: { b: '-(r1 + r2)', c: 'r1*r2', prod: 'r1*r2' },
lhs: 'x', rhs: '{r1}*{r2}', display: 'Найдите произведение корней уравнения x² + {b}x + {c} = 0.',
answerVar: 'x', answer: 'prod', integerAnswer: true,
solution: [
{ note: 'По теореме Виета произведение корней приведённого уравнения равно свободному члену c.', tex: 'x = {c}' },
{ note: 'Считаем.', tex: 'x = {ans}' }
]
},
/* составить уравнение по корням */
{
id: 'quad-build-eq', topic: 'quadratic', order: 13, subject: 'algebra', grade: 8, kind: 'simplify',
title: 'Составить уравнение по корням',
pick: { r1: [-6, 6], r2: [-6, 6] }, constraint: 'r1 != r2',
derive: { b: '-(r1 + r2)', c: 'r1*r2' },
srcExpr: '(x - {r1})*(x - {r2})', answerExpr: 'x^2 + {b}*x + {c}', answerVars: ['x'],
display: 'Составьте приведённое квадратное уравнение (левую часть) с корнями {r1} и {r2}.',
solution: [
{ note: 'По Виета: сумма корней = −b, произведение = c. Значит b = ({r1} + {r2}), c = {r1}·{r2}.', tex: '' },
{ note: 'Левая часть уравнения:', tex: 'x^2 + {b}*x + {c}' }
]
},
/* двойной (кратный) корень */
{
id: 'quad-double-root', topic: 'quadratic', order: 14, subject: 'algebra', grade: 8, kind: 'roots',
title: 'Кратный корень (D = 0)',
pick: { p: [-7, 7] }, constraint: 'p != 0',
derive: { b: '2*p', c: 'p*p' },
lhs: 'x^2 + {b}*x + {c}', rhs: '0', display: 'x² + {b}x + {c} = 0',
answerVar: 'x', answers: ['-p'], integerAnswer: true,
solution: [
{ note: 'Это полный квадрат: x² + {b}x + {c} = (x + {p})².', tex: '(x + {p})^2 = 0' },
{ note: 'Дискриминант равен нулю — единственный корень:', tex: 'x = -{p}' }
]
},
/* ── Прогрессии ── */
/* сумма n членов арифметической прогрессии */
{
id: 'prog-arith-sum', topic: 'progressions', order: 3, subject: 'algebra', grade: 9, kind: 'compute',
title: 'Сумма арифм. прогрессии',
pick: { a: [-8, 12], d: [-6, 6], n: [4, 12] }, require: 'd != 0',
derive: { an: 'a + (n - 1)*d', sum: 'n*(a + an)/2' },
lhs: 'x', rhs: '{n}*({a} + {an})/2', display: 'Арифметическая прогрессия: a₁ = {a}, d = {d}. Найдите сумму первых {n} членов.',
answerVar: 'x', answer: 'sum', integerAnswer: true,
solution: [
{ note: 'Сначала {n}-й член: aₙ = a₁ + (n 1)d = {an}.', tex: '{a} + ({n} - 1)*{d} = {an}' },
{ note: 'Сумма Sₙ = n(a₁ + aₙ)/2.', tex: 'x = {n} * ({a} + {an}) / 2' },
{ note: 'Считаем.', tex: 'x = {ans}' }
]
},
/* найти разность d по двум членам */
{
id: 'prog-arith-find-d', topic: 'progressions', order: 4, subject: 'algebra', grade: 9, kind: 'compute',
title: 'Найти разность d',
pick: { a: [-6, 10], d: [-5, 5], n: [4, 10] }, require: 'd != 0',
derive: { an: 'a + (n - 1)*d' },
lhs: 'x', rhs: '({an} - {a})/({n} - 1)', display: 'В арифметической прогрессии a₁ = {a}, а член с номером {n} равен {an}. Найдите разность d.',
answerVar: 'x', answer: 'd', integerAnswer: true,
solution: [
{ note: 'Из формулы aₙ = a₁ + (n − 1)d выражаем d.', tex: 'd = ({an} - {a}) / ({n} - 1)' },
{ note: 'Считаем.', tex: 'd = {ans}' }
]
},
/* найти номер члена n */
{
id: 'prog-arith-find-n', topic: 'progressions', order: 5, subject: 'algebra', grade: 9, kind: 'compute',
title: 'Номер члена прогрессии',
pick: { a: [-6, 10], d: [-5, 5], n: [4, 12] }, require: 'd != 0',
derive: { an: 'a + (n - 1)*d' },
lhs: 'x', rhs: '({an} - {a})/{d} + 1', display: 'В арифметической прогрессии a₁ = {a}, d = {d}. Каким по счёту является член, равный {an}?',
answerVar: 'x', answer: 'n', integerAnswer: true,
solution: [
{ note: 'Из aₙ = a₁ + (n − 1)d выражаем номер n.', tex: 'n = ({an} - {a}) / {d} + 1' },
{ note: 'Считаем.', tex: 'n = {ans}' }
]
},
/* среднее арифметическое (вставить член) */
{
id: 'prog-arith-mean', topic: 'progressions', order: 6, subject: 'algebra', grade: 9, kind: 'compute',
title: 'Среднее арифметическое',
pick: { m: [-9, 9], d: [-7, 7] }, require: 'd != 0',
derive: { a: 'm - d', c: 'm + d' },
lhs: 'x', rhs: '({a} + {c})/2', display: 'Числа {a}, x, {c} образуют арифметическую прогрессию. Найдите x.',
answerVar: 'x', answer: 'm', integerAnswer: true,
solution: [
{ note: 'Средний член равен среднему арифметическому соседних: x = (a + c)/2.', tex: 'x = ({a} + {c}) / 2' },
{ note: 'Считаем.', tex: 'x = {ans}' }
]
},
/* найти знаменатель q */
{
id: 'prog-geom-find-q', topic: 'progressions', order: 7, subject: 'algebra', grade: 9, kind: 'compute',
title: 'Найти знаменатель q',
pick: { b: [1, 5], q: [2, 4] },
derive: { b2: 'b*q' },
lhs: 'x', rhs: '{b2}/{b}', display: 'Геометрическая прогрессия: b₁ = {b}, b₂ = {b2}. Найдите знаменатель q.',
answerVar: 'x', answer: 'q', integerAnswer: true,
solution: [
{ note: 'Знаменатель — отношение соседних членов: q = b₂/b₁.', tex: 'q = {b2} / {b}' },
{ note: 'Считаем.', tex: 'q = {ans}' }
]
},
/* геометрическое среднее (вставить член) */
{
id: 'prog-geom-mean', topic: 'progressions', order: 8, subject: 'algebra', grade: 9, kind: 'compute',
title: 'Геометрическое среднее',
pick: { g: [2, 10], q: [2, 3] }, require: 'mod(g, q) == 0',
derive: { a: 'g/q', c: 'g*q' },
lhs: 'x', rhs: 'sqrt({a}*{c})', display: 'Числа {a}, x, {c} образуют геометрическую прогрессию (все положительны). Найдите x.',
answerVar: 'x', answer: 'g', integerAnswer: true,
solution: [
{ note: 'Средний член геометрической прогрессии: x = √(a · c).', tex: 'x = sqrt({a} * {c})' },
{ note: 'Считаем.', tex: 'x = {ans}' }
]
},
/* сумма n членов геометрической прогрессии */
{
id: 'prog-geom-sum', topic: 'progressions', order: 9, subject: 'algebra', grade: 9, kind: 'compute',
title: 'Сумма геом. прогрессии',
pick: { b: [1, 4], q: [2, 3], n: [2, 5] },
derive: { qn: 'q^n', sum: 'b*(q^n - 1)/(q - 1)' },
lhs: 'x', rhs: '{b}*({q}^{n} - 1)/({q} - 1)', display: 'Геометрическая прогрессия: b₁ = {b}, q = {q}. Найдите сумму первых {n} членов.',
answerVar: 'x', answer: 'sum', integerAnswer: true,
solution: [
{ note: 'Сумма Sₙ = b₁(qⁿ 1)/(q 1).', tex: 'x = {b} * ({q}^{n} - 1) / ({q} - 1)' },
{ note: 'Считаем.', tex: 'x = {ans}' }
]
},
/* текстовая задача (ряды кресел) */
{
id: 'prog-arith-word', topic: 'progressions', order: 10, subject: 'algebra', grade: 9, kind: 'compute',
title: 'Задача (ряды кресел)',
pick: { a: [10, 20], d: [2, 5], n: [5, 12] },
derive: { an: 'a + (n - 1)*d', sum: 'n*(a + an)/2' },
lhs: 'x', rhs: '{n}*({a} + {an})/2', display: 'В первом ряду зала {a} кресел, в каждом следующем на {d} больше. Сколько всего кресел в {n} рядах?',
answerVar: 'x', answer: 'sum', integerAnswer: true,
solution: [
{ note: 'Кресла по рядам — арифметическая прогрессия. В последнем ряду: {a} + ({n} 1)·{d} = {an}.', tex: '{a} + ({n} - 1)*{d} = {an}' },
{ note: 'Всего кресел — сумма Sₙ = n(a₁ + aₙ)/2.', tex: 'x = {n} * ({a} + {an}) / 2' },
{ note: 'Считаем.', tex: 'x = {ans}' }
]
}
];
// Структурная сложность генератора (1 — простейшая форма, 3 — больше действий /
// скобки / дроби / переменная в обеих частях). Определяет, какой ВАРИАНТ внутри
// темы даётся на выбранном уровне сложности (не просто масштаб чисел).
var LEVELS = {
// Уравнения: ax+b=c → скобки/обе части/дроби → (ax+b)/c=d
'lin-basic': 1, 'lin-paren': 2, 'lin-both-sides': 2, 'lin-frac-denom': 2,
'lin-coef-frac': 2, 'lin-paren-both': 3, 'lin-frac-eq': 3,
// Пропорции
'prop-x-right': 1, 'prop-x-left': 1, 'prop-x-denom': 2,
// Проценты
'pct-of': 1, 'pct-what': 2, 'pct-whole': 2,
// Упрощение
'simp-like': 1, 'simp-expand': 2,
// Степени
'pow-eval': 1, 'pow-mult': 2, 'pow-pow': 3,
// Формулы сокр. умножения
'sq-sum': 2, 'sq-diff': 2, 'diff-sq': 3,
// Неравенства (смена знака — сложнее)
'ineq-lt': 1, 'ineq-ge': 1, 'ineq-flip': 3,
// Системы 2 уравнений
'sys-2x2': 2, 'sys-2x2-neg': 3,
// Задачи (текстовые)
'app-move-dist': 1, 'app-move-speed': 1, 'app-move-time': 2, 'app-alloy': 2, 'app-discount': 2,
// Квадратные
'quad-diff': 2, 'quad-factored': 3,
// Прогрессии
'prog-arith-term': 2, 'prog-geom-term': 3,
// Геометрия — Углы
'ang-adjacent': 1, 'ang-triangle': 2, 'ang-exterior': 2,
// Геометрия — Пифагор
'pyth-hyp': 2, 'pyth-leg': 3,
// Геометрия — Площади
'area-square': 1, 'area-rect': 1, 'area-triangle': 2,
'area-parallelogram': 2, 'area-trapezoid': 3, 'area-rhombus': 2,
// Геометрия — Многоугольники / Подобие
'poly-angles-sum': 1, 'poly-regular-angle': 2, 'sim-side': 1, 'sim-perimeter': 2,
// Геометрия — Окружность
'circ-length': 1, 'circ-diam': 1, 'circ-area': 2, 'circ-arc': 3,
// V4.1 — Линейные: новые формы
'lin-both-frac': 2, 'lin-x-denom': 3, 'lin-k-over-x': 2, 'lin-abs': 3,
'lin-frac-eq-frac': 3, 'lin-nested-paren': 3, 'lin-literal': 3,
'ineq-both-sides': 2, 'ineq-both-flip': 3, 'ineq-paren': 2, 'ineq-count-int': 2,
'sys-sum-diff': 1, 'sys-subst': 2, 'sys-word': 2, 'sys-3x3': 3,
// V4.1 — Пропорции/Проценты/Текстовые
'prop-direct-word': 1, 'prop-inverse-word': 2, 'prop-scale-map': 2, 'prop-compound': 3, 'prop-share-ratio': 2,
'pct-increase': 2, 'pct-decrease': 2, 'pct-change': 3, 'pct-simple-interest': 2, 'pct-compound-2y': 3, 'pct-restore-before': 3,
'app-meet': 2, 'app-overtake': 3, 'app-upstream': 2, 'app-work-joint': 3, 'app-mix-blend': 3, 'app-profit-pct': 3,
// V4.1 — Выражения (упрощение/формулы/степени)
'simp-like-multivar': 2, 'simp-like-const': 2, 'simp-sub-bracket': 3, 'simp-distribute-combine': 3,
'simp-factor-common': 2, 'simp-factor-group': 3, 'simp-eval-at': 2,
'diff-sq-factor': 3, 'sq-trinom-factor': 3, 'sq-sum-coef': 3, 'cube-sum': 3, 'sum-cubes-factor': 3,
'fmt-blank-square': 2, 'fmt-fix-square': 3,
'pow-div': 2, 'pow-product-base': 2, 'pow-frac-combine': 3, 'pow-numeric-laws': 2, 'pow-standard-form': 2, 'pow-which-law': 2,
// V4.1 — Квадратные/Прогрессии
'quad-incomplete-bx': 2, 'quad-incomplete-c': 2, 'quad-disc-clean': 3, 'quad-trinomial-factor': 2,
'quad-find-b': 3, 'quad-count-roots': 2, 'quad-vertex-x': 2, 'quad-complete-square': 3,
'quad-roots-sum': 2, 'quad-roots-prod': 2, 'quad-build-eq': 3, 'quad-double-root': 2,
'prog-arith-sum': 2, 'prog-arith-find-d': 2, 'prog-arith-find-n': 3, 'prog-arith-mean': 2,
'prog-geom-find-q': 2, 'prog-geom-mean': 3, 'prog-geom-sum': 3, 'prog-arith-word': 2,
// НОД/НОК / Дроби / Десятичные / Отрицательные
'gcd-pair': 1, 'lcm-pair': 2,
'frac-of-number': 1, 'frac-add-same': 2,
'dec-add': 1, 'dec-sub': 1, 'dec-mult': 2,
'neg-add': 1, 'neg-sub': 2, 'neg-mult': 2
};
GENERATORS.forEach(function (g) { g.level = LEVELS[g.id] || 1; });
function get(id) {
for (var i = 0; i < GENERATORS.length; i++) if (GENERATORS[i].id === id) return GENERATORS[i];
return null;
}
function byTopic(key) {
return GENERATORS.filter(function (g) { return g.topic === key; })
.sort(function (a, b) { return (a.order || 0) - (b.order || 0); });
}
global.TrainerGenerators = {
list: function () { return GENERATORS.slice(); },
topics: function () { return TOPICS.slice(); },
byTopic: byTopic,
get: get,
GENERATORS: GENERATORS,
TOPICS: TOPICS
};
})(typeof window !== 'undefined' ? window : globalThis);