diff --git a/frontend/textbooks/geometry_8_ch3.html b/frontend/textbooks/geometry_8_ch3.html index e4831aa..f8594e5 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:()=>buildP1stub(),p2:()=>buildP2stub(),p3:()=>buildP3stub(),p4:()=>buildP4stub(),p5:()=>buildP5stub(),p6:()=>buildP6stub(),p7:()=>buildP7stub(),p8:()=>buildP8stub(),p9:()=>buildP9stub(),final3:()=>buildFinal3stub()}; +const BUILDERS={p1:()=>buildP1(),p2:()=>buildP2(),p3:()=>buildP3(),p4:()=>buildP4stub(),p5:()=>buildP5stub(),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);} @@ -382,6 +382,7 @@ let _confettiCanvas=null,_confettiParticles=[],_confettiRaf=null; function confetti(){if(!_confettiCanvas){_confettiCanvas=document.createElement('canvas');_confettiCanvas.style.cssText='position:fixed;top:0;left:0;width:100%;height:100%;pointer-events:none;z-index:9999';document.body.appendChild(_confettiCanvas);}const c=_confettiCanvas;c.width=window.innerWidth;c.height=window.innerHeight;const ctx=c.getContext('2d');const colors=['#7c3aed','#8b5cf6','#a78bfa','#f59e0b','#10b981'];for(let i=0;i<80;i++){_confettiParticles.push({x:window.innerWidth/2+(Math.random()-.5)*200,y:window.innerHeight/2,vx:(Math.random()-.5)*14,vy:-10-Math.random()*10,g:.4,life:100,color:colors[i%colors.length],r:4+Math.random()*4,rot:0,vRot:(Math.random()-.5)*.3});}if(_confettiRaf)cancelAnimationFrame(_confettiRaf);function frame(){ctx.clearRect(0,0,c.width,c.height);_confettiParticles=_confettiParticles.filter(p=>{p.x+=p.vx;p.y+=p.vy;p.vy+=p.g;p.life--;p.rot+=p.vRot;ctx.save();ctx.translate(p.x,p.y);ctx.rotate(p.rot);ctx.fillStyle=p.color;ctx.fillRect(-p.r,-p.r/2,p.r*2,p.r);ctx.restore();return p.life>0&&p.y0)_confettiRaf=requestAnimationFrame(frame);else{ctx.clearRect(0,0,c.width,c.height);_confettiRaf=null;}}frame();} const GLOSSARY=[ + {term:'пропорциональность',def:'Равенство двух отношений: $a/b = c/d$. Числа $a,b,c,d$ называются пропорциональными.',sec:'p1',aliases:['пропорциональность','пропорциональны','пропорциональные','пропорциональных','пропорциональными']}, {term:'подобные треугольники',def:'Треугольники, у которых углы равны попарно и стороны пропорциональны.',sec:'p3',aliases:['подобные треугольники','подобных треугольников','подобными треугольниками','подобный треугольник','подобного треугольника']}, {term:'коэффициент подобия',def:'Отношение соответственных сторон подобных треугольников.',sec:'p3',aliases:['коэффициент подобия','коэффициента подобия','коэффициенте подобия']}, {term:'биссектриса',def:'Луч из вершины угла, делящий угол пополам.',sec:'p8',aliases:['биссектриса','биссектрисы','биссектрису','биссектрисой']}, @@ -413,9 +414,1137 @@ function initSidebarToggle(){const side=document.getElementById('col-side'),back function init(){loadProgress();initTheme();initSidebarToggle();initGlossaryTip();initSearch();buildParaSelector();refreshProgressUI();loadServerReadState();goTo('p1');setTimeout(()=>achievement('start','Начало главы 3!'),600);if(window.LS&&window.LS.xp){window.LS.xp.load().then(function(s){if(s&&s.xp>STATE.xp){STATE.xp=s.xp;STATE.level=calcLevel(STATE.xp);saveProgress();refreshProgressUI();if(STATE.current)buildSidebar(STATE.current);}});}} document.addEventListener('DOMContentLoaded',init); -function buildP1stub(){ document.getElementById('p1-body').innerHTML='

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

'+secNav(null,'p2'); } -function buildP2stub(){ document.getElementById('p2-body').innerHTML='

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

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

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

'+secNav('p2','p4'); } +function buildP1(){ + const box=document.getElementById('p1-body'); + let html=''; + + html+=makeCard('theory','Теорема Фалеса (классическая)','1.1',` +

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

+

Следствие (обобщённая теорема Фалеса). Если несколько параллельных прямых пересекают две секущие прямые, то они отсекают на этих секущих пропорциональные отрезки:

+ $$\\dfrac{AB}{BC} = \\dfrac{A'B'}{B'C'}$$ +

где $A,B,C$ — точки на первой секущей, $A',B',C'$ — точки на второй секущей, отсекаемые теми же параллельными прямыми.

+
+ + + + + + + + + + + + + + + + + + + + + A + B + C + + A' + B' + C' + O + AB/BC = A'B'/B'C' + +
`); + + html+=makeCard('rule','Пропорциональность отрезков','1.2',` +

Обозначим точки пересечения параллельных прямых $\\ell_1,\\ell_2,\\ell_3$ со сторонами угла как $A,B,C$ и $A',B',C'$ соответственно. Тогда:

+ $$\\dfrac{AB}{BC} = \\dfrac{A'B'}{B'C'}, \\quad \\dfrac{AB}{AC} = \\dfrac{A'B'}{A'C'}$$ +

Это выражает пропорциональность отрезков, отсекаемых параллельными прямыми.

+

Применение: с помощью теоремы Фалеса доказывают подобие треугольников, делят отрезок в заданном отношении, строят пропорциональные отрезки.

+
+ + + + + + + + A + B + C + D + E + DE ∥ BC + AD/DB = AE/EC + +
`); + + html+=makeCard('example','Пример применения','1.3',` +

Пример. Параллельные прямые отсекают на первой стороне угла отрезки $AB = 6$ и $BC = 9$. На второй стороне $A'B' = 4$. Найти $B'C'$.

+

Решение: по теореме Фалеса $\\dfrac{AB}{BC}=\\dfrac{A'B'}{B'C'}$, то есть $\\dfrac{6}{9}=\\dfrac{4}{B'C'}$.

+

$B'C' = \\dfrac{4 \\cdot 9}{6} = 6$.

`); + + /* ИНТЕРАКТИВ 1 — SVG-угол с параллельными прямыми */ + html+=`
+
ИНТЕРАКТИВ 1
Угол с параллельными прямыми
+
Меняй количество параллельных прямых и угол наклона второй стороны. Видишь, как отношения остаются равными!
+
+ + +
+
+
+
`; + + /* ИНТЕРАКТИВ 2 — Пошаговое доказательство */ + html+=`
+
ИНТЕРАКТИВ 2
Доказательство теоремы Фалеса — по шагам
+
Нажимай «Далее» — каждый шаг показывает ключевую идею.
+
+
+
+ + +
+
`; + + /* ИНТЕРАКТИВ 3 — Калькулятор пропорций */ + html+=`
+
ИНТЕРАКТИВ 3
Калькулятор пропорций (Теорема Фалеса)
+
Дано три отрезка из пропорции $\\dfrac{a}{b}=\\dfrac{c}{x}$ — найди четвёртый.
+
+
+ + AB +
+ / +
+ + BC +
+ = +
+ + A'B' +
+ / +
+ + B'C' +
+ +
+ +
`; + + /* ИНТЕРАКТИВ 4 — Тренажёр */ + html+=`
+
ИНТЕРАКТИВ 4
Тренажёр §1 — Теорема Фалеса
+
5 задач на пропорциональность отрезков. Введи ответ и нажми «Проверить».
+
Задача 1 / 5Очки: 0
+
+
+ + + +
+ +
`; + + /* ИНТЕРАКТИВ 5 — DnD-сортер */ + html+=`
+
ИНТЕРАКТИВ 5
Определи: пропорциональные или нет?
+
Перетащи каждую карточку в нужную колонку.
+
+
+
Пропорциональные
+
Непропорциональные
+
+
+ +
`; + + /* ИНТЕРАКТИВ 6 — Босс §1 */ + html+=`
+
БОСС §1
Итоговые задачи
+
4 задачи — каждая верная даёт +5 XP.
+
+
`; + + html+=`
+ +
`; + html+=secNav(null,'p2'); + box.innerHTML=html; + if(window.renderMathInElement) setTimeout(()=>renderMath(box),0); + + /* == INIT ИНТЕРАКТИВ 1: угол с параллелями == */ + (function(){ + const nSl=document.getElementById('p1-npar-sl'); + const nVal=document.getElementById('p1-npar-val'); + const aSl=document.getElementById('p1-angle-sl'); + const aVal=document.getElementById('p1-angle-val'); + const svgWrap=document.getElementById('p1-angle-svg'); + const info=document.getElementById('p1-angle-info'); + function draw(){ + const n=+nSl.value; + const angDeg=+aSl.value; + nVal.textContent=n; + aVal.textContent=angDeg; + const W=320, H=180; + const Ox=20, Oy=H-20; + const ang=angDeg*Math.PI/180; + const L=280; + // луч 1: горизонталь вправо + // луч 2: под углом ang вверх + const pts1=[]; // точки на луче1 (горизональном) + const pts2=[]; // точки на луче2 + const step=L/(n); + for(let i=1;i<=n;i++){ + const x=Ox+step*i; + pts1.push({x, y:Oy}); + pts2.push({x, y:Oy-step*i*Math.tan(ang)}); + } + let s=``; + // лучи + s+=``; + s+=``; + // параллельные прямые (вертикальные) + for(let i=0;i`; + s+=``; + s+=``; + const lbl=String.fromCharCode(65+i); + s+=`${lbl}`; + s+=`${lbl}'`; + } + s+=`O`; + s+=''; + svgWrap.innerHTML=s; + + // вычисляем отрезки + let infoHtml=''; + for(let i=0;i${lA}${lB} = ${seg1} px; ${lA}'${lB}' = ${fmt(seg2)} px`; + } + if(n>=2){ + const r1=Math.round((pts1[1].x-pts1[0].x)/(pts1[0].x-pts1[0].x+1)*1000)/1000; + const dy0=pts2[1].y-pts2[0].y, dx0=pts2[1].x-pts2[0].x; + const s1=pts1[1].x-pts1[0].x; + const s2=Math.sqrt(dx0*dx0+dy0*dy0); + infoHtml+=`
Отношение AB/A'B' = ${fmt(s1/s2)} ≈ постоянно для всех пар
`; + } + info.innerHTML=infoHtml; + addXp(1,'p1-angle'); + } + nSl.addEventListener('input',draw); + aSl.addEventListener('input',draw); + draw(); + })(); + + /* == INIT ИНТЕРАКТИВ 2: пошаговое доказательство == */ + (function(){ + const steps=[ + {desc:'Шаг 1. Даны два луча из вершины O и три параллельные прямые, пересекающие их в точках A, B, C и A\', B\', C\'.', + svg:()=>{ + const W=260,H=160,Ox=20,Oy=140; + let s=``; + s+=``; + s+=``; + [[70,140,70,65],[150,140,150,92],[230,140,230,119]].forEach(([x1,y1,x2,y2])=>{ + s+=``; + }); + s+=`O`; + ['A','B','C'].forEach((l,i)=>s+=`${l}`); + ['A\'','B\'','C\''].forEach((l,i)=>s+=`${l}`); + s+='';return s;}}, + {desc:'Шаг 2. Через точки A, B, C проводим прямые, параллельные второму лучу. Получаем параллелограммы.', + svg:()=>{ + const W=260,H=160,Ox=20,Oy=140; + let s=``; + s+=``; + s+=``; + [[70,140,70,65],[150,140,150,92],[230,140,230,119]].forEach(([x1,y1,x2,y2])=>{ + s+=``; + }); + // вспомогательные параллельные линии через A, B + s+=``; + s+=``; + s+=`параллелограмм`; + s+='';return s;}}, + {desc:'Шаг 3. В параллелограмме противоположные стороны равны: $A_1B_1 = AB_2 = AB$, поэтому параллельная прямая откладывает равные отрезки на обоих лучах (если исходные части равны).', + svg:()=>{ + const W=260,H=160; + let s=``; + s+=``; + s+=`Параллелограмм`; + s+=`AB = A'B'`; + s+='';return s;}}, + {desc:'Шаг 4. Если параллельные прямые делят луч на равные части, то и второй луч делится на равные части. Это и есть теорема Фалеса в классической форме.', + svg:()=>{ + const W=260,H=160,Ox=20,Oy=140; + let s=``; + s+=``; + s+=``; + [[70,140,70,65],[150,140,150,92],[230,140,230,119]].forEach(([x1,y1,x2,y2])=>{ + s+=``; + }); + // равные отрезки + s+=`равно`; + s+=`равно`; + s+='';return s;}}, + {desc:'Шаг 5. Обобщённая теорема Фалеса: при произвольных параллельных прямых (не обязательно с равными частями) отрезки на двух лучах всё равно пропорциональны: $\\dfrac{AB}{BC}=\\dfrac{A\'B\'}{B\'C\'}$. Доказано.', + svg:()=>{ + const W=260,H=160; + let s=``; + s+=``; + s+=``; + s+=``; + s+=``; + s+=`AB/BC = A'B'/B'C'`; + s+=`QED`; + s+='';return s;}}, + ]; + let step=0; + const svgEl=document.getElementById('p1-proof-svg'); + const descEl=document.getElementById('p1-proof-desc'); + function show(){ + svgEl.innerHTML=steps[step].svg(); + descEl.innerHTML=steps[step].desc; + renderMath(descEl); + } + document.getElementById('p1-proof-next').addEventListener('click',()=>{ + if(step{step=0;show();}); + show(); + })(); + + /* == INIT ИНТЕРАКТИВ 3: калькулятор пропорций == */ + (function(){ + document.getElementById('p1-pcalc').addEventListener('click',()=>{ + const a=parseFloat(document.getElementById('p1-pa').value); + const b=parseFloat(document.getElementById('p1-pb').value); + const c=parseFloat(document.getElementById('p1-pc').value); + const out=document.getElementById('p1-pcalc-out'); + if(!isFinite(a)||!isFinite(b)||!isFinite(c)||a<=0||b<=0||c<=0){ + out.style.display='block';out.innerHTML='Введи три положительных числа.';return; + } + const x=b*c/a; + out.style.display='block'; + out.innerHTML=`По теореме Фалеса: $x = \\dfrac{b \\cdot c}{a} = \\dfrac{${fmt(b)} \\cdot ${fmt(c)}}{${fmt(a)}} = ${fmt(x)}$`; + renderMath(out); + addXp(2,'p1-pcalc');bumpProgress('p1',5); + }); + })(); + + /* == INIT ИНТЕРАКТИВ 4: тренажёр == */ + (function(){ + const tasks=[ + {q:'Параллельные прямые отсекают на первом луче отрезки $AB=4$, $BC=6$. На втором луче $A\'B\'=6$. Найди $B\'C\'$.', ans:9, hint:'BC·A\'B\'/AB = 6·6/4 = 9.'}, + {q:'$AB=3$, $BC=9$, $A\'B\'=5$. Найди $B\'C\'$.', ans:15, hint:'9·5/3 = 15.'}, + {q:'Параллельные прямые отсекают $AB=8$, $BC=12$, $B\'C\'=9$. Найди $A\'B\'$.', ans:6, hint:'A\'B\' = AB·B\'C\'/BC = 8·9/12 = 6.'}, + {q:'$AB=5$, $A\'B\'=7$, $B\'C\'=14$. Найди $BC$.', ans:10, hint:'BC = AB·B\'C\'/A\'B\' = 5·14/7 = 10.'}, + {q:'Три параллельные прямые отсекают на луче отрезки $2$ и $3$. На другом луче первый отрезок равен $4$. Найди второй отрезок.', ans:6, hint:'4·3/2 = 6.'}, + ]; + let idx=0,score=0; + function show(){ + document.getElementById('p1-tr-i').textContent=idx+1; + const t=document.getElementById('p1-tr-task'); + t.innerHTML=tasks[idx].q; + renderMath(t); + document.getElementById('p1-tr-ans').value=''; + document.getElementById('p1-tr-fb').style.display='none'; + } + document.getElementById('p1-tr-start').addEventListener('click',()=>{idx=0;score=0;document.getElementById('p1-tr-score').textContent=0;show();}); + document.getElementById('p1-tr-go').addEventListener('click',()=>{ + if(idx>=tasks.length)return; + const ans=+document.getElementById('p1-tr-ans').value; + const fb=document.getElementById('p1-tr-fb'); + if(Math.abs(ans-tasks[idx].ans)<0.01){ + score++;document.getElementById('p1-tr-score').textContent=score; + addXp(3,'p1-tr-'+idx);bumpProgress('p1',4); + if(idxshow(),900);} + else{feedback(fb,true,'Все задачи решены! +5 XP');addXp(5,'p1-tr-all');bumpProgress('p1',10);confetti();} + } else { + feedback(fb,false,'Неверно. '+tasks[idx].hint); + } + }); + document.getElementById('p1-tr-ans').addEventListener('keydown',e=>{if(e.key==='Enter')document.getElementById('p1-tr-go').click();}); + show(); + })(); + + /* == INIT ИНТЕРАКТИВ 5: DnD-сортер == */ + (function(){ + const items=[ + {text:'AB=3, BC=6, A\'B\'=4, B\'C\'=8',yes:true}, + {text:'AB=2, BC=4, A\'B\'=3, B\'C\'=7',yes:false}, + {text:'AB=5, BC=10, A\'B\'=1, B\'C\'=2',yes:true}, + {text:'AB=6, BC=3, A\'B\'=8, B\'C\'=5',yes:false}, + {text:'AB=4, BC=8, A\'B\'=3, B\'C\'=6',yes:true}, + ]; + const pool=document.getElementById('p1-dnd-pool'); + const yesBox=document.getElementById('p1-drop-yes-items'); + const noBox=document.getElementById('p1-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('p1-drop-yes'),document.getElementById('p1-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('p1-drop-yes')?yesBox:box===document.getElementById('p1-drop-no')?noBox:pool; + target.appendChild(dragging); + }); + }); + document.getElementById('p1-dnd-check').addEventListener('click',()=>{ + const fb=document.getElementById('p1-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,'p1-dnd');bumpProgress('p1',8);} + else{feedback(fb,false,'Есть ошибки — перепроверь отношения AB/BC и A\'B\'/B\'C\'.');} + }); + document.getElementById('p1-dnd-reset').addEventListener('click',()=>{ + [...yesBox.children].forEach(c=>pool.appendChild(c)); + [...noBox.children].forEach(c=>pool.appendChild(c)); + document.getElementById('p1-dnd-fb').style.display='none'; + }); + })(); + + /* == INIT: Босс §1 == */ + (function(){ + const tasks=[ + {q:'AB=10, BC=?, A\'B\'=6, B\'C\'=9$AB=10$, $A\'B\'=6$, $B\'C\'=9$. Найди $BC$.', ans:15, hint:'BC = AB·B\'C\'/A\'B\' = 10·9/6 = 15.'}, + {q:'Параллельные прямые отсекают на двух лучах: луч 1 — отрезки $4$ и $x$, луч 2 — отрезки $6$ и $12$. Найди $x$.', ans:8, hint:'4/x = 6/12 → x = 4·12/6 = 8.'}, + {q:'Прямая $DE \\parallel BC$ в треугольнике $ABC$. $AD=6$, $DB=9$, $AE=8$. Найди $EC$.', ans:12, hint:'AD/DB = AE/EC → EC = DB·AE/AD = 9·8/6 = 12.'}, + {q:'$AB=15$, $BC=25$, $B\'C\'=20$. Найди $A\'B\'$.', ans:12, hint:'A\'B\' = AB·B\'C\'/BC = 15·20/25 = 12.'}, + ]; + const bossBox=document.getElementById('p1-boss-tasks'); + bossBox.innerHTML=tasks.map((t,i)=>` +
+
${t.q}
+
+ + +
+ +
`).join(''); + window.p1BossSolved=new Set(); + renderMath(bossBox); + })(); +} +function buildP2(){ + const box=document.getElementById('p2-body'); + let html=''; + + html+=makeCard('theory','Деление отрезка в заданном отношении','2.1',` +

Определение. Говорят, что точка $C$ делит отрезок $AB$ в отношении $m:n$ (внутреннее деление), если $C$ лежит между $A$ и $B$, и:

+ $$\\dfrac{AC}{CB} = \\dfrac{m}{n}, \\quad m,n > 0$$ +

Формула координат. Если $A = (x_A, y_A)$, $B = (x_B, y_B)$, то точка деления:

+ $$C = \\left(\\dfrac{n\\,x_A + m\\,x_B}{m+n},\\; \\dfrac{n\\,y_A + m\\,y_B}{m+n}\\right)$$ +

Частный случай $m=n$: точка $C$ — середина $AB$.

+
+ + + + + + + + + + + m = 2 + n = 3 + A + C + B + +
`); + + html+=makeCard('algo','Построение циркулем и линейкой','2.2',` +

Чтобы разделить отрезок $AB$ в отношении $m:n$:

+
    +
  1. Из точки $A$ проводим луч $AK$, не совпадающий с $AB$.
  2. +
  3. На луче $AK$ последовательно откладываем $m+n$ равных отрезков единичной длины: точки $P_1, P_2, \\ldots, P_{m+n}$.
  4. +
  5. Соединяем точку $P_{m+n}$ с точкой $B$.
  6. +
  7. Через $P_m$ проводим прямую, параллельную $P_{m+n}B$ — она пересекает $AB$ в нужной точке $C$.
  8. +
+

По теореме Фалеса $\\dfrac{AC}{CB} = \\dfrac{m}{n}$. $\\square$

+
+ + + + + + A + B + + + + + + + + + + P₁ + P₂ + P_m + P₅ + + + + + + + C + +
`); + + html+=makeCard('example','Пример','2.3',` +

Пример 1. $A=(0,0)$, $B=(10,0)$, разделить в отношении $3:2$.

+

$C_x = \\dfrac{2\\cdot 0 + 3\\cdot 10}{3+2} = \\dfrac{30}{5} = 6$. Ответ: $C=(6,0)$.

+

Пример 2. $A=(1,2)$, $B=(7,8)$, разделить в отношении $1:2$.

+

$C_x = \\dfrac{2\\cdot 1+1\\cdot 7}{3}=3$, $C_y=\\dfrac{2\\cdot 2+1\\cdot 8}{3}=4$. Ответ: $C=(3,4)$.

`); + + /* ИНТЕРАКТИВ 1 — SVG-построение */ + html+=`
+
ИНТЕРАКТИВ 1
Построение деления отрезка m:n
+
Меняй m и n — смотри, как перемещается точка C на отрезке AB.
+
+ + +
+
+
+
`; + + /* ИНТЕРАКТИВ 2 — Калькулятор */ + html+=`
+
ИНТЕРАКТИВ 2
Калькулятор деления отрезка
+
Введи длину отрезка и отношение m:n — получи расстояние AC от начала.
+
+
+ AB + +
+
+ m + +
+
+ n + +
+ +
+ +
`; + + /* ИНТЕРАКТИВ 3 — Пошаговое доказательство */ + html+=`
+
ИНТЕРАКТИВ 3
Доказательство формулы — по шагам
+
4 шага — вывод формулы координат точки деления через теорему Фалеса.
+
+
+
+ + +
+
`; + + /* ИНТЕРАКТИВ 4 — Тренажёр */ + html+=`
+
ИНТЕРАКТИВ 4
Тренажёр §2
+
5 задач на деление отрезка. Введи числовой ответ.
+
Задача 1 / 5Очки: 0
+
+
+ + + +
+ +
`; + + /* ИНТЕРАКТИВ 5 — Босс §2 */ + html+=`
+
БОСС §2
Итоговые задачи
+
4 задачи — каждая верная даёт +5 XP.
+
+
`; + + html+=`
+ +
`; + html+=secNav('p1','p3'); + box.innerHTML=html; + if(window.renderMathInElement) setTimeout(()=>renderMath(box),0); + + /* == INIT ИНТЕРАКТИВ 1: построение == */ + (function(){ + const mSl=document.getElementById('p2-m-sl'); + const nSl=document.getElementById('p2-n-sl'); + const mVal=document.getElementById('p2-m-val'); + const nVal=document.getElementById('p2-n-val'); + const svgWrap=document.getElementById('p2-build-svg'); + const infoEl=document.getElementById('p2-build-info'); + function draw(){ + const m=+mSl.value, n=+nSl.value; + mVal.textContent=m; nVal.textContent=n; + const W=320, H=140; + const Ax=24, Ay=50, Bx=296, By=50; + const AB=Bx-Ax; + const Cx=Ax+m/(m+n)*AB; + const Cy=50; + // луч AK: вниз под углом 30° + const rayLen=(m+n)*22; + const rayAngle=Math.PI/6; + const Kx=Ax+rayLen*Math.cos(rayAngle); + const Ky=Ay+rayLen*Math.sin(rayAngle); + let s=``; + // отрезок AB + s+=``; + s+=``; + s+=``; + s+=`A`; + s+=`B`; + // луч AK + s+=``; + // точки P1..P(m+n) на луче + for(let i=1;i<=m+n;i++){ + const px=Ax+i*22*Math.cos(rayAngle); + const py=Ay+i*22*Math.sin(rayAngle); + const isM=(i===m); + s+=``; + s+=`P${i}${isM?' (m)':''}`; + } + // линия P(m+n)→B + const Pmn_x=Ax+(m+n)*22*Math.cos(rayAngle); + const Pmn_y=Ay+(m+n)*22*Math.sin(rayAngle); + s+=``; + // параллельная через Pm → C + const Pm_x=Ax+m*22*Math.cos(rayAngle); + const Pm_y=Ay+m*22*Math.sin(rayAngle); + s+=``; + // точка C + s+=``; + s+=`C`; + // метки AC, CB + s+=``; + s+=``; + s+=`m=${m}`; + s+=`n=${n}`; + s+=''; + svgWrap.innerHTML=s; + const AClen=fmt(m/(m+n)*100); + const CBlen=fmt(n/(m+n)*100); + infoEl.innerHTML=`Отношение $AC:CB = ${m}:${n}$. Если $AB=100$, то $AC=${AClen}$, $CB=${CBlen}$.`; + renderMath(infoEl); + addXp(1,'p2-build'); + } + mSl.addEventListener('input',draw); + nSl.addEventListener('input',draw); + draw(); + })(); + + /* == INIT ИНТЕРАКТИВ 2: калькулятор == */ + (function(){ + document.getElementById('p2-lcalc').addEventListener('click',()=>{ + const AB=parseFloat(document.getElementById('p2-lab').value); + const m=parseFloat(document.getElementById('p2-lm').value); + const n=parseFloat(document.getElementById('p2-ln').value); + const out=document.getElementById('p2-lcalc-out'); + if(!isFinite(AB)||!isFinite(m)||!isFinite(n)||AB<=0||m<=0||n<=0){ + out.style.display='block';out.innerHTML='Введи положительные числа.';return; + } + const AC=m/(m+n)*AB; + const CB=n/(m+n)*AB; + out.style.display='block'; + out.innerHTML=`$AC = \\dfrac{m}{m+n}\\cdot AB = \\dfrac{${fmt(m)}}{${fmt(m+n)}}\\cdot ${fmt(AB)} = ${fmt(AC)}$
$CB = \\dfrac{${fmt(n)}}{${fmt(m+n)}}\\cdot ${fmt(AB)} = ${fmt(CB)}$`; + renderMath(out); + addXp(2,'p2-calc');bumpProgress('p2',5); + }); + })(); + + /* == INIT ИНТЕРАКТИВ 3: доказательство == */ + (function(){ + const steps=[ + {desc:'Шаг 1. Даны точки $A$ и $B$ на прямой. Хотим найти точку $C$ такую, что $AC:CB = m:n$.', + svg:`ABAC : CB = m : n = ?`}, + {desc:'Шаг 2. Проводим из $A$ луч $AK$ и откладываем $m+n$ равных единичных отрезков. Последняя точка — $P_{m+n}$, средняя (после $m$ шагов) — $P_m$.', + svg:`P_mP_{m+n}AB`}, + {desc:'Шаг 3. Соединяем $P_{m+n}$ с $B$. Через $P_m$ проводим прямую, параллельную $P_{m+n}B$. По теореме Фалеса она пересекает $AB$ в точке $C$, делящей $AB$ в отношении $m:n$.', + svg:`CP_mAB`}, + {desc:'Шаг 4. Итог: по теореме Фалеса $\\dfrac{AC}{CB}=\\dfrac{m}{n}$. Координаты точки $C$: $C_x = \\dfrac{n\\,x_A+m\\,x_B}{m+n}$, $C_y = \\dfrac{n\\,y_A+m\\,y_B}{m+n}$. Доказано.', + svg:`ACBC = (n·A + m·B) / (m+n)`}, + ]; + let step=0; + const svgEl=document.getElementById('p2-proof-svg'); + const descEl=document.getElementById('p2-proof-desc'); + function show(){ + svgEl.innerHTML=steps[step].svg; + descEl.innerHTML=steps[step].desc; + renderMath(descEl); + } + document.getElementById('p2-proof-next').addEventListener('click',()=>{ + if(step{step=0;show();}); + show(); + })(); + + /* == INIT ИНТЕРАКТИВ 4: тренажёр == */ + (function(){ + const tasks=[ + {q:'Отрезок $AB=20$ делится точкой $C$ в отношении $1:4$. Найди $AC$.', ans:4, hint:'AC = 1/(1+4)·20 = 4.'}, + {q:'$AB=15$, $AC:CB=2:3$. Найди $CB$.', ans:9, hint:'CB = 3/(2+3)·15 = 9.'}, + {q:'$A=(0,0)$, $B=(8,0)$, деление $3:1$. Найди $x$-координату точки $C$.', ans:6, hint:'C_x = (1·0+3·8)/4 = 6.'}, + {q:'Отрезок $AB=30$ делится в отношении $2:1$. Найди расстояние от $C$ до $B$.', ans:10, hint:'CB = 1/(2+1)·30 = 10.'}, + {q:'$A=(0,0)$, $B=(0,12)$, деление $1:2$. Найди $y$-координату точки $C$.', ans:4, hint:'C_y = (2·0+1·12)/3 = 4.'}, + ]; + let idx=0,score=0; + function show(){ + document.getElementById('p2-tr-i').textContent=idx+1; + const t=document.getElementById('p2-tr-task'); + t.innerHTML=tasks[idx].q; + renderMath(t); + document.getElementById('p2-tr-ans').value=''; + document.getElementById('p2-tr-fb').style.display='none'; + } + document.getElementById('p2-tr-start').addEventListener('click',()=>{idx=0;score=0;document.getElementById('p2-tr-score').textContent=0;show();}); + document.getElementById('p2-tr-go').addEventListener('click',()=>{ + if(idx>=tasks.length)return; + const ans=+document.getElementById('p2-tr-ans').value; + const fb=document.getElementById('p2-tr-fb'); + if(Math.abs(ans-tasks[idx].ans)<0.01){ + score++;document.getElementById('p2-tr-score').textContent=score; + addXp(3,'p2-tr-'+idx);bumpProgress('p2',4); + if(idxshow(),900);} + else{feedback(fb,true,'Все задачи решены! +5 XP');addXp(5,'p2-tr-all');bumpProgress('p2',10);confetti();} + } else { + feedback(fb,false,'Неверно. '+tasks[idx].hint); + } + }); + document.getElementById('p2-tr-ans').addEventListener('keydown',e=>{if(e.key==='Enter')document.getElementById('p2-tr-go').click();}); + show(); + })(); + + /* == INIT: Босс §2 == */ + (function(){ + const tasks=[ + {q:'$AB=24$, деление в отношении $5:3$. Найди $AC$.', ans:15, hint:'AC = 5/8·24 = 15.'}, + {q:'$A=(0,0)$, $B=(10,10)$, деление $3:2$. Найди $x_C+y_C$.', ans:12, hint:'C_x=6, C_y=6, сумма=12.'}, + {q:'Точка $C$ делит $AB$ в отношении $AC:CB=4:1$. $CB=7$. Найди $AB$.', ans:35, hint:'AB = (4+1)·7 = 35.'}, + {q:'$AB=100$, $C$ делит $AB$ в отношении $3:7$. Найди $BC$.', ans:70, hint:'BC = 7/10·100 = 70.'}, + ]; + const bossBox=document.getElementById('p2-boss-tasks'); + bossBox.innerHTML=tasks.map((t,i)=>` +
+
${t.q}
+
+ + +
+ +
`).join(''); + window.p2BossSolved=new Set(); + renderMath(bossBox); + })(); +} +function buildP3(){ + const box=document.getElementById('p3-body'); + let html=''; + + html+=makeCard('theory','Определение подобных треугольников','3.1',` +

Определение. Треугольники $\\triangle ABC$ и $\\triangle A'B'C'$ называются подобными ($\\triangle ABC \\sim \\triangle A'B'C'$), если:

+
    +
  1. Соответственные углы равны: $\\angle A = \\angle A'$, $\\angle B = \\angle B'$, $\\angle C = \\angle C'$.
  2. +
  3. Соответственные стороны пропорциональны: $\\dfrac{a}{a'} = \\dfrac{b}{b'} = \\dfrac{c}{c'} = k$,
  4. +
+

где $k > 0$ — коэффициент подобия.

+

Обозначения: стороны треугольника: $a=BC$, $b=CA$, $c=AB$ и $a'=B'C'$, $b'=C'A'$, $c'=A'B'$.

+
+ + + + A + B + C + + + A' + B' + C' + + k = a/a' = b/b' = c/c' + + ∠B + ∠B' + +
`); + + html+=makeCard('rule','Коэффициент подобия и свойства','3.2',` +

Коэффициент подобия $k = \\dfrac{a}{a'} = \\dfrac{b}{b'} = \\dfrac{c}{c'}$ показывает, во сколько раз стороны одного треугольника больше соответственных сторон другого.

+

Свойства подобия (отношение эквивалентности):

+
    +
  • Рефлексивность: $\\triangle ABC \\sim \\triangle ABC$ (с $k=1$).
  • +
  • Симметричность: если $\\triangle ABC \\sim \\triangle A'B'C'$ с коэффициентом $k$, то $\\triangle A'B'C' \\sim \\triangle ABC$ с коэффициентом $\\tfrac{1}{k}$.
  • +
  • Транзитивность: если $\\triangle ABC \\sim \\triangle A'B'C'$ и $\\triangle A'B'C' \\sim \\triangle A''B''C''$, то $\\triangle ABC \\sim \\triangle A''B''C''$.
  • +
`); + + html+=makeCard('example','Пример','3.3',` +

Пример. $\\triangle ABC$: стороны $6, 8, 10$. $\\triangle A'B'C'$: стороны $3, 4, 5$. Подобны ли треугольники?

+

$\\dfrac{6}{3}=2,\\; \\dfrac{8}{4}=2,\\; \\dfrac{10}{5}=2$ — отношения равны. Значит, $\\triangle ABC \\sim \\triangle A'B'C'$ с коэффициентом $k=2$.

+

Пример 2. Треугольники $5,7,9$ и $10,15,18$ — подобны ли?

+

$10/5=2$, $15/7\\approx 2.14$ — отношения неравны. Не подобны.

`); + + /* ИНТЕРАКТИВ 1 — SVG два треугольника с slider k */ + html+=`
+
ИНТЕРАКТИВ 1
Два подобных треугольника — коэффициент k
+
Меняй коэффициент подобия $k$ — второй треугольник масштабируется. Углы всегда равны, стороны пропорциональны.
+
+ +
+
+
+
`; + + /* ИНТЕРАКТИВ 2 — Калькулятор */ + html+=`
+
ИНТЕРАКТИВ 2
Калькулятор подобия
+
Введи стороны одного треугольника и коэффициент $k$ — получи стороны подобного.
+
+
a
+
b
+
c
+
k
+
+
+ +
`; + + /* ИНТЕРАКТИВ 3 — DnD-сортер подобные / неподобные */ + html+=`
+
ИНТЕРАКТИВ 3
Подобные или нет? — Сортировка
+
Перетащи каждую пару треугольников в нужную колонку.
+
+
+
Подобные
+
Не подобные
+
+
+ +
`; + + /* ИНТЕРАКТИВ 4 — Тренажёр */ + html+=`
+
ИНТЕРАКТИВ 4
Тренажёр §3 — Подобные треугольники
+
5 задач на коэффициент подобия и неизвестные стороны.
+
Задача 1 / 5Очки: 0
+
+
+ + + +
+ +
`; + + /* ИНТЕРАКТИВ 5 — Мини-квиз */ + html+=`
+
ИНТЕРАКТИВ 5
Мини-квиз: теория подобия
+
4 вопроса на проверку понимания теории.
+
+
+ +
`; + + /* ИНТЕРАКТИВ 6 — Босс §3 */ + html+=`
+
БОСС §3
Итоговые задачи
+
4 задачи — каждая верная даёт +5 XP.
+
+
`; + + html+=`
+ +
`; + html+=secNav('p2','p4'); + box.innerHTML=html; + if(window.renderMathInElement) setTimeout(()=>renderMath(box),0); + + /* == INIT ИНТЕРАКТИВ 1: два треугольника == */ + (function(){ + const kSl=document.getElementById('p3-k-sl'); + const kVal=document.getElementById('p3-k-val'); + const svgWrap=document.getElementById('p3-sim-svg'); + const infoEl=document.getElementById('p3-sim-info'); + // базовый треугольник: A=(80,20), B=(20,120), C=(160,120) + const Ax=80,Ay=20,Bx=20,By=120,Cx=160,Cy=120; + const a=Math.hypot(Cx-Bx,Cy-By); // BC + const b=Math.hypot(Ax-Cx,Ay-Cy); // CA + const c=Math.hypot(Bx-Ax,By-Ay); // AB + function draw(){ + const k=+kSl.value/10; + kVal.textContent=k.toFixed(1); + // второй треугольник масштабируем от центра C' = (240, 120) + const ox=240, oy=120; + const Ax2=ox+(Ax-Cx)/k, Ay2=oy+(Ay-Cy)/k; + const Bx2=ox+(Bx-Cx)/k, By2=oy+(By-Cy)/k; + const Cx2=ox, Cy2=oy; + const W=380, H=160; + let s=``; + // большой треугольник + s+=``; + s+=`A`; + s+=`B`; + s+=`C`; + // подписи сторон + s+=`a=${fmt(a/10)}`; + s+=`c=${fmt(c/10)}`; + s+=`b=${fmt(b/10)}`; + // второй треугольник + s+=``; + s+=`A'`; + s+=`B'`; + s+=`C'`; + // подписи сторон 2 + const a2=a/k,b2=b/k,c2=c/k; + s+=`a'=${fmt(a2/10)}`; + // k-label + s+=`k = ${k.toFixed(1)}`; + s+=''; + svgWrap.innerHTML=s; + infoEl.innerHTML=`$k=${k.toFixed(1)}$: $a/a'=${fmt(a/a*k/k)} \\to a'=${fmt(a/10/k)}$, $b'=${fmt(b/10/k)}$, $c'=${fmt(c/10/k)}$. Углы всегда равны: $\\angle A=\\angle A', \\angle B=\\angle B', \\angle C=\\angle C'$.`; + renderMath(infoEl); + addXp(1,'p3-sim'); + } + kSl.addEventListener('input',draw); + draw(); + })(); + + /* == INIT ИНТЕРАКТИВ 2: калькулятор == */ + (function(){ + document.getElementById('p3-ccalc').addEventListener('click',()=>{ + const a=parseFloat(document.getElementById('p3-ca').value); + const b=parseFloat(document.getElementById('p3-cb').value); + const c=parseFloat(document.getElementById('p3-cc').value); + const k=parseFloat(document.getElementById('p3-ck').value); + const out=document.getElementById('p3-ccalc-out'); + if([a,b,c,k].some(v=>!isFinite(v)||v<=0)){ + out.style.display='block';out.innerHTML='Введи положительные числа для a, b, c, k.';return; + } + out.style.display='block'; + out.innerHTML=`Стороны подобного треугольника при $k=${fmt(k)}$:
$a'=a/k=${fmt(a/k)}$, $b'=b/k=${fmt(b/k)}$, $c'=c/k=${fmt(c/k)}$`; + renderMath(out); + addXp(2,'p3-calc');bumpProgress('p3',5); + }); + })(); + + /* == INIT ИНТЕРАКТИВ 3: DnD == */ + (function(){ + const items=[ + {text:'(3,4,5) и (6,8,10)',yes:true}, + {text:'(5,7,9) и (10,15,18)',yes:false}, + {text:'(2,3,4) и (4,6,8)',yes:true}, + {text:'(1,2,3) и (2,4,7)',yes:false}, + {text:'(6,8,10) и (3,4,5)',yes:true}, + ]; + const pool=document.getElementById('p3-dnd-pool'); + const yesBox=document.getElementById('p3-drop-yes-items'); + const noBox=document.getElementById('p3-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('p3-drop-yes'),document.getElementById('p3-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('p3-drop-yes')?yesBox:box===document.getElementById('p3-drop-no')?noBox:pool; + target.appendChild(dragging); + }); + }); + document.getElementById('p3-dnd-check').addEventListener('click',()=>{ + const fb=document.getElementById('p3-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,'p3-dnd');bumpProgress('p3',8);} + else{feedback(fb,false,'Есть ошибки — проверь пропорциональность сторон.');} + }); + document.getElementById('p3-dnd-reset').addEventListener('click',()=>{ + [...yesBox.children].forEach(c=>pool.appendChild(c)); + [...noBox.children].forEach(c=>pool.appendChild(c)); + document.getElementById('p3-dnd-fb').style.display='none'; + }); + })(); + + /* == INIT ИНТЕРАКТИВ 4: тренажёр == */ + (function(){ + const tasks=[ + {q:'$\\triangle ABC$ со сторонами $6,8,10$ подобен $\\triangle A\'B\'C\'$ со сторонами $3,4,5$. Чему равен коэффициент подобия?', ans:2, hint:'k = 6/3 = 8/4 = 10/5 = 2.'}, + {q:'$\\triangle ABC \\sim \\triangle A\'B\'C\'$, коэффициент $k=3$. Сторона $a=15$. Найди $a\'$.', ans:5, hint:'a\' = a/k = 15/3 = 5.'}, + {q:'$\\triangle ABC \\sim \\triangle A\'B\'C\'$, $k=2$. Сторона $b\'=7$. Найди $b$.', ans:14, hint:'b = k·b\' = 2·7 = 14.'}, + {q:'Стороны треугольников $4,6,8$ и $6,9,12$. Найди коэффициент подобия.', ans:1.5, hint:'k = 6/4 = 9/6 = 12/8 = 1.5.'}, + {q:'$\\triangle ABC \\sim \\triangle A\'B\'C\'$, $a=20$, $a\'=4$. Чему равен $k$?', ans:5, hint:'k = a/a\' = 20/4 = 5.'}, + ]; + let idx=0,score=0; + function show(){ + document.getElementById('p3-tr-i').textContent=idx+1; + const t=document.getElementById('p3-tr-task'); + t.innerHTML=tasks[idx].q; + renderMath(t); + document.getElementById('p3-tr-ans').value=''; + document.getElementById('p3-tr-fb').style.display='none'; + } + document.getElementById('p3-tr-start').addEventListener('click',()=>{idx=0;score=0;document.getElementById('p3-tr-score').textContent=0;show();}); + document.getElementById('p3-tr-go').addEventListener('click',()=>{ + if(idx>=tasks.length)return; + const ans=+document.getElementById('p3-tr-ans').value; + const fb=document.getElementById('p3-tr-fb'); + if(Math.abs(ans-tasks[idx].ans)<0.05){ + score++;document.getElementById('p3-tr-score').textContent=score; + addXp(3,'p3-tr-'+idx);bumpProgress('p3',4); + if(idxshow(),900);} + else{feedback(fb,true,'Все задачи решены! +5 XP');addXp(5,'p3-tr-all');bumpProgress('p3',10);confetti();} + } else { + feedback(fb,false,'Неверно. '+tasks[idx].hint); + } + }); + document.getElementById('p3-tr-ans').addEventListener('keydown',e=>{if(e.key==='Enter')document.getElementById('p3-tr-go').click();}); + show(); + })(); + + /* == INIT ИНТЕРАКТИВ 5: мини-квиз == */ + (function(){ + const qs=[ + {q:'Коэффициент подобия равен 1. Что это означает?', opts:['Треугольники конгруэнтны','Треугольники не подобны','Треугольники равновелики по площади','Треугольники прямоугольные'], ans:0}, + {q:'Если $\\triangle ABC \\sim \\triangle A\'B\'C\'$ с $k=3$, то $\\triangle A\'B\'C\' \\sim \\triangle ABC$ с коэффициентом:', opts:['3','1/3','9','1/9'], ans:1}, + {q:'Что является достаточным условием подобия треугольников?', opts:['Равенство двух углов','Равенство одной стороны','Равенство периметров','Равенство площадей'], ans:0}, + {q:'Подобие — это:', opts:['Отношение эквивалентности','Только рефлексивное отношение','Только транзитивное отношение','Отношение порядка'], ans:0}, + ]; + const body=document.getElementById('p3-quiz-body'); + body.innerHTML=qs.map((q,qi)=>` +
+
${qi+1}. ${q.q}
+ ${q.opts.map((o,oi)=>``).join('')} +
`).join(''); + document.getElementById('p3-quiz-check').addEventListener('click',()=>{ + const fb=document.getElementById('p3-quiz-fb'); + let correct=0; + qs.forEach((q,qi)=>{ + const sel=document.querySelector(`input[name="p3q${qi}"]:checked`); + if(sel&&+sel.value===q.ans)correct++; + }); + if(correct===qs.length){ + feedback(fb,true,`Все ${qs.length} верно! +10 XP`); + addXp(10,'p3-quiz');bumpProgress('p3',10);confetti(); + } else { + feedback(fb,false,`Верно ${correct} из ${qs.length}. Перечитай карточки теории.`); + } + }); + })(); + + /* == INIT: Босс §3 == */ + (function(){ + const tasks=[ + {q:'$\\triangle ABC$ со сторонами $9,12,15$. Коэффициент подобия с $\\triangle A\'B\'C\'$ равен $3$. Найди наименьшую сторону $\\triangle A\'B\'C\'$.', ans:3, hint:'a\' = 9/3 = 3.'}, + {q:'$\\triangle ABC \\sim \\triangle A\'B\'C\'$. Стороны $\\triangle A\'B\'C\'$: $5,7,x$, стороны $\\triangle ABC$: $10,14,16$. Найди $x$.', ans:8, hint:'k=2, x = 16/2 = 8.'}, + {q:'Периметр $\\triangle ABC = 36$, $k=3$. Найди периметр подобного треугольника $\\triangle A\'B\'C\'$.', ans:12, hint:'P\' = P/k = 36/3 = 12.'}, + {q:'$\\triangle ABC \\sim \\triangle A\'B\'C\'$, $k=4$. Сторона $c=20$. Найди $c\'$.', ans:5, hint:'c\' = c/k = 20/4 = 5.'}, + ]; + const bossBox=document.getElementById('p3-boss-tasks'); + bossBox.innerHTML=tasks.map((t,i)=>` +
+
${t.q}
+
+ + +
+ +
`).join(''); + window.p3BossSolved=new Set(); + 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 buildP6stub(){ document.getElementById('p6-body').innerHTML='

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

'+secNav('p5','p7'); }