From b6bb1d9f4835b0d192351ae2fa999ae20797740a Mon Sep 17 00:00:00 2001 From: Maxim Dolgolyov Date: Fri, 29 May 2026 14:07:51 +0300 Subject: [PATCH] =?UTF-8?q?feat(geom11=20ch1=20wave1):=20=C2=A71=20=C2=AB?= =?UTF-8?q?=D0=9F=D1=80=D0=B8=D0=B7=D0=BC=D0=B0=C2=BB=20+=203D-=D0=BA?= =?UTF-8?q?=D0=BE=D0=BD=D1=81=D1=82=D1=80=D1=83=D0=BA=D1=82=D0=BE=D1=80=20?= =?UTF-8?q?+=20=D0=BA=D0=B0=D0=BB=D1=8C=D0=BA=D1=83=D0=BB=D1=8F=D1=82?= =?UTF-8?q?=D0=BE=D1=80=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/textbooks/geometry_11_ch1.html | 376 +++++++++++++++++++++++- 1 file changed, 373 insertions(+), 3 deletions(-) diff --git a/frontend/textbooks/geometry_11_ch1.html b/frontend/textbooks/geometry_11_ch1.html index c6f0800..3a77c31 100644 --- a/frontend/textbooks/geometry_11_ch1.html +++ b/frontend/textbooks/geometry_11_ch1.html @@ -392,7 +392,7 @@ function buildParaSelector(){ } const BUILT=new Set(); -const BUILDERS = { p1:()=>buildStub('p1'), p2:()=>buildStub('p2'), final1:()=>buildStub('final1') }; +const BUILDERS = { p1:()=>buildP1(), p2:()=>buildStub('p2'), final1:()=>buildStub('final1') }; function ensureBuilt(id){ if(BUILT.has(id)) return; const fn=BUILDERS[id]; if(fn){ fn(); BUILT.add(id); } } function goTo(id){ STATE.current=id; ensureBuilt(id); @@ -407,13 +407,13 @@ function goTo(id){ } const SIDEBARS = { - p1:{title:"Шпаргалка § 1", rows:[["Тема", "Призма"],["Формула","$S_{бок}=Pl$, $V=S_{осн}h$"]]}, + p1:{title:"Шпаргалка § 1", rows:[["Тема","Призма"],["Прямая","$S_{бок}=P_{осн}\\\\cdot h$"],["Наклонная","$S_{бок}=P_{пер}\\\\cdot l$"],["Объём","$V=S_{осн}\\\\cdot h$"],["Диагональ пар.","$d=\\\\sqrt{a^2+b^2+c^2}$"]]}, p2:{title:"Шпаргалка § 2", rows:[["Тема", "Цилиндр"],["Формула","$S_{бок}=2\\\\pi Rh$, $V=\\\\pi R^2h$"]]}, final1:{title:"Финал раздела 1", rows:[["§ 1–§ 2","теория раздела 1"],["Награда","+50 XP"]]} }; const TIPS=[ - {sec:'p1',html:"§ 1 «Призма» — содержание в разработке. $S_{бок}=Pl$, $V=S_{осн}h$"}, + {sec:'p1',html:"§ 1 «Призма» — крути 3D-модель в интерактиве 1, проверь формулы в калькуляторе. Главное: $V=S_{осн}\\\\cdot h$, $S_{бок}=P_{осн}\\\\cdot h$ (для прямой)."}, {sec:'p2',html:"§ 2 «Цилиндр» — содержание в разработке. $S_{бок}=2\\\\\\\\pi Rh$, $V=\\\\\\\\pi R^2h$"}, {sec:'final1',html:"Финал раздела 1 — интегрированные задачи по разделу."} ]; @@ -619,6 +619,376 @@ function wireReadBtn(paraId){ }); } +/* ===== §1 «Призма» — Wave 1 ===== */ +function buildP1(){ + const box = document.getElementById('p1-body'); + if(!box) return; + let html = ''; + + /* === ТЕОРИЯ === */ + + html += makeCard('theory', 'Определение и виды призм', '§ 1.1', + '

Призма — многогранник, две грани которого (основания) — равные многоугольники, лежащие в параллельных плоскостях, а остальные грани (боковые) — параллелограммы.

' + + '

Виды призм:

' + + '' + + '

Параллелепипед — призма с параллелограммом в основании. У неё $6$ граней, $12$ рёбер, $8$ вершин.

' + + '

Прямой параллелепипед — боковые рёбра $\\perp$ основанию. Прямоугольный параллелепипед — прямой, у которого основание — прямоугольник (значит, все грани — прямоугольники). Куб — прямоугольный параллелепипед с равными рёбрами.

' + + '

Свойства параллелепипеда:

' + + ''); + + html += makeCard('rule', 'Площадь поверхности и объём', '§ 1.2', + '

Боковая поверхность.

' + + '' + + '

Полная поверхность: $S_{полн}=S_{бок}+2\\cdot S_{осн}$.

' + + '

Объём (для любой призмы):

' + + '

$$V=S_{осн}\\cdot h$$

' + + '

где $h$ — высота призмы (расстояние между плоскостями оснований).

' + + '
Пример: правильная 6-угольная призма
' + + '

Сторона основания $a=4$, высота $h=10$:

' + + '
    ' + + '
  • $S_{осн}=\\dfrac{3\\sqrt{3}}{2}\\,a^2=24\\sqrt{3}\\approx 41{,}57$
  • ' + + '
  • $P_{осн}=6a=24$
  • ' + + '
  • $S_{бок}=24\\cdot 10=240$
  • ' + + '
  • $V=24\\sqrt{3}\\cdot 10=240\\sqrt{3}\\approx 415{,}7$
  • ' + + '
' + + '
'); + + html += makeCard('example', 'Диагональ прямоугольного параллелепипеда', '§ 1.3', + '

Пусть у прямоугольного параллелепипеда измерения $a$, $b$, $c$ (длина, ширина, высота).

' + + '

Диагональ грани (например, нижнего основания): $d_{грани}=\\sqrt{a^2+b^2}$.

' + + '

Главная диагональ — отрезок, соединяющий противоположные вершины. Тогда:

' + + '

$$d^2=a^2+b^2+c^2$$

' + + '

Это трёхмерная теорема Пифагора.

' + + '
Доказательство
' + + '

Возьмём вершину $A$ нижнего основания и противоположную $A_1$ верхнего. Соединим $A$ с вершиной $C$ нижнего основания, потом $C$ с $A_1$.

' + + '

В треугольнике $ACA_1$ угол при $C$ прямой (ребро $CC_1=c$ перпендикулярно плоскости основания). По Пифагору в нижнем основании: $AC^2=a^2+b^2$. В $\\triangle ACA_1$: $AA_1^2=AC^2+CA_1^2=a^2+b^2+c^2$.

' + + '
' + + '

Пример: куб со стороной $3 \\Rightarrow d=\\sqrt{9+9+9}=3\\sqrt{3}\\approx 5{,}20$.

'); + + /* === ИНТЕРАКТИВ 1 — 3D-конструктор === */ + html += '
' + + '
3D · конструктор
Правильная n-угольная призма
' + + '
Меняй число сторон основания $n$, радиус описанной окружности $R$ и высоту $h$. Вращай мышью или выбирай вид. После 4 разных конфигураций — +10 XP.
' + + '
' + + '' + + '' + + '' + + '
' + + '
' + + '' + + '' + + '' + + '' + + '
' + + '
' + + '
' + + '$P_{осн}=$' + + '$S_{осн}=$' + + '$S_{бок}=$' + + '$S_{полн}=$' + + '$V=$' + + '
' + + '
Конфигураций изучено: 0 / 4
' + + '
'; + + /* === ИНТЕРАКТИВ 2 — Калькулятор === */ + html += '
' + + '
калькулятор
$V$, $S_{полн}$ и диагональ
' + + '
Выбери тип призмы и задай размеры. Получишь полный разбор формул.
' + + '
' + + '' + + '' + + '
' + + '
' + + '' + + '' + + '' + + '
' + + '' + + '
' + + '
' + + '
'; + + /* === ИНТЕРАКТИВ 3 — DnD сортер === */ + html += '
' + + '
сортер
Какая это призма?
' + + '
Перетащи описание в нужный ящик. Кликни чип, затем ящик — тоже сработает.
' + + '
6 описаний → 3 типа
' + + '
' + + '
' + + '
Прямая
' + + '
Правильная
' + + '
Наклонная
' + + '
' + + '
' + + '' + + '
'; + + /* === ИНТЕРАКТИВ 4 — Тренажёр === */ + html += '
' + + '
тренажёр · 6 задач
$V$, $S$ и диагональ
' + + '
Введи числовой ответ. Допуск $\\pm 0{,}05$ для дробных значений.
' + + '
' + + '
Решено: 0 / 6
' + + '
'; + + html += secNavFor('p1'); + html += readButton('p1'); + + box.innerHTML = html; + renderMath(box); + + /* ====== JS-логика интерактивов ====== */ + + /* IV1 — 3D конструктор */ + (function(){ + if(!window.G3D) return; + const svg = document.getElementById('p1-iv1-svg'); + const elN = document.getElementById('p1-iv1-n'); + const elR = document.getElementById('p1-iv1-R'); + const elH = document.getElementById('p1-iv1-h'); + const vN = document.getElementById('p1-iv1-n-v'); + const vR = document.getElementById('p1-iv1-R-v'); + const vH = document.getElementById('p1-iv1-h-v'); + const oP = document.getElementById('p1-iv1-P'); + const oSb = document.getElementById('p1-iv1-Sb'); + const oSs = document.getElementById('p1-iv1-Ss'); + const oSt = document.getElementById('p1-iv1-St'); + const oV = document.getElementById('p1-iv1-V'); + const oCnt = document.getElementById('p1-iv1-cnt'); + if(!svg) return; + const scene = G3D.createScene({W:480, H:400, scale:50, camDist:8, rotX:-0.35, rotY:0.7}); + const seen = new Set(); + let xpGiven = false; + + function draw(){ + const n = +elN.value, R = +elR.value, h = +elH.value; + vN.textContent = n; + vR.textContent = R.toFixed(1); + vH.textContent = h.toFixed(1); + const mesh = G3D.prismMesh(n, R, h); + const M = G3D.buildRotMatrix(scene); + svg.innerHTML = G3D.renderMesh(mesh, M, scene, { + fillBase:'rgba(252,231,243,.55)', + fillSide:'rgba(219,234,254,.55)', + strokeVisible:'#0f172a', + strokeHidden:'#94a3b8' + }); + /* Формулы для правильного n-угольника, вписанного в окружность радиуса R */ + const a = 2*R*Math.sin(Math.PI/n); + const P = n*a; + const Sb = 0.5*n*R*R*Math.sin(2*Math.PI/n); + const Ss = P*h; + const St = Ss + 2*Sb; + const V = Sb*h; + oP.textContent = P.toFixed(2); + oSb.textContent = Sb.toFixed(2); + oSs.textContent = Ss.toFixed(2); + oSt.textContent = St.toFixed(2); + oV.textContent = V.toFixed(2); + const key = n+'|'+R.toFixed(1)+'|'+h.toFixed(1); + seen.add(key); + oCnt.textContent = Math.min(seen.size, 4); + if(seen.size >= 4 && !xpGiven){ + xpGiven = true; + addXp(10, 'p1-iv1'); + bumpProgress('p1', 15); + const note = document.createElement('div'); + note.className = 'feedback ok'; + note.innerHTML = '✓ +10 XP за изучение 4 разных призм!'; + note.style.cssText = 'display:block;margin-top:8px'; + const host = document.getElementById('p1-iv1'); + if(host) host.appendChild(note); + setTimeout(function(){ try{ note.remove(); }catch(e){} }, 3000); + } + } + draw(); + G3D.attachOrbit(svg, scene, draw); + [elN, elR, elH].forEach(function(el){ el.addEventListener('input', draw); }); + document.querySelectorAll('#p1-iv1 .g3d-tools .btn').forEach(function(b){ + b.addEventListener('click', function(){ G3D.presetView(scene, b.dataset.view, draw); }); + }); + })(); + + /* IV2 — Калькулятор */ + (function(){ + const radios = document.querySelectorAll('input[name="p1-iv2-type"]'); + const fldReg = document.getElementById('p1-iv2-fields-reg'); + const fldRect = document.getElementById('p1-iv2-fields-rect'); + const elN = document.getElementById('p1-iv2-n'); + const elA = document.getElementById('p1-iv2-a'); + const elH = document.getElementById('p1-iv2-h'); + const elRa = document.getElementById('p1-iv2-ra'); + const elRb = document.getElementById('p1-iv2-rb'); + const elRc = document.getElementById('p1-iv2-rc'); + const labels = { + 'p1-iv2-n':'p1-iv2-n-v', 'p1-iv2-a':'p1-iv2-a-v', 'p1-iv2-h':'p1-iv2-h-v', + 'p1-iv2-ra':'p1-iv2-ra-v', 'p1-iv2-rb':'p1-iv2-rb-v', 'p1-iv2-rc':'p1-iv2-rc-v' + }; + Object.keys(labels).forEach(function(k){ + const el = document.getElementById(k), lab = document.getElementById(labels[k]); + if(!el || !lab) return; + const upd = function(){ lab.textContent = el.step === '1' ? el.value : (+el.value).toFixed(1); }; + el.addEventListener('input', upd); upd(); + }); + radios.forEach(function(r){ r.addEventListener('change', function(){ + const v = document.querySelector('input[name="p1-iv2-type"]:checked').value; + fldReg.style.display = v === 'reg' ? '' : 'none'; + fldRect.style.display = v === 'rect' ? '' : 'none'; + }); }); + let xpGiven = false; + document.getElementById('p1-iv2-calc').addEventListener('click', function(){ + const out = document.getElementById('p1-iv2-out'); + const v = document.querySelector('input[name="p1-iv2-type"]:checked').value; + let html = ''; + if(v === 'reg'){ + const n = +elN.value, a = +elA.value, h = +elH.value; + const P = n*a; + const apo = a / (2*Math.tan(Math.PI/n)); + const Sb = 0.5 * P * apo; + const Ss = P * h; + const St = Ss + 2*Sb; + const V = Sb * h; + html = '
' + + '

Правильная '+n+'-угольная призма, $a='+a.toFixed(2)+'$, $h='+h.toFixed(2)+'$

' + + '

$P_{осн}=n\\cdot a='+n+'\\cdot '+a.toFixed(2)+'='+P.toFixed(2)+'$

' + + '

$S_{осн}=\\dfrac{1}{2}P\\cdot a_{апо}=\\dfrac{n a^2}{4}\\cot\\dfrac{\\pi}{n}\\approx '+Sb.toFixed(2)+'$

' + + '

$S_{бок}=P_{осн}\\cdot h='+P.toFixed(2)+'\\cdot '+h.toFixed(2)+'='+Ss.toFixed(2)+'$

' + + '

$S_{полн}=S_{бок}+2S_{осн}\\approx '+St.toFixed(2)+'$

' + + '

$V=S_{осн}\\cdot h\\approx '+V.toFixed(2)+'$

' + + '
'; + } else { + const a = +elRa.value, b = +elRb.value, c = +elRc.value; + const V = a*b*c; + const St = 2*(a*b + b*c + a*c); + const d = Math.sqrt(a*a + b*b + c*c); + html = '
' + + '

Прямоугольный параллелепипед, $a='+a.toFixed(2)+'$, $b='+b.toFixed(2)+'$, $c='+c.toFixed(2)+'$

' + + '

$V=abc='+a.toFixed(2)+'\\cdot '+b.toFixed(2)+'\\cdot '+c.toFixed(2)+'='+V.toFixed(2)+'$

' + + '

$S_{полн}=2(ab+bc+ac)='+St.toFixed(2)+'$

' + + '

$d=\\sqrt{a^2+b^2+c^2}=\\sqrt{'+(a*a+b*b+c*c).toFixed(2)+'}\\approx '+d.toFixed(2)+'$

' + + '
'; + } + out.innerHTML = html; + renderMath(out); + if(!xpGiven){ + xpGiven = true; + addXp(10, 'p1-iv2'); + bumpProgress('p1', 15); + } + }); + })(); + + /* IV3 — DnD сортер */ + (function(){ + const items = [ + { id:'i1', html:'Основание — правильный 6-угольник, боковые рёбра $\\perp$ основанию', cat:'regular' }, + { id:'i2', html:'Боковые рёбра наклонены к основанию под углом 60°', cat:'oblique' }, + { id:'i3', html:'Все 6 граней — прямоугольники, все рёбра равны (куб)', cat:'straight' }, + { id:'i4', html:'Боковые рёбра $\\perp$ основанию, основание — параллелограмм', cat:'straight' }, + { id:'i5', html:'Основание — квадрат со стороной 3, высота 5, боковые рёбра $\\perp$', cat:'regular' }, + { id:'i6', html:'Боковые грани — параллелограммы, не прямоугольники', cat:'oblique' } + ]; + const sorter = setupSorter({ + poolId:'p1-iv3-pool', + scopeSelector:'#p1-iv3', + items: items, + cats: ['straight','regular','oblique'] + }); + let xpGiven = false; + document.getElementById('p1-iv3-check').addEventListener('click', function(){ + const fb = document.getElementById('p1-iv3-fb'); + let correct = 0; + items.forEach(function(it){ if(sorter.placed[it.id] === it.cat) correct++; }); + if(correct === items.length){ + feedback(fb, true, '✓ Все 6 правильно! +15 XP'); + if(!xpGiven){ + xpGiven = true; + addXp(15, 'p1-iv3'); + bumpProgress('p1', 25); + } + } else { + feedback(fb, false, '✗ Правильно: '+correct+' из '+items.length+'. Попробуй ещё раз.'); + } + }); + document.getElementById('p1-iv3-reset').addEventListener('click', function(){ + sorter.reset(); + const fb = document.getElementById('p1-iv3-fb'); fb.style.display = 'none'; + }); + })(); + + /* IV4 — Тренажёр */ + (function(){ + const tasks = [ + { q:'Прямоугольный параллелепипед $3\\times 4\\times 5$. $V=\\,?$', a:60, tol:0.05 }, + { q:'Куб со стороной 2. $V=\\,?$', a:8, tol:0.05 }, + { q:'Куб со стороной 3. Диагональ $d=\\,?$ (точность 0,01)', a:5.20, tol:0.05 }, + { q:'Прямоугольный параллелепипед $2\\times 3\\times 6$. Главная диагональ?', a:7, tol:0.05 }, + { q:'Правильная 4-угольная призма со стороной основания 4 и высотой 5. $V=\\,?$', a:80, tol:0.05 }, + { q:'Прямоугольный параллелепипед $3\\times 4\\times 5$. $S_{полн}=\\,?$', a:94, tol:0.05 } + ]; + const list = document.getElementById('p1-iv4-list'); + const scoreEl = document.getElementById('p1-iv4-score'); + const solved = new Set(); + let xpGiven = false; + + list.innerHTML = tasks.map(function(t, i){ + return '
' + + '
Задача '+(i+1)+'. '+t.q+'
' + + '
' + + '' + + '' + + '
' + + '' + + '
'; + }).join(''); + renderMath(list); + + list.querySelectorAll('button[data-i]').forEach(function(b){ + b.addEventListener('click', function(){ + const i = +b.dataset.i, t = tasks[i]; + const inp = document.getElementById('p1-iv4-inp-'+i); + const fb = document.getElementById('p1-iv4-fb-'+i); + const raw = (inp.value || '').replace(',', '.').trim(); + const val = parseFloat(raw); + if(!isFinite(val)){ feedback(fb, false, '✗ Введи число'); return; } + if(Math.abs(val - t.a) <= t.tol){ + feedback(fb, true, '✓ Верно!'); + if(!solved.has(i)){ + solved.add(i); + scoreEl.textContent = solved.size; + if(solved.size === tasks.length && !xpGiven){ + xpGiven = true; + addXp(15, 'p1-iv4'); + bumpProgress('p1', 25); + setTimeout(function(){ achievement('p1_done'); }, 400); + } + } + } else { + feedback(fb, false, '✗ Не точно. Пересчитай аккуратно.'); + } + }); + }); + })(); + + wireReadBtn('p1'); +} + /* ===== STUB BUILDER — единый для всех параграфов раздела (Phase 0) ===== */ function buildStub(id){