Files
Learn_System/frontend/js/trainer/generators.js
T
Maxim Dolgolyov c370eaa803 feat(trainer): ИИ-тренажёр — генераторы задач + SimExpr-верификатор, прогресс, фича-флаг
- движок _trainer_engine.js: instantiate/generateBatch/verifyRoot/checkStudentAnswer/exprToLatex
- 5 генераторов уравнений 7 класса (generators.js), приём «корень-вперёд» → целые ответы
- страница /trainer: KaTeX-рендер, чипы-темы, мгновенная проверка, подсказка/решение, авто-выбор навыка
- прогресс practice_progress (мигр.081) + /api/practice/progress|attempt + LS.practiceProgressList/Submit
- фича-флаг trainer: тумблер в админке (Модули), requireFeature, FEATURE_HREFS (скрытие сайдбара+редирект), MODULE_CATALOG
- fix: подключён Lucide CDN на странице (иначе иконки сайдбара пустые)
- тесты practice.test.js (10/10); план развития plans/ai-trainer/PLAN.md

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

130 lines
5.7 KiB
JavaScript

'use strict';
/* ════════════════════════════════════════════════════════════════════════
Генераторы уравнений — 7 класс (прототип). Это ДАННЫЕ, не код.
Приём «корень-вперёд»: выбираем целый корень (или множитель) и коэффициенты,
затем ВЫВОДИМ свободный член так, чтобы ответ гарантированно был целым, а
уравнение — решаемым. Поэтому самопроверка движка (verifyRoot) всегда
проходит. Шаг решения — { note(текст), tex(формула) }; tex рендерится в KaTeX
через TrainerEngine.exprToLatex (одно равенство на шаг, без цепочек a=b=c).
Прогрессия 7 класса: простое линейное → скобки → переменная в обеих частях →
уравнение с дробью в знаменателе → дробный коэффициент. Дальше (Уровень 1):
текстовые задачи через LLM с той же подстановочной верификацией.
════════════════════════════════════════════════════════════════════════ */
(function (global) {
var GENERATORS = [
/* 1. ax + b = c */
{
id: 'lin-basic',
skill: 'linear-basic',
title: 'Линейное: ax + b = c',
grade: 7,
pick: { a: [2, 9], b: [1, 20], root: [-9, 9] },
require: 'root != 0',
derive: { c: 'a*root + b', cmb: 'a*root' }, // cmb = c - b
lhs: '{a}*x + {b}', rhs: '{c}',
display: '{a}x + {b} = {c}',
answerVar: 'x', answer: 'root', integerAnswer: true,
solution: [
{ note: 'Переносим число вправо:', tex: '{a}x = {cmb}' },
{ note: 'Делим обе части на {a}:', tex: 'x = {cmb} / {a}' },
{ note: 'Ответ:', tex: 'x = {ans}' }
]
},
/* 2. a(x + b) = c */
{
id: 'lin-paren',
skill: 'linear-parentheses',
title: 'Со скобками: a(x + b) = c',
grade: 7,
pick: { a: [2, 8], b: [1, 12], root: [-9, 9] },
require: 'root != 0',
derive: { c: 'a*(root + b)', ca: 'root + b' }, // ca = c / a
lhs: '{a}*(x + {b})', rhs: '{c}',
display: '{a}(x + {b}) = {c}',
answerVar: 'x', answer: 'root', integerAnswer: true,
solution: [
{ note: 'Делим обе части на {a}:', tex: 'x + {b} = {ca}' },
{ note: 'Переносим {b} влево:', tex: 'x = {ca} - {b}' },
{ note: 'Ответ:', tex: 'x = {ans}' }
]
},
/* 3. ax + b = cx + d */
{
id: 'lin-both-sides',
skill: 'linear-both-sides',
title: 'Переменная с двух сторон: ax + b = cx + d',
grade: 7,
pick: { a: [3, 9], c: [1, 8], b: [1, 20], root: [-9, 9] },
constraint: 'c < a', // гарантируем a - c > 0
require: 'root != 0',
derive: { d: '(a - c)*root + b', amc: 'a - c', dmb: '(a - c)*root' }, // dmb = d - b
lhs: '{a}*x + {b}', rhs: '{c}*x + {d}',
display: '{a}x + {b} = {c}x + {d}',
answerVar: 'x', answer: 'root', integerAnswer: true,
solution: [
{ note: 'Собираем x слева, числа справа:', tex: '({a} - {c})x = {d} - {b}' },
{ note: 'Приводим подобные:', tex: '{amc}x = {dmb}' },
{ note: 'Делим на {amc}:', tex: 'x = {dmb} / {amc}' },
{ note: 'Ответ:', tex: 'x = {ans}' }
]
},
/* 4. x/a + b = c (дробь в знаменателе) */
{
id: 'lin-frac-denom',
skill: 'linear-fraction-denom',
title: 'Дробь: x/a + b = c',
grade: 7,
pick: { a: [2, 6], k: [-6, 6], b: [1, 12] },
require: 'k != 0',
derive: { root: 'a*k', c: 'k + b', cmb: 'k' }, // root = a·k, cmb = c - b = k
lhs: 'x/{a} + {b}', rhs: '{c}',
display: 'x/{a} + {b} = {c}',
answerVar: 'x', answer: 'root', integerAnswer: true,
solution: [
{ note: 'Вычитаем {b}:', tex: 'x/{a} = {cmb}' },
{ note: 'Умножаем обе части на {a}:', tex: 'x = {cmb} * {a}' },
{ note: 'Ответ:', tex: 'x = {ans}' }
]
},
/* 5. (a·x)/b = c (дробный коэффициент) */
{
id: 'lin-coef-frac',
skill: 'linear-coef-frac',
title: 'Дробный коэффициент: ax/b = c',
grade: 7,
pick: { a: [2, 5], b: [2, 5], m: [-5, 5] },
require: 'm != 0',
derive: { root: 'b*m', c: 'a*m', cb: 'a*m*b' }, // root = b·m, c = a·m, cb = c·b
lhs: '{a}*x/{b}', rhs: '{c}',
display: '{a}x/{b} = {c}',
answerVar: 'x', answer: 'root', integerAnswer: true,
solution: [
{ note: 'Умножаем обе части на {b}:', tex: '{a}x = {cb}' },
{ note: 'Делим на {a}:', tex: 'x = {cb} / {a}' },
{ note: 'Ответ:', tex: 'x = {ans}' }
]
}
];
function get(id) {
for (var i = 0; i < GENERATORS.length; i++) if (GENERATORS[i].id === id) return GENERATORS[i];
return null;
}
global.TrainerGenerators = {
list: function () { return GENERATORS.slice(); },
get: get,
GENERATORS: GENERATORS
};
})(typeof window !== 'undefined' ? window : globalThis);