diff --git a/frontend/textbooks/geometry_8_ch1.html b/frontend/textbooks/geometry_8_ch1.html
index 085ce5d..ddd52df 100644
--- a/frontend/textbooks/geometry_8_ch1.html
+++ b/frontend/textbooks/geometry_8_ch1.html
@@ -492,8 +492,8 @@ function buildParaSelector(){
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(), p11:()=>buildP11stub(), p12:()=>buildP12stub(),
+ p5:()=>buildP5(), p6:()=>buildP6(), p7:()=>buildP7(), p8:()=>buildP8(),
+ p9:()=>buildP9(), p10:()=>buildP10(), p11:()=>buildP11stub(), p12:()=>buildP12stub(),
p13:()=>buildP13stub(), p14:()=>buildP14stub(), p15:()=>buildP15stub(), p16:()=>buildP16stub(),
final1:()=>buildFinal1stub(),
};
@@ -1892,12 +1892,1475 @@ function buildP4(){
})();
renderMath(box);
}
-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'); }
-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 buildP5(){
+ const box = document.getElementById('p5-body');
+ let html = '';
+
+ html += makeCard('theory','Свойства параллелограмма','5.1',`
+ Теорема. В параллелограмме:
+
+ - Свойство 1: противоположные стороны равны: $AB = CD$, $BC = AD$
+ - Свойство 2: противоположные углы равны: $\\angle A = \\angle C$, $\\angle B = \\angle D$
+ - Свойство 3: диагонали точкой пересечения $O$ делятся пополам: $AO = OC$, $BO = OD$
+ - Свойство 4: сумма соседних углов равна $180°$: $\\angle A + \\angle B = 180°$
+
`);
+
+ html += makeCard('rule','Доказательство свойств 1 и 2','5.2',`
+ Проводим диагональ $AC$. Образуются $\\triangle ABC$ и $\\triangle CDA$.
+ $AB \\parallel CD$ $\\Rightarrow$ $\\angle BAC = \\angle DCA$ (накрест лежащие).
+ $BC \\parallel AD$ $\\Rightarrow$ $\\angle BCA = \\angle DAC$ (накрест лежащие).
+ $AC$ — общая сторона. По признаку «угол–сторона–угол»: $\\triangle ABC = \\triangle CDA$.
+ Из равенства треугольников: $AB=CD$, $BC=DA$, $\\angle B=\\angle D$. А $\\angle A=\\angle C$ — аналогично через диагональ $BD$.
`);
+
+ html += makeCard('rule','Доказательство свойства 3','5.3',`
+ Рассмотрим треугольники $\\triangle AOB$ и $\\triangle COD$, где $O$ — точка пересечения диагоналей.
+ $AB = CD$ (свойство 1), $\\angle OAB = \\angle OCD$, $\\angle OBA = \\angle ODC$ (накрест лежащие). По «угол–сторона–угол»: $\\triangle AOB = \\triangle COD$.
+ Следовательно: $AO = CO$ и $BO = DO$. Диагонали делятся пополам. $\\square$
`);
+
+ /* --- INTERACTIVE 1: SVG-параллелограмм с живыми метриками --- */
+ html += `
+
+
Тащи вершины B и D. Все четыре свойства проверяются в реальном времени.
+
+
+
`;
+
+ /* --- INTERACTIVE 2: Пошаговое доказательство свойства 1 --- */
+ html += `
+
+
Нажимай «Дальше» — смотри, как подсвечиваются треугольники.
+
+
+
+
+
+
+
`;
+
+ /* --- INTERACTIVE 3: Доказательство свойства 3 --- */
+ html += `
+
+
Диагонали делятся точкой пересечения пополам — доказательство через равные треугольники.
+
+
+
+
+
+
+
`;
+
+ /* --- INTERACTIVE 4: DnD — свойство → иллюстрация --- */
+ html += `
+
+
Перетащи каждое свойство в правильную категорию.
+ ${DND_HINT_HTML}
+
+
+
+
+
`;
+
+ /* --- INTERACTIVE 5: Тренажёр --- */
+ html += `
+
+
Задача 1 / 5Очки: 0
+
+
+
+
+
+
+
+
`;
+
+ /* --- INTERACTIVE 6: Босс §5 --- */
+ html += `
+
+
+5 XP за каждую верную задачу.
+
+
`;
+
+ html += `
+
+
`;
+
+ html += secNav('p4','p6');
+ box.innerHTML = html;
+
+ /* == SVG-параллелограмм == */
+ (function(){
+ const W=380, H=280;
+ let A={x:55,y:210}, B={x:195,y:210}, D={x:110,y:80};
+ function getC(){ return {x:D.x+(B.x-A.x), y:D.y+(B.y-A.y)}; }
+ function dist(a,b){ return Math.hypot(b.x-a.x,b.y-a.y); }
+ function angDeg(O,P,Q){ const ax=P.x-O.x,ay=P.y-O.y,bx=Q.x-O.x,by=Q.y-O.y; return Math.acos(Math.max(-1,Math.min(1,(ax*bx+ay*by)/(Math.hypot(ax,ay)*Math.hypot(bx,by)))))*180/Math.PI; }
+ function intersect(A,C,B,D){ const r={x:C.x-A.x,y:C.y-A.y},s={x:D.x-B.x,y:D.y-B.y}; const den=r.x*s.y-r.y*s.x; if(Math.abs(den)<1e-9) return {x:(A.x+C.x)/2,y:(A.y+C.y)/2}; const t=((B.x-A.x)*s.y-(B.y-A.y)*s.x)/den; return {x:A.x+t*r.x,y:A.y+t*r.y}; }
+ function redraw(){
+ const C=getC(); const pts=[A,B,C,D]; const labels=['A','B','C','D'];
+ const cx=(A.x+B.x+C.x+D.x)/4, cy=(A.y+B.y+C.y+D.y)/4;
+ const O=intersect(A,C,B,D);
+ let s='';
+ const wrap=document.getElementById('p5-svg-wrap');
+ wrap.innerHTML=s;
+ const svgEl=wrap.querySelector('svg');
+ svgEl.querySelectorAll('.p5-vh').forEach(el=>{
+ el.style.cursor='grab';
+ el.addEventListener('pointerdown',ev=>{
+ if(ev.button!==undefined&&ev.button!==0) return;
+ const vname=el.dataset.v;
+ try{el.setPointerCapture(ev.pointerId);}catch(e){}
+ function onMove(e){ const rect=svgEl.getBoundingClientRect(); const sx=W/rect.width,sy=H/rect.height; const nx=Math.max(10,Math.min(W-10,(e.clientX-rect.left)*sx)); const ny=Math.max(10,Math.min(H-10,(e.clientY-rect.top)*sy)); if(vname==='B') B={x:nx,y:ny}; else if(vname==='D') D={x:nx,y:ny}; redraw(); }
+ function onUp(){ el.removeEventListener('pointermove',onMove);el.removeEventListener('pointerup',onUp);el.removeEventListener('pointercancel',onUp); }
+ el.addEventListener('pointermove',onMove); el.addEventListener('pointerup',onUp); el.addEventListener('pointercancel',onUp);
+ });
+ });
+ const C2=getC(); const O2=intersect(A,C2,B,D);
+ const ab=dist(A,B), bc=dist(B,C2), ao=dist(A,O2), bo=dist(B,O2);
+ const angA=angDeg(A,D,B), angB=angDeg(B,A,C2);
+ document.getElementById('p5-info').innerHTML=`
+
+
+
+
+ ∠A = ∠C
${angA.toFixed(1)}°
+ ∠A + ∠B
${(angA+angB).toFixed(1)}° `;
+ }
+ redraw();
+ })();
+
+ /* == Доказательство свойства 1 == */
+ (function(){
+ const A={x:30,y:160},B={x:185,y:160},C={x:265,y:50},D={x:110,y:50};
+ const cx=(A.x+B.x+C.x+D.x)/4,cy=(A.y+B.y+C.y+D.y)/4;
+ const steps=[
+ {text:'Дано: $ABCD$ — параллелограмм. $AB\\parallel CD$, $BC\\parallel AD$. Проведём диагональ $AC$.', h:''},
+ {text:'Шаг 1. $AB\\parallel CD$, $AC$ — секущая. $\\angle BAC = \\angle DCA$ — накрест лежащие углы.', h:'diag'},
+ {text:'Шаг 2. $BC\\parallel AD$, $AC$ — секущая. $\\angle BCA = \\angle DAC$ — накрест лежащие углы.', h:'diag'},
+ {text:'Шаг 3. $AC$ — общая сторона. По признаку «уголь–сторона–угол»: $\\triangle ABC = \\triangle CDA$.', h:'both'},
+ {text:'Вывод. $AB = CD$ и $BC = DA$. Свойство 1 доказано. $\\square$', h:'both'},
+ ];
+ let step=0;
+ function draw(h){
+ let s='';
+ document.getElementById('p5-proof1-svg').innerHTML=s;
+ }
+ function show(){ const st=steps[step]; document.getElementById('p5-proof1-step').innerHTML=st.text; renderMath(document.getElementById('p5-proof1-step')); draw(st.h); document.getElementById('p5-proof1-next').textContent=step{ if(step{step=0;show();document.getElementById('p5-proof1-next').disabled=false;});
+ show();
+ })();
+
+ /* == Доказательство свойства 3 == */
+ (function(){
+ const A={x:30,y:160},B={x:185,y:160},C={x:265,y:50},D={x:110,y:50};
+ const O={x:(A.x+C.x)/2,y:(A.y+C.y)/2};
+ const cx=(A.x+B.x+C.x+D.x)/4,cy=(A.y+B.y+C.y+D.y)/4;
+ const steps=[
+ {text:'Дано: $ABCD$ — параллелограмм, $O$ — точка пересечения диагоналей. Нужно доказать: $AO=OC$, $BO=OD$.', h:''},
+ {text:'Шаг 1. $AB\\parallel CD$ и $AB=CD$ (свойство 1). Рассмотрим $\\triangle AOB$ и $\\triangle COD$.', h:'tri1'},
+ {text:'Шаг 2. $\\angle OAB = \\angle OCD$ (накрест лежащие при $AB\\parallel CD$); $\\angle OBA=\\angle ODC$ (накрест лежащие).', h:'tri1'},
+ {text:'Шаг 3. $AB=CD$, два угла равны. По «угол–сторона–угол»: $\\triangle AOB = \\triangle COD$.', h:'both3'},
+ {text:'Вывод. $AO=CO$, $BO=DO$. Диагонали точкой пересечения делятся пополам. $\\square$', h:'both3'},
+ ];
+ let step=0;
+ function draw(h){
+ let s='';
+ document.getElementById('p5-proof2-svg').innerHTML=s;
+ }
+ function show(){ const st=steps[step]; document.getElementById('p5-proof2-step').innerHTML=st.text; renderMath(document.getElementById('p5-proof2-step')); draw(st.h); document.getElementById('p5-proof2-next').textContent=step{ if(step{step=0;show();document.getElementById('p5-proof2-next').disabled=false;});
+ show();
+ })();
+
+ /* == DnD == */
+ (function(){
+ const items=[
+ {id:'s1',html:'$AB = CD$', ans:'sides'},
+ {id:'s2',html:'$BC = AD$', ans:'sides'},
+ {id:'a1',html:'$\\angle A = \\angle C$', ans:'angles'},
+ {id:'a2',html:'$\\angle B = \\angle D$', ans:'angles'},
+ {id:'a3',html:'$\\angle A + \\angle B = 180°$', ans:'angles'},
+ {id:'d1',html:'$AO = OC$', ans:'diag'},
+ {id:'d2',html:'$BO = OD$', ans:'diag'},
+ ];
+ const sorter=setupSorter({poolId:'p5-dnd-pool',scopeSelector:'#p5-dnd-wrap',items,cats:['sides','angles','diag']});
+ document.getElementById('p5-dnd-reset').addEventListener('click',()=>{sorter.reset();document.getElementById('p5-dnd-fb').style.display='none';});
+ document.getElementById('p5-dnd-check').addEventListener('click',()=>{
+ let ok=0; items.forEach(it=>{if(sorter.placed[it.id]===it.ans)ok++;});
+ const fb=document.getElementById('p5-dnd-fb');
+ if(ok===items.length){feedback(fb,true,'Все '+items.length+' верно! +5 XP');addXp(5,'p5-dnd');bumpProgress('p5',15);}
+ else feedback(fb,false,'Верно: '+ok+' из '+items.length+'.');
+ });
+ })();
+
+ /* == Тренажёр == */
+ (function(){
+ const tasks=[
+ {q:'В параллелограмме $\\angle A = 65°$. Найди $\\angle B$.', ans:115, hint:'∠A+∠B=180°, ∠B=115°'},
+ {q:'В параллелограмме $\\angle A = 65°$. Найди $\\angle C$.', ans:65, hint:'∠C=∠A=65°'},
+ {q:'В параллелограмме $\\angle A = 65°$. Найди $\\angle D$.', ans:115, hint:'∠D=∠B=115°'},
+ {q:'В параллелограмме $AB = 12$, периметр $P = 44$. Найди $BC$.', ans:10, hint:'P=2(12+BC), BC=(44/2-12)=10'},
+ {q:'В параллелограмме $BD = 18$. Найди $BO$ (половину диагонали).', ans:9, hint:'BO=BD/2=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; renderMath(document.getElementById('p5-tr-task')); 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',()=>{
+ const ans=+document.getElementById('p5-tr-ans').value; const fb=document.getElementById('p5-tr-fb');
+ if(ans===tasks[idx].ans){ score++;document.getElementById('p5-tr-score').textContent=score;addXp(3,'p5-train');bumpProgress('p5',5); if(idxshow(),900);}else{feedback(fb,true,'Все задачи! +5 XP');addXp(5,'p5-train-all');} }
+ 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();
+ })();
+
+ /* == Босс §5 == */
+ (function(){
+ const tasks=[
+ {q:'В параллелограмме $\\angle A = 48°$. Найди $\\angle B$.', ans:132, hint:'∠A+∠B=180°'},
+ {q:'В параллелограмме $AB=15$, $P=58$. Найди $BC$.', ans:14, hint:'P=2(AB+BC), BC=29-15=14'},
+ {q:'Диагональ параллелограмма $AC=22$. Найди $AO$ ($O$ — точка пересечения диагоналей).', ans:11, hint:'AO=AC/2=11'},
+ {q:'В параллелограмме $\\angle D=110°$. Найди $\\angle A$.', ans:70, hint:'∠A+∠D=180°, ∠A=70°'},
+ ];
+ const bossBox=document.getElementById('p5-boss-tasks');
+ bossBox.innerHTML=tasks.map((t,i)=>`
+
+
${t.q}
+
+
+
+
+
+
`).join('');
+ window.p5BossSolved=new Set();
+ })();
+ renderMath(box);
+}
+function buildP6(){
+ const box = document.getElementById('p6-body');
+ let html = '';
+
+ html += makeCard('theory','Признаки параллелограмма','6.1',`
+ Четырёхугольник является параллелограммом, если выполнен хотя бы один из признаков:
+
+ - Признак 1. Две пары противоположных сторон равны: $AB=CD$ и $BC=AD$.
+ - Признак 2. Одна пара противоположных сторон одновременно параллельна и равна: $AB\\parallel CD$ и $AB=CD$.
+ - Признак 3. Диагонали точкой пересечения делятся пополам: $AO=OC$ и $BO=OD$.
+
`);
+
+ html += makeCard('rule','Доказательство признака 1','6.2',`
+ Дано: $AB=CD$, $BC=AD$. Проведём диагональ $AC$.
+ В $\\triangle ABC$ и $\\triangle CDA$: $AB=CD$, $BC=DA$, $AC=CA$ (общая). По признаку «три стороны»: $\\triangle ABC=\\triangle CDA$.
+ Из равенства треугольников: $\\angle BAC=\\angle DCA$ и $\\angle BCA=\\angle DAC$. Это накрест лежащие углы, значит $AB\\parallel CD$ и $BC\\parallel AD$. Следовательно, $ABCD$ — параллелограмм. $\\square$
`);
+
+ html += makeCard('rule','Доказательство признака 3','6.3',`
+ Дано: $AO=OC$, $BO=OD$. В $\\triangle AOB$ и $\\triangle COD$: $AO=CO$, $BO=DO$, $\\angle AOB=\\angle COD$ (вертикальные). По признаку «сторона–угол–сторона»: $\\triangle AOB=\\triangle COD$.
+ Отсюда $\\angle OAB=\\angle OCD$ — накрест лежащие, значит $AB\\parallel CD$. Аналогично $BC\\parallel AD$. Четырёхугольник — параллелограмм. $\\square$
`);
+
+ /* --- INTERACTIVE 1: Три SVG-демонстрации признаков --- */
+ html += `
+
+
Нажми кнопку признака — смотри иллюстрацию и вывод.
+
+
+
+
+
+
+
+
`;
+
+ /* --- INTERACTIVE 2: Тренажёр выбора признака --- */
+ html += `
+
+
Прочитай условие и выбери, какой признак доказывает, что фигура — параллелограмм.
+
Вопрос 1 / 5Очки: 0
+
+
+
+
`;
+
+ /* --- INTERACTIVE 3: DnD — условие → признак --- */
+ html += `
+
+
Перетащи условие к соответствующему признаку параллелограмма.
+ ${DND_HINT_HTML}
+
+
+
+
+
`;
+
+ /* --- INTERACTIVE 4: Мини-доказательство признака 1 --- */
+ html += `
+
+
+
+
+
+
+
+
`;
+
+ /* --- INTERACTIVE 5: Босс §6 --- */
+ html += `
+
+
+5 XP за каждую верную задачу.
+
+
`;
+
+ html += `
+
+
`;
+
+ html += secNav('p5','p7');
+ box.innerHTML = html;
+
+ /* == Три признака — SVG-демонстрации == */
+ (function(){
+ const A={x:40,y:155},B={x:175,y:155},C={x:245,y:55},D={x:110,y:55};
+ const cx=(A.x+B.x+C.x+D.x)/4,cy=(A.y+B.y+C.y+D.y)/4;
+ function baseShape(){ return ''; }
+ function labels(){ let s=''; ['A','B','C','D'].forEach((lbl,i)=>{ const v=[A,B,C,D][i]; s+=''; const lx=v.x+(v.x-cx)*0.28,ly=v.y+(v.y-cy)*0.28; s+=''+lbl+''; }); return s; }
+ function midTick(p1,p2,col,n){ const mx=(p1.x+p2.x)/2,my=(p1.y+p2.y)/2,dx=p2.x-p1.x,dy=p2.y-p1.y,len=Math.hypot(dx,dy); const nx=-dy/len*6,ny=dx/len*6; let s=''; for(let k=0;k'; } return s; }
+ function showSign(n){
+ let s='';
+ document.getElementById('p6-sign-svg').innerHTML=s;
+ renderMath(document.getElementById('p6-sign-text'));
+ [1,2,3].forEach(k=>{ const btn=document.getElementById('p6-sign-btn'+k); btn.className='btn'+(k===n?' primary':''); });
+ }
+ document.getElementById('p6-sign-btn1').addEventListener('click',()=>showSign(1));
+ document.getElementById('p6-sign-btn2').addEventListener('click',()=>showSign(2));
+ document.getElementById('p6-sign-btn3').addEventListener('click',()=>showSign(3));
+ showSign(1);
+ })();
+
+ /* == Тренажёр выбора признака == */
+ (function(){
+ const qs=[
+ {q:'В четырёхугольнике $ABCD$: $AB=CD=7$ и $BC=AD=5$. Это параллелограмм?',opts:['Признак 1','Признак 2','Признак 3','Нет'],ans:0},
+ {q:'В четырёхугольнике $AB\\parallel CD$ и $AB=CD$. Это параллелограмм?',opts:['Признак 1','Признак 2','Признак 3','Нет'],ans:1},
+ {q:'Диагонали пересекаются в точке $O$: $AO=OC=6$, $BO=OD=8$. Это параллелограмм?',opts:['Признак 1','Признак 2','Признак 3','Нет'],ans:2},
+ {q:'В четырёхугольнике все стороны разной длины и диагонали не делятся пополам.',opts:['Признак 1','Признак 2','Признак 3','Нет'],ans:3},
+ {q:'В четырёхугольнике $BC\\parallel AD$ и $BC=AD$. Это параллелограмм?',opts:['Признак 1','Признак 2','Признак 3','Нет'],ans:1},
+ ];
+ let qi=0,qscore=0,answered=false;
+ function showQ(){
+ answered=false;
+ const q=qs[qi];
+ document.getElementById('p6-quiz-i').textContent=qi+1;
+ document.getElementById('p6-quiz-q').innerHTML=q.q;
+ renderMath(document.getElementById('p6-quiz-q'));
+ document.getElementById('p6-quiz-opts').innerHTML=q.opts.map((o,i)=>``).join('');
+ document.getElementById('p6-quiz-fb').style.display='none';
+ }
+ window.p6QuizAns=function(i){
+ if(answered)return; answered=true;
+ const q=qs[qi]; const fb=document.getElementById('p6-quiz-fb');
+ if(i===q.ans){qscore++;feedback(fb,true,'Верно! +3 XP');addXp(3,'p6-quiz');bumpProgress('p6',7);}
+ else feedback(fb,false,'Неверно. Правильно: '+q.opts[q.ans]);
+ document.querySelectorAll('[id^="p6-qopt-"]').forEach((b,bi)=>{b.disabled=true;if(bi===q.ans)b.style.background='var(--ok-bg)';else if(bi===i)b.style.background='var(--fail-bg)';});
+ setTimeout(()=>{ qi++; if(qiКвиз завершён! '+qscore+'/'+qs.length+''; },1300);
+ };
+ showQ();
+ })();
+
+ /* == DnD == */
+ (function(){
+ const items=[
+ {id:'c1',html:'$AB=CD$ и $BC=AD$', ans:'r1'},
+ {id:'c2',html:'Обе пары противоположных сторон равны', ans:'r1'},
+ {id:'c3',html:'$AB\\parallel CD$ и $AB=CD$', ans:'r2'},
+ {id:'c4',html:'Одна пара ∥ и =', ans:'r2'},
+ {id:'c5',html:'$AO=OC$ и $BO=OD$', ans:'r3'},
+ {id:'c6',html:'Диагонали делятся пополам', ans:'r3'},
+ ];
+ const sorter=setupSorter({poolId:'p6-dnd-pool',scopeSelector:'#p6-dnd-wrap',items,cats:['r1','r2','r3']});
+ document.getElementById('p6-dnd-reset').addEventListener('click',()=>{sorter.reset();document.getElementById('p6-dnd-fb').style.display='none';});
+ document.getElementById('p6-dnd-check').addEventListener('click',()=>{
+ let ok=0; items.forEach(it=>{if(sorter.placed[it.id]===it.ans)ok++;});
+ const fb=document.getElementById('p6-dnd-fb');
+ if(ok===items.length){feedback(fb,true,'Все верно! +5 XP');addXp(5,'p6-dnd');bumpProgress('p6',15);}
+ else feedback(fb,false,'Верно: '+ok+' из '+items.length+'.');
+ });
+ })();
+
+ /* == Доказательство признака 1 == */
+ (function(){
+ const A={x:40,y:155},B={x:175,y:155},C={x:245,y:55},D={x:110,y:55};
+ const cx=(A.x+B.x+C.x+D.x)/4,cy=(A.y+B.y+C.y+D.y)/4;
+ const steps=[
+ {text:'Дано: $AB=CD$, $BC=AD$. Проведём диагональ $AC$.', h:''},
+ {text:'Шаг 1. В $\\triangle ABC$ и $\\triangle CDA$: $AB=CD$, $BC=DA$, $AC=CA$ (общая сторона).', h:'diag'},
+ {text:'Шаг 2. По признаку «три стороны»: $\\triangle ABC = \\triangle CDA$.', h:'both'},
+ {text:'Шаг 3. Из равенства: $\\angle BAC=\\angle DCA$ и $\\angle BCA=\\angle DAC$ — накрест лежащие углы. Значит $AB\\parallel CD$ и $BC\\parallel AD$.', h:'both'},
+ {text:'Вывод. Обе пары противоположных сторон параллельны $\\Rightarrow$ $ABCD$ — параллелограмм. $\\square$', h:'both'},
+ ];
+ let step=0;
+ function draw(h){
+ let s='';
+ document.getElementById('p6-proof-svg').innerHTML=s;
+ }
+ function show(){ const st=steps[step]; document.getElementById('p6-proof-step').innerHTML=st.text; renderMath(document.getElementById('p6-proof-step')); draw(st.h); document.getElementById('p6-proof-next').textContent=step{ if(step{step=0;show();document.getElementById('p6-proof-next').disabled=false;});
+ show();
+ })();
+
+ /* == Босс §6 == */
+ (function(){
+ const tasks=[
+ {q:'В четырёхугольнике $AB=CD=9$, $BC=AD=6$. Это параллелограмм? Напиши номер признака (1, 2 или 3).', ans:1, hint:'Признак 1: две пары равных сторон'},
+ {q:'В параллелограмме $\\angle A=75°$. Найди $\\angle C$.', ans:75, hint:'∠A=∠C в параллелограмме'},
+ {q:'В четырёхугольнике $AO=OC=5$ и $BO=OD=7$. Это параллелограмм — какой признак? (1/2/3)', ans:3, hint:'Признак 3: диагонали делятся пополам'},
+ {q:'В параллелограмме $AB=16$, $P=54$. Найди $BC$.', ans:11, hint:'P=2(16+BC), BC=27-16=11'},
+ ];
+ const bossBox=document.getElementById('p6-boss-tasks');
+ bossBox.innerHTML=tasks.map((t,i)=>`
+
+
${t.q}
+
+
+
+
+
+
`).join('');
+ window.p6BossSolved=new Set();
+ })();
+ renderMath(box);
+}
+function buildP7(){
+ const box = document.getElementById('p7-body');
+ let html = '';
+
+ html += makeCard('theory','Прямоугольник — определение','7.1',`
+ Прямоугольник — параллелограмм, у которого один угол прямой.
+ Так как в параллелограмме сумма соседних углов равна $180°$, а один угол равен $90°$, то все углы прямоугольника прямые.
+ Обозначение: $\\square ABCD$, где $\\angle A=\\angle B=\\angle C=\\angle D=90°$.
`);
+
+ html += makeCard('rule','Свойство диагоналей прямоугольника','7.2',`
+ Теорема. Диагонали прямоугольника равны: $AC = BD$.
+ Доказательство. Рассмотрим $\\triangle ABC$ и $\\triangle BAD$: $AB=BA$ (общая), $\\angle ABC=\\angle BAD=90°$, $BC=AD$ (как в параллелограмме). По признаку «угол–сторона–угол»: $\\triangle ABC=\\triangle BAD$.
+ Следовательно: $AC=BD$. $\\square$
+ По теореме Пифагора: $d = \\sqrt{a^2 + b^2}$, где $a$, $b$ — стороны прямоугольника.
`);
+
+ /* --- INTERACTIVE 1: SVG-прямоугольник с draggable B --- */
+ html += `
+
+
Тащи вершину B, чтобы изменить размеры прямоугольника. Диагонали всегда остаются равными.
+
+
+
`;
+
+ /* --- INTERACTIVE 2: Пошаговое доказательство --- */
+ html += `
+
+
+
+
+
+
+
+
`;
+
+ /* --- INTERACTIVE 3: Калькулятор диагонали --- */
+ html += `
+
+
Введи стороны $a$ и $b$ — получи диагональ по теореме Пифагора.
+
+
+
+
+
+
+
`;
+
+ /* --- INTERACTIVE 4: Тренажёр --- */
+ html += `
+
+
Задача 1 / 5Очки: 0
+
+
+
+
+
+
+
+
`;
+
+ /* --- INTERACTIVE 5: DnD прямоугольники --- */
+ html += `
+
+
Разложи фигуры: является ли она прямоугольником?
+ ${DND_HINT_HTML}
+
+
+
+
+
`;
+
+ /* --- INTERACTIVE 6: Босс §7 --- */
+ html += `
+
+
+5 XP за каждую верную задачу.
+
+
`;
+
+ html += `
+
+
`;
+
+ html += secNav('p6','p8');
+ box.innerHTML = html;
+
+ /* == SVG-прямоугольник == */
+ (function(){
+ const W=380, H=270;
+ let B={x:240,y:200};
+ const A={x:60,y:200};
+ function getRect(){ return {A:{x:A.x,y:A.y}, B:{x:B.x,y:A.y}, C:{x:B.x,y:B.y}, D:{x:A.x,y:B.y}}; }
+ function dist(a,b){ return Math.hypot(b.x-a.x,b.y-a.y); }
+ function redraw(){
+ const r=getRect(); const {A:Ra,B:Rb,C:Rc,D:Rd}=r;
+ const cx=(Ra.x+Rb.x+Rc.x+Rd.x)/4, cy=(Ra.y+Rb.y+Rc.y+Rd.y)/4;
+ let s='';
+ const wrap=document.getElementById('p7-rect-svg');
+ wrap.innerHTML=s;
+ const svgEl=wrap.querySelector('svg');
+ svgEl.querySelectorAll('.p7-vh').forEach(el=>{
+ el.style.cursor='grab';
+ el.addEventListener('pointerdown',ev=>{
+ if(ev.button!==undefined&&ev.button!==0)return;
+ try{el.setPointerCapture(ev.pointerId);}catch(e){}
+ function onMove(e){ const rect=svgEl.getBoundingClientRect(); const sx=W/rect.width,sy=H/rect.height; B={x:Math.max(A.x+30,Math.min(W-10,(e.clientX-rect.left)*sx)),y:Math.max(30,Math.min(H-10,(e.clientY-rect.top)*sy))}; redraw(); }
+ function onUp(){ el.removeEventListener('pointermove',onMove);el.removeEventListener('pointerup',onUp);el.removeEventListener('pointercancel',onUp); }
+ el.addEventListener('pointermove',onMove); el.addEventListener('pointerup',onUp); el.addEventListener('pointercancel',onUp);
+ });
+ });
+ const rr=getRect(); const ab=dist(rr.A,rr.B), bc=dist(rr.B,rr.C), ac=dist(rr.A,rr.C), bd=dist(rr.B,rr.D);
+ document.getElementById('p7-rect-info').innerHTML=`
+
+
+
+ `;
+ }
+ redraw();
+ })();
+
+ /* == Доказательство == */
+ (function(){
+ const A={x:40,y:155},B={x:230,y:155},C={x:230,y:55},D={x:40,y:55};
+ const cx=(A.x+B.x+C.x+D.x)/4,cy=(A.y+B.y+C.y+D.y)/4;
+ const steps=[
+ {text:'Дано: $ABCD$ — прямоугольник. $\\angle A=\\angle B=90°$. Нужно доказать: $AC=BD$.', h:''},
+ {text:'Шаг 1. Рассмотрим $\\triangle ABC$ и $\\triangle BAD$. $AB=BA$ — общая сторона.', h:'t1'},
+ {text:'Шаг 2. $\\angle ABC=\\angle BAD=90°$ — прямые углы прямоугольника. $BC=AD$ — как в параллелограмме.', h:'t1'},
+ {text:'Шаг 3. По признаку «угол–сторона–угол» (или двум катетам): $\\triangle ABC=\\triangle BAD$.', h:'both7'},
+ {text:'Вывод. $AC=BD$ — диагонали прямоугольника равны. $\\square$', h:'both7'},
+ ];
+ let step=0;
+ function draw(h){
+ let s='';
+ document.getElementById('p7-proof-svg').innerHTML=s;
+ }
+ function show(){ const st=steps[step]; document.getElementById('p7-proof-step').innerHTML=st.text; renderMath(document.getElementById('p7-proof-step')); draw(st.h); document.getElementById('p7-proof-next').textContent=step{ if(step{step=0;show();document.getElementById('p7-proof-next').disabled=false;});
+ show();
+ })();
+
+ /* == Калькулятор диагонали == */
+ (function(){
+ function calc(){
+ const a=+document.getElementById('p7-ca').value, b=+document.getElementById('p7-cb').value;
+ if(a<=0||b<=0||isNaN(a)||isNaN(b)){ document.getElementById('p7-calc-out').innerHTML='Введи положительные числа.'; return; }
+ const d=Math.sqrt(a*a+b*b);
+ const dStr=Number.isInteger(d)?String(d):d.toFixed(4).replace(/0+$/,'');
+ document.getElementById('p7-calc-out').innerHTML=`$d = \\sqrt{a^2+b^2} = \\sqrt{${a}^2+${b}^2} = \\sqrt{${a*a}+${b*b}} = \\sqrt{${a*a+b*b}}$
$d = ${dStr}$`;
+ renderMath(document.getElementById('p7-calc-out'));
+ addXp(2,'p7-calc');
+ }
+ document.getElementById('p7-calc-go').addEventListener('click',calc);
+ document.getElementById('p7-ca').addEventListener('keydown',e=>{if(e.key==='Enter')calc();});
+ document.getElementById('p7-cb').addEventListener('keydown',e=>{if(e.key==='Enter')calc();});
+ calc();
+ })();
+
+ /* == Тренажёр == */
+ (function(){
+ const tasks=[
+ {q:'Стороны прямоугольника $a=6$, $b=8$. Найди диагональ.', ans:10, hint:'d=√(36+64)=√100=10'},
+ {q:'Диагональ прямоугольника $d=13$, сторона $a=5$. Найди $b$.', ans:12, hint:'b=√(169-25)=√144=12'},
+ {q:'Периметр прямоугольника $P=20$, сторона $a=3$. Найди площадь $S$.', ans:21, hint:'b=P/2-a=10-3=7, S=3·7=21'},
+ {q:'В прямоугольнике $\\angle A=90°$. Найди $\\angle B$.', ans:90, hint:'Все углы прямоугольника = 90°'},
+ {q:'Стороны прямоугольника $a=9$, $b=12$. Найди диагональ.', ans:15, hint:'d=√(81+144)=√225=15'},
+ ];
+ let idx=0,score=0;
+ function show(){ document.getElementById('p7-tr-i').textContent=idx+1; document.getElementById('p7-tr-task').innerHTML=tasks[idx].q; renderMath(document.getElementById('p7-tr-task')); 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',()=>{
+ const ans=+document.getElementById('p7-tr-ans').value; const fb=document.getElementById('p7-tr-fb');
+ if(ans===tasks[idx].ans){ score++;document.getElementById('p7-tr-score').textContent=score;addXp(3,'p7-train');bumpProgress('p7',5); if(idxshow(),900);}else{feedback(fb,true,'Все задачи! +5 XP');addXp(5,'p7-train-all');} }
+ 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();
+ })();
+
+ /* == DnD == */
+ (function(){
+ const items=[
+ {id:'sq',html:'Квадрат', ans:'yes'},
+ {id:'rect',html:'Параллелограмм с углом 90°', ans:'yes'},
+ {id:'rhm',html:'Ромб с углом 90°', ans:'yes'},
+ {id:'pgr',html:'Произвольный параллелограмм (угол ≠ 90°)', ans:'no'},
+ {id:'trap',html:'Трапеция', ans:'no'},
+ {id:'rhm2',html:'Ромб с углом 60°', ans:'no'},
+ ];
+ const sorter=setupSorter({poolId:'p7-dnd-pool',scopeSelector:'#p7-dnd-wrap',items,cats:['yes','no']});
+ document.getElementById('p7-dnd-reset').addEventListener('click',()=>{sorter.reset();document.getElementById('p7-dnd-fb').style.display='none';});
+ document.getElementById('p7-dnd-check').addEventListener('click',()=>{
+ let ok=0; items.forEach(it=>{if(sorter.placed[it.id]===it.ans)ok++;});
+ const fb=document.getElementById('p7-dnd-fb');
+ if(ok===items.length){feedback(fb,true,'Все верно! +5 XP');addXp(5,'p7-dnd');bumpProgress('p7',15);}
+ else feedback(fb,false,'Верно: '+ok+' из '+items.length+'. Квадрат — тоже прямоугольник!');
+ });
+ })();
+
+ /* == Босс §7 == */
+ (function(){
+ const tasks=[
+ {q:'Стороны прямоугольника $a=5$, $b=12$. Найди диагональ.', ans:13, hint:'d=√(25+144)=√169=13'},
+ {q:'В прямоугольнике диагональ $d=10$, сторона $a=6$. Найди вторую сторону $b$.', ans:8, hint:'b=√(100-36)=√64=8'},
+ {q:'Периметр прямоугольника равен $34$, одна сторона $= 7$. Найди площадь.', ans:70, hint:'b=17-7=10, S=7·10=70'},
+ {q:'Все углы прямоугольника. Чему равна сумма всех углов прямоугольника?', ans:360, hint:'4·90°=360°'},
+ ];
+ const bossBox=document.getElementById('p7-boss-tasks');
+ bossBox.innerHTML=tasks.map((t,i)=>`
+
+
${t.q}
+
+
+
+
+
+
`).join('');
+ window.p7BossSolved=new Set();
+ })();
+ renderMath(box);
+}
+function buildP8(){
+ const box = document.getElementById('p8-body');
+ let html = '';
+
+ html += makeCard('theory','Признак прямоугольника','8.1',`
+ Теорема. Если у параллелограмма диагонали равны, то он является прямоугольником.
+ Доказательство. Пусть в параллелограмме $ABCD$ дано $AC=BD$. Рассмотрим $\\triangle ABD$ и $\\triangle BAC$:
+
+ - $AB=BA$ — общая сторона
+ - $AD=BC$ — противоположные стороны параллелограмма
+ - $BD=AC$ — по условию
+
+ По признаку «три стороны»: $\\triangle ABD=\\triangle BAC$. Следовательно, $\\angle DAB=\\angle CBA$.
+ Но $\\angle DAB+\\angle CBA=180°$ (смежные в параллелограмме). Значит $\\angle DAB=\\angle CBA=90°$. Параллелограмм — прямоугольник. $\\square$
`);
+
+ /* --- INTERACTIVE 1: SVG-демонстрация признака --- */
+ html += `
+
+
Тащи вершину D. Когда диагонали сравняются — оба индикатора загорятся зелёным.
+
+
+
`;
+
+ /* --- INTERACTIVE 2: Пошаговое доказательство --- */
+ html += `
+
+
+
+
+
+
+
+
`;
+
+ /* --- INTERACTIVE 3: Mini-quiz --- */
+ html += `
+
+
Для каждого утверждения выбери «Верно» или «Неверно».
+
+
`;
+
+ /* --- INTERACTIVE 4: Тренажёр --- */
+ html += `
+
+
Задача 1 / 4Очки: 0
+
+
+
+
+
+
+
+
`;
+
+ /* --- INTERACTIVE 5: Босс §8 --- */
+ html += `
+
+
+5 XP за каждую верную задачу.
+
+
`;
+
+ html += `
+
+
`;
+
+ html += secNav('p7','p9');
+ box.innerHTML = html;
+
+ /* == SVG-демонстрация признака == */
+ (function(){
+ const W=380, H=280;
+ let A={x:55,y:215}, B={x:215,y:215}, D={x:100,y:85};
+ function getC(){ return {x:D.x+(B.x-A.x),y:D.y+(B.y-A.y)}; }
+ function dist(a,b){ return Math.hypot(b.x-a.x,b.y-a.y); }
+ function redraw(){
+ const C=getC(); const pts=[A,B,C,D]; const labels=['A','B','C','D'];
+ const cx=(A.x+B.x+C.x+D.x)/4,cy=(A.y+B.y+C.y+D.y)/4;
+ const ac=dist(A,C), bd=dist(B,D);
+ const eq=Math.abs(ac-bd)<4;
+ const col=eq?'#10b981':'#2563eb';
+ let s='';
+ const wrap=document.getElementById('p8-demo-svg');
+ wrap.innerHTML=s;
+ const svgEl=wrap.querySelector('svg');
+ svgEl.querySelectorAll('.p8-vh').forEach(el=>{
+ el.style.cursor='grab';
+ el.addEventListener('pointerdown',ev=>{
+ if(ev.button!==undefined&&ev.button!==0)return;
+ try{el.setPointerCapture(ev.pointerId);}catch(e){}
+ function onMove(e){ const rect=svgEl.getBoundingClientRect(); const sx=W/rect.width,sy=H/rect.height; D={x:Math.max(10,Math.min(W-10,(e.clientX-rect.left)*sx)),y:Math.max(10,Math.min(H-10,(e.clientY-rect.top)*sy))}; redraw(); }
+ function onUp(){ el.removeEventListener('pointermove',onMove);el.removeEventListener('pointerup',onUp);el.removeEventListener('pointercancel',onUp); }
+ el.addEventListener('pointermove',onMove); el.addEventListener('pointerup',onUp); el.addEventListener('pointercancel',onUp);
+ });
+ });
+ const okCol=eq?'#10b981':'#94a3b8';
+ document.getElementById('p8-demo-indicators').innerHTML=`
+ Диагонали равны: ${eq?'ДА':'НЕТ'} (AC=${ac.toFixed(1)}, BD=${bd.toFixed(1)})
+ Прямоугольник: ${eq?'ДА':'НЕТ'}
`;
+ }
+ redraw();
+ })();
+
+ /* == Доказательство == */
+ (function(){
+ const A={x:40,y:155},B={x:230,y:155},C={x:265,y:55},D={x:75,y:55};
+ const cx=(A.x+B.x+C.x+D.x)/4,cy=(A.y+B.y+C.y+D.y)/4;
+ const steps=[
+ {text:'Дано: $ABCD$ — параллелограмм, $AC=BD$. Доказать: $\\angle DAB=90°$.', h:''},
+ {text:'Шаг 1. Рассмотрим $\\triangle ABD$ и $\\triangle BAC$: $AB=BA$ (общая), $AD=BC$ (стороны ||грамма), $BD=AC$ (по условию).', h:'t1'},
+ {text:'Шаг 2. По признаку «три стороны»: $\\triangle ABD=\\triangle BAC$.', h:'t2'},
+ {text:'Шаг 3. Следовательно $\\angle DAB=\\angle CBA$. Но они смежные в параллелограмме: $\\angle DAB+\\angle CBA=180°$.', h:'t2'},
+ {text:'Вывод. $2\\angle DAB=180°$, $\\angle DAB=90°$. $ABCD$ — прямоугольник. $\\square$', h:'t2'},
+ ];
+ let step=0;
+ function draw(h){
+ let s='';
+ document.getElementById('p8-proof-svg').innerHTML=s;
+ }
+ function show(){ const st=steps[step]; document.getElementById('p8-proof-step').innerHTML=st.text; renderMath(document.getElementById('p8-proof-step')); draw(st.h); document.getElementById('p8-proof-next').textContent=step{ if(step{step=0;show();document.getElementById('p8-proof-next').disabled=false;});
+ show();
+ })();
+
+ /* == Mini-quiz == */
+ (function(){
+ const items=[
+ {text:'Параллелограмм с равными диагоналями — прямоугольник.', ans:true},
+ {text:'У любого параллелограмма диагонали равны.', ans:false},
+ {text:'Прямоугольник — частный случай параллелограмма.', ans:true},
+ {text:'Ромб с равными диагоналями является квадратом.', ans:true},
+ ];
+ const solved=new Set();
+ document.getElementById('p8-quiz-list').innerHTML=items.map((it,i)=>`
+
+
${it.text}
+
+
+
+
+
+
`).join('');
+ window.p8QuizCheck=function(i,v){
+ const it=items[i]; const fb=document.getElementById('p8-qi-fb-'+i);
+ if(v===it.ans){ feedback(fb,true,'Верно! +3 XP'); if(!solved.has(i)){solved.add(i);addXp(3,'p8-quiz'+i);bumpProgress('p8',6);} }
+ else feedback(fb,false,'Неверно. '+( it.ans?'Утверждение истинно.':'Утверждение ложно.'));
+ };
+ })();
+
+ /* == Тренажёр == */
+ (function(){
+ const tasks=[
+ {q:'В параллелограмме $AC=14$, $BD=14$. Прямоугольник? Введи 1 (да) или 0 (нет).', ans:1, hint:'Признак: равные диагонали → прямоугольник'},
+ {q:'В параллелограмме $AC=10$, $BD=12$. Прямоугольник? Введи 1 (да) или 0 (нет).', ans:0, hint:'Диагонали не равны → не прямоугольник'},
+ {q:'В прямоугольнике $a=8$, $b=15$. Найди диагональ.', ans:17, hint:'d=√(64+225)=√289=17'},
+ {q:'В прямоугольнике диагональ $d=25$, сторона $a=7$. Найди $b$.', ans:24, hint:'b=√(625-49)=√576=24'},
+ ];
+ let idx=0,score=0;
+ function show(){ document.getElementById('p8-tr-i').textContent=idx+1; document.getElementById('p8-tr-task').innerHTML=tasks[idx].q; renderMath(document.getElementById('p8-tr-task')); document.getElementById('p8-tr-ans').value=''; document.getElementById('p8-tr-fb').style.display='none'; }
+ 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',()=>{
+ const ans=+document.getElementById('p8-tr-ans').value; const fb=document.getElementById('p8-tr-fb');
+ if(ans===tasks[idx].ans){ score++;document.getElementById('p8-tr-score').textContent=score;addXp(3,'p8-train');bumpProgress('p8',5); if(idxshow(),900);}else{feedback(fb,true,'Все задачи! +5 XP');addXp(5,'p8-train-all');} }
+ 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();
+ })();
+
+ /* == Босс §8 == */
+ (function(){
+ const tasks=[
+ {q:'У параллелограмма диагонали $AC=BD=20$. Прямоугольник? (1=да, 0=нет)', ans:1, hint:'Признак: равные диагонали'},
+ {q:'В прямоугольнике $a=3$, $b=4$. Найди $d$.', ans:5, hint:'d=√(9+16)=5'},
+ {q:'В прямоугольнике $d=26$, $a=10$. Найди $b$.', ans:24, hint:'b=√(676-100)=√576=24'},
+ {q:'Периметр прямоугольника $P=26$, $a=5$. Найди $d$.', ans:13, hint:'b=13-5=8, d=√(25+64)=√169=13'},
+ ];
+ const bossBox=document.getElementById('p8-boss-tasks');
+ bossBox.innerHTML=tasks.map((t,i)=>`
+
+
${t.q}
+
+
+
+
+
+
`).join('');
+ window.p8BossSolved=new Set();
+ })();
+ renderMath(box);
+}
+function buildP9(){
+ const box = document.getElementById('p9-body');
+ let html = '';
+
+ html += makeCard('theory','Ромб — определение и свойства','9.1',`
+ Ромб — параллелограмм, у которого все стороны равны: $AB=BC=CD=DA$.
+ Свойство диагоналей ромба:
+
+ - Диагонали ромба взаимно перпендикулярны: $AC \\perp BD$.
+ - Каждая диагональ является биссектрисой соответствующих углов.
+ - Диагонали точкой пересечения делятся пополам (как в любом параллелограмме).
+
`);
+
+ html += makeCard('rule','Доказательство: диагонали ромба перпендикулярны','9.2',`
+ Рассмотрим $\\triangle AOB$ и $\\triangle COB$, где $O$ — точка пересечения диагоналей.
+ $AO=OC$ (диагональ делится пополам), $OB=OB$ (общая), $AB=CB$ (стороны ромба).
+ По признаку «три стороны»: $\\triangle AOB=\\triangle COB$. Следовательно, $\\angle AOB=\\angle COB$.
+ Но $\\angle AOB+\\angle COB=180°$ (смежные). Значит $\\angle AOB=90°$, т.е. $AC\\perp BD$. $\\square$
`);
+
+ html += makeCard('rule','Признаки ромба','9.3',`
+ Признак 1. Если у параллелограмма диагонали взаимно перпендикулярны, то он является ромбом.
+ Признак 2. Если у параллелограмма диагональ является биссектрисой угла, то он является ромбом.
+ Площадь ромба: $S = \\dfrac{d_1 \\cdot d_2}{2}$, где $d_1$, $d_2$ — диагонали.
+ Также: $S = a^2 \\sin\\alpha$, где $a$ — сторона, $\\alpha$ — угол ромба.
`);
+
+ /* --- INTERACTIVE 1: SVG-ромб с draggable вершиной --- */
+ html += `
+
+
Тащи вершину B или D. Все стороны остаются равными, диагонали — всегда перпендикулярны.
+
+
+
`;
+
+ /* --- INTERACTIVE 2: Пошаговое доказательство --- */
+ html += `
+
+
+
+
+
+
+
+
`;
+
+ /* --- INTERACTIVE 3: Калькулятор площади ромба --- */
+ html += `
+
+
Введи диагонали — получи площадь и сторону ромба.
+
+
+
+
+
+
+
`;
+
+ /* --- INTERACTIVE 4: DnD — свойства ромба, прямоугольника, параллелограмма --- */
+ html += `
+
+
Разложи свойства: только ромба, только прямоугольника, или любого параллелограмма.
+ ${DND_HINT_HTML}
+
+
+
+
+
`;
+
+ /* --- INTERACTIVE 5: Тренажёр --- */
+ html += `
+
+
Задача 1 / 5Очки: 0
+
+
+
+
+
+
+
+
`;
+
+ /* --- INTERACTIVE 6: Босс §9 --- */
+ html += `
+
+
+5 XP за каждую верную задачу.
+
+
`;
+
+ html += `
+
+
`;
+
+ html += secNav('p8','p10');
+ box.innerHTML = html;
+
+ /* == SVG-ромб == */
+ (function(){
+ const W=360, H=300, cx=180, cy=150;
+ let half1=110, half2=70; // half-diagonals
+ let dragV=null;
+ function getVerts(h1,h2){ return {A:{x:cx-h1,y:cy},B:{x:cx,y:cy-h2},C:{x:cx+h1,y:cy},D:{x:cx,y:cy+h2}}; }
+ function dist(a,b){ return Math.hypot(b.x-a.x,b.y-a.y); }
+ function angDeg(O,P,Q){ const ax=P.x-O.x,ay=P.y-O.y,bx=Q.x-O.x,by=Q.y-O.y; return Math.acos(Math.max(-1,Math.min(1,(ax*bx+ay*by)/(Math.hypot(ax,ay)*Math.hypot(bx,by)))))*180/Math.PI; }
+ function redraw(){
+ const {A,B,C,D}=getVerts(half1,half2);
+ const side=dist(A,B);
+ const angA=angDeg(A,D,B)*2;
+ let s='';
+ const wrap=document.getElementById('p9-rhombus-svg'); wrap.innerHTML=s;
+ const svgEl=wrap.querySelector('svg');
+ svgEl.querySelectorAll('.p9-vh').forEach(el=>{
+ el.style.cursor='grab';
+ el.addEventListener('pointerdown',ev=>{
+ if(ev.button!==undefined&&ev.button!==0)return;
+ const vname=el.dataset.v;
+ try{el.setPointerCapture(ev.pointerId);}catch(e){}
+ function onMove(e){ const rect=svgEl.getBoundingClientRect(); const sx=W/rect.width,sy=H/rect.height; const nx=(e.clientX-rect.left)*sx; const ny=(e.clientY-rect.top)*sy; if(vname==='B'){ half2=Math.max(20,Math.min(H/2-10,cy-ny)); } else if(vname==='D'){ half2=Math.max(20,Math.min(H/2-10,ny-cy)); } else if(vname==='A'){ half1=Math.max(20,Math.min(W/2-10,cx-nx)); } else if(vname==='C'){ half1=Math.max(20,Math.min(W/2-10,nx-cx)); } redraw(); }
+ function onUp(){ el.removeEventListener('pointermove',onMove);el.removeEventListener('pointerup',onUp);el.removeEventListener('pointercancel',onUp); }
+ el.addEventListener('pointermove',onMove); el.addEventListener('pointerup',onUp); el.addEventListener('pointercancel',onUp);
+ });
+ });
+ const {A:A2,B:B2}=getVerts(half1,half2); const side2=dist(A2,B2);
+ const S=half1*half2*2;
+ document.getElementById('p9-rhombus-info').innerHTML=`
+ Сторона AB=BC=CD=DA
${side2.toFixed(1)}
+ Диагональ AC
${(half1*2).toFixed(1)}
+ Диагональ BD
${(half2*2).toFixed(1)}
+
+ Площадь S = d₁d₂/2
${S.toFixed(1)} `;
+ }
+ redraw();
+ })();
+
+ /* == Доказательство == */
+ (function(){
+ const cx=150,cy=110;
+ const A={x:cx-100,y:cy},B={x:cx,y:cy-70},C={x:cx+100,y:cy},D={x:cx,y:cy+70};
+ const O={x:cx,y:cy};
+ const steps=[
+ {text:'Дано: $ABCD$ — ромб (все стороны равны). $O$ — точка пересечения диагоналей. Доказать: $AC\\perp BD$.', h:''},
+ {text:'Шаг 1. Рассмотрим $\\triangle AOB$ и $\\triangle COB$. $AO=OC$ (диагональ делится пополам), $OB=OB$ (общая), $AB=CB$ (стороны ромба).', h:'tri'},
+ {text:'Шаг 2. По признаку «три стороны»: $\\triangle AOB=\\triangle COB$.', h:'tri'},
+ {text:'Шаг 3. $\\angle AOB=\\angle COB$. Но $\\angle AOB+\\angle COB=180°$ (смежные). Значит $\\angle AOB=90°$.', h:'right'},
+ {text:'Вывод. $AC\\perp BD$ — диагонали ромба взаимно перпендикулярны. $\\square$', h:'right'},
+ ];
+ let step=0;
+ function draw(h){
+ let s='';
+ document.getElementById('p9-proof-svg').innerHTML=s;
+ }
+ function show(){ const st=steps[step]; document.getElementById('p9-proof-step').innerHTML=st.text; renderMath(document.getElementById('p9-proof-step')); draw(st.h); document.getElementById('p9-proof-next').textContent=step{ if(step{step=0;show();document.getElementById('p9-proof-next').disabled=false;});
+ show();
+ })();
+
+ /* == Калькулятор площади ромба == */
+ (function(){
+ function calc(){
+ const d1=+document.getElementById('p9-cd1').value, d2=+document.getElementById('p9-cd2').value;
+ if(d1<=0||d2<=0||isNaN(d1)||isNaN(d2)){ document.getElementById('p9-calc-out').innerHTML='Введи положительные числа.'; return; }
+ const S=d1*d2/2;
+ const side=Math.sqrt((d1/2)*(d1/2)+(d2/2)*(d2/2));
+ const sideStr=Number.isInteger(side)?String(side):side.toFixed(4).replace(/0+$/,'');
+ document.getElementById('p9-calc-out').innerHTML=`$S = \\dfrac{d_1 \\cdot d_2}{2} = \\dfrac{${d1} \\cdot ${d2}}{2} = ${S}$
Сторона: $a = \\sqrt{\\left(\\dfrac{d_1}{2}\\right)^2+\\left(\\dfrac{d_2}{2}\\right)^2} = \\sqrt{${d1/2}^2+${d2/2}^2} = ${sideStr}$`;
+ renderMath(document.getElementById('p9-calc-out'));
+ addXp(2,'p9-calc');
+ }
+ document.getElementById('p9-calc-go').addEventListener('click',calc);
+ calc();
+ })();
+
+ /* == DnD == */
+ (function(){
+ const items=[
+ {id:'pr1',html:'Противоположные стороны равны', ans:'any'},
+ {id:'pr2',html:'Диагонали делятся пополам', ans:'any'},
+ {id:'pr3',html:'Сумма соседних углов 180°', ans:'any'},
+ {id:'re1',html:'Все углы 90°', ans:'rect'},
+ {id:'re2',html:'Диагонали равны', ans:'rect'},
+ {id:'rh1',html:'Все стороны равны', ans:'rhm'},
+ {id:'rh2',html:'Диагонали перпендикулярны', ans:'rhm'},
+ {id:'rh3',html:'Диагонали — биссектрисы углов', ans:'rhm'},
+ ];
+ const sorter=setupSorter({poolId:'p9-dnd-pool',scopeSelector:'#p9-dnd-wrap',items,cats:['any','rect','rhm']});
+ document.getElementById('p9-dnd-reset').addEventListener('click',()=>{sorter.reset();document.getElementById('p9-dnd-fb').style.display='none';});
+ document.getElementById('p9-dnd-check').addEventListener('click',()=>{
+ let ok=0; items.forEach(it=>{if(sorter.placed[it.id]===it.ans)ok++;});
+ const fb=document.getElementById('p9-dnd-fb');
+ if(ok===items.length){feedback(fb,true,'Все верно! +5 XP');addXp(5,'p9-dnd');bumpProgress('p9',15);}
+ else feedback(fb,false,'Верно: '+ok+' из '+items.length+'.');
+ });
+ })();
+
+ /* == Тренажёр == */
+ (function(){
+ const tasks=[
+ {q:'Диагонали ромба $d_1=10$, $d_2=24$. Найди сторону ромба.', ans:13, hint:'a=√(5²+12²)=√169=13'},
+ {q:'Диагонали ромба $d_1=10$, $d_2=24$. Найди площадь.', ans:120, hint:'S=10·24/2=120'},
+ {q:'Периметр ромба $P=40$, диагональ $d_1=12$. Найди вторую диагональ $d_2$.', ans:16, hint:'a=10, d2=2√(100-36)=2·8=16'},
+ {q:'Угол между диагоналями ромба (в градусах)?', ans:90, hint:'Диагонали ромба всегда ⊥'},
+ {q:'Площадь ромба $d_1=6$, $d_2=8$. Чему равна площадь?', ans:24, hint:'S=6·8/2=24'},
+ ];
+ let idx=0,score=0;
+ function show(){ document.getElementById('p9-tr-i').textContent=idx+1; document.getElementById('p9-tr-task').innerHTML=tasks[idx].q; renderMath(document.getElementById('p9-tr-task')); document.getElementById('p9-tr-ans').value=''; document.getElementById('p9-tr-fb').style.display='none'; }
+ document.getElementById('p9-tr-start').addEventListener('click',()=>{idx=0;score=0;document.getElementById('p9-tr-score').textContent=0;show();});
+ document.getElementById('p9-tr-go').addEventListener('click',()=>{
+ const ans=+document.getElementById('p9-tr-ans').value; const fb=document.getElementById('p9-tr-fb');
+ if(ans===tasks[idx].ans){ score++;document.getElementById('p9-tr-score').textContent=score;addXp(3,'p9-train');bumpProgress('p9',5); if(idxshow(),900);}else{feedback(fb,true,'Все задачи! +5 XP');addXp(5,'p9-train-all');} }
+ else feedback(fb,false,'Неверно. Подсказка: '+tasks[idx].hint);
+ });
+ document.getElementById('p9-tr-ans').addEventListener('keydown',e=>{if(e.key==='Enter')document.getElementById('p9-tr-go').click();});
+ show();
+ })();
+
+ /* == Босс §9 == */
+ (function(){
+ const tasks=[
+ {q:'Диагонали ромба $d_1=16$, $d_2=12$. Найди сторону.', ans:10, hint:'a=√(8²+6²)=√100=10'},
+ {q:'Диагонали ромба $d_1=16$, $d_2=12$. Найди площадь.', ans:96, hint:'S=16·12/2=96'},
+ {q:'Сторона ромба $a=10$, одна диагональ $d_1=12$. Найди вторую диагональ $d_2$.', ans:16, hint:'d2=2√(100-36)=2·8=16'},
+ {q:'Периметр ромба $P=52$. Найди сторону.', ans:13, hint:'a=P/4=52/4=13'},
+ ];
+ const bossBox=document.getElementById('p9-boss-tasks');
+ bossBox.innerHTML=tasks.map((t,i)=>`
+
+
${t.q}
+
+
+
+
+
+
`).join('');
+ window.p9BossSolved=new Set();
+ })();
+ renderMath(box);
+}
+function buildP10(){
+ const box = document.getElementById('p10-body');
+ let html = '';
+
+ html += makeCard('theory','Квадрат — определение','10.1',`
+ Квадрат — прямоугольник, у которого все стороны равны.
+ Эквивалентно: квадрат — это ромб с прямыми углами.
+ Таким образом, квадрат одновременно является:
+
+ - Параллелограммом
+ - Прямоугольником
+ - Ромбом
+
`);
+
+ html += makeCard('rule','Свойства квадрата','10.2',`
+ В квадрате со стороной $a$:
+
+ - Все стороны равны: $AB=BC=CD=DA=a$
+ - Все углы прямые: $\\angle A=\\angle B=\\angle C=\\angle D=90°$
+ - Диагонали равны: $AC=BD=a\\sqrt{2}$
+ - Диагонали взаимно перпендикулярны: $AC\\perp BD$
+ - Диагонали делятся пополам и делят углы пополам
+ - Площадь: $S=a^2$
+ - Периметр: $P=4a$
+
`);
+
+ html += makeCard('example','Формулы квадрата','10.3',`
+ $a$ — сторона, $d$ — диагональ, $P$ — периметр, $S$ — площадь:
+ \\[d = a\\sqrt{2} \\qquad a = \\dfrac{d}{\\sqrt{2}} = \\dfrac{d\\sqrt{2}}{2}\\]
+ \\[P = 4a \\qquad S = a^2 = \\dfrac{d^2}{2}\\]`);
+
+ /* --- INTERACTIVE 1: SVG-квадрат со слайдером --- */
+ html += `
+
+
Меняй сторону слайдером — все свойства обновляются мгновенно.
+
+
+
+
`;
+
+ /* --- INTERACTIVE 2: Иерархия фигур --- */
+ html += `
+
+
Нажимай на фигуры — увидишь, какие свойства ей принадлежат.
+
+
+
+
+
+
+
+
`;
+
+ /* --- INTERACTIVE 3: Калькулятор квадрата --- */
+ html += `
+
+
Введи сторону или диагональ — получи все остальные значения.
+
+
+
+
+
+
+
`;
+
+ /* --- INTERACTIVE 4: DnD — категоризация фигур --- */
+ html += `
+
+
Для каждой фигуры выбери самое точное название (квадрат → квадрат, не «прямоугольник»).
+ ${DND_HINT_HTML}
+
+
+
+
+
`;
+
+ /* --- INTERACTIVE 5: Тренажёр --- */
+ html += `
+
+
Задача 1 / 5Очки: 0
+
+
+
+
+
+
+
+
`;
+
+ /* --- INTERACTIVE 6: Босс §10 --- */
+ html += `
+
+
+5 XP за каждую верную задачу.
+
+
`;
+
+ html += `
+
+
`;
+
+ html += secNav('p9','p11');
+ box.innerHTML = html;
+
+ /* == SVG-квадрат со слайдером == */
+ (function(){
+ const W=300, H=300, cx=150, cy=150;
+ function redraw(){
+ const sl=document.getElementById('p10-sq-sl');
+ const a=+sl.value;
+ document.getElementById('p10-sq-aval').textContent=a;
+ const half=a/2;
+ const A={x:cx-half,y:cy+half},B={x:cx+half,y:cy+half},C={x:cx+half,y:cy-half},D={x:cx-half,y:cy-half};
+ const d=a*Math.sqrt(2);
+ let s='';
+ document.getElementById('p10-sq-svg').innerHTML=s;
+ const dStr=(d%1===0)?String(d):d.toFixed(4).replace(/0+$/,'');
+ document.getElementById('p10-sq-info').innerHTML=`
+
+
+
+ `;
+ }
+ document.getElementById('p10-sq-sl').addEventListener('input',redraw);
+ redraw();
+ })();
+
+ /* == Иерархия == */
+ (function(){
+ const data={
+ pg:{label:'Параллелограмм',props:['Противоположные стороны попарно параллельны','Противоположные стороны равны ($AB=CD$, $BC=AD$)','Противоположные углы равны','Сумма соседних углов $= 180°$','Диагонали делятся пополам']},
+ re:{label:'Прямоугольник',props:['Все свойства параллелограмма','Все углы прямые ($90°$)','Диагонали равны ($AC=BD$)']},
+ rh:{label:'Ромб',props:['Все свойства параллелограмма','Все стороны равны','Диагонали взаимно перпендикулярны','Диагонали делят углы пополам']},
+ sq:{label:'Квадрат',props:['Все свойства параллелограмма','Все стороны равны','Все углы прямые','Диагонали равны $d=a\\sqrt{2}$','Диагонали взаимно перпендикулярны','Диагонали делят углы пополам по $45°$','$S=a^2$, $P=4a$']},
+ };
+ function show(k){
+ const d=data[k];
+ document.getElementById('p10-hier-out').innerHTML=''+d.label+':'+d.props.map(p=>'- '+p+'
').join('')+'
';
+ renderMath(document.getElementById('p10-hier-out'));
+ Object.keys(data).forEach(kk=>{ const btn=document.getElementById('p10-hier-'+kk); btn.className='btn'+(kk===k?' primary':''); });
+ }
+ ['pg','re','rh','sq'].forEach(k=>document.getElementById('p10-hier-'+k).addEventListener('click',()=>show(k)));
+ show('sq');
+ })();
+
+ /* == Калькулятор квадрата == */
+ (function(){
+ function calc(){
+ let a=+document.getElementById('p10-ca').value;
+ const dInp=+document.getElementById('p10-cd').value;
+ if(dInp>0){ a=dInp/Math.sqrt(2); }
+ if(a<=0||isNaN(a)){ document.getElementById('p10-calc-out').innerHTML='Введи положительное значение.'; return; }
+ const d=a*Math.sqrt(2), P=4*a, S=a*a;
+ const fmt2=x=>Number.isInteger(x)?String(x):x.toFixed(4).replace(/0+$/,'');
+ document.getElementById('p10-calc-out').innerHTML=`$a = ${fmt2(a)}$
$P = 4a = ${fmt2(P)}$
$S = a^2 = ${fmt2(S)}$
$d = a\\sqrt{2} = ${fmt2(d)}$`;
+ renderMath(document.getElementById('p10-calc-out'));
+ addXp(2,'p10-calc');
+ }
+ document.getElementById('p10-calc-go').addEventListener('click',calc);
+ calc();
+ })();
+
+ /* == DnD == */
+ (function(){
+ const items=[
+ {id:'f1',html:'Параллелограмм с углом 60° и сторонами 5 и 8', ans:'pg'},
+ {id:'f2',html:'Параллелограмм, у которого все углы 90°, стороны 4 и 7', ans:'re'},
+ {id:'f3',html:'Параллелограмм, все стороны = 6, угол 120°', ans:'rh'},
+ {id:'f4',html:'Параллелограмм, все стороны = 5, все углы 90°', ans:'sq'},
+ {id:'f5',html:'Прямоугольник со сторонами 3 и 3', ans:'sq'},
+ {id:'f6',html:'Ромб с углом 90°', ans:'sq'},
+ ];
+ const sorter=setupSorter({poolId:'p10-dnd-pool',scopeSelector:'#p10-dnd-wrap',items,cats:['pg','re','rh','sq']});
+ document.getElementById('p10-dnd-reset').addEventListener('click',()=>{sorter.reset();document.getElementById('p10-dnd-fb').style.display='none';});
+ document.getElementById('p10-dnd-check').addEventListener('click',()=>{
+ let ok=0; items.forEach(it=>{if(sorter.placed[it.id]===it.ans)ok++;});
+ const fb=document.getElementById('p10-dnd-fb');
+ if(ok===items.length){feedback(fb,true,'Все верно! +5 XP');addXp(5,'p10-dnd');bumpProgress('p10',15);}
+ else feedback(fb,false,'Верно: '+ok+' из '+items.length+'. Подсказка: квадрат — ромб с прямыми углами.');
+ });
+ })();
+
+ /* == Тренажёр == */
+ (function(){
+ const tasks=[
+ {q:'Сторона квадрата $a=7$. Найди периметр.', ans:28, hint:'P=4·7=28'},
+ {q:'Сторона квадрата $a=9$. Найди площадь.', ans:81, hint:'S=9²=81'},
+ {q:'Площадь квадрата $S=49$. Найди сторону.', ans:7, hint:'a=√49=7'},
+ {q:'Сторона квадрата $a=5$. Найди диагональ (округли до целого).', ans:7, hint:'d=5√2≈7.07≈7'},
+ {q:'Периметр квадрата $P=36$. Найди сторону.', ans:9, hint:'a=P/4=36/4=9'},
+ ];
+ let idx=0,score=0;
+ function show(){ document.getElementById('p10-tr-i').textContent=idx+1; document.getElementById('p10-tr-task').innerHTML=tasks[idx].q; renderMath(document.getElementById('p10-tr-task')); document.getElementById('p10-tr-ans').value=''; document.getElementById('p10-tr-fb').style.display='none'; }
+ document.getElementById('p10-tr-start').addEventListener('click',()=>{idx=0;score=0;document.getElementById('p10-tr-score').textContent=0;show();});
+ document.getElementById('p10-tr-go').addEventListener('click',()=>{
+ const ans=+document.getElementById('p10-tr-ans').value; const fb=document.getElementById('p10-tr-fb');
+ if(ans===tasks[idx].ans){ score++;document.getElementById('p10-tr-score').textContent=score;addXp(3,'p10-train');bumpProgress('p10',5); if(idxshow(),900);}else{feedback(fb,true,'Все задачи! +5 XP');addXp(5,'p10-train-all');} }
+ else feedback(fb,false,'Неверно. Подсказка: '+tasks[idx].hint);
+ });
+ document.getElementById('p10-tr-ans').addEventListener('keydown',e=>{if(e.key==='Enter')document.getElementById('p10-tr-go').click();});
+ show();
+ })();
+
+ /* == Босс §10 == */
+ (function(){
+ const tasks=[
+ {q:'Диагональ квадрата $d=10\\sqrt{2}$. Найди сторону.', ans:10, hint:'a=d/√2=10√2/√2=10'},
+ {q:'Площадь квадрата $S=144$. Найди периметр.', ans:48, hint:'a=12, P=4·12=48'},
+ {q:'Периметр квадрата $P=32$. Найди площадь.', ans:64, hint:'a=8, S=64'},
+ {q:'Сторона квадрата $a=10$. Найди площадь.', ans:100, hint:'S=10²=100'},
+ ];
+ const bossBox=document.getElementById('p10-boss-tasks');
+ bossBox.innerHTML=tasks.map((t,i)=>`
+
+
${t.q}
+
+
+
+
+
+
`).join('');
+ window.p10BossSolved=new Set();
+ })();
+ renderMath(box);
+}
function buildP11stub(){ document.getElementById('p11-body').innerHTML = '§11 — Волна 1: содержимое появится в следующем обновлении.
' + secNav('p10','p12'); }
function buildP12stub(){ document.getElementById('p12-body').innerHTML = '§12 — Волна 1: содержимое появится в следующем обновлении.
' + secNav('p11','p13'); }
function buildP13stub(){ document.getElementById('p13-body').innerHTML = '§13 — Волна 1: содержимое появится в следующем обновлении.
' + secNav('p12','p14'); }