diff --git a/frontend/textbooks/geometry_8_ch3.html b/frontend/textbooks/geometry_8_ch3.html index f8594e5..5c8297f 100644 --- a/frontend/textbooks/geometry_8_ch3.html +++ b/frontend/textbooks/geometry_8_ch3.html @@ -339,7 +339,7 @@ const PARAS=[ function buildParaSelector(){const g=document.getElementById('psel-grid');g.innerHTML='';PARAS.forEach(p=>{const card=document.createElement('div');card.className='psel-card'+(p.final?' final':'');card.dataset.id=p.id;card.dataset.progCard=p.id;card.innerHTML=`
${p.num}
${p.name}
`;card.addEventListener('click',()=>goTo(p.id));g.appendChild(card);});} const BUILT=new Set(); -const BUILDERS={p1:()=>buildP1(),p2:()=>buildP2(),p3:()=>buildP3(),p4:()=>buildP4stub(),p5:()=>buildP5stub(),p6:()=>buildP6stub(),p7:()=>buildP7stub(),p8:()=>buildP8stub(),p9:()=>buildP9stub(),final3:()=>buildFinal3stub()}; +const BUILDERS={p1:()=>buildP1(),p2:()=>buildP2(),p3:()=>buildP3(),p4:()=>buildP4(),p5:()=>buildP5(),p6:()=>buildP6stub(),p7:()=>buildP7stub(),p8:()=>buildP8stub(),p9:()=>buildP9stub(),final3:()=>buildFinal3stub()}; 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);document.querySelectorAll('.sec').forEach(s=>s.classList.remove('active'));const el=document.getElementById('sec-'+id);if(el)el.classList.add('active');document.querySelectorAll('.psel-card').forEach(c=>c.classList.toggle('active',c.dataset.id===id));buildSidebar(id);window.scrollTo({top:0,behavior:'smooth'});if((STATE.progress[id]||0)<10)bumpProgress(id,10);if(window.renderMathInElement)setTimeout(()=>renderMath(el),0);setTimeout(()=>{try{wrapGlossary(el);}catch(e){}},60);markLastPara(id);} @@ -1545,8 +1545,788 @@ function buildP3(){ renderMath(bossBox); })(); } -function buildP4stub(){ document.getElementById('p4-body').innerHTML='

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

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

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

'+secNav('p4','p6'); } +function buildP4(){ + const box=document.getElementById('p4-body'); + let html=''; + + /* ---- Theory cards ---- */ + html+=makeCard('theory','Теорема о прямой, параллельной стороне треугольника','4.1',` +

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

+

Формально: в $\\triangle ABC$ прямая $MN \\parallel BC$ пересекает $AB$ в точке $M$ и $AC$ в точке $N$. Тогда $\\triangle AMN \\sim \\triangle ABC$ с коэффициентом подобия:

+ $$k = \\dfrac{AM}{AB} = \\dfrac{AN}{AC} = \\dfrac{MN}{BC}$$ +
+ + + + + + + + + + A + B + C + M + N + MN ∥ BC + △AMN ∼ △ABC + + k=AM/AB + +
`); + + html+=makeCard('rule','Следствие — теорема Фалеса для треугольника','4.2',` +

Следствие. Если $MN \\parallel BC$ в $\\triangle ABC$, то:

+ $$\\dfrac{AM}{MB} = \\dfrac{AN}{NC}$$ +

То есть прямая, параллельная стороне треугольника, делит две другие стороны пропорционально.

+

Это прямое следствие обобщённой теоремы Фалеса: прямые $BC$, $MN$ и $A$ порождают пропорциональное деление сторон $AB$ и $AC$.

+
+ + + + + + + A + B + C + M + N + + AM + MB + + AN + NC + AM/MB = AN/NC + +
`); + + html+=makeCard('example','Пример вычисления','4.3',` +

Пример. В $\\triangle ABC$ прямая $MN \\parallel BC$. $AM = 6$, $AB = 10$, $BC = 15$. Найти $MN$.

+

Решение: коэффициент подобия $k = AM/AB = 6/10 = 0{,}6$.

+

$MN = k \\cdot BC = 0{,}6 \\cdot 15 = 9$.

+

Пример 2. $AM = 4$, $MB = 6$. Найти $AN/NC$.

+

По следствию: $AN/NC = AM/MB = 4/6 = 2/3$.

`); + + /* ---- ИНТЕРАКТИВ 1: SVG треугольник со slider ---- */ + html+=`
+
ИНТЕРАКТИВ 1
Параллельная прямая отсекает подобный треугольник
+
Перемещай прямую $MN \\parallel BC$ по высоте треугольника. Коэффициент подобия $k$ меняется — $\\triangle AMN \\sim \\triangle ABC$.
+
+ +
+
+
+
`; + + /* ---- ИНТЕРАКТИВ 2: Пошаговое доказательство ---- */ + html+=`
+
ИНТЕРАКТИВ 2
Доказательство — по шагам
+
Нажимай «Далее» — каждый шаг раскрывает ключевую идею доказательства.
+
+
+
+ + +
+
`; + + /* ---- ИНТЕРАКТИВ 3: Калькулятор ---- */ + html+=`
+
ИНТЕРАКТИВ 3
Калькулятор: параллельная сторона
+
Введи $AM$, $AB$, $BC$ → найди $MN = BC \\cdot AM/AB$. Или задай $MN$, $BC$ → найди $AM/AB$.
+
+
AM
+
AB
+
BC
+
+
+ +
`; + + /* ---- ИНТЕРАКТИВ 4: Тренажёр ---- */ + html+=`
+
ИНТЕРАКТИВ 4
Тренажёр §4
+
5 задач на нахождение MN, AN, AM и отношений.
+
Задача 1 / 5Очки: 0
+
+
+ + + +
+ +
`; + + /* ---- ИНТЕРАКТИВ 5: DnD-сортер ---- */ + html+=`
+
ИНТЕРАКТИВ 5
Соотнеси параллельные прямые и пропорции
+
Перетащи каждую карточку: «Пропорция верна» или «Пропорция неверна».
+
+
+
Пропорция верна
+
Пропорция неверна
+
+
+ +
`; + + /* ---- ИНТЕРАКТИВ 6: Босс §4 ---- */ + html+=`
+
БОСС §4
Итоговые задачи
+
4 задачи — каждая верная даёт +5 XP.
+
+
`; + + html+=`
+ +
`; + html+=secNav('p3','p5'); + box.innerHTML=html; + if(window.renderMathInElement) setTimeout(()=>renderMath(box),0); + + /* == INIT ИНТЕРАКТИВ 1: slider параллельной прямой == */ + (function(){ + const tSl=document.getElementById('p4-t-sl'); + const tVal=document.getElementById('p4-t-val'); + const svgWrap=document.getElementById('p4-par-svg'); + const infoEl=document.getElementById('p4-par-info'); + // base triangle: A=(140,15), B=(30,155), C=(250,155) + const Ax=140,Ay=15,Bx=30,By=155,Cx=250,Cy=155; + const BC=Math.hypot(Cx-Bx,Cy-By); + const AB=Math.hypot(Bx-Ax,By-Ay); + const AC=Math.hypot(Cx-Ax,Cy-Ay); + function draw(){ + const t=+tSl.value/100; + tVal.textContent=t.toFixed(2); + const Mx=Ax+t*(Bx-Ax), My=Ay+t*(By-Ay); + const Nx=Ax+t*(Cx-Ax), Ny=Ay+t*(Cy-Ay); + const MN=Math.hypot(Nx-Mx,Ny-My); + const AM=Math.hypot(Mx-Ax,My-Ay); + const AN=Math.hypot(Nx-Ax,Ny-Ay); + const W=300, H=180; + let s=``; + // full triangle light + s+=``; + // inner triangle AMN highlighted + s+=``; + // MN line + s+=``; + // points + s+=``; + s+=``; + // labels + s+=`A`; + s+=`B`; + s+=`C`; + s+=`M`; + s+=`N`; + // k badge + s+=`k = ${t.toFixed(2)}`; + s+=''; + svgWrap.innerHTML=s; + infoEl.innerHTML=`$k = AM/AB = ${t.toFixed(3)}$. $MN = k \\cdot BC = ${t.toFixed(3)} \\cdot ${fmt(BC/10)} = ${fmt(MN/10)}$.
$AM/MB = ${fmt(t/(1-t+1e-9))}$. По следствию: $AN/NC = AM/MB = ${fmt(t/(1-t+1e-9))}$.`; + renderMath(infoEl); + addXp(1,'p4-par'); + } + tSl.addEventListener('input',draw); + draw(); + })(); + + /* == INIT ИНТЕРАКТИВ 2: пошаговое доказательство == */ + (function(){ + const steps=[ + {desc:'Шаг 1. Дан $\\triangle ABC$. Прямая $MN \\parallel BC$ пересекает $AB$ в $M$ и $AC$ в $N$. Требуется доказать $\\triangle AMN \\sim \\triangle ABC$.', + svg:`ABCMNMN ∥ BC`}, + {desc:'Шаг 2. $\\angle AMN = \\angle ABC$, так как $MN \\parallel BC$ и $AB$ — секущая: это соответственные углы при параллельных прямых и секущей.', + svg:`ABCMN∠AMN = ∠ABC`}, + {desc:'Шаг 3. Аналогично $\\angle ANM = \\angle ACB$: $MN \\parallel BC$ и $AC$ — секущая, получаем соответственные углы.', + svg:`ABCMN∠ANM = ∠ACB`}, + {desc:'Шаг 4. Угол $\\angle A$ общий у $\\triangle AMN$ и $\\triangle ABC$. Два угла $\\triangle AMN$ равны соответствующим двум углам $\\triangle ABC$ → по признаку ДД (два угла) $\\triangle AMN \\sim \\triangle ABC$.', + svg:`ABCMN△AMN ∼ △ABC`}, + {desc:'Шаг 5. Из подобия следует пропорциональность сторон: $AM/AB = AN/AC = MN/BC = k$. Следствие: $AM/MB = AN/NC$ — прямое следствие теоремы Фалеса. Доказано.', + svg:`AM/AB = AN/AC = MN/BC = kAM/MB = AN/NCQED ∎`}, + ]; + let step=0; + const svgEl=document.getElementById('p4-proof-svg'); + const descEl=document.getElementById('p4-proof-desc'); + function show(){ + svgEl.innerHTML=steps[step].svg; + descEl.innerHTML=steps[step].desc; + renderMath(descEl); + } + document.getElementById('p4-proof-next').addEventListener('click',()=>{ + if(step{step=0;show();}); + show(); + })(); + + /* == INIT ИНТЕРАКТИВ 3: калькулятор == */ + (function(){ + document.getElementById('p4-ccalc').addEventListener('click',()=>{ + const AM=parseFloat(document.getElementById('p4-cAM').value); + const AB=parseFloat(document.getElementById('p4-cAB').value); + const BC=parseFloat(document.getElementById('p4-cBC').value); + const out=document.getElementById('p4-ccalc-out'); + if(!isFinite(AM)||!isFinite(AB)||!isFinite(BC)||AM<=0||AB<=0||BC<=0||AM>AB){ + out.style.display='block';out.innerHTML='Введи положительные числа; AM должно быть ≤ AB.';return; + } + const k=AM/AB; + const MN=k*BC; + const AN_over_NC=AM/(AB-AM); + out.style.display='block'; + out.innerHTML=`$k = AM/AB = ${fmt(AM)}/${fmt(AB)} = ${fmt(k)}$
$MN = k \\cdot BC = ${fmt(k)} \\cdot ${fmt(BC)} = ${fmt(MN)}$
Следствие: $AM/MB = AN/NC = ${fmt(AM)}/${fmt(AB-AM)} = ${fmt(AN_over_NC)}$`; + renderMath(out); + addXp(2,'p4-calc');bumpProgress('p4',5); + }); + })(); + + /* == INIT ИНТЕРАКТИВ 4: тренажёр == */ + (function(){ + const tasks=[ + {q:'В $\\triangle ABC$ прямая $MN \\parallel BC$, $AM=4$, $AB=10$, $BC=20$. Найди $MN$.',ans:8,hint:'k=4/10=0.4; MN=0.4·20=8.'}, + {q:'В $\\triangle ABC$ прямая $MN \\parallel BC$, $AM=6$, $AB=9$, $BC=12$. Найди $MN$.',ans:8,hint:'k=6/9=2/3; MN=2/3·12=8.'}, + {q:'$MN \\parallel BC$, $AM=5$, $MB=10$. Найди $AN/NC$.',ans:0.5,hint:'AN/NC = AM/MB = 5/10 = 0.5.'}, + {q:'$MN \\parallel BC$, $k=0.4$, $BC=30$. Найди $MN$.',ans:12,hint:'MN=k·BC=0.4·30=12.'}, + {q:'$MN \\parallel BC$, $AM=3$, $MB=6$. Чему равно $AN/AC$?',ans:0.333,hint:'AN/AC = AM/AB = 3/(3+6) = 1/3 ≈ 0.333.'}, + ]; + let idx=0,score=0; + function show(){ + document.getElementById('p4-tr-i').textContent=idx+1; + const t=document.getElementById('p4-tr-task'); + t.innerHTML=tasks[idx].q; + renderMath(t); + document.getElementById('p4-tr-ans').value=''; + document.getElementById('p4-tr-fb').style.display='none'; + } + document.getElementById('p4-tr-start').addEventListener('click',()=>{idx=0;score=0;document.getElementById('p4-tr-score').textContent=0;show();}); + document.getElementById('p4-tr-go').addEventListener('click',()=>{ + if(idx>=tasks.length)return; + const ans=+document.getElementById('p4-tr-ans').value; + const fb=document.getElementById('p4-tr-fb'); + if(Math.abs(ans-tasks[idx].ans)<0.01){ + score++;document.getElementById('p4-tr-score').textContent=score; + addXp(3,'p4-tr-'+idx);bumpProgress('p4',4); + if(idxshow(),900);} + else{feedback(fb,true,'Все задачи решены! +5 XP');addXp(5,'p4-tr-all');bumpProgress('p4',10);confetti();} + } else { + feedback(fb,false,'Неверно. '+tasks[idx].hint); + } + }); + document.getElementById('p4-tr-ans').addEventListener('keydown',e=>{if(e.key==='Enter')document.getElementById('p4-tr-go').click();}); + show(); + })(); + + /* == INIT ИНТЕРАКТИВ 5: DnD-сортер == */ + (function(){ + const items=[ + {text:'MN∥BC, AM=3, AB=6, AN=4, AC=8 → AM/MB=AN/NC',yes:true}, + {text:'MN∥BC, AM=4, MB=6, AN=3, NC=5 → AM/MB≠AN/NC',yes:false}, + {text:'MN∥BC, AM/AB=0.5, MN/BC=0.5',yes:true}, + {text:'MN∥BC, AM=2, MB=4, AN=3, NC=6 → AM/MB=AN/NC',yes:true}, + {text:'MN∥BC, k=1/3, MN=BC/2',yes:false}, + ]; + const pool=document.getElementById('p4-dnd-pool'); + const yesBox=document.getElementById('p4-drop-yes-items'); + const noBox=document.getElementById('p4-drop-no-items'); + let dragging=null; + function makeChip(it,idx){ + const chip=document.createElement('div'); + chip.className='dnd-chip'; + chip.dataset.idx=idx; + chip.textContent=it.text; + chip.draggable=true; + chip.addEventListener('dragstart',e=>{dragging=chip;chip.classList.add('dragging');e.dataTransfer.effectAllowed='move';}); + chip.addEventListener('dragend',()=>{chip.classList.remove('dragging');dragging=null;}); + return chip; + } + items.forEach((it,i)=>pool.appendChild(makeChip(it,i))); + [document.getElementById('p4-drop-yes'),document.getElementById('p4-drop-no'),pool].forEach(box=>{ + box.addEventListener('dragover',e=>{e.preventDefault();box.classList.add('over');}); + box.addEventListener('dragleave',()=>box.classList.remove('over')); + box.addEventListener('drop',e=>{ + e.preventDefault();box.classList.remove('over'); + if(!dragging)return; + const target=box===document.getElementById('p4-drop-yes')?yesBox:box===document.getElementById('p4-drop-no')?noBox:pool; + target.appendChild(dragging); + }); + }); + document.getElementById('p4-dnd-check').addEventListener('click',()=>{ + const fb=document.getElementById('p4-dnd-fb'); + const yChips=[...yesBox.querySelectorAll('.dnd-chip')]; + const nChips=[...noBox.querySelectorAll('.dnd-chip')]; + if(yChips.length+nChips.length{if(!items[+c.dataset.idx].yes)ok=false;}); + nChips.forEach(c=>{if(items[+c.dataset.idx].yes)ok=false;}); + if(ok){feedback(fb,true,'Верно! +5 XP');addXp(5,'p4-dnd');bumpProgress('p4',8);} + else{feedback(fb,false,'Есть ошибки. Проверь: MN∥BC → AM/MB=AN/NC и MN/BC=AM/AB.');} + }); + document.getElementById('p4-dnd-reset').addEventListener('click',()=>{ + [...yesBox.children].forEach(c=>pool.appendChild(c)); + [...noBox.children].forEach(c=>pool.appendChild(c)); + document.getElementById('p4-dnd-fb').style.display='none'; + }); + })(); + + /* == INIT: Босс §4 == */ + (function(){ + const tasks=[ + {q:'ABCMNAM=5, AB=8, BC=24$MN \\parallel BC$. $AM=5$, $AB=8$, $BC=24$. Найди $MN$.',ans:15,hint:'k=5/8; MN=5/8·24=15.'}, + {q:'$MN \\parallel BC$, $AM=6$, $MB=9$. Найди $AN/NC$.',ans:0.667,hint:'AN/NC = AM/MB = 6/9 = 2/3 ≈ 0.667.'}, + {q:'$MN \\parallel BC$, $MN=8$, $BC=12$. Найди $AM/AB$.',ans:0.667,hint:'AM/AB = MN/BC = 8/12 = 2/3 ≈ 0.667.'}, + {q:'В $\\triangle ABC$ прямая $MN \\parallel BC$, $AM=3$, $AB=9$, $BC=18$. Найди $MN$.',ans:6,hint:'k=3/9=1/3; MN=1/3·18=6.'}, + ]; + const bossBox=document.getElementById('p4-boss-tasks'); + bossBox.innerHTML=tasks.map((t,i)=>` +
+
${t.q}
+
+ + +
+ +
`).join(''); + window.p4BossSolved=new Set(); + renderMath(bossBox); + })(); +} + +function buildP5(){ + const box=document.getElementById('p5-body'); + let html=''; + + /* ---- Theory cards ---- */ + html+=makeCard('theory','Первый признак подобия треугольников (ДД — два угла)','5.1',` +

Теорема (1-й признак подобия). Если два угла одного треугольника соответственно равны двум углам другого треугольника, то такие треугольники подобны.

+

Если $\\angle A = \\angle A'$ и $\\angle B = \\angle B'$, то $\\triangle ABC \\sim \\triangle A'B'C'$.

+

Почему достаточно двух углов? Сумма углов треугольника равна $180°$. Если два угла равны, третий автоматически тоже равен: $\\angle C = 180° - \\angle A - \\angle B = 180° - \\angle A' - \\angle B' = \\angle C'$.

+
+ + + + A + B + C + + + + + + A' + B' + C' + + + + ∠A=∠A', ∠B=∠B' → △ABC∼△A'B'C' + +
`); + + html+=makeCard('rule','Следствие: прямоугольные треугольники','5.2',` +

Следствие. Два прямоугольных треугольника подобны, если у них равны острые углы (достаточно одной пары).

+

Если $\\angle C = \\angle C' = 90°$ и $\\angle A = \\angle A'$, то $\\triangle ABC \\sim \\triangle A'B'C'$.

+

Это потому, что прямой угол — один из двух равных углов, а второй угол задан условием.

+
+ + + + + + A + B + C + 90° + + + + + A' + B' + C' + ∠B=∠B'=90°, ∠A=∠A' → подобны + +
`); + + html+=makeCard('example','Пример применения признака ДД','5.3',` +

Пример 1. В $\\triangle ABC$: $\\angle A = 50°$, $\\angle B = 70°$. В $\\triangle A'B'C'$: $\\angle A' = 50°$, $\\angle C' = 60°$. Подобны ли треугольники?

+

$\\angle C = 180° - 50° - 70° = 60°$. $\\angle B' = 180° - 50° - 60° = 70°$. Углы: $50°, 70°, 60°$ в обоих. По признаку ДД: $\\triangle ABC \\sim \\triangle A'C'B'$.

+

Пример 2. Два прямоугольных треугольника, у одного острый угол $35°$, у другого $35°$. Подобны ли?

+

Да. Оба имеют $90°$ и $35°$ — два совпадающих угла.

`); + + /* ---- ИНТЕРАКТИВ 1: SVG два треугольника, слайдер углов ---- */ + html+=`
+
ИНТЕРАКТИВ 1
Два угла задают форму — первый признак
+
Задай углы $\\alpha$ и $\\beta$. Оба треугольника строятся с этими углами — они подобны. Коэффициент $k$ определяется масштабом.
+
+ + + +
+
+
+
`; + + /* ---- ИНТЕРАКТИВ 2: Пошаговое доказательство ---- */ + html+=`
+
ИНТЕРАКТИВ 2
Доказательство 1-го признака — по шагам
+
Нажимай «Далее» — шаг за шагом увидишь логику доказательства.
+
+
+
+ + +
+
`; + + /* ---- ИНТЕРАКТИВ 3: Тренажёр ---- */ + html+=`
+
ИНТЕРАКТИВ 3
Тренажёр §5 — Признак ДД
+
5 задач на подобие по углам и нахождение сторон.
+
Задача 1 / 5Очки: 0
+
+
+ + + +
+ +
`; + + /* ---- ИНТЕРАКТИВ 4: DnD-сортер ---- */ + html+=`
+
ИНТЕРАКТИВ 4
Подобные пары или нет? — Сортировка по углам
+
Перетащи каждую пару треугольников в нужную колонку.
+
+
+
Подобны (ДД)
+
Не подобны
+
+
+ +
`; + + /* ---- ИНТЕРАКТИВ 5: Калькулятор ---- */ + html+=`
+
ИНТЕРАКТИВ 5
Калькулятор: найти сторону через подобие ДД
+
Введи два угла обоих треугольников и одну сторону первого — получи соответствующую сторону второго.
+
+
∠A₁ (°)
+
∠B₁ (°)
+
∠A₂ (°)
+
∠B₂ (°)
+
сторона a₁
+
+
+ +
`; + + /* ---- ИНТЕРАКТИВ 6: Босс §5 ---- */ + html+=`
+
БОСС §5
Итоговые задачи
+
4 задачи — каждая верная даёт +5 XP.
+
+
`; + + html+=`
+ +
`; + html+=secNav('p4','p6'); + box.innerHTML=html; + if(window.renderMathInElement) setTimeout(()=>renderMath(box),0); + + /* == INIT ИНТЕРАКТИВ 1: слайдер углов == */ + (function(){ + const aSl=document.getElementById('p5-a-sl'); + const bSl=document.getElementById('p5-b-sl'); + const kSl=document.getElementById('p5-k-sl'); + const aVal=document.getElementById('p5-a-val'); + const bVal=document.getElementById('p5-b-val'); + const kVal=document.getElementById('p5-k-val'); + const svgWrap=document.getElementById('p5-ang-svg'); + const infoEl=document.getElementById('p5-ang-info'); + + function buildTriFromAngles(alpha,beta,baseLen,ox,oy){ + // alpha at A (left), beta at B (right) + // base AB horizontal, C above + const gamma=Math.PI-alpha-beta; + if(gamma<=0.05) return null; + // by sine rule: a/sin(alpha) = base/sin(gamma) + const sinG=Math.sin(gamma); + const AB=baseLen; + const BC=AB*Math.sin(alpha)/sinG; + const AC=AB*Math.sin(beta)/sinG; + // place A at (ox,oy), B at (ox+AB,oy) + const Ax=ox, Ay=oy; + const Bx=ox+AB, By=oy; + // C: from A at angle alpha above AB + const Cx=Ax+AC*Math.cos(alpha); + const Cy=Ay-AC*Math.sin(alpha); + return {Ax,Ay,Bx,By,Cx,Cy,AB,BC,AC}; + } + + function draw(){ + const alpha=+aSl.value*Math.PI/180; + const beta=+bSl.value*Math.PI/180; + const k=+kSl.value/10; + aVal.textContent=+aSl.value; + bVal.textContent=+bSl.value; + kVal.textContent=k.toFixed(1); + + const gamma=(Math.PI-alpha-beta)*180/Math.PI; + if(gamma<=3){ + svgWrap.innerHTML='
Сумма углов превышает 180°. Уменьши углы.
'; + infoEl.innerHTML='Сумма углов не должна превышать 180°.'; + return; + } + + const W=360, H=170; + const t1=buildTriFromAngles(alpha,beta,90,20,145); + if(!t1){svgWrap.innerHTML='';return;} + const t2=buildTriFromAngles(alpha,beta,90/k,240,145); + if(!t2){svgWrap.innerHTML='';return;} + + let s=``; + // triangle 1 + s+=``; + s+=`A`; + s+=`B`; + s+=`C`; + // angle markers t1 + s+=``; + s+=``; + // triangle 2 (smaller) + s+=``; + s+=`A'`; + s+=`B'`; + s+=`C'`; + // angle markers t2 + s+=``; + s+=``; + // label + s+=`k = ${k.toFixed(1)}`; + s+=''; + svgWrap.innerHTML=s; + infoEl.innerHTML=`$\\alpha=${+aSl.value}°$, $\\beta=${+bSl.value}°$, $\\gamma=${fmt(gamma)}°$. Оба треугольника имеют одинаковые углы → по признаку ДД они подобны. Коэффициент подобия $k=${k.toFixed(1)}$.`; + renderMath(infoEl); + addXp(1,'p5-ang'); + } + aSl.addEventListener('input',draw); + bSl.addEventListener('input',draw); + kSl.addEventListener('input',draw); + draw(); + })(); + + /* == INIT ИНТЕРАКТИВ 2: пошаговое доказательство == */ + (function(){ + const steps=[ + {desc:'Шаг 1. Даны $\\triangle ABC$ и $\\triangle A\'B\'C\'$ с $\\angle A = \\angle A\'$ и $\\angle B = \\angle B\'$. Требуется доказать $\\triangle ABC \\sim \\triangle A\'B\'C\'$.', + svg:`ABCA'B'C'∠A=∠A', ∠B=∠B' — условие`}, + {desc:'Шаг 2. Из суммы углов треугольника: $\\angle C = 180° - \\angle A - \\angle B$ и $\\angle C\' = 180° - \\angle A\' - \\angle B\'$. Так как $\\angle A=\\angle A\'$ и $\\angle B=\\angle B\'$, получаем $\\angle C = \\angle C\'$.', + svg:`∠A+∠B+∠C = 180°∠A'+∠B'+∠C' = 180°∠C = 180°−∠A−∠B = 180°−∠A'−∠B' = ∠C'`}, + {desc:'Шаг 3. На луче $A\'B\'$ откладываем отрезок $A\'M = AB$. Через $M$ проводим прямую, параллельную $B\'C\'$ — она встречает $A\'C\'$ в точке $N$. По теореме §4: $\\triangle A\'MN \\sim \\triangle A\'B\'C\'$.', + svg:`A'B'C'MN△A'MN∼△A'B'C'`}, + {desc:'Шаг 4. Поскольку $A\'M = AB$ и углы треугольников $\\triangle A\'MN$ и $\\triangle ABC$ попарно равны (все три угла), а $\\angle A\' = \\angle A$ — вершины совпадают, то $\\triangle A\'MN \\cong \\triangle ABC$ (по условию и построению).', + svg:`A'M = AB, ∠A'=∠A, ∠B'=∠B→ △A'MN ≅ △ABC (признак у-с-у)Следовательно MN = BC, A'N = AC`}, + {desc:'Шаг 5. Итог: $\\triangle A\'MN \\cong \\triangle ABC$ и $\\triangle A\'MN \\sim \\triangle A\'B\'C\'$ — отсюда $\\triangle ABC \\sim \\triangle A\'B\'C\'$ (транзитивность подобия). Первый признак подобия доказан.', + svg:`∠A=∠A', ∠B=∠B' → △ABC ∼ △A'B'C'Признак ДД — первый признак подобияQED ∎`}, + ]; + let step=0; + const svgEl=document.getElementById('p5-proof-svg'); + const descEl=document.getElementById('p5-proof-desc'); + function show(){ + svgEl.innerHTML=steps[step].svg; + descEl.innerHTML=steps[step].desc; + renderMath(descEl); + } + document.getElementById('p5-proof-next').addEventListener('click',()=>{ + if(step{step=0;show();}); + show(); + })(); + + /* == INIT ИНТЕРАКТИВ 3: тренажёр == */ + (function(){ + const tasks=[ + {q:'В $\\triangle ABC$: $\\angle A=40°$, $\\angle B=70°$. В $\\triangle A\'B\'C\'$: $\\angle A\'=40°$, $\\angle B\'=70°$. Чему равен $\\angle C\'$?',ans:70,hint:'∠C\'=180−40−70=70°.'}, + {q:'$\\triangle ABC \\sim \\triangle A\'B\'C\'$ по признаку ДД. $AB=12$, $A\'B\'=4$. Найди коэффициент подобия $k$.',ans:3,hint:'k=AB/A\'B\'=12/4=3.'}, + {q:'$\\triangle ABC \\sim \\triangle A\'B\'C\'$, $k=2.5$. Сторона $a\'=6$. Найди $a$.',ans:15,hint:'a=k·a\'=2.5·6=15.'}, + {q:'Два прямоугольных треугольника. В первом острый угол $37°$, во втором $37°$. Сторона при прямом угле в первом — $10$, во втором — $6$. Найди коэффициент подобия.',ans:1.667,hint:'k=10/6≈1.667.'}, + {q:'$\\angle A=\\angle A\'=55°$, $\\angle B=\\angle B\'=65°$. Сторона $c=18$ в $\\triangle ABC$, $c\'=9$ в $\\triangle A\'B\'C\'$. Найди $k$.',ans:2,hint:'k=c/c\'=18/9=2.'}, + ]; + let idx=0,score=0; + function show(){ + document.getElementById('p5-tr-i').textContent=idx+1; + const t=document.getElementById('p5-tr-task'); + t.innerHTML=tasks[idx].q; + renderMath(t); + 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.02){ + score++;document.getElementById('p5-tr-score').textContent=score; + addXp(3,'p5-tr-'+idx);bumpProgress('p5',4); + if(idxshow(),900);} + else{feedback(fb,true,'Все задачи решены! +5 XP');addXp(5,'p5-tr-all');bumpProgress('p5',10);confetti();} + } 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 ИНТЕРАКТИВ 4: DnD-сортер == */ + (function(){ + const items=[ + {text:'(50°,70°,60°) и (50°,70°,60°)',yes:true}, + {text:'(40°,60°,80°) и (40°,50°,90°)',yes:false}, + {text:'(90°,35°,55°) и (90°,35°,55°)',yes:true}, + {text:'(30°,60°,90°) и (45°,45°,90°)',yes:false}, + {text:'(80°,60°,40°) и (80°,40°,60°)',yes:true}, + ]; + const pool=document.getElementById('p5-dnd-pool'); + const yesBox=document.getElementById('p5-drop-yes-items'); + const noBox=document.getElementById('p5-drop-no-items'); + let dragging=null; + function makeChip(it,idx){ + const chip=document.createElement('div'); + chip.className='dnd-chip'; + chip.dataset.idx=idx; + chip.textContent=it.text; + chip.draggable=true; + chip.addEventListener('dragstart',e=>{dragging=chip;chip.classList.add('dragging');e.dataTransfer.effectAllowed='move';}); + chip.addEventListener('dragend',()=>{chip.classList.remove('dragging');dragging=null;}); + return chip; + } + items.forEach((it,i)=>pool.appendChild(makeChip(it,i))); + [document.getElementById('p5-drop-yes'),document.getElementById('p5-drop-no'),pool].forEach(box=>{ + box.addEventListener('dragover',e=>{e.preventDefault();box.classList.add('over');}); + box.addEventListener('dragleave',()=>box.classList.remove('over')); + box.addEventListener('drop',e=>{ + e.preventDefault();box.classList.remove('over'); + if(!dragging)return; + const target=box===document.getElementById('p5-drop-yes')?yesBox:box===document.getElementById('p5-drop-no')?noBox:pool; + target.appendChild(dragging); + }); + }); + document.getElementById('p5-dnd-check').addEventListener('click',()=>{ + const fb=document.getElementById('p5-dnd-fb'); + const yChips=[...yesBox.querySelectorAll('.dnd-chip')]; + const nChips=[...noBox.querySelectorAll('.dnd-chip')]; + if(yChips.length+nChips.length{if(!items[+c.dataset.idx].yes)ok=false;}); + nChips.forEach(c=>{if(items[+c.dataset.idx].yes)ok=false;}); + if(ok){feedback(fb,true,'Верно! +5 XP');addXp(5,'p5-dnd');bumpProgress('p5',8);} + else{feedback(fb,false,'Есть ошибки. Два треугольника подобны, если у них есть хотя бы две пары равных углов.');} + }); + document.getElementById('p5-dnd-reset').addEventListener('click',()=>{ + [...yesBox.children].forEach(c=>pool.appendChild(c)); + [...noBox.children].forEach(c=>pool.appendChild(c)); + document.getElementById('p5-dnd-fb').style.display='none'; + }); + })(); + + /* == INIT ИНТЕРАКТИВ 5: калькулятор == */ + (function(){ + document.getElementById('p5-ccalc').addEventListener('click',()=>{ + const A1=parseFloat(document.getElementById('p5-cA1').value); + const B1=parseFloat(document.getElementById('p5-cB1').value); + const A2=parseFloat(document.getElementById('p5-cA2').value); + const B2=parseFloat(document.getElementById('p5-cB2').value); + const a1=parseFloat(document.getElementById('p5-ca1').value); + const out=document.getElementById('p5-ccalc-out'); + if([A1,B1,A2,B2,a1].some(v=>!isFinite(v)||v<=0)){ + out.style.display='block';out.innerHTML='Введи все поля.';return; + } + const C1=180-A1-B1, C2=180-A2-B2; + if(C1<=0||C2<=0){ + out.style.display='block';out.innerHTML='Сумма углов превышает 180°.';return; + } + // check similarity: sort angles and compare + const ang1=[A1,B1,C1].sort((a,b)=>a-b); + const ang2=[A2,B2,C2].sort((a,b)=>a-b); + const similar=ang1.every((v,i)=>Math.abs(v-ang2[i])<0.5); + if(!similar){ + out.style.display='block';out.innerHTML=`$\\angle C_1=${fmt(C1)}°$, $\\angle C_2=${fmt(C2)}°$. Наборы углов различаются — треугольники не подобны. Признак ДД не выполнен.`; + renderMath(out);return; + } + // find matching side using sine rule: a/sin(A)=b/sin(B) + // k = a1 / (2R sin(A)) ... use ratio of sides + // match angles: find which angle in t2 corresponds to A1 + // simplification: by ratio of corresponding sides via sine rule + // a1/sin(A1) = a2/sin(A2) → a2 = a1*sin(A2*pi/180)/sin(A1*pi/180) + const a2=a1*Math.sin(A2*Math.PI/180)/Math.sin(A1*Math.PI/180); + const k=a1/a2; + out.style.display='block'; + out.innerHTML=`Треугольники подобны по признаку ДД.
$\\angle C_1 = ${fmt(C1)}°$, $\\angle C_2 = ${fmt(C2)}°$.
По теореме синусов: $a_2 = a_1 \\cdot \\dfrac{\\sin \\angle A_2}{\\sin \\angle A_1} = ${fmt(a1)} \\cdot \\dfrac{${fmt(Math.sin(A2*Math.PI/180).toFixed(4))}}{${fmt(Math.sin(A1*Math.PI/180).toFixed(4))}} = ${fmt(a2)}$.
Коэффициент подобия $k = a_1/a_2 = ${fmt(k)}$.`; + renderMath(out); + addXp(3,'p5-calc');bumpProgress('p5',5); + }); + })(); + + /* == INIT: Босс §5 == */ + (function(){ + const tasks=[ + {q:'ABCA\'B\'C\'∠A=∠A\'=60°, ∠B=∠B\'=80°$\\angle A=\\angle A\'=60°$, $\\angle B=\\angle B\'=80°$. $AB=15$, $A\'B\'=5$. Найди $k$.',ans:3,hint:'k=AB/A\'B\'=15/5=3.'}, + {q:'Два прямоугольных треугольника. Острый угол одного $42°$, другого $42°$. Подобны ли? Гипотенуза первого $13$, второго $6.5$. Найди $k$.',ans:2,hint:'Подобны (ДД). k=13/6.5=2.'}, + {q:'$\\triangle ABC \\sim \\triangle A\'B\'C\'$ по ДД. $k=4$. Периметр $\\triangle A\'B\'C\'=18$. Найди периметр $\\triangle ABC$.',ans:72,hint:'P=k·P\'=4·18=72.'}, + {q:'В $\\triangle ABC$ и $\\triangle DEF$: $\\angle A=\\angle D=55°$, $\\angle B=\\angle E=75°$. $BC=20$, $EF=8$. Найди $k=BC/EF$.',ans:2.5,hint:'k=20/8=2.5.'}, + ]; + const bossBox=document.getElementById('p5-boss-tasks'); + bossBox.innerHTML=tasks.map((t,i)=>` +
+
${t.q}
+
+ + +
+ +
`).join(''); + window.p5BossSolved=new Set(); + renderMath(bossBox); + })(); +} 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'); }