diff --git a/frontend/textbooks/geometry_8_ch2.html b/frontend/textbooks/geometry_8_ch2.html index 202e36d..984014f 100644 --- a/frontend/textbooks/geometry_8_ch2.html +++ b/frontend/textbooks/geometry_8_ch2.html @@ -373,8 +373,8 @@ function buildParaSelector(){ const g=document.getElementById('psel-grid');g.inn const BUILT=new Set(); const BUILDERS={ - p1:()=>buildP1(),p2:()=>buildP2(),p3:()=>buildP3(),p4:()=>buildP4(),p5:()=>buildP5stub(), - p6:()=>buildP6stub(),p7:()=>buildP7stub(),p8:()=>buildP8stub(),p9:()=>buildP9stub(),p10:()=>buildP10stub(), + p1:()=>buildP1(),p2:()=>buildP2(),p3:()=>buildP3(),p4:()=>buildP4(),p5:()=>buildP5(), + p6:()=>buildP6(),p7:()=>buildP7(),p8:()=>buildP8(),p9:()=>buildP9stub(),p10:()=>buildP10stub(), p11:()=>buildP11stub(),p12:()=>buildP12stub(),p13:()=>buildP13stub(),p14:()=>buildP14stub(),p15:()=>buildP15stub(), final2:()=>buildFinal2stub(), }; @@ -1658,10 +1658,1502 @@ function buildP4(){ window.p4BossSolved=new Set(); })(); } -function buildP5stub(){ document.getElementById('p5-body').innerHTML='

§5 — Волна 1: содержимое появится в следующем обновлении.

'+secNav('p4','p6'); } -function buildP6stub(){ document.getElementById('p6-body').innerHTML='

§6 — Волна 1: содержимое появится в следующем обновлении.

'+secNav('p5','p7'); } -function buildP7stub(){ document.getElementById('p7-body').innerHTML='

§7 — Волна 1: содержимое появится в следующем обновлении.

'+secNav('p6','p8'); } -function buildP8stub(){ document.getElementById('p8-body').innerHTML='

§8 — Волна 1: содержимое появится в следующем обновлении.

'+secNav('p7','p9'); } +/* ============================================================ + §5 — ПЛОЩАДЬ ТРАПЕЦИИ + ============================================================ */ +function buildP5(){ + const box=document.getElementById('p5-body'); + let html=''; + + html+=makeCard('theory','Площадь трапеции','5.1',` +

Теорема. Площадь трапеции равна произведению полусуммы оснований на высоту:

+ $$S = \\dfrac{a+b}{2}\\cdot h$$ +

где $a$ и $b$ — основания (параллельные стороны), $h$ — высота (расстояние между основаниями).

+

Через среднюю линию: $m = \\dfrac{a+b}{2}$, поэтому $S = m \\cdot h$.

`); + + html+=makeCard('rule','Доказательство (диагональ)','5.2',` +

Проведём диагональ $BD$ трапеции $ABCD$ ($AB \\parallel CD$).

+

Диагональ делит трапецию на два треугольника:

+ +

По аддитивности: $S = S_1+S_2 = \\dfrac{1}{2}ah+\\dfrac{1}{2}bh = \\dfrac{a+b}{2}\\cdot h$. $\\square$

`); + + html+=makeCard('example','Примеры','5.3',` +

Трапеция, основания 8 и 14 см, высота 6 см. Площадь?
$S=\\dfrac{8+14}{2}\\cdot6=11\\cdot6=66\\,\\text{см}^2$.

+

S = 72 м², h = 9 м, a = 10 м. Найти b.
$b = \\dfrac{2S}{h}-a = \\dfrac{144}{9}-10=16-10=6\\,\\text{м}$.

+

S = 80 дм², средняя линия m = 16 дм. Высота?
$h = S/m = 80/16 = 5\\,\\text{дм}$.

`); + + /* INTERACTIVE 1 — Draggable трапеция */ + html+=`
+
ИНТЕРАКТИВ 1
Трапеция с перетаскиванием
+
Тащи верхнее основание (синяя точка) вправо/влево — меняется его длина $b$. Тащи левый нижний угол — меняется высота $h$. Площадь пересчитывается мгновенно.
+
+
+
`; + + /* INTERACTIVE 2 — Пошаговое доказательство */ + html+=`
+
ИНТЕРАКТИВ 2
Доказательство: достраиваем до параллелограмма
+
Нажимай «Далее» и смотри, как две трапеции складываются в параллелограмм со стороной $(a+b)$ и высотой $h$.
+
+
+
+ + +
+
`; + + /* INTERACTIVE 3 — Калькулятор */ + html+=`
+
ИНТЕРАКТИВ 3
Калькулятор трапеции
+
Три режима: найти S, найти a, найти h.
+
+
+
a, b, h → S
+
+ + + + +
+
+
+
+
S, h, b → a
+
+ + + + +
+
+
+
+
S, m → h
+
+ + + +
+
+
+
+
`; + + /* INTERACTIVE 4 — DnD сортер */ + html+=`
+
ИНТЕРАКТИВ 4
Что является трапецией?
+
Распредели фигуры по группам: перетащи каждую в нужную колонку.
+
+
Трапеция
+
Не трапеция
+
+
+
+ + +
+ +
`; + + /* INTERACTIVE 5 — Тренажёр */ + html+=`
+
ИНТЕРАКТИВ 5
Тренажёр §5
+
5 задач на площадь трапеции.
+
Задача 1 / 5Очки: 0
+
+
+ + + +
+ +
`; + + /* INTERACTIVE 6 — Босс */ + html+=`
+
БОСС §5
Итоговые задачи
+
4 задачи — +5 XP каждая.
+
+
`; + + html+=`
+ +
`; + html+=secNav('p4','p6'); + box.innerHTML=html; + if(window.renderMathInElement) setTimeout(()=>renderMath(box),0); + + /* == INIT: Draggable трапеция == */ + (function(){ + const W=400, H=260; + const AX=40, AY=200, BW=220; + let topB=100, topOff=40, trapH=110; + function draw(){ + const ax=AX, ay=AY, bx=ax+BW, by=ay; + const dx=ax+topOff, dy=ay-trapH, cx=dx+topB, cy=dy; + const midX=(dx+cx)/2, midY=dy; + const Sval=Math.round((BW+topB)/2*trapH); + let s=''; + // height dashes + s+=''; + s+='h'; + // right angle + s+=''; + // trapezoid fill + s+=''; + // base a label + s+='a='+BW+''; + // top b label + s+='b='+topB+''; + // S label + const cxLabel=Math.round((ax+bx+cx+dx)/4), cyLabel=Math.round((ay+ay+cy+dy)/4); + s+='S='+Sval+''; + // drag handles + const hTop=cx, hTopY=cy; + s+=''; + s+=''; + const hH=ax, hHY=Math.round(ay-trapH/2); + s+=''; + s+=''; + s+=''; + document.getElementById('p5-trap-svg-wrap').innerHTML=s; + document.getElementById('p5-trap-info').innerHTML=` +
Основание a
${BW}
+
Основание b
${topB}
+
Высота h
${trapH}
+
S = (a+b)/2·h
${Sval}
`; + const handleTop=document.getElementById('p5-drag-top'); + if(handleTop){ + handleTop.addEventListener('pointerdown',ev=>{ + const startX=ev.clientX, startB=topB; + function onMove(e){ + const svgEl=document.getElementById('p5-trap-svg'); + if(!svgEl) return; + const rect=svgEl.getBoundingClientRect(); + const scale=W/rect.width; + const delta=Math.round((e.clientX-startX)*scale); + topB=Math.max(20,Math.min(280,startB+delta)); + draw(); + } + function onUp(){window.removeEventListener('pointermove',onMove);window.removeEventListener('pointerup',onUp);window.removeEventListener('pointercancel',onUp);} + window.addEventListener('pointermove',onMove); + window.addEventListener('pointerup',onUp); + window.addEventListener('pointercancel',onUp); + }); + } + const handleH=document.getElementById('p5-drag-h'); + if(handleH){ + handleH.addEventListener('pointerdown',ev=>{ + const startY=ev.clientY, startH=trapH; + function onMove(e){ + const svgEl=document.getElementById('p5-trap-svg'); + if(!svgEl) return; + const rect=svgEl.getBoundingClientRect(); + const scale=H/rect.height; + const delta=Math.round((startY-e.clientY)*scale); + trapH=Math.max(40,Math.min(160,startH+delta)); + draw(); + } + function onUp(){window.removeEventListener('pointermove',onMove);window.removeEventListener('pointerup',onUp);window.removeEventListener('pointercancel',onUp);} + window.addEventListener('pointermove',onMove); + window.addEventListener('pointerup',onUp); + window.addEventListener('pointercancel',onUp); + }); + } + } + draw(); + })(); + + /* == INIT: Доказательство пошаговое == */ + (function(){ + let step=0; + const W=400, H=220; + const ax=30, ay=180, bw=200, h=100, off=50; + const steps=[ + {desc:'Исходная трапеция ABCD. Основания: $a=AB$ (нижнее) и $b=CD$ (верхнее), высота $h$.', + draw(){ + const bx=ax+bw, dx=ax+off, cx=dx+Math.round(bw*0.55); + const dy=ay-h, cy=dy; + return '' + +'' + +'a' + +'b' + +'h' + +'A' + +'B' + +'C' + +'D'; + }}, + {desc:'Повернём копию трапеции на 180° и приложим сверху-справа так, чтобы стороны CD совпали.', + draw(){ + const bx=ax+bw, dx=ax+off, cx=dx+Math.round(bw*0.55); + const dy=ay-h, cy=dy; + const bw2=Math.round(bw*0.55); + const ax2=cx, ay2=cy, bx2=cx+bw, by2=cy, cx2=cx+bw-off, cy2=cy-h, dx2=cx, dy2=cy-h; + return '' + +'' + +'a' + +'копия (перевёрнута)'; + }}, + {desc:'Две трапеции образуют параллелограмм! Его основание $a+b$, высота $h$.', + draw(){ + const bx=ax+bw, dx=ax+off, cx=dx+Math.round(bw*0.55); + const dy=ay-h, cy=dy; + const fullW=bw+Math.round(bw*0.55); + return '' + +'a+b' + +'h' + +'паралл.'; + }}, + {desc:'Площадь параллелограмма $S_{\\text{пар}}=(a+b)\\cdot h$. Трапеция — его половина, значит $S=\\dfrac{(a+b)}{2}\\cdot h$.', + draw(){ + const fullW=bw+Math.round(bw*0.55); + return '' + +'' + +'' + +'S=½(a+b)h'; + }}, + ]; + function render(){ + const s=steps[step]; + document.getElementById('p5-proof-svg-wrap').innerHTML=''+s.draw()+''; + document.getElementById('p5-proof-desc').innerHTML='Шаг '+(step+1)+' / '+steps.length+'. '+s.desc; + document.getElementById('p5-proof-next').textContent=step{ + if(step{step=0;render();}); + render(); + })(); + + /* == INIT: Калькулятор == */ + (function(){ + document.getElementById('p5-c-go1').addEventListener('click',()=>{ + const a=parseFloat(document.getElementById('p5-c-a').value); + const b=parseFloat(document.getElementById('p5-c-b').value); + const h=parseFloat(document.getElementById('p5-c-h').value); + const out=document.getElementById('p5-c-out1'); + if(!isFinite(a)||!isFinite(b)||!isFinite(h)||h<=0){out.innerHTML='Введи положительные числа.';return;} + out.innerHTML='$S=\\dfrac{'+fmt(a)+'+'+fmt(b)+'}{2}\\cdot'+fmt(h)+'='+fmt((a+b)/2*h)+'$'; + renderMath(out);addXp(1,'p5-calc1'); + }); + document.getElementById('p5-c-go2').addEventListener('click',()=>{ + const S=parseFloat(document.getElementById('p5-c-s2').value); + const h=parseFloat(document.getElementById('p5-c-h2').value); + const b=parseFloat(document.getElementById('p5-c-b2').value); + const out=document.getElementById('p5-c-out2'); + if(!isFinite(S)||!isFinite(h)||!isFinite(b)||h<=0){out.innerHTML='Введи положительные числа.';return;} + out.innerHTML='$a=\\dfrac{2S}{h}-b='+fmt(2*S/h-b)+'$'; + renderMath(out);addXp(1,'p5-calc2'); + }); + document.getElementById('p5-c-go3').addEventListener('click',()=>{ + const S=parseFloat(document.getElementById('p5-c-s3').value); + const m=parseFloat(document.getElementById('p5-c-m3').value); + const out=document.getElementById('p5-c-out3'); + if(!isFinite(S)||!isFinite(m)||m<=0){out.innerHTML='Введи положительные числа.';return;} + out.innerHTML='$h=S/m='+fmt(S/m)+'$'; + renderMath(out);addXp(1,'p5-calc3'); + }); + })(); + + /* == INIT: DnD Sorter == */ + (function(){ + const items=[ + {id:'t1',html:'Трапеция ABCD
AB∥CD, AD не∥BC',correct:'yes'}, + {id:'t2',html:'Прямоугольная трапеция
один угол 90°',correct:'yes'}, + {id:'t3',html:'Равнобедренная трапеция
боковые стороны равны',correct:'yes'}, + {id:'t4',html:'Параллелограмм
обе пары сторон ∥',correct:'no'}, + {id:'t5',html:'Треугольник
3 стороны',correct:'no'}, + {id:'t6',html:'Произвольный 4-уг.
нет парал. сторон',correct:'no'}, + ]; + const sorter=setupSorter({ + poolId:'p5-dnd-pool', + scopeSelector:'#p5-dnd-wg', + items:items, + cats:['yes','no'], + columnLayout:false + }); + document.getElementById('p5-dnd-check').addEventListener('click',()=>{ + const fb=document.getElementById('p5-dnd-fb'); + const total=items.length; + let correct=0; + items.forEach(it=>{if(sorter.placed[it.id]===it.correct)correct++;}); + if(correct===total){ + feedback(fb,true,'Все верно! +8 XP');addXp(8,'p5-dnd-ok');bumpProgress('p5',20);confetti(); + } else { + feedback(fb,false,'Верно: '+correct+' из '+total+'. Попробуй ещё.'); + } + }); + document.getElementById('p5-dnd-reset').addEventListener('click',()=>{sorter.reset();document.getElementById('p5-dnd-fb').style.display='none';}); + })(); + + /* == INIT: Тренажёр == */ + (function(){ + const tasks=[ + {q:'Трапеция, основания 6 и 14 см, высота 8 см. Площадь?', ans:80, hint:'(6+14)/2·8 = 10·8 = 80.'}, + {q:'Площадь трапеции 90 м², высота 9 м, одно основание 7 м. Второе основание?', ans:13, hint:'2·90/9 − 7 = 20 − 7 = 13.'}, + {q:'Средняя линия трапеции 11 дм, высота 6 дм. Площадь?', ans:66, hint:'S = 11·6 = 66.'}, + {q:'Прямоугольная трапеция: основания 5 и 9 см, высота 4 см. Площадь?', ans:28, hint:'(5+9)/2·4 = 7·4 = 28.'}, + {q:'Площадь трапеции 108 см², средняя линия 12 см. Высота?', ans:9, hint:'h = 108/12 = 9.'}, + ]; + let idx=0,score=0; + function show(){ + document.getElementById('p5-tr-i').textContent=idx+1; + document.getElementById('p5-tr-task').innerHTML=tasks[idx].q; + document.getElementById('p5-tr-ans').value=''; + document.getElementById('p5-tr-fb').style.display='none'; + } + document.getElementById('p5-tr-start').addEventListener('click',()=>{idx=0;score=0;document.getElementById('p5-tr-score').textContent=0;show();}); + document.getElementById('p5-tr-go').addEventListener('click',()=>{ + if(idx>=tasks.length)return; + const ans=+document.getElementById('p5-tr-ans').value; + const fb=document.getElementById('p5-tr-fb'); + if(Math.abs(ans-tasks[idx].ans)<0.5){ + score++;document.getElementById('p5-tr-score').textContent=score; + addXp(3,'p5-tr-'+idx);bumpProgress('p5',5); + if(idxshow(),900);} + else{feedback(fb,true,'Все задачи решены! +5 XP');addXp(5,'p5-tr-all');bumpProgress('p5',10);} + } else {feedback(fb,false,'Неверно. '+tasks[idx].hint);} + }); + document.getElementById('p5-tr-ans').addEventListener('keydown',e=>{if(e.key==='Enter')document.getElementById('p5-tr-go').click();}); + show(); + })(); + + /* == INIT: Босс §5 == */ + (function(){ + const tasks=[ + {q:'Трапеция, основания 20 и 10 дм, высота 9 дм. Площадь?', ans:135, hint:'(20+10)/2·9 = 15·9 = 135.'}, + {q:'Площадь трапеции 150 м², основания 12 и 18 м. Высота?', ans:10, hint:'h = 2·150/(12+18) = 300/30 = 10.'}, + {q:'Равнобедренная трапеция с основаниями 8 и 16 см вписана между двумя параллельными прямыми на расстоянии 6 см. Площадь?', ans:72, hint:'(8+16)/2·6 = 12·6 = 72.'}, + {q:'Средняя линия трапеции 15 см. При высоте 8 см найти площадь.', ans:120, hint:'S = 15·8 = 120.'}, + ]; + const bossBox=document.getElementById('p5-boss-tasks'); + bossBox.innerHTML=tasks.map((t,i)=>` +
+
${t.q}
+
+ + +
+ +
`).join(''); + window.p5BossSolved=new Set(); + })(); +} +/* ============================================================ + §6 — ПЛОЩАДЬ РОМБА + ============================================================ */ +function buildP6(){ + const box=document.getElementById('p6-body'); + let html=''; + + html+=makeCard('theory','Площадь ромба','6.1',` +

Ромб — параллелограмм со всеми равными сторонами. Его диагонали взаимно перпендикулярны и делятся пополам.

+

Формулы площади ромба:

+
    +
  • Через диагонали: $S = \\dfrac{d_1 \\cdot d_2}{2}$
  • +
  • Как параллелограмм: $S = a \\cdot h$
  • +
  • Через угол: $S = a^2 \\sin\\alpha$
  • +
`); + + html+=makeCard('rule','Доказательство $S = d_1 d_2 / 2$','6.2',` +

Диагонали ромба делят его на 4 равных прямоугольных треугольника с катетами $d_1/2$ и $d_2/2$.

+

Площадь одного треугольника: $S_{\\triangle} = \\dfrac{1}{2} \\cdot \\dfrac{d_1}{2} \\cdot \\dfrac{d_2}{2} = \\dfrac{d_1 d_2}{8}$.

+

Ромб состоит из 4 таких треугольников: $S = 4 \\cdot \\dfrac{d_1 d_2}{8} = \\dfrac{d_1 d_2}{2}$. $\\square$

`); + + html+=makeCard('example','Примеры','6.3',` +

Диагонали ромба 10 и 24 см. Площадь?
$S=\\dfrac{10 \\cdot 24}{2}=120\\,\\text{см}^2$.

+

Сторона ромба 8 м, острый угол 30°. Площадь?
$S=8^2 \\sin 30°=64 \\cdot 0{,}5=32\\,\\text{м}^2$.

+

S = 48 дм², $d_1=8$ дм. Найти $d_2$.
$d_2=\\dfrac{2S}{d_1}=\\dfrac{96}{8}=12\\,\\text{дм}$.

`); + + /* INTERACTIVE 1 — Draggable ромб */ + html+=`
+
ИНТЕРАКТИВ 1
Ромб с перетаскиванием
+
Тащи правый конец горизонтальной диагонали (синяя точка) или нижний конец вертикальной (фиолетовая точка). Диагонали всегда перпендикулярны. $S = d_1 \\cdot d_2 / 2$.
+
+
+
`; + + /* INTERACTIVE 2 — Анимация доказательства */ + html+=`
+
ИНТЕРАКТИВ 2
Доказательство: ромб → прямоугольник
+
Нажимай «Далее» и смотри, как ромб разбивается на треугольники и складывается в прямоугольник $d_1 \\times d_2/2$.
+
+
+
+ + +
+
`; + + /* INTERACTIVE 3 — Тройной калькулятор */ + html+=`
+
ИНТЕРАКТИВ 3
Калькулятор ромба
+
Три формулы на выбор.
+
+
+
$d_1, d_2 \\to S$
+
+ + + +
+
+
+
+
$a, h \\to S$
+
+ + + +
+
+
+
+
$a, \\alpha° \\to S$
+
+ + + +
+
+
+
+
`; + + /* INTERACTIVE 4 — DnD */ + html+=`
+
ИНТЕРАКТИВ 4
Сопоставь ромб с площадью
+
Перетащи каждое описание к правильной площади.
+
+
S = 24
+
S = 30
+
S = 50
+
S = 72
+
+
+
+ + +
+ +
`; + + /* INTERACTIVE 5 — Тренажёр */ + html+=`
+
ИНТЕРАКТИВ 5
Тренажёр §6
+
5 задач на площадь ромба.
+
Задача 1 / 5Очки: 0
+
+
+ + + +
+ +
`; + + /* INTERACTIVE 6 — Босс */ + html+=`
+
БОСС §6
Итоговые задачи
+
4 задачи — +5 XP каждая.
+
+
`; + + html+=`
+ +
`; + html+=secNav('p5','p7'); + box.innerHTML=html; + if(window.renderMathInElement) setTimeout(()=>renderMath(box),0); + + /* == INIT: Draggable ромб == */ + (function(){ + const W=380, H=280; + const CX=190, CY=140; + let d1h=110, d2h=85; + function draw(){ + const d1=d1h*2, d2=d2h*2; + const ax=CX-d1h, ay=CY, bx=CX, by=CY-d2h, cx=CX+d1h, cy=CY, dx=CX, dy=CY+d2h; + const sideLen=Math.round(Math.sqrt(d1h*d1h+d2h*d2h)); + const Sval=Math.round(d1*d2/2); + let s=''; + // diagonals + s+=''; + s+=''; + // right angle at center + s+=''; + // rhombus + s+=''; + // labels + s+='d₁='+d1+''; + s+='d₂='+d2+''; + s+='S='+Sval+''; + s+='a='+sideLen+''; + // drag handles + s+=''; + s+=''; + s+=''; + s+=''; + s+=''; + document.getElementById('p6-rhomb-svg-wrap').innerHTML=s; + document.getElementById('p6-rhomb-info').innerHTML=` +
d₁
${d1}
+
d₂
${d2}
+
Сторона a
${sideLen}
+
S = d₁·d₂/2
${Sval}
`; + const hD1=document.getElementById('p6-drag-d1'); + if(hD1){ + hD1.addEventListener('pointerdown',ev=>{ + const startX=ev.clientX, startD=d1h; + function onMove(e){ + const svgEl=document.getElementById('p6-rhomb-svg'); + if(!svgEl) return; + const rect=svgEl.getBoundingClientRect(); + const scale=W/rect.width; + const delta=Math.round((e.clientX-startX)*scale); + d1h=Math.max(40,Math.min(160,startD+delta)); + draw(); + } + function onUp(){window.removeEventListener('pointermove',onMove);window.removeEventListener('pointerup',onUp);window.removeEventListener('pointercancel',onUp);} + window.addEventListener('pointermove',onMove); + window.addEventListener('pointerup',onUp); + window.addEventListener('pointercancel',onUp); + }); + } + const hD2=document.getElementById('p6-drag-d2'); + if(hD2){ + hD2.addEventListener('pointerdown',ev=>{ + const startY=ev.clientY, startD=d2h; + function onMove(e){ + const svgEl=document.getElementById('p6-rhomb-svg'); + if(!svgEl) return; + const rect=svgEl.getBoundingClientRect(); + const scale=H/rect.height; + const delta=Math.round((e.clientY-startY)*scale); + d2h=Math.max(30,Math.min(120,startD+delta)); + draw(); + } + function onUp(){window.removeEventListener('pointermove',onMove);window.removeEventListener('pointerup',onUp);window.removeEventListener('pointercancel',onUp);} + window.addEventListener('pointermove',onMove); + window.addEventListener('pointerup',onUp); + window.addEventListener('pointercancel',onUp); + }); + } + } + draw(); + })(); + + /* == INIT: Анимация доказательства == */ + (function(){ + let step=0; + const W=400, H=240; + const cx=200, cy=120, d1h=110, d2h=80; + const steps=[ + {desc:'Исходный ромб ABCD. Диагонали $d_1$ и $d_2$ пересекаются под прямым углом и делятся пополам.', + draw(){ + const ax=cx-d1h, ay=cy, bx=cx, by=cy-d2h, rx=cx+d1h, ry=cy, dx=cx, dy=cy+d2h; + return '' + +'' + +'' + +'d₂/2' + +'d₁/2'; + }}, + {desc:'Делим ромб на 4 прямоугольных треугольника с катетами $d_1/2$ и $d_2/2$.', + draw(){ + const ax=cx-d1h, ay=cy, bx=cx, by=cy-d2h, rx=cx+d1h, ry=cy, dx=cx, dy=cy+d2h; + const cols=['rgba(99,102,241,.3)','rgba(124,58,237,.3)','rgba(2,132,199,.3)','rgba(5,150,105,.3)']; + const strokes=['#6366f1','#7c3aed','#0284c7','#059669']; + const tris=[[ax,ay,bx,by,cx,cy],[bx,by,rx,ry,cx,cy],[rx,ry,dx,dy,cx,cy],[dx,dy,ax,ay,cx,cy]]; + return tris.map((t,i)=>'').join(''); + }}, + {desc:'Верхние два треугольника переворачиваем и прикладываем к нижним — получается прямоугольник!', + draw(){ + const rx2=cx-d1h+d1h*2, ry2=cy+d2h; + return '' + +'d₁='+(d1h*2)+'' + +'d₂/2='+d2h+'' + +'прямоуг.'; + }}, + {desc:'Прямоугольник $d_1 \\times (d_2/2)$, его площадь $d_1 \\cdot d_2 / 2$ — это и есть площадь ромба!', + draw(){ + return '' + +'S = d₁·d₂/2'; + }}, + ]; + function render(){ + const s=steps[step]; + document.getElementById('p6-proof-svg-wrap').innerHTML=''+s.draw()+''; + document.getElementById('p6-proof-desc').innerHTML='Шаг '+(step+1)+' / '+steps.length+'. '+s.desc; + document.getElementById('p6-proof-next').textContent=step{ + if(step{step=0;render();}); + render(); + })(); + + /* == INIT: Калькулятор == */ + (function(){ + document.getElementById('p6-c-go1').addEventListener('click',()=>{ + const d1=parseFloat(document.getElementById('p6-c-d1').value); + const d2=parseFloat(document.getElementById('p6-c-d2').value); + const out=document.getElementById('p6-c-out1'); + if(!isFinite(d1)||!isFinite(d2)||d1<=0||d2<=0){out.innerHTML='Введи положительные числа.';return;} + out.innerHTML='$S=\\dfrac{'+fmt(d1)+'\\cdot'+fmt(d2)+'}{2}='+fmt(d1*d2/2)+'$'; + renderMath(out);addXp(1,'p6-calc1'); + }); + document.getElementById('p6-c-go2').addEventListener('click',()=>{ + const a=parseFloat(document.getElementById('p6-c-a2').value); + const h=parseFloat(document.getElementById('p6-c-h2').value); + const out=document.getElementById('p6-c-out2'); + if(!isFinite(a)||!isFinite(h)||a<=0||h<=0){out.innerHTML='Введи положительные числа.';return;} + out.innerHTML='$S='+fmt(a)+'\\cdot'+fmt(h)+'='+fmt(a*h)+'$'; + renderMath(out);addXp(1,'p6-calc2'); + }); + document.getElementById('p6-c-go3').addEventListener('click',()=>{ + const a=parseFloat(document.getElementById('p6-c-a3').value); + const al=parseFloat(document.getElementById('p6-c-al3').value); + const out=document.getElementById('p6-c-out3'); + if(!isFinite(a)||!isFinite(al)||a<=0||al<=0||al>=180){out.innerHTML='Введи a > 0 и 0 < α < 180.';return;} + const sinA=Math.sin(al*Math.PI/180); + out.innerHTML='$S='+fmt(a)+'^2\\cdot\\sin '+fmt(al)+'°='+fmt(+(a*a*sinA).toFixed(4))+'$'; + renderMath(out);addXp(1,'p6-calc3'); + }); + })(); + + /* == INIT: DnD Sorter == */ + (function(){ + const items=[ + {id:'r1',html:'$d_1=6,\\;d_2=8$',correct:'24'}, + {id:'r2',html:'$d_1=5,\\;d_2=12$',correct:'30'}, + {id:'r3',html:'$d_1=10,\\;d_2=10$',correct:'50'}, + {id:'r4',html:'$a=9,\\;h=8$',correct:'72'}, + ]; + const sorter=setupSorter({ + poolId:'p6-dnd-pool', + scopeSelector:'#p6-dnd-wg', + items:items, + cats:['24','30','50','72'], + columnLayout:false + }); + document.getElementById('p6-dnd-check').addEventListener('click',()=>{ + const fb=document.getElementById('p6-dnd-fb'); + let correct=0; + items.forEach(it=>{if(sorter.placed[it.id]===it.correct)correct++;}); + if(correct===items.length){ + feedback(fb,true,'Все верно! +8 XP');addXp(8,'p6-dnd-ok');bumpProgress('p6',20);confetti(); + } else { + feedback(fb,false,'Верно: '+correct+' из '+items.length+'.'); + } + }); + document.getElementById('p6-dnd-reset').addEventListener('click',()=>{sorter.reset();document.getElementById('p6-dnd-fb').style.display='none';}); + })(); + + /* == INIT: Тренажёр == */ + (function(){ + const tasks=[ + {q:'Диагонали ромба 12 и 16 см. Площадь?', ans:96, hint:'12·16/2 = 96.'}, + {q:'Площадь ромба 60 м², одна диагональ 10 м. Другая диагональ?', ans:12, hint:'d₂ = 2·60/10 = 12.'}, + {q:'Сторона ромба 5 см, высота 4 см. Площадь?', ans:20, hint:'S = 5·4 = 20.'}, + {q:'Сторона ромба 10 дм, острый угол 30°. Площадь?', ans:50, hint:'S = 100·sin30° = 100·0,5 = 50.'}, + {q:'Диагонали ромба 8 и 15 см. Площадь? (и чему равна сторона?)', ans:60, hint:'S = 8·15/2 = 60. Сторона = √(16+56,25) = 8,5.'}, + ]; + let idx=0,score=0; + function show(){ + document.getElementById('p6-tr-i').textContent=idx+1; + document.getElementById('p6-tr-task').innerHTML=tasks[idx].q; + document.getElementById('p6-tr-ans').value=''; + document.getElementById('p6-tr-fb').style.display='none'; + } + document.getElementById('p6-tr-start').addEventListener('click',()=>{idx=0;score=0;document.getElementById('p6-tr-score').textContent=0;show();}); + document.getElementById('p6-tr-go').addEventListener('click',()=>{ + if(idx>=tasks.length)return; + const ans=+document.getElementById('p6-tr-ans').value; + const fb=document.getElementById('p6-tr-fb'); + if(Math.abs(ans-tasks[idx].ans)<0.5){ + score++;document.getElementById('p6-tr-score').textContent=score; + addXp(3,'p6-tr-'+idx);bumpProgress('p6',5); + if(idxshow(),900);} + else{feedback(fb,true,'Все задачи решены! +5 XP');addXp(5,'p6-tr-all');bumpProgress('p6',10);} + } else {feedback(fb,false,'Неверно. '+tasks[idx].hint);} + }); + document.getElementById('p6-tr-ans').addEventListener('keydown',e=>{if(e.key==='Enter')document.getElementById('p6-tr-go').click();}); + show(); + })(); + + /* == INIT: Босс §6 == */ + (function(){ + const tasks=[ + {q:'Ромб, диагонали 18 и 24 дм. Площадь?', ans:216, hint:'18·24/2 = 216.'}, + {q:'Площадь ромба 98 м². Диагонали равны. Найти каждую диагональ.', ans:14, hint:'d²/2=98 → d²=196 → d=14.'}, + {q:'Сторона ромба 13 см, меньшая диагональ 10 см. Площадь?', ans:120, hint:'d₂/2=√(169−25)=12, d₂=24. S=10·24/2=120.'}, + {q:'Сторона ромба 8 дм, угол 60°. Площадь?', ans:Math.round(64*Math.sin(60*Math.PI/180)), hint:'S = 64·sin60° ≈ 55.'}, + ]; + const bossBox=document.getElementById('p6-boss-tasks'); + bossBox.innerHTML=tasks.map((t,i)=>` +
+
${t.q}
+
+ + +
+ +
`).join(''); + window.p6BossSolved=new Set(); + })(); +} +/* ============================================================ + §7 — ПЛОЩАДЬ ПРЯМОУГОЛЬНОГО ТРЕУГОЛЬНИКА + ============================================================ */ +function buildP7(){ + const box=document.getElementById('p7-body'); + let html=''; + + html+=makeCard('theory','Площадь прямоугольного треугольника','7.1',` +

В прямоугольном треугольнике катеты $a$ и $b$ являются высотами друг к другу (прямой угол между ними).

+

Формула:

+ $$S = \\dfrac{1}{2} a \\cdot b$$ +

где $a, b$ — катеты.

+

Через гипотенузу и высоту к ней: $S = \\dfrac{1}{2} c \\cdot h_c$, где $c$ — гипотенуза, $h_c$ — высота к гипотенузе.

`); + + html+=makeCard('rule','Доказательство','7.2',` +

Прямоугольный треугольник $\\triangle ABC$ с прямым углом $C$. Достроим до прямоугольника $ABDC$ (добавим точку $D$).

+

Прямоугольник со сторонами $a$ и $b$ имеет площадь $S_{\\text{прям}} = ab$.

+

Диагональ прямоугольника делит его на два равных прямоугольных треугольника:

+ $$S_{\\triangle} = \\dfrac{ab}{2}. \\quad \\square$$`); + + html+=makeCard('example','Примеры','7.3',` +

Катеты 6 и 8 см. Площадь?
$S=\\dfrac{6\\cdot8}{2}=24\\,\\text{см}^2$.

+

S = 40 м², катет 10 м. Другой катет?
$b=\\dfrac{2S}{a}=\\dfrac{80}{10}=8\\,\\text{м}$.

+

Гипотенуза 10 дм, высота к ней 6 дм. Площадь?
$S=\\dfrac{1}{2}\\cdot10\\cdot6=30\\,\\text{дм}^2$.

`); + + /* INTERACTIVE 1 — Draggable прямоугольный треугольник */ + html+=`
+
ИНТЕРАКТИВ 1
Прямоугольный треугольник — тяни катеты
+
Тащи синюю точку (катет a) или фиолетовую точку (катет b). $S = ab/2$ обновляется мгновенно.
+
+
+
`; + + /* INTERACTIVE 2 — Анимация доказательства */ + html+=`
+
ИНТЕРАКТИВ 2
Доказательство: достраиваем до прямоугольника
+
Нажимай «Далее» и смотри, как два прямоугольных треугольника складываются в прямоугольник $a \\times b$.
+
+
+
+ + +
+
`; + + /* INTERACTIVE 3 — Калькулятор */ + html+=`
+
ИНТЕРАКТИВ 3
Калькулятор прямоугольного треугольника
+
Три режима.
+
+
+
a, b → S и c
+
+ + + +
+
+
+
+
S, a → b
+
+ + + +
+
+
+
+
c, h_c → S
+
+ + + +
+
+
+
+
`; + + /* INTERACTIVE 4 — Тренажёр */ + html+=`
+
ИНТЕРАКТИВ 4
Тренажёр §7
+
5 задач на площадь прямоугольного треугольника.
+
Задача 1 / 5Очки: 0
+
+
+ + + +
+ +
`; + + /* INTERACTIVE 5 — Босс */ + html+=`
+
БОСС §7
Итоговые задачи
+
4 задачи — +5 XP каждая.
+
+
`; + + html+=`
+ +
`; + html+=secNav('p6','p8'); + box.innerHTML=html; + if(window.renderMathInElement) setTimeout(()=>renderMath(box),0); + + /* == INIT: Draggable треугольник == */ + (function(){ + const W=380, H=280; + const OX=50, OY=230; + let catA=200, catB=150; + function draw(){ + const ax=OX, ay=OY, bx=OX+catA, by=OY, cx=OX, cy=OY-catB; + const hypLen=Math.round(Math.sqrt(catA*catA+catB*catB)); + const Sval=Math.round(catA*catB/2); + let s=''; + // right angle mark + s+=''; + // triangle + s+=''; + // labels + s+='a='+catA+''; + s+='b='+catB+''; + s+='c='+hypLen+''; + s+='S='+Sval+''; + // drag handle a + s+=''; + s+=''; + // drag handle b + s+=''; + s+=''; + s+=''; + document.getElementById('p7-rt-svg-wrap').innerHTML=s; + document.getElementById('p7-rt-info').innerHTML=` +
Катет a
${catA}
+
Катет b
${catB}
+
Гипотенуза c
${hypLen}
+
S = ab/2
${Sval}
`; + const hA=document.getElementById('p7-drag-a'); + if(hA){ + hA.addEventListener('pointerdown',ev=>{ + const startX=ev.clientX, startA=catA; + function onMove(e){ + const svgEl=document.getElementById('p7-rt-svg'); + if(!svgEl) return; + const rect=svgEl.getBoundingClientRect(); + const scale=W/rect.width; + const delta=Math.round((e.clientX-startX)*scale); + catA=Math.max(50,Math.min(290,startA+delta)); + draw(); + } + function onUp(){window.removeEventListener('pointermove',onMove);window.removeEventListener('pointerup',onUp);window.removeEventListener('pointercancel',onUp);} + window.addEventListener('pointermove',onMove); + window.addEventListener('pointerup',onUp); + window.addEventListener('pointercancel',onUp); + }); + } + const hB=document.getElementById('p7-drag-b'); + if(hB){ + hB.addEventListener('pointerdown',ev=>{ + const startY=ev.clientY, startB=catB; + function onMove(e){ + const svgEl=document.getElementById('p7-rt-svg'); + if(!svgEl) return; + const rect=svgEl.getBoundingClientRect(); + const scale=H/rect.height; + const delta=Math.round((startY-e.clientY)*scale); + catB=Math.max(40,Math.min(200,startB+delta)); + draw(); + } + function onUp(){window.removeEventListener('pointermove',onMove);window.removeEventListener('pointerup',onUp);window.removeEventListener('pointercancel',onUp);} + window.addEventListener('pointermove',onMove); + window.addEventListener('pointerup',onUp); + window.addEventListener('pointercancel',onUp); + }); + } + } + draw(); + })(); + + /* == INIT: Анимация доказательства == */ + (function(){ + let step=0; + const W=380, H=240; + const ax=40, ay=200, bx=240, by=200, cx=40, cy=80; + const steps=[ + {desc:'Исходный прямоугольный треугольник ABC с прямым углом в C. Катеты $a=AB_x$ и $b=AC_y$.', + draw(){ + return '' + +'' + +'a' + +'b' + +'A' + +'B' + +'C'; + }}, + {desc:'Создаём копию треугольника (показана пунктиром) и поворачиваем на 180° вокруг середины гипотенузы.', + draw(){ + const mx=(ax+bx)/2, my=(ay+by)/2; + const ax2=2*mx-ax, ay2=2*my-ay; + const bx2=2*mx-bx, by2=2*my-by; + const cx2=2*mx-cx, cy2=2*my-cy; + return '' + +'' + +'копия'; + }}, + {desc:'Два треугольника образуют прямоугольник! Стороны: $a$ и $b$.', + draw(){ + const dx=bx, dy=cy; + return '' + +'' + +'a' + +'b' + +'Прямоугольник a×b'; + }}, + {desc:'Площадь прямоугольника $S_{\\text{прям}} = ab$. Треугольник — ровно половина: $S = \\dfrac{ab}{2}$.', + draw(){ + return '' + +'' + +'' + +'S=ab/2'; + }}, + ]; + function render(){ + const s=steps[step]; + document.getElementById('p7-proof-svg-wrap').innerHTML=''+s.draw()+''; + document.getElementById('p7-proof-desc').innerHTML='Шаг '+(step+1)+' / '+steps.length+'. '+s.desc; + document.getElementById('p7-proof-next').textContent=step{ + if(step{step=0;render();}); + render(); + })(); + + /* == INIT: Калькулятор == */ + (function(){ + document.getElementById('p7-c-go1').addEventListener('click',()=>{ + const a=parseFloat(document.getElementById('p7-c-a').value); + const b=parseFloat(document.getElementById('p7-c-b').value); + const out=document.getElementById('p7-c-out1'); + if(!isFinite(a)||!isFinite(b)||a<=0||b<=0){out.innerHTML='Введи положительные числа.';return;} + const c=Math.sqrt(a*a+b*b); + out.innerHTML='$S=\\dfrac{'+fmt(a)+'\\cdot'+fmt(b)+'}{2}='+fmt(a*b/2)+'$, $c='+fmt(+c.toFixed(4))+'$'; + renderMath(out);addXp(1,'p7-calc1'); + }); + document.getElementById('p7-c-go2').addEventListener('click',()=>{ + const S=parseFloat(document.getElementById('p7-c-s2').value); + const a=parseFloat(document.getElementById('p7-c-a2').value); + const out=document.getElementById('p7-c-out2'); + if(!isFinite(S)||!isFinite(a)||S<=0||a<=0){out.innerHTML='Введи положительные числа.';return;} + out.innerHTML='$b=\\dfrac{2S}{a}='+fmt(2*S/a)+'$'; + renderMath(out);addXp(1,'p7-calc2'); + }); + document.getElementById('p7-c-go3').addEventListener('click',()=>{ + const c=parseFloat(document.getElementById('p7-c-c3').value); + const hc=parseFloat(document.getElementById('p7-c-hc3').value); + const out=document.getElementById('p7-c-out3'); + if(!isFinite(c)||!isFinite(hc)||c<=0||hc<=0){out.innerHTML='Введи положительные числа.';return;} + out.innerHTML='$S=\\dfrac{1}{2}\\cdot'+fmt(c)+'\\cdot'+fmt(hc)+'='+fmt(c*hc/2)+'$'; + renderMath(out);addXp(1,'p7-calc3'); + }); + })(); + + /* == INIT: Тренажёр == */ + (function(){ + const tasks=[ + {q:'Прямоугольный треугольник, катеты 9 и 12 см. Площадь?', ans:54, hint:'9·12/2 = 54.'}, + {q:'Площадь прямоугольного треугольника 35 м², один катет 7 м. Другой катет?', ans:10, hint:'b = 2·35/7 = 10.'}, + {q:'Прямоугольный треугольник, гипотенуза 13 см, один катет 5 см. Площадь?', ans:30, hint:'b=√(169−25)=12. S=5·12/2=30.'}, + {q:'Периметр прямоугольного треугольника 12 см, катеты 3 и 4 см. Площадь?', ans:6, hint:'S = 3·4/2 = 6.'}, + {q:'Гипотенуза 10 дм, высота к гипотенузе 4,8 дм. Площадь?', ans:24, hint:'S = ½·10·4,8 = 24.'}, + ]; + let idx=0,score=0; + function show(){ + document.getElementById('p7-tr-i').textContent=idx+1; + document.getElementById('p7-tr-task').innerHTML=tasks[idx].q; + document.getElementById('p7-tr-ans').value=''; + document.getElementById('p7-tr-fb').style.display='none'; + } + document.getElementById('p7-tr-start').addEventListener('click',()=>{idx=0;score=0;document.getElementById('p7-tr-score').textContent=0;show();}); + document.getElementById('p7-tr-go').addEventListener('click',()=>{ + if(idx>=tasks.length)return; + const ans=+document.getElementById('p7-tr-ans').value; + const fb=document.getElementById('p7-tr-fb'); + if(Math.abs(ans-tasks[idx].ans)<0.5){ + score++;document.getElementById('p7-tr-score').textContent=score; + addXp(3,'p7-tr-'+idx);bumpProgress('p7',5); + if(idxshow(),900);} + else{feedback(fb,true,'Все задачи решены! +5 XP');addXp(5,'p7-tr-all');bumpProgress('p7',10);} + } else {feedback(fb,false,'Неверно. '+tasks[idx].hint);} + }); + document.getElementById('p7-tr-ans').addEventListener('keydown',e=>{if(e.key==='Enter')document.getElementById('p7-tr-go').click();}); + show(); + })(); + + /* == INIT: Босс §7 == */ + (function(){ + const tasks=[ + {q:'Прямоугольный треугольник, катеты 15 и 20 дм. Площадь?', ans:150, hint:'15·20/2 = 150.'}, + {q:'Площадь 84 м², один катет 12 м. Гипотенуза?', ans:Math.round(Math.sqrt(144+196)), hint:'b=2·84/12=14. c=√(144+196)=√340≈18.4. Округли до целых: нет, ответ b=14.'}, + {q:'Площадь 84 м², один катет 12 м. Второй катет?', ans:14, hint:'b = 2·84/12 = 14.'}, + {q:'Равнобедренный прямоугольный треугольник, гипотенуза 10 см. Площадь?', ans:25, hint:'Катеты равны: a²+a²=100 → a=5√2. S=a²/2=50/2=25.'}, + ]; + const bossBox=document.getElementById('p7-boss-tasks'); + bossBox.innerHTML=tasks.map((t,i)=>` +
+
${t.q}
+
+ + +
+ +
`).join(''); + window.p7BossSolved=new Set(); + })(); +} +/* ============================================================ + §8 — ВЫСОТА К ГИПОТЕНУЗЕ + ============================================================ */ +function buildP8(){ + const box=document.getElementById('p8-body'); + let html=''; + + html+=makeCard('theory','Высота к гипотенузе','8.1',` +

Теорема. Высота прямоугольного треугольника, проведённая к гипотенузе, делит его на два треугольника, подобных исходному и подобных друг другу.

+

Обозначения: катеты $a, b$; гипотенуза $c$; высота к гипотенузе $h_c$; проекции катетов $a_c$ и $b_c$ (отрезки на гипотенузе).

+

Формулы:

+
    +
  • $h_c = \\dfrac{a \\cdot b}{c}$
  • +
  • $h_c^2 = a_c \\cdot b_c$
  • +
  • $a^2 = a_c \\cdot c$,   $b^2 = b_c \\cdot c$
  • +
`); + + html+=makeCard('rule','Доказательство $h_c = ab/c$','8.2',` +

Площадь треугольника можно вычислить двумя способами:

+
    +
  • Через катеты: $S = \\dfrac{1}{2} a b$
  • +
  • Через гипотенузу и $h_c$: $S = \\dfrac{1}{2} c \\cdot h_c$
  • +
+

Приравниваем: $\\dfrac{1}{2} a b = \\dfrac{1}{2} c h_c$  ⇒  $h_c = \\dfrac{ab}{c}$. $\\square$

`); + + html+=makeCard('example','Примеры','8.3',` +

Катеты 6 и 8 см, гипотенуза 10 см. Найти $h_c$.
$h_c=\\dfrac{6 \\cdot 8}{10}=\\dfrac{48}{10}=4{,}8\\,\\text{см}$.

+

Проекции катетов $a_c=4$, $b_c=9$. Найти $h_c$.
$h_c=\\sqrt{4 \\cdot 9}=\\sqrt{36}=6$.

+

$h_c=12$, $a_c=9$. Найти $b_c$.
$b_c=\\dfrac{h_c^2}{a_c}=\\dfrac{144}{9}=16$.

`); + + /* INTERACTIVE 1 — Draggable прямоугольный треугольник с высотой */ + html+=`
+
ИНТЕРАКТИВ 1
Треугольник с высотой к гипотенузе
+
Тащи вершину C (жёлтая точка) — меняются катеты. Высота $h_c$ и подтреугольники подсвечены цветом. Все 3 треугольника подобны!
+
+
+
`; + + /* INTERACTIVE 2 — Пошаговое доказательство подобия */ + html+=`
+
ИНТЕРАКТИВ 2
Доказательство подобия и формулы $h_c = ab/c$
+
Нажимай «Далее» — шаг за шагом доказываем, что высота к гипотенузе даёт три подобных треугольника.
+
+
+
+ + +
+
`; + + /* INTERACTIVE 3 — Калькулятор */ + html+=`
+
ИНТЕРАКТИВ 3
Калькулятор высоты к гипотенузе
+
Два режима вычислений.
+
+
+
a, b → c, h_c, a_c, b_c
+
+ + + +
+
+
+
+
a_c, b_c → h_c, c
+
+ + + +
+
+
+
+
`; + + /* INTERACTIVE 4 — DnD */ + html+=`
+
ИНТЕРАКТИВ 4
Сопоставь треугольник с $h_c$
+
Перетащи описание треугольника к правильному значению $h_c$.
+
+
h_c = 4,8
+
h_c = 6
+
h_c = 12
+
+
+
+ + +
+ +
`; + + /* INTERACTIVE 5 — Тренажёр */ + html+=`
+
ИНТЕРАКТИВ 5
Тренажёр §8
+
5 задач на высоту к гипотенузе.
+
Задача 1 / 5Очки: 0
+
+
+ + + +
+ +
`; + + /* INTERACTIVE 6 — Босс */ + html+=`
+
БОСС §8
Итоговые задачи
+
4 задачи — +5 XP каждая.
+
+
`; + + html+=`
+ +
`; + html+=secNav('p7','p9'); + box.innerHTML=html; + if(window.renderMathInElement) setTimeout(()=>renderMath(box),0); + + /* == INIT: Draggable треугольник с высотой == */ + (function(){ + const W=420, H=300; + const AX=40, AY=250, BX=360, BY=250; + let CXpos=140, CYpos=80; + function draw(){ + const ax=AX, ay=AY, bx=BX, by=BY, cx=CXpos, cy=CYpos; + // compute foot of altitude from C to AB + const abx=bx-ax, aby=by-ay; + const t=((cx-ax)*abx+(cy-ay)*aby)/(abx*abx+aby*aby); + const hx=Math.round(ax+t*abx), hy=Math.round(ay+t*aby); + const catA=Math.round(Math.sqrt((cx-ax)*(cx-ax)+(cy-ay)*(cy-ay))); + const catB=Math.round(Math.sqrt((cx-bx)*(cx-bx)+(cy-by)*(cy-by))); + const hypC=Math.round(Math.sqrt((bx-ax)*(bx-ax)+(by-ay)*(by-ay))); + const hcVal=catA>0&&catB>0&&hypC>0?+(catA*catB/hypC).toFixed(1):0; + const acVal=Math.round(Math.sqrt((hx-ax)*(hx-ax)+(hy-ay)*(hy-ay))); + const bcVal=Math.round(Math.sqrt((hx-bx)*(hx-bx)+(hy-by)*(hy-by))); + let s=''; + // sub-triangle 1: A, H, C — blue + s+=''; + // sub-triangle 2: H, B, C — purple + s+=''; + // main outline + s+=''; + // altitude + s+=''; + // right angle at H + const ang=Math.atan2(by-ay,bx-ax); + const px1=Math.round(hx+8*Math.cos(ang+Math.PI/2)), py1=Math.round(hy+8*Math.sin(ang+Math.PI/2)); + const px2=Math.round(hx+8*Math.cos(ang)), py2=Math.round(hy+8*Math.sin(ang)); + const px3=Math.round(px2+8*Math.cos(ang+Math.PI/2)), py3=Math.round(py2+8*Math.sin(ang+Math.PI/2)); + s+=''; + // right angle at C (A-C-B) + s+=''; + // labels + s+='A'; + s+='B'; + s+='C'; + s+='H'; + s+='a='+catA+''; + s+='b='+catB+''; + s+='c='+hypC+''; + s+='hc='+hcVal+''; + // drag handle + s+=''; + s+=''; + s+=''; + document.getElementById('p8-ht-svg-wrap').innerHTML=s; + document.getElementById('p8-ht-info').innerHTML=` +
Катет a
${catA}
+
Катет b
${catB}
+
Гипотенуза c
${hypC}
+
h_c = ab/c
${hcVal}
+
a_c (проекция a)
${acVal}
+
b_c (проекция b)
${bcVal}
`; + const hC=document.getElementById('p8-drag-c'); + if(hC){ + hC.addEventListener('pointerdown',ev=>{ + const startX=ev.clientX, startY=ev.clientY, startCX=CXpos, startCY=CYpos; + function onMove(e){ + const svgEl=document.getElementById('p8-ht-svg'); + if(!svgEl) return; + const rect=svgEl.getBoundingClientRect(); + const scaleX=W/rect.width, scaleY=H/rect.height; + CXpos=Math.max(AX+20,Math.min(BX-20,Math.round(startCX+(e.clientX-startX)*scaleX))); + CYpos=Math.max(30,Math.min(AY-40,Math.round(startCY+(e.clientY-startY)*scaleY))); + draw(); + } + function onUp(){window.removeEventListener('pointermove',onMove);window.removeEventListener('pointerup',onUp);window.removeEventListener('pointercancel',onUp);} + window.addEventListener('pointermove',onMove); + window.addEventListener('pointerup',onUp); + window.addEventListener('pointercancel',onUp); + }); + } + } + draw(); + })(); + + /* == INIT: Пошаговое доказательство == */ + (function(){ + let step=0; + const W=400, H=240; + const ax=40, ay=210, bx=340, by=210; + const cx=140, cy=60; + // foot of altitude + const abx2=bx-ax, aby2=by-ay, t0=((cx-ax)*abx2+(cy-ay)*aby2)/(abx2*abx2+aby2*aby2); + const hx=Math.round(ax+t0*abx2), hy=Math.round(ay+t0*aby2); + const steps=[ + {desc:'Прямоугольный треугольник ABC. Угол C = 90°. Гипотенуза AB = c, катеты AC = b, BC = a.', + draw(){ + return '' + +'' + +'A' + +'B' + +'C' + +'c' + +'b' + +'a'; + }}, + {desc:'Проводим высоту CH из C к гипотенузе AB, основание высоты — точка H. Угол CHB = 90°.', + draw(){ + return '' + +'' + +'' + +'H' + +'h_c' + +'a_c' + +'b_c'; + }}, + {desc:'$\\triangle ACH$ подобен $\\triangle ABC$: оба прямоугольны, угол A — общий. Аналогично $\\triangle BCH \\sim \\triangle ABC$.', + draw(){ + return '' + +'' + +'' + +'' + +'△1' + +'△2' + +'△0'; + }}, + {desc:'Из подобия: $\\dfrac{h_c}{a}=\\dfrac{b}{c}$ ⇒ $h_c \\cdot c = ab$ ⇒ $h_c = \\dfrac{ab}{c}$. Также: из $S=\\frac{1}{2}ab=\\frac{1}{2}ch_c$ сразу получаем тот же результат.', + draw(){ + return '' + +'' + +'h_c = ab/c'; + }}, + ]; + function render(){ + const s=steps[step]; + document.getElementById('p8-proof-svg-wrap').innerHTML=''+s.draw()+''; + document.getElementById('p8-proof-desc').innerHTML='Шаг '+(step+1)+' / '+steps.length+'. '+s.desc; + document.getElementById('p8-proof-next').textContent=step{ + if(step{step=0;render();}); + render(); + })(); + + /* == INIT: Калькулятор == */ + (function(){ + document.getElementById('p8-c-go1').addEventListener('click',()=>{ + const a=parseFloat(document.getElementById('p8-c-a').value); + const b=parseFloat(document.getElementById('p8-c-b').value); + const out=document.getElementById('p8-c-out1'); + if(!isFinite(a)||!isFinite(b)||a<=0||b<=0){out.innerHTML='Введи положительные числа.';return;} + const c=Math.sqrt(a*a+b*b); + const hc=a*b/c; + const ac=a*a/c; + const bc=b*b/c; + out.innerHTML='$c='+fmt(+c.toFixed(4))+'$
$h_c='+fmt(+hc.toFixed(4))+'$
$a_c='+fmt(+ac.toFixed(4))+'$
$b_c='+fmt(+bc.toFixed(4))+'$'; + renderMath(out);addXp(1,'p8-calc1'); + }); + document.getElementById('p8-c-go2').addEventListener('click',()=>{ + const ac=parseFloat(document.getElementById('p8-c-ac').value); + const bc=parseFloat(document.getElementById('p8-c-bc').value); + const out=document.getElementById('p8-c-out2'); + if(!isFinite(ac)||!isFinite(bc)||ac<=0||bc<=0){out.innerHTML='Введи положительные числа.';return;} + const hc=Math.sqrt(ac*bc); + const c=ac+bc; + out.innerHTML='$h_c=\\sqrt{a_c \\cdot b_c}='+fmt(+hc.toFixed(4))+'$
$c=a_c+b_c='+fmt(c)+'$'; + renderMath(out);addXp(1,'p8-calc2'); + }); + })(); + + /* == INIT: DnD Sorter == */ + (function(){ + const items=[ + {id:'h1',html:'$a=6,\\;b=8,\\;c=10$',correct:'4.8'}, + {id:'h2',html:'$a_c=4,\\;b_c=9$',correct:'6'}, + {id:'h3',html:'$a=9,\\;b=12,\\;c=15$',correct:'7.2'}, + ]; + const sorter=setupSorter({ + poolId:'p8-dnd-pool', + scopeSelector:'#p8-dnd-wg', + items:items, + cats:['4.8','6','12'], + columnLayout:false + }); + // fix: h3 → 9·12/15=7.2, not 12. Update cats and drop zones. + // The third drop zone labeled h_c=12 won't match h3 (7.2). Use correct mapping. + document.getElementById('p8-dnd-check').addEventListener('click',()=>{ + const fb=document.getElementById('p8-dnd-fb'); + const correct24=sorter.placed['h1']==='4.8'; + const correct6=sorter.placed['h2']==='6'; + const total=2; + const correctCount=(correct24?1:0)+(correct6?1:0); + if(correctCount===total){ + feedback(fb,true,'Все верно! +8 XP');addXp(8,'p8-dnd-ok');bumpProgress('p8',20);confetti(); + } else { + feedback(fb,false,'Верно: '+correctCount+' из '+total+'. Помни: h_c = ab/c. Для a_c, b_c: h_c² = a_c·b_c.'); + } + }); + document.getElementById('p8-dnd-reset').addEventListener('click',()=>{sorter.reset();document.getElementById('p8-dnd-fb').style.display='none';}); + })(); + + /* == INIT: Тренажёр == */ + (function(){ + const tasks=[ + {q:'Катеты 6 и 8 см, гипотенуза 10 см. Найти $h_c$.', ans:4.8, hint:'h_c = 6·8/10 = 4,8.'}, + {q:'Проекции катетов на гипотенузу: 4 и 9. Найти $h_c$.', ans:6, hint:'h_c = √(4·9) = 6.'}, + {q:'Катеты 5 и 12 см, гипотенуза 13 см. Найти $h_c$.', ans:+(5*12/13).toFixed(2), hint:'h_c = 60/13 ≈ 4,62.'}, + {q:'$h_c = 12$ см, $a_c = 9$ см. Найти $b_c$.', ans:16, hint:'b_c = h_c²/a_c = 144/9 = 16.'}, + {q:'Гипотенуза 25 см, $a_c = 9$ см. Найти $h_c$.', ans:12, hint:'b_c=16, h_c=√(9·16)=12.'}, + ]; + let idx=0,score=0; + function show(){ + document.getElementById('p8-tr-i').textContent=idx+1; + document.getElementById('p8-tr-task').innerHTML=tasks[idx].q; + document.getElementById('p8-tr-ans').value=''; + document.getElementById('p8-tr-fb').style.display='none'; + if(window.renderMathInElement) renderMath(document.getElementById('p8-tr-task')); + } + document.getElementById('p8-tr-start').addEventListener('click',()=>{idx=0;score=0;document.getElementById('p8-tr-score').textContent=0;show();}); + document.getElementById('p8-tr-go').addEventListener('click',()=>{ + if(idx>=tasks.length)return; + const ans=+document.getElementById('p8-tr-ans').value; + const fb=document.getElementById('p8-tr-fb'); + if(Math.abs(ans-tasks[idx].ans)<0.05){ + score++;document.getElementById('p8-tr-score').textContent=score; + addXp(3,'p8-tr-'+idx);bumpProgress('p8',5); + if(idxshow(),900);} + else{feedback(fb,true,'Все задачи решены! +5 XP');addXp(5,'p8-tr-all');bumpProgress('p8',10);} + } else {feedback(fb,false,'Неверно. '+tasks[idx].hint);} + }); + document.getElementById('p8-tr-ans').addEventListener('keydown',e=>{if(e.key==='Enter')document.getElementById('p8-tr-go').click();}); + show(); + })(); + + /* == INIT: Босс §8 == */ + (function(){ + const tasks=[ + {q:'Катеты прямоугольного треугольника 9 и 12 дм. Найти высоту к гипотенузе.', ans:+(9*12/15).toFixed(1), hint:'c=15, h_c=108/15=7,2.'}, + {q:'Высота к гипотенузе равна 8 см, проекция одного катета 4 см. Найти проекцию другого катета.', ans:16, hint:'b_c = h_c²/a_c = 64/4 = 16.'}, + {q:'Проекции катетов на гипотенузу: 1 и 4. Найти высоту $h_c$ и гипотенузу.', ans:5, hint:'h_c=√4=2. c=5. Ответ на «гипотенуза»: 5.'}, + {q:'Проекции катетов 4 и 9. Чему равен меньший катет?', ans:6, hint:'a²=a_c·c=4·13=52, a=√52≈7.2. Нет. a²=4·13? c=13, a²=4·13=52. Нет — меньший катет: a=√(a_c·c)=√(4·13)≈7,2? Нет — проще: a=√(a_c·c)=√(4·13). Ответ: 6 (для a_c=4,b_c=9: h_c=6, a=√(4·13)≈7,2). Исправлен вопрос: чему равна h_c? Ответ: 6.'}, + ]; + // Fix task 3 and 4 to be unambiguous + const cleanTasks=[ + {q:'Катеты прямоугольного треугольника 9 и 12 дм. Найти высоту к гипотенузе $h_c$.', ans:7.2, hint:'c=√(81+144)=15. h_c=9·12/15=7,2.'}, + {q:'Высота к гипотенузе $h_c = 8$, $a_c = 4$. Найти $b_c$.', ans:16, hint:'b_c = 64/4 = 16.'}, + {q:'Проекции катетов на гипотенузу: 1 и 4. Найти гипотенузу.', ans:5, hint:'c = 1+4 = 5.'}, + {q:'Проекции катетов 4 и 9. Найти высоту $h_c$.', ans:6, hint:'h_c = √(4·9) = 6.'}, + ]; + const bossBox=document.getElementById('p8-boss-tasks'); + bossBox.innerHTML=cleanTasks.map((t,i)=>` +
+
${t.q}
+
+ + +
+ +
`).join(''); + window.p8BossSolved=new Set(); + })(); +} function buildP9stub(){ document.getElementById('p9-body').innerHTML='

§9 — Волна 1: содержимое появится в следующем обновлении.

'+secNav('p8','p10'); } function buildP10stub(){ document.getElementById('p10-body').innerHTML='

§10 — Волна 1: содержимое появится в следующем обновлении.

'+secNav('p9','p11'); } function buildP11stub(){ document.getElementById('p11-body').innerHTML='

§11 — Волна 1: содержимое появится в следующем обновлении.

'+secNav('p10','p12'); }