feat(trainer): тема «Окружность» + режим «читать условие с чертежа»
Окружность (новая геом-тема g-circle, 9 кл, π ≈ 3,14 → ответ — конечная десятичная дробь, ученик вводит её): 4 генератора — длина окружности по радиусу (2πr), по диаметру (πd), площадь круга (πr²), длина дуги ((n/360)·2πr, n=45·k, require r·k чётно → дробь конечная). Новые типы фигур: circle (радиус/диаметр/ заливка) и circle-arc (два радиуса под центральным углом + выделенная дуга). Режим «читать значения с чертежа»: у всех 19 геом-генераторов добавлено figurePrompt (краткое условие); переключатель «Текст / На чертеже» (#tr-figmode) на странице, выбор сохраняется в localStorage. В режиме чертежа числа берутся с фигуры, текст минимальный. Движок прокидывает figurePrompt; showStatement выбирает полный текст или промпт; renderFigureToggle показан только для задач с чертежом; для текстовых/алгебраических задач режим скрыт, проверка ответа от режима не зависит. На чертеж n-угольника выведено число сторон (n = …). Верификация: headless-смоук 6968 проверок / 1140 рендеров; ответы окружности конечные и принимаются движком (1600 экземпляров, округление до 2 знаков ok); inline-скрипт парсится; адверсариал-ревью — circle clean, toggle без high/medium (2 low устранены: скрытие тумблера при неудаче генерации + подпись n сторон). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+38
-4
@@ -230,6 +230,13 @@
|
||||
.tr-diff-btn:hover { border-color: var(--g1); color: var(--accent-ink); }
|
||||
.tr-diff-btn.on { color: #fff; border-color: transparent; background: linear-gradient(135deg, var(--g1), var(--g2)); box-shadow: 0 8px 16px -6px rgba(99,102,241,.5); }
|
||||
|
||||
/* ── переключатель «условие текстом / на чертеже» (геометрия) ── */
|
||||
.tr-figmode { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; justify-content: center; margin-bottom: 16px; }
|
||||
.tr-fm-label { font-size: .68rem; font-weight: 800; color: var(--ink-faint); text-transform: uppercase; letter-spacing: .07em; margin-right: 4px; }
|
||||
.tr-fm-btn { font: inherit; font-size: .8rem; font-weight: 800; cursor: pointer; padding: 6px 14px; border-radius: 99px; border: 1px solid var(--line); background: #fff; color: var(--ink-soft); transition: .14s var(--ease); }
|
||||
.tr-fm-btn:hover { border-color: var(--g1); color: var(--accent-ink); }
|
||||
.tr-fm-btn.on { color: #fff; border-color: transparent; background: linear-gradient(135deg, var(--g1), var(--g2)); box-shadow: 0 8px 16px -6px rgba(99,102,241,.5); }
|
||||
|
||||
/* строка ответа */
|
||||
.tr-inrow { display: flex; gap: 10px; align-items: stretch; max-width: 460px; margin: 0 auto; }
|
||||
#tr-eqx { font-family: 'Cambria Math', serif; font-size: 1.55rem; font-weight: 600; color: var(--accent-ink); align-self: center; padding-left: 4px; }
|
||||
@@ -448,6 +455,7 @@
|
||||
<div class="tr-figure" id="tr-figure" style="display:none"></div>
|
||||
</div>
|
||||
<div class="tr-work">
|
||||
<div class="tr-figmode" id="tr-figmode" style="display:none"></div>
|
||||
<div class="tr-difficulty" id="tr-difficulty"></div>
|
||||
|
||||
<div id="tr-answerbox">
|
||||
@@ -600,6 +608,22 @@
|
||||
if (svg) { box.innerHTML = svg; box.style.display = ''; }
|
||||
else { box.innerHTML = ''; box.style.display = 'none'; }
|
||||
}
|
||||
// Условие: полный текст ИЛИ краткий промпт (числа читаются с чертежа).
|
||||
function showStatement(problem) {
|
||||
var eq = $('tr-eq'); if (!eq || !problem) return;
|
||||
var useFig = figureMode && problem.figure && problem.figurePrompt;
|
||||
if (useFig) { eq.classList.add('tr-eq-text'); setMath(eq, null, problem.figurePrompt, true); }
|
||||
else { eq.classList.toggle('tr-eq-text', !problem.latex); setMath(eq, problem.latex, problem.display, true); }
|
||||
}
|
||||
// Переключатель «Текст / На чертеже» — только для задач с чертежом и кратким условием.
|
||||
function renderFigureToggle() {
|
||||
var box = $('tr-figmode'); if (!box) return;
|
||||
if (!(cur && cur.figure && cur.figurePrompt)) { box.style.display = 'none'; box.innerHTML = ''; return; }
|
||||
box.style.display = '';
|
||||
box.innerHTML = '<span class="tr-fm-label">Условие</span>' +
|
||||
'<button type="button" class="tr-fm-btn' + (!figureMode ? ' on' : '') + '" data-fm="0">Текст</button>' +
|
||||
'<button type="button" class="tr-fm-btn' + (figureMode ? ' on' : '') + '" data-fm="1">На чертеже</button>';
|
||||
}
|
||||
|
||||
var topics = (TG.topics ? TG.topics() : [{ key: null, label: 'Задачи' }]).concat([{ key: 'word', label: 'Текстовые задачи', word: true }]);
|
||||
var isTeacher = !!(ip && ip.isTeacher);
|
||||
@@ -608,6 +632,8 @@
|
||||
var diffMode = 'auto'; // уровень сложности: 'auto' | 1 | 2 | 3 (= структурный вариант)
|
||||
var pinned = null; // закреплённый навык (id) при явном клике по чипу
|
||||
var customGens = []; // пользовательские генераторы (P13), тема «Авторские»
|
||||
var figureMode = false; // «читать условие с чертежа» (числа на фигуре, текст краткий)
|
||||
try { figureMode = localStorage.getItem('tr-figure-mode') === '1'; } catch (e) {}
|
||||
function skillKey(g) { return g.skill || g.id; }
|
||||
function skillsOf(topicKey) {
|
||||
if (topicKey === 'custom') return customGens;
|
||||
@@ -641,6 +667,7 @@
|
||||
function serveWordProblem() {
|
||||
var eq = $('tr-eq'); eq.classList.add('tr-eq-text');
|
||||
renderFigure(null); // текстовые задачи — без чертежа
|
||||
var fmb = $('tr-figmode'); if (fmb) { fmb.style.display = 'none'; fmb.innerHTML = ''; }
|
||||
$('tr-solution').style.display = 'none'; $('tr-solution').innerHTML = '';
|
||||
var fb = $('tr-feedback'); fb.className = 'tr-feedback'; fb.textContent = '';
|
||||
if (!wordPool.length) {
|
||||
@@ -937,14 +964,13 @@
|
||||
// strict:false + несколько попыток на случай редкой неудачи с ограничениями
|
||||
cur = null;
|
||||
for (var i = 0; i < 6 && !cur; i++) cur = TE.instantiate(curGen, { seed: randSeed(), strict: false });
|
||||
if (!cur) { $('tr-eq').textContent = 'Не удалось сгенерировать задачу'; return; }
|
||||
if (!cur) { $('tr-eq').textContent = 'Не удалось сгенерировать задачу'; renderFigure(null); renderFigureToggle(); return; }
|
||||
|
||||
renderSkills(); // подсветить активный навык (мог смениться вместе с уровнем)
|
||||
$('tr-skill').textContent = curGen.title;
|
||||
var eq = $('tr-eq');
|
||||
eq.classList.toggle('tr-eq-text', !cur.latex); // текстовый prompt (проценты/упрощение) — другим шрифтом
|
||||
setMath(eq, cur.latex, cur.display, true);
|
||||
showStatement(cur); // условие: полный текст ИЛИ краткий промпт (числа на чертеже)
|
||||
renderFigure(cur); // чертёж для геометрии (иначе скрыт)
|
||||
renderFigureToggle(); // переключатель «Текст / На чертеже» (если уместен)
|
||||
applyInputMode();
|
||||
var inp = $('tr-input');
|
||||
inp.value = ''; inp.disabled = false;
|
||||
@@ -1202,6 +1228,14 @@
|
||||
$('tr-teacher').addEventListener('click', function (e) { if (e.target === $('tr-teacher')) $('tr-teacher').style.display = 'none'; });
|
||||
$('tr-analytics-btn').addEventListener('click', openAnalytics);
|
||||
$('tr-builder-btn').addEventListener('click', function () { location.href = '/trainer-builder'; });
|
||||
$('tr-figmode').addEventListener('click', function (e) {
|
||||
var b = e.target.closest('.tr-fm-btn'); if (!b) return;
|
||||
var v = b.getAttribute('data-fm') === '1';
|
||||
if (v === figureMode) return;
|
||||
figureMode = v;
|
||||
try { localStorage.setItem('tr-figure-mode', v ? '1' : '0'); } catch (_) {}
|
||||
showStatement(cur); renderFigureToggle();
|
||||
});
|
||||
$('tr-difficulty').addEventListener('click', function (e) {
|
||||
var b = e.target.closest('.tr-diff-btn'); if (!b) return;
|
||||
var d = b.getAttribute('data-d');
|
||||
|
||||
Reference in New Issue
Block a user