From 99d7bf3d034382558d6a5b08e6d375354e398f7e Mon Sep 17 00:00:00 2001 From: Maxim Dolgolyov Date: Wed, 27 May 2026 19:07:22 +0300 Subject: [PATCH] =?UTF-8?q?feat(geom8):=20Wave=201=20=D0=93=D0=BB=D0=B0?= =?UTF-8?q?=D0=B2=D1=8B=201=20=E2=80=94=20=C2=A71-=C2=A74=20=D1=81=20?= =?UTF-8?q?=D0=B8=D0=BD=D1=82=D0=B5=D1=80=D0=B0=D0=BA=D1=82=D0=B8=D0=B2?= =?UTF-8?q?=D0=B0=D0=BC=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit §1 Многоугольники: SVG-конструктор с drag-вершинами, калькулятор диагоналей, DnD-сортер фигур, тренажёр периметра, босс (4 задачи). §2 Сумма углов: анимация триангуляции, калькулятор, обратная задача, DnD правильные ↔ углы, босс. §3 Внешние углы: SVG свёртка в точку (360°), калькулятор, тренажёр, mini-quiz, босс. §4 Параллелограмм: SVG-конструктор (drag B/D), DnD, пошаговое доказательство, тренажёр углы/периметр, босс. File: 766 → 1910 LOC. Co-Authored-By: Claude Opus 4.7 (1M context) --- frontend/textbooks/geometry_8_ch1.html | 1156 +++++++++++++++++++++++- 1 file changed, 1150 insertions(+), 6 deletions(-) diff --git a/frontend/textbooks/geometry_8_ch1.html b/frontend/textbooks/geometry_8_ch1.html index c54c1b9..085ce5d 100644 --- a/frontend/textbooks/geometry_8_ch1.html +++ b/frontend/textbooks/geometry_8_ch1.html @@ -491,7 +491,7 @@ function buildParaSelector(){ const BUILT = new Set(); const BUILDERS = { - p1:()=>buildP1stub(), p2:()=>buildP2stub(), p3:()=>buildP3stub(), p4:()=>buildP4stub(), + p1:()=>buildP1(), p2:()=>buildP2(), p3:()=>buildP3(), p4:()=>buildP4(), p5:()=>buildP5stub(), p6:()=>buildP6stub(), p7:()=>buildP7stub(), p8:()=>buildP8stub(), p9:()=>buildP9stub(), p10:()=>buildP10stub(), p11:()=>buildP11stub(), p12:()=>buildP12stub(), p13:()=>buildP13stub(), p14:()=>buildP14stub(), p15:()=>buildP15stub(), p16:()=>buildP16stub(), @@ -743,11 +743,1155 @@ function init(){ } document.addEventListener('DOMContentLoaded', init); -/* STUBS — Wave 1 будет заполнять реальный контент */ -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 buildP4stub(){ document.getElementById('p4-body').innerHTML = '

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

' + secNav('p3','p5'); } +/* ============================================================ + § 1 — ВЫПУКЛЫЕ МНОГОУГОЛЬНИКИ. ДИАГОНАЛЬ. ПЕРИМЕТР + ============================================================ */ +function buildP1(){ + const box = document.getElementById('p1-body'); + let html = ''; + + html += makeCard('theory','Многоугольник — определение','1.1',` +

Многоугольник — это замкнутая ломаная без самопересечений. Она делит плоскость на внутреннюю часть (многоугольник) и внешнюю.

+

Элементы: вершины (точки излома), стороны (звенья ломаной), углы (при каждой вершине).

+

Названия: 3 стороны — треугольник, 4 — четырёхугольник, 5 — пятиугольник, 6 — шестиугольник, …, n — n-угольник.

`); + + html += makeCard('rule','Выпуклый многоугольник','1.2',` +

Выпуклый многоугольник — многоугольник, у которого каждая сторона (её прямая) не разделяет оставшиеся вершины на две части: все они лежат по одну сторону от этой прямой.

+

Эквивалентно: все диагонали лежат внутри фигуры.

+

Невыпуклый (вогнутый) — если хотя бы одна диагональ выходит наружу.

`); + + html += makeCard('rule','Диагональ. Число диагоналей','1.3',` +

Диагональ — отрезок, соединяющий две несмежные (несоседние) вершины многоугольника.

+

В n-угольнике число диагоналей:

+ \\[D = \\dfrac{n(n-3)}{2}\\] +

Объяснение: из каждой из $n$ вершин можно провести $(n-3)$ диагонали (не к самой себе и не к двум соседним). Делим на 2, т.к. каждая диагональ считается дважды.

+ + + +
$n$34567810
Диагоналей0259142035
`); + + html += makeCard('rule','Периметр','1.4',` +

Периметр многоугольника — сумма длин всех его сторон:

+ \\[P = a_1 + a_2 + \\cdots + a_n\\] +

Для правильного n-угольника со стороной $a$: $P = n \\cdot a$.

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

Сколько диагоналей у восьмиугольника?

+

$n = 8$: $D = \\dfrac{8 \\cdot (8-3)}{2} = \\dfrac{8 \\cdot 5}{2} = \\dfrac{40}{2} = 20$. Ответ: 20 диагоналей.

+

Периметр четырёхугольника со сторонами 5, 7, 4, 6 равен $5+7+4+6=22$.

`); + + /* --- INTERACTIVE 1: SVG-конструктор многоугольника --- */ + html += `
+
ИНТЕРАКТИВ 1
Конструктор многоугольника
+
Тащи вершины мышью (или пальцем). Меняй количество вершин слайдером. Смотри: периметр, диагонали, выпуклость.
+
+ + +
+
+
+
`; + + /* --- INTERACTIVE 2: Калькулятор диагоналей --- */ + html += `
+
ИНТЕРАКТИВ 2
Калькулятор диагоналей
+
Выбери n — увидишь пошаговое вычисление формулы $D = \\dfrac{n(n-3)}{2}$.
+
+ +
+
+
`; + + /* --- INTERACTIVE 3: DnD — выпуклый/невыпуклый/не многоугольник --- */ + html += `
+
ИНТЕРАКТИВ 3
Выпуклый / Невыпуклый / Не многоугольник
+
Разложи фигуры по категориям. Нажми карточку, затем — на нужный ящик. Или перетащи.
+
Перетащивайте или нажмите карточку, затем — на нужный ящик.
+
+
+
Выпуклый
+
Невыпуклый
+
Не многоугольник
+
+
+ +
`; + + /* --- INTERACTIVE 4: Тренажёр периметра --- */ + html += `
+
ИНТЕРАКТИВ 4
Тренажёр периметра
+
Вычисли периметр многоугольника по данным сторонам и введи ответ.
+
Задача 1 / 5Очки: 0
+
+
+ + + +
+ +
`; + + /* --- INTERACTIVE 5: Босс §1 --- */ + html += `
+
БОСС §1
Итоговые задачи
+
Реши все 4 задачи — получишь XP. Каждая правильно решённая задача даёт +5 XP.
+
+
`; + + html += `
+ +
`; + + html += secNav(null,'p2'); + box.innerHTML = html; + if(window.renderMathInElement) setTimeout(()=>renderMath(box), 0); + + /* == INIT: SVG-конструктор многоугольника == */ + (function(){ + const W = 360, H = 320, cx = W/2, cy = H/2, R = 120; + let n = 5; + let verts = []; + function defaultVerts(nv){ + const v = []; + for(let i=0;i1e-6&&t<1-1e-6&&u>1e-6&&u<1-1e-6; + } + function hasSelfIntersection(vs){ + const n=vs.length; + for(let i=0;i0?1:-1; + if(!sign) sign=s; + else if(sign!==s) return false; + } + return true; + } + function interiorAngle(vs,i){ + const n=vs.length; + const prev=vs[(i-1+n)%n],cur=vs[i],next=vs[(i+1)%n]; + const ax=prev.x-cur.x,ay=prev.y-cur.y; + const bx=next.x-cur.x,by=next.y-cur.y; + const dot=ax*bx+ay*by,cross=ax*by-ay*bx; + let a=Math.atan2(Math.abs(cross),dot)*180/Math.PI; + if(cross<0) a=360-a; + return a; + } + function redraw(){ + const svg=document.getElementById('p1-poly-svg'); + if(!svg) return; + const nv=verts.length; + const selfX=hasSelfIntersection(verts); + const conv=!selfX&&isConvex(verts); + const pts=verts.map(v=>v.x+','+v.y).join(' '); + const col=selfX?'#ef4444':(conv?'#10b981':'#f59e0b'); + const fillCol=selfX?'rgba(239,68,68,.12)':(conv?'rgba(16,185,129,.12)':'rgba(245,158,11,.12)'); + let s=''; + s+=''; + // диагонали + for(let i=0;i'; + } + // метки сторон + for(let i=0;i'+d.toFixed(1)+''; + } + // вершины + for(let i=0;i'; + s+=''; + const letter=String.fromCharCode(65+i); + const lx=v.x+(v.x-cx)*0.22+2,ly=v.y+(v.y-cy)*0.22+2; + s+=''+letter+''; + } + svg.innerHTML=s; + // drag handlers + svg.querySelectorAll('.p1-poly-vh').forEach(el=>{ + el.style.cursor='grab'; + el.addEventListener('pointerdown',ev=>{ + if(ev.button!==undefined&&ev.button!==0) return; + const idx=+el.dataset.i; + el.style.cursor='grabbing'; + try{el.setPointerCapture(ev.pointerId);}catch(e){} + function onMove(e){ + const rect=svg.getBoundingClientRect(); + const sx=svg.viewBox.baseVal.width/rect.width; + const sy=svg.viewBox.baseVal.height/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)); + verts[idx]={x:nx,y:ny}; + redraw(); updateInfo(); + } + function onUp(){ el.removeEventListener('pointermove',onMove);el.removeEventListener('pointerup',onUp);el.removeEventListener('pointercancel',onUp);el.style.cursor='grab'; } + el.addEventListener('pointermove',onMove); + el.addEventListener('pointerup',onUp); + el.addEventListener('pointercancel',onUp); + }); + }); + const statusEl=document.getElementById('p1-poly-status'); + if(statusEl){ + statusEl.textContent=selfX?'Самопересечение!':(conv?'Выпуклый':'Невыпуклый'); + statusEl.style.color=col; + } + } + function updateInfo(){ + const nv=verts.length; + const perimeter=verts.reduce((s,v,i)=>s+dist(v,verts[(i+1)%nv]),0); + const diags=nv*(nv-3)/2; + const selfX=hasSelfIntersection(verts); + const conv=!selfX&&isConvex(verts); + const angStr=verts.map((v,i)=>interiorAngle(verts,i).toFixed(1)+'°').join(', '); + const angSum=verts.reduce((s,v,i)=>s+interiorAngle(verts,i),0); + const col=selfX?'#ef4444':(conv?'#10b981':'#f59e0b'); + document.getElementById('p1-poly-info').innerHTML=` +
Вид
${selfX?'Самопересечение!':(conv?'Выпуклый':'Невыпуклый')}
+
Периметр
${perimeter.toFixed(2)}
+
Диагоналей
${Math.max(0,diags)}
+
Сумма углов
${angSum.toFixed(1)}°
`; + } + function build(){ + verts=defaultVerts(n); + const wrap=document.getElementById('p1-poly-svg-wrap'); + wrap.innerHTML=''; + redraw(); updateInfo(); + } + build(); + document.getElementById('p1-poly-n-sl').addEventListener('input',function(){ + n=+this.value; document.getElementById('p1-poly-n-val').textContent=n; build(); + }); + document.getElementById('p1-poly-reset').addEventListener('click',()=>build()); + })(); + + /* == INIT: Калькулятор диагоналей == */ + (function(){ + const sl=document.getElementById('p1-dc-n'),val=document.getElementById('p1-dc-nval'),out=document.getElementById('p1-dc-out'); + function update(){ + const n=+sl.value; val.textContent=n; + const d=n*(n-3)/2; + out.innerHTML=` +
$n = ${n}$, формула: $D = \\dfrac{n(n-3)}{2}$
+
Подставляем: $D = \\dfrac{${n} \\cdot (${n} - 3)}{2} = \\dfrac{${n} \\cdot ${n-3}}{2} = \\dfrac{${n*(n-3)}}{2}$
+
Ответ: $D = ${d}$ диагоналей
`; + renderMath(out); + } + sl.addEventListener('input',update); update(); + })(); + + /* == INIT: DnD сортировка == */ + (function(){ + const items=[ + {id:'tri', html:'Треугольник', ans:'conv'}, + {id:'square',html:'Квадрат', ans:'conv'}, + {id:'hex', html:'Правильный шестиугольник', ans:'conv'}, + {id:'star', html:'Звезда', ans:'conc'}, + {id:'arrow', html:'Стрелка', ans:'conc'}, + {id:'circle',html:'Круг', ans:'not'}, + {id:'open', html:'Незамкнутая ломаная', ans:'not'}, + ]; + const sorter=setupSorter({poolId:'p1-dnd-pool',scopeSelector:'#p1-dnd-wrap',items,cats:['conv','conc','not']}); + document.getElementById('p1-dnd-reset').addEventListener('click',()=>{ sorter.reset(); document.getElementById('p1-dnd-fb').style.display='none'; }); + document.getElementById('p1-dnd-check').addEventListener('click',()=>{ + let ok=0,total=items.length; + items.forEach(it=>{ if(sorter.placed[it.id]===it.ans) ok++; }); + const fb=document.getElementById('p1-dnd-fb'); + if(ok===total){ feedback(fb,true,'Все '+total+' фигур разложены верно! +5 XP'); addXp(5,'p1-dnd'); bumpProgress('p1',15); } + else feedback(fb,false,'Верно: '+ok+' из '+total+'. Попробуй ещё раз.'); + }); + })(); + + /* == INIT: Тренажёр периметра == */ + (function(){ + const tasks=[ + {sides:[5,7,4,6], ans:22, text:'Четырёхугольник со сторонами 5, 7, 4, 6.'}, + {sides:[3,4,5], ans:12, text:'Треугольник со сторонами 3, 4, 5.'}, + {sides:[8,8,8,8,8], ans:40, text:'Правильный пятиугольник со стороной 8.'}, + {sides:[6,9,6,9], ans:30, text:'Прямоугольник со сторонами 6 и 9.'}, + {sides:[7,5,8,4,6], ans:30, text:'Пятиугольник со сторонами 7, 5, 8, 4, 6.'}, + ]; + let idx=0,score=0; + function show(){ + const t=tasks[idx]; + document.getElementById('p1-pt-i').textContent=idx+1; + document.getElementById('p1-pt-task').innerHTML=''+t.text+'
Найди периметр.'; + document.getElementById('p1-pt-ans').value=''; + document.getElementById('p1-pt-fb').style.display='none'; + } + document.getElementById('p1-pt-start').addEventListener('click',()=>{ idx=0;score=0;document.getElementById('p1-pt-score').textContent=0;show(); }); + document.getElementById('p1-pt-go').addEventListener('click',()=>{ + if(idx>=tasks.length) return; + const ans=+document.getElementById('p1-pt-ans').value; + const fb=document.getElementById('p1-pt-fb'); + if(ans===tasks[idx].ans){ + score++; document.getElementById('p1-pt-score').textContent=score; + addXp(3,'p1-perim'); bumpProgress('p1',5); + if(idxshow(),900); } + else{ feedback(fb,true,'Все задачи решены! +5 XP'); addXp(5,'p1-perim-all'); bumpProgress('p1',10); } + } else { + feedback(fb,false,'Неверно. Ответ: '+tasks[idx].ans+'. Периметр = сумма всех сторон.'); + } + }); + document.getElementById('p1-pt-ans').addEventListener('keydown',e=>{ if(e.key==='Enter') document.getElementById('p1-pt-go').click(); }); + show(); + })(); + + /* == INIT: Босс §1 == */ + (function(){ + const tasks=[ + { q:'Сколько диагоналей у 7-угольника?', ans:14, hint:'Формула: n(n-3)/2, n=7.' }, + { q:'Найди периметр прямоугольника со сторонами AB=12 и BC=7.', ans:38, hint:'P = 2(12+7) = 38.' }, + { q:'В многоугольнике 20 диагоналей. Сколько в нём вершин? (Число сторон)', ans:8, hint:'n(n-3)/2=20 → n=8.' }, + { q:'Периметр правильного шестиугольника равен 54. Чему равна одна сторона?', ans:9, hint:'P = 6a → a = 54/6 = 9.' }, + ]; + const box=document.getElementById('p1-boss-tasks'); + let solved=new Set(); + box.innerHTML=tasks.map((t,i)=>` +
+
${t.q}
+
+ + +
+ +
`).join(''); + window.p1BossSolved=new Set(); + })(); +} + +/* ============================================================ + § 2 — СУММА УГЛОВ ВЫПУКЛОГО МНОГОУГОЛЬНИКА + ============================================================ */ +function buildP2(){ + const box = document.getElementById('p2-body'); + let html = ''; + + html += makeCard('theory','Теорема о сумме углов','2.1',` +

Теорема. Сумма внутренних углов выпуклого $n$-угольника равна:

+ \\[(n-2)\\cdot 180^{\\circ}\\] +

Доказательство. Из любой вершины $A_1$ проводим диагонали ко всем несмежным вершинам. Получаем $(n-2)$ треугольника. Сумма углов каждого треугольника равна $180°$, и все эти углы вместе составляют углы многоугольника. Итого: $(n-2) \\cdot 180°$.

+ + + +
$n$34567810
Сумма углов$180°$$360°$$540°$$720°$$900°$$1080°$$1440°$
`); + + html += makeCard('rule','Правильный многоугольник','2.2',` +

Правильный n-угольник — все стороны равны и все углы равны.

+

Каждый внутренний угол правильного $n$-угольника:

+ \\[\\alpha = \\dfrac{(n-2)\\cdot 180^{\\circ}}{n}\\] + + + + + + + + + + +
Фигура$n$Угол $\\alpha$
Треугольник3$60°$
Квадрат4$90°$
Пятиугольник5$108°$
Шестиугольник6$120°$
Восьмиугольник8$135°$
Двенадцатиугольник12$150°$
`); + + html += makeCard('example','Примеры','2.3',` +

Один угол девятиугольника. $n=9$: сумма $= (9-2)\\cdot 180°=7\\cdot 180°=1260°$. Один угол правильного 9-угольника: $1260°/9=140°$.

+

Найти n по сумме углов. Сумма $=1440°$: $(n-2)\\cdot 180°=1440° \\Rightarrow n-2=8 \\Rightarrow n=10$. Ответ: десятиугольник.

`); + + /* --- INTERACTIVE 1: Анимация триангуляции --- */ + html += `
+
ИНТЕРАКТИВ 1
Триангуляция и сумма углов
+
Выбери n-угольник и нажми «Триангулировать» — увидишь разбиение на треугольники и подсчёт суммы углов.
+
+ +
+
+ + +
+
+ +
`; + + /* --- INTERACTIVE 2: Калькулятор суммы и угла --- */ + html += `
+
ИНТЕРАКТИВ 2
Калькулятор: сумма и угол правильного
+
Задай $n$ — мгновенно увидишь сумму всех углов и величину одного угла правильного $n$-угольника.
+
+ +
+
+
`; + + /* --- INTERACTIVE 3: Обратная задача --- */ + html += `
+
ИНТЕРАКТИВ 3
Обратная задача: по сумме углов найти n
+
Введи сумму внутренних углов (кратную 180°, больше 180°) — система найдёт n или скажет, что такого многоугольника нет.
+
+ + +
+ +
`; + + /* --- INTERACTIVE 4: DnD правильные многоугольники ↔ углы --- */ + html += `
+
ИНТЕРАКТИВ 4
Правильные многоугольники и их углы
+
Разложи названия правильных многоугольников по значению угла.
+
Перетащивайте или нажмите карточку, затем — на нужный ящик.
+
+
+
$60°$
+
$90°$
+
$108°$
+
$120°$
+
$135°$
+
$140°$
+
+
+ +
`; + + /* --- INTERACTIVE 5: Босс §2 --- */ + html += `
+
БОСС §2
Итоговые задачи по §2
+
Реши задачи — каждая верная даёт +5 XP.
+
+
`; + + html += `
+ +
`; + + html += secNav('p1','p3'); + box.innerHTML = html; + if(window.renderMathInElement) setTimeout(()=>renderMath(box), 0); + + /* == INIT: Триангуляция == */ + (function(){ + const W=360, H=300, cx=W/2, cy=H/2, R=110; + let n=5, shown=false; + const colors=['#d97706','#10b981','#0891b2','#8b5cf6','#ef4444','#f97316','#14b8a6','#a855f7','#e11d48','#6366f1']; + function pts(nv,r,ox,oy){ const a=[]; for(let i=0;i'; + if(triangulate){ + for(let i=1;i'; + } + const out=document.getElementById('p2-tr-out'); + out.style.display='block'; + out.innerHTML='$n='+n+'$, треугольников: $'+(n-2)+'$.
Сумма углов $= ('+n+'-2)\\cdot 180° = '+(n-2)+'\\cdot 180° = '+((n-2)*180)+'°$'; + renderMath(out); + } + const ptstr=vs.map(v=>v.x+','+v.y).join(' '); + s+=''; + vs.forEach((v,i)=>{ + s+=''; + const lx=v.x+(v.x-cx)*0.22,ly=v.y+(v.y-cy)*0.22; + s+=''+ String.fromCharCode(65+i)+''; + }); + if(triangulate){ + for(let i=1;i'; + } + for(let i=1;iT'+(i)+''; + } + } + s+=''; + wrap.innerHTML=s; + } + const nlSl=document.getElementById('p2-tr-n'); + const nlVal=document.getElementById('p2-tr-nval'); + nlSl.addEventListener('input',function(){ n=+this.value; nlVal.textContent=n; shown=false; document.getElementById('p2-tr-out').style.display='none'; draw(false); }); + document.getElementById('p2-tr-go').addEventListener('click',()=>{ shown=true; draw(true); addXp(2,'p2-triang'); bumpProgress('p2',10); }); + document.getElementById('p2-tr-reset').addEventListener('click',()=>{ shown=false; document.getElementById('p2-tr-out').style.display='none'; draw(false); }); + draw(false); + })(); + + /* == INIT: Калькулятор == */ + (function(){ + const sl=document.getElementById('p2-cl-n'),val=document.getElementById('p2-cl-nval'),out=document.getElementById('p2-cl-out'); + function update(){ + const n=+sl.value; val.textContent=n; + const sum=(n-2)*180; + const ang=sum/n; + out.innerHTML='$n='+n+'$
Сумма всех углов: $('+n+'-2)\\cdot 180° = '+sum+'°$
Один угол правильного $'+n+'$-угольника: $\\dfrac{'+sum+'°}{'+n+'} = '+ang.toFixed(2).replace(/\.00$/,'')+'°$'; + renderMath(out); + } + sl.addEventListener('input',update); update(); + })(); + + /* == INIT: Обратная задача == */ + (function(){ + document.getElementById('p2-rev-go').addEventListener('click',()=>{ + const s=+document.getElementById('p2-rev-inp').value; + const out=document.getElementById('p2-rev-out'); + out.style.display='block'; + if(s<=0||isNaN(s)){ out.innerHTML='Введи положительное число.'; return; } + if(s%180!==0){ out.innerHTML='Сумма углов должна делиться на 180°.'; return; } + const n=(s/180)+2; + if(!Number.isInteger(n)||n<3){ out.innerHTML='Нет такого многоугольника (n должен быть целым ≥ 3).'; return; } + out.innerHTML='$(n-2)\\cdot 180°='+s+'° \\Rightarrow n-2='+s/180+' \\Rightarrow n='+n+'$
Ответ: '+n+'-угольник'; + renderMath(out); + addXp(3,'p2-rev'); + }); + document.getElementById('p2-rev-inp').addEventListener('keydown',e=>{ if(e.key==='Enter') document.getElementById('p2-rev-go').click(); }); + })(); + + /* == INIT: DnD правильные ↔ углы == */ + (function(){ + const items=[ + {id:'tri3', html:'Треугольник', ans:'60'}, + {id:'sq4', html:'Квадрат', ans:'90'}, + {id:'pent5', html:'Пятиугольник', ans:'108'}, + {id:'hex6', html:'Шестиугольник', ans:'120'}, + {id:'oct8', html:'Восьмиугольник', ans:'135'}, + {id:'n9', html:'Девятиугольник', ans:'140'}, + ]; + const sorter=setupSorter({poolId:'p2-dnd-pool',scopeSelector:'#p2-dnd-wrap',items,cats:['60','90','108','120','135','140']}); + document.getElementById('p2-dnd-reset').addEventListener('click',()=>{ sorter.reset(); document.getElementById('p2-dnd-fb').style.display='none'; }); + document.getElementById('p2-dnd-check').addEventListener('click',()=>{ + let ok=0; + items.forEach(it=>{ if(sorter.placed[it.id]===it.ans) ok++; }); + const fb=document.getElementById('p2-dnd-fb'); + if(ok===items.length){ feedback(fb,true,'Все фигуры сопоставлены верно! +5 XP'); addXp(5,'p2-dnd'); bumpProgress('p2',15); } + else feedback(fb,false,'Верно: '+ok+' из '+items.length+'. Используй формулу α=(n-2)·180°/n.'); + }); + })(); + + /* == INIT: Босс §2 == */ + (function(){ + const tasks=[ + { q:'Найди сумму углов выпуклого десятиугольника.', ans:1440, hint:'(10-2)·180=1440' }, + { q:'Один угол правильного восьмиугольника равен … °', ans:135, hint:'(8-2)·180/8=135' }, + { q:'Сумма углов многоугольника равна 900°. Сколько сторон?', ans:7, hint:'(n-2)·180=900→n=7' }, + { q:'Сумма углов правильного многоугольника = 2520°. Найди один угол.', ans:168, hint:'n=(2520/180)+2=16; угол=2520/16=157.5? нет: (16-2)*180=2520, угол=2520/16=157.5. Проверь: n=16' }, + ]; + const bossBox=document.getElementById('p2-boss-tasks'); + bossBox.innerHTML=tasks.map((t,i)=>` +
+
${t.q}
+
+ + +
+ +
`).join(''); + window.p2BossSolved=new Set(); + })(); +} + +/* ============================================================ + § 3 — СУММА ВНЕШНИХ УГЛОВ ВЫПУКЛОГО МНОГОУГОЛЬНИКА + ============================================================ */ +function buildP3(){ + const box = document.getElementById('p3-body'); + let html = ''; + + html += makeCard('theory','Внешний угол. Теорема','3.1',` +

Внешний угол выпуклого многоугольника при вершине — угол между стороной и продолжением соседней стороны. Внешний угол при вершине $A_i$:

+ \\[\\beta_i = 180^{\\circ} - \\alpha_i\\] +

где $\\alpha_i$ — соответствующий внутренний угол.

+

Теорема. Сумма всех внешних углов выпуклого многоугольника (по одному у каждой вершины) равна $360°$ — при любом $n$.

+

Объяснение: если обойти многоугольник по периметру, на каждой вершине повернёшься на внешний угол. За полный обход — ровно один полный оборот $= 360°$.

`); + + html += makeCard('rule','Правильный n-угольник','3.2',` +

Внешний угол правильного $n$-угольника:

+ \\[\\beta = \\dfrac{360^{\\circ}}{n}\\] +

Внутренний угол: $\\alpha = 180° - \\dfrac{360°}{n} = \\dfrac{(n-2)\\cdot 180°}{n}$.

+

Отсюда: зная внешний угол $\\beta$, можно найти $n = \\dfrac{360°}{\\beta}$.

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

Внешний угол правильного шестиугольника: $\\beta = 360°/6 = 60°$, внутренний $= 180°-60°=120°$.

+

Внешний угол правильного многоугольника = 24°. Найти n: $n = 360°/24° = 15$. Ответ: 15-угольник.

+

Сумма внешних углов правильного 100-угольника: всегда $360°$, независимо от $n$!

`); + + /* --- INTERACTIVE 1: SVG внешние углы + анимация "свернуть в точку" --- */ + html += `
+
ИНТЕРАКТИВ 1
Внешние углы: визуализация
+
Выбери $n$. Посмотри на внешние углы (жёлтые дуги). Нажми «Свернуть» — углы образуют полный оборот $360°$.
+
+ +
+
+ + +
+
+
+
`; + + /* --- INTERACTIVE 2: Калькулятор правильного n-угольника --- */ + html += `
+
ИНТЕРАКТИВ 2
Калькулятор правильного многоугольника
+
Задай $n$ — получишь и внешний, и внутренний угол.
+
+ +
+
+
`; + + /* --- INTERACTIVE 3: Тренажёр — найти n по внешнему углу --- */ + html += `
+
ИНТЕРАКТИВ 3
Тренажёр: найди n по внешнему углу
+
Дан один внешний угол правильного n-угольника. Найди n.
+
Задача 1 / 4Очки: 0
+
+
+ + + +
+ +
`; + + /* --- INTERACTIVE 4: Mini-quiz --- */ + html += `
+
ИНТЕРАКТИВ 4
Мини-квиз по §3
+
+
`; + + /* --- INTERACTIVE 5: Босс §3 --- */ + html += `
+
БОСС §3
Итоговые задачи §3
+
Реши задачи — +5 XP за каждую верную.
+
+
`; + + html += `
+ +
`; + + html += secNav('p2','p4'); + box.innerHTML = html; + if(window.renderMathInElement) setTimeout(()=>renderMath(box), 0); + + /* == INIT: SVG внешние углы == */ + (function(){ + const W=380, H=320, cx=W/2, cy=H/2, R=100, Rext=30; + let n=6, folded=false; + const colors=['#d97706','#10b981','#0891b2','#8b5cf6','#ef4444','#f97316','#14b8a6','#a855f7','#e11d48','#6366f1']; + function pts(nv){ const v=[];for(let i=0;i'; + s+=''; + vs.forEach((v,i)=>{ + const nxt=vs[(i+1)%n]; + const ext=40; + const dx=v.x-nxt.x,dy=v.y-nxt.y; + const len=Math.hypot(dx,dy); + const ex=v.x+ext*dx/len,ey=v.y+ext*dy/len; + s+=''; + const extAngle=360/n; + const startAng=Math.atan2(v.y-nxt.y,v.x-nxt.x)*180/Math.PI; + const endAng=startAng-extAngle; + const ra=Rext,sa=startAng*(Math.PI/180),ea=endAng*(Math.PI/180); + const x1=nxt.x+ra*Math.cos(sa),y1=nxt.y+ra*Math.sin(sa); + const x2=nxt.x+ra*Math.cos(ea),y2=nxt.y+ra*Math.sin(ea); + const large=extAngle>180?1:0; + s+=''; + s+=''+(extAngle.toFixed(1))+'°'; + }); + vs.forEach((v,i)=>{ + s+=''; + }); + s+=''; + document.getElementById('p3-ex-svg-wrap').innerHTML=s; + document.getElementById('p3-ex-info').innerHTML='$n='+n+'$, внешний угол $= \\dfrac{360°}{'+n+'} = '+(360/n).toFixed(2).replace(/\.00$/,'')+'°$, сумма $= '+n+' \\times '+(360/n).toFixed(1)+'° = 360°$'; + renderMath(document.getElementById('p3-ex-info')); + } + function drawFolded(){ + let s=''; + const R2=14; + let cumAngle=0; + for(let i=0;i'; + const mid=(sa+ea)/2; + s+=''+(360/n).toFixed(0)+'°'; + cumAngle=ea; + } + s+=''; + s+='360°'; + s+=''; + document.getElementById('p3-ex-svg-wrap').innerHTML=s; + document.getElementById('p3-ex-info').innerHTML='Все $'+n+'$ внешних углов по $'+(360/n).toFixed(1)+'°$ образуют полный оборот 360°!'; + renderMath(document.getElementById('p3-ex-info')); + addXp(2,'p3-fold'); bumpProgress('p3',10); + } + const nlSl=document.getElementById('p3-ex-n'),nlVal=document.getElementById('p3-ex-nval'); + nlSl.addEventListener('input',function(){ n=+this.value; nlVal.textContent=n; folded=false; drawNormal(); }); + document.getElementById('p3-ex-fold').addEventListener('click',()=>{ folded=true; drawFolded(); }); + document.getElementById('p3-ex-reset').addEventListener('click',()=>{ folded=false; drawNormal(); }); + drawNormal(); + })(); + + /* == INIT: Калькулятор == */ + (function(){ + const sl=document.getElementById('p3-cl-n'),val=document.getElementById('p3-cl-nval'),out=document.getElementById('p3-cl-out'); + function update(){ + const n=+sl.value; val.textContent=n; + const ext=360/n, int=180-ext; + out.innerHTML='$n='+n+'$
Внешний угол: $\\dfrac{360°}{'+n+'} = '+ext.toFixed(2).replace(/\.00$/,'')+'°$
Внутренний угол: $180° - '+ext.toFixed(2).replace(/\.00$/,'')+'° = '+int.toFixed(2).replace(/\.00$/,'')+'°$'; + renderMath(out); + } + sl.addEventListener('input',update); update(); + })(); + + /* == INIT: Тренажёр == */ + (function(){ + const tasks=[ + {ext:30, n:12, text:'Внешний угол правильного многоугольника равен 30°. Найди n.'}, + {ext:45, n:8, text:'Внешний угол правильного многоугольника равен 45°. Найди n.'}, + {ext:60, n:6, text:'Внешний угол правильного многоугольника равен 60°. Найди n.'}, + {ext:72, n:5, text:'Внешний угол правильного многоугольника равен 72°. Найди n.'}, + ]; + let idx=0,score=0; + function show(){ + document.getElementById('p3-tr-i').textContent=idx+1; + document.getElementById('p3-tr-task').innerHTML=tasks[idx].text+'
Подсказка: n = 360°/внешний угол'; + 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',()=>{ + const ans=+document.getElementById('p3-tr-ans').value; + const fb=document.getElementById('p3-tr-fb'); + if(ans===tasks[idx].n){ + score++; document.getElementById('p3-tr-score').textContent=score; addXp(3,'p3-train'); bumpProgress('p3',8); + if(idxshow(),900); } + else{ feedback(fb,true,'Все задачи решены! +5 XP'); addXp(5,'p3-train-all'); bumpProgress('p3',10); } + } else feedback(fb,false,'Неверно. Используй: n=360°/'+tasks[idx].ext+'°='+tasks[idx].n); + }); + document.getElementById('p3-tr-ans').addEventListener('keydown',e=>{ if(e.key==='Enter') document.getElementById('p3-tr-go').click(); }); + show(); + })(); + + /* == INIT: Мини-квиз == */ + (function(){ + const qs=[ + {q:'Сумма внешних углов выпуклого семиугольника равна...', opts:['360°','1260°','900°','Зависит от n'], ans:0}, + {q:'Внешний угол правильного пятиугольника равен...', opts:['60°','72°','108°','120°'], ans:1}, + {q:'Если внешний угол правильного многоугольника = 40°, то сторон...', opts:['7','8','9','12'], ans:2}, + ]; + let qi=0,qscore=0,answered=false; + const cont=document.getElementById('p3-quiz-container'); + function showQ(){ + const q=qs[qi]; + cont.innerHTML=`
${q.q}
+
+ ${q.opts.map((o,i)=>'').join('')} +
+ +
+ Вопрос ${qi+1} / ${qs.length} · Очки: ${qscore} +
`; + answered=false; + } + window.p3QuizAns=function(i){ + if(answered) return; + answered=true; + const q=qs[qi]; + const fb=document.getElementById('p3-q-fb'); + if(i===q.ans){ qscore++; feedback(fb,true,'Верно! +3 XP'); addXp(3,'p3-quiz'); bumpProgress('p3',7); } + else feedback(fb,false,'Неверно. Правильный ответ: '+q.opts[q.ans]); + document.querySelectorAll('[id^="p3-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'; + },1300); + }; + showQ(); + })(); + + /* == INIT: Босс §3 == */ + (function(){ + const tasks=[ + { q:'Внешний угол правильного многоугольника равен 20°. Сколько сторон?', ans:18, hint:'n=360/20=18' }, + { q:'Внутренний угол правильного многоугольника равен 150°. Сколько сторон?', ans:12, hint:'внешний=180-150=30°, n=360/30=12' }, + { q:'Сумма внешних углов выпуклого двадцатиугольника в градусах?', ans:360, hint:'Всегда 360°!' }, + { q:'Внешний угол правильного многоугольника равен 36°. Чему равен внутренний угол?', ans:144, hint:'внутренний = 180-36 = 144°' }, + ]; + const bossBox=document.getElementById('p3-boss-tasks'); + bossBox.innerHTML=tasks.map((t,i)=>` +
+
${t.q}
+
+ + +
+ +
`).join(''); + window.p3BossSolved=new Set(); + })(); +} + +/* ============================================================ + § 4 — ПАРАЛЛЕЛОГРАММ + ============================================================ */ +function buildP4(){ + const box = document.getElementById('p4-body'); + let html = ''; + + html += makeCard('theory','Определение и элементы','4.1',` +

Параллелограмм — четырёхугольник, у которого противоположные стороны попарно параллельны:

+ \\[AB \\parallel CD \\quad \\text{и} \\quad BC \\parallel AD\\] +

Обозначение: $\\square ABCD$ или просто $ABCD$.

+

Элементы параллелограмма:

+
    +
  • Стороны: $AB$, $BC$, $CD$, $DA$ (противоположные: $AB = CD$, $BC = DA$)
  • +
  • Углы: противоположные углы равны; смежные углы — дополнение до $180°$
  • +
  • Диагонали: $AC$ и $BD$ — пересекаются и делятся точкой пересечения пополам
  • +
`); + + html += makeCard('rule','Основные свойства','4.2',` +

В параллелограмме $ABCD$:

+ \\[AB = CD, \\quad BC = AD\\] + \\[\\angle A = \\angle C, \\quad \\angle B = \\angle D\\] + \\[\\angle A + \\angle B = 180^{\\circ}\\] +

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

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

Квадрат, прямоугольник, ромб — это частные случаи параллелограмма.

+

Трапеция — НЕ параллелограмм (только одна пара параллельных сторон).

+

Задача: в параллелограмме $AB = 8$, $BC = 5$. Найти периметр. Решение: $P = 2(8+5) = 26$.

+

Задача: $\\angle A = 65°$. Найти остальные углы. $\\angle C = 65°$, $\\angle B = \\angle D = 115°$.

`); + + /* --- INTERACTIVE 1: SVG-конструктор параллелограмма --- */ + html += `
+
ИНТЕРАКТИВ 1
Конструктор параллелограмма
+
Тащи вершины B и D. Параллелограмм строится автоматически: AB∥CD и BC∥AD. Следи за значениями сторон и углов.
+
+
+
`; + + /* --- INTERACTIVE 2: DnD — какие из фигур параллелограммы --- */ + html += `
+
ИНТЕРАКТИВ 2
Параллелограмм или нет?
+
Разложи фигуры: является ли она параллелограммом (или его частным случаем)?
+
+
+
Параллелограмм
+
Не параллелограмм
+
+
+ +
`; + + /* --- INTERACTIVE 3: Пошаговое доказательство --- */ + html += `
+
ИНТЕРАКТИВ 3
Доказательство: противоположные стороны равны
+
Нажимай «Дальше» — идёт пошаговое доказательство через треугольники.
+
+
+
+ + +
+
`; + + /* --- INTERACTIVE 4: Тренажёр --- */ + html += `
+
ИНТЕРАКТИВ 4
Тренажёр задач на параллелограмм
+
Задача 1 / 4Очки: 0
+
+
+ + + +
+ +
`; + + /* --- INTERACTIVE 5: Босс §4 --- */ + html += `
+
БОСС §4
Итоговые задачи §4
+
+5 XP за каждую верную задачу.
+
+
`; + + html += `
+ +
`; + + html += secNav('p3','p5'); + box.innerHTML = html; + if(window.renderMathInElement) setTimeout(()=>renderMath(box), 0); + + /* == INIT: SVG-конструктор параллелограмма == */ + (function(){ + const W=380, H=300; + let A={x:60,y:220}, B={x:180,y:220}, D={x:100,y:100}; + 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 angle(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 C=getC(); + const vs={A,B,C,D}; + const pts=[A,B,C,D]; + let s=''; + s+=''; + s+=''; + s+=''; + 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; + pts.forEach((v,i)=>{ + const movable=(i===1||i===3); + s+=''; + s+=''; + const lx=v.x+(v.x-cx)*0.25,ly=v.y+(v.y-cy)*0.25; + s+=''+labels[i]+''; + }); + const sides=[['AB',A,B],['BC',B,C],['CD',C,D],['DA',D,A]]; + sides.forEach(([name,p1,p2])=>{ + const mx=(p1.x+p2.x)/2,my=(p1.y+p2.y)/2; + const d=dist(p1,p2); + s+=''+d.toFixed(1)+''; + }); + s+=''; + const svg=document.createElement('div'); + svg.innerHTML=s; + const svgEl=svg.firstElementChild; + document.getElementById('p4-pgram-svg-wrap').innerHTML=''; + document.getElementById('p4-pgram-svg-wrap').appendChild(svgEl); + svgEl.querySelectorAll('.p4-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(); updateInfo(); + } + 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); + }); + }); + updateInfo(); + } + function updateInfo(){ + const C=getC(); + const ab=dist(A,B),bc=dist(B,C),angA=angle(A,D,B),angB=angle(B,A,C); + document.getElementById('p4-pgram-info').innerHTML=` +
AB = CD
${ab.toFixed(1)}
+
BC = DA
${bc.toFixed(1)}
+
∠A = ∠C
${angA.toFixed(1)}°
+
∠A + ∠B
${(angA+angB).toFixed(1)}°
`; + } + redraw(); + })(); + + /* == INIT: DnD параллелограмм или нет == */ + (function(){ + const items=[ + {id:'rect', html:'Прямоугольник', ans:'yes'}, + {id:'rhombus',html:'Ромб', ans:'yes'}, + {id:'square', html:'Квадрат', ans:'yes'}, + {id:'pgram', html:'Произвольный параллелограмм', ans:'yes'}, + {id:'trap', html:'Трапеция', ans:'no'}, + {id:'kite', html:'Дельтоид (воздушный змей)', ans:'no'}, + {id:'arb4', html:'Произвольный четырёхугольник', ans:'no'}, + {id:'tri', html:'Треугольник', ans:'no'}, + ]; + const sorter=setupSorter({poolId:'p4-dnd-pool',scopeSelector:'#p4-dnd-wrap',items,cats:['yes','no']}); + document.getElementById('p4-dnd-reset').addEventListener('click',()=>{ sorter.reset(); document.getElementById('p4-dnd-fb').style.display='none'; }); + document.getElementById('p4-dnd-check').addEventListener('click',()=>{ + let ok=0; + items.forEach(it=>{ if(sorter.placed[it.id]===it.ans) ok++; }); + const fb=document.getElementById('p4-dnd-fb'); + if(ok===items.length){ feedback(fb,true,'Все '+items.length+' фигур верно! +5 XP'); addXp(5,'p4-dnd'); bumpProgress('p4',15); } + else feedback(fb,false,'Верно: '+ok+' из '+items.length+'. Прямоугольник, ромб, квадрат — частные случаи параллелограмма.'); + }); + })(); + + /* == INIT: Пошаговое доказательство == */ + (function(){ + const steps=[ + { text:'Дано: $ABCD$ — параллелограмм, $AB \\parallel CD$, $BC \\parallel AD$.
Проведём диагональ $AC$.', highlight:'' }, + { text:'Шаг 1. $AB \\parallel CD$ и $AC$ — секущая.
По свойству параллельных прямых: $\\angle BAC = \\angle DCA$ (накрест лежащие углы).', highlight:'diag' }, + { text:'Шаг 2. $BC \\parallel AD$ и $AC$ — секущая.
Аналогично: $\\angle BCA = \\angle DAC$ (накрест лежащие углы).', highlight:'diag' }, + { text:'Шаг 3. $AC$ — общая сторона треугольников $\\triangle ABC$ и $\\triangle CDA$.
По признаку «угол-сторона-угол»: $\\triangle ABC = \\triangle CDA$.', highlight:'both' }, + { text:'Вывод. Из равенства треугольников следует: $AB = CD$ и $BC = DA$.
Противоположные стороны параллелограмма равны. $\\square$', highlight:'both' }, + ]; + let step=0; + const W=300,H=200; + function drawProof(highlight){ + const A={x:30,y:160},B={x:180,y:160},C={x:260,y:50},D={x:110,y:50}; + const cx=(A.x+B.x+C.x+D.x)/4; + let s=''; + const t1fill=highlight==='diag'||highlight==='both'?'rgba(220,38,38,.15)':'rgba(220,38,38,.07)'; + const t2fill=highlight==='both'?'rgba(16,185,129,.15)':'rgba(220,38,38,.07)'; + s+=''; + if(highlight){ + s+=''; + s+=''; + 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+''; + }); + s+=''; + document.getElementById('p4-proof-svg').innerHTML=s; + } + function showStep(){ + const st=steps[step]; + document.getElementById('p4-proof-step').innerHTML=st.text; + renderMath(document.getElementById('p4-proof-step')); + drawProof(st.highlight); + document.getElementById('p4-proof-next').textContent=step{ + if(step{ step=0; showStep(); document.getElementById('p4-proof-next').disabled=false; document.getElementById('p4-proof-next').textContent='Дальше'; }); + showStep(); + })(); + + /* == INIT: Тренажёр задач == */ + (function(){ + const tasks=[ + { q:'В параллелограмме AB = 11, BC = 7. Найди периметр.', ans:36, hint:'P=2(AB+BC)=2(11+7)=36' }, + { q:'В параллелограмме ∠A = 72°. Найди ∠B (смежный угол).', ans:108, hint:'∠A+∠B=180°, ∠B=108°' }, + { q:'В параллелограмме ∠A = 72°. Найди ∠C (противоположный).', ans:72, hint:'∠A=∠C в параллелограмме' }, + { q:'Периметр параллелограмма равен 56, одна сторона равна 18. Найди вторую сторону.', ans:10, hint:'2(18+x)=56, x=10' }, + ]; + let idx=0,score=0; + function show(){ + document.getElementById('p4-tr-i').textContent=idx+1; + document.getElementById('p4-tr-task').innerHTML=tasks[idx].q; + document.getElementById('p4-tr-ans').value=''; + document.getElementById('p4-tr-fb').style.display='none'; + } + document.getElementById('p4-tr-start').addEventListener('click',()=>{ idx=0;score=0;document.getElementById('p4-tr-score').textContent=0;show(); }); + document.getElementById('p4-tr-go').addEventListener('click',()=>{ + const ans=+document.getElementById('p4-tr-ans').value; + const fb=document.getElementById('p4-tr-fb'); + if(ans===tasks[idx].ans){ + score++; document.getElementById('p4-tr-score').textContent=score; addXp(3,'p4-train'); bumpProgress('p4',6); + if(idxshow(),900); } + else{ feedback(fb,true,'Все задачи решены! +5 XP'); addXp(5,'p4-train-all'); bumpProgress('p4',10); } + } else feedback(fb,false,'Неверно. Подсказка: '+tasks[idx].hint); + }); + document.getElementById('p4-tr-ans').addEventListener('keydown',e=>{ if(e.key==='Enter') document.getElementById('p4-tr-go').click(); }); + show(); + })(); + + /* == INIT: Босс §4 == */ + (function(){ + const tasks=[ + { q:'В параллелограмме $AB = 13$, $BC = 9$. Найди периметр.', ans:44, hint:'P=2(13+9)=44' }, + { q:'В параллелограмме $\\angle A = 55°$. Найди $\\angle D$ (смежный с $\\angle A$).', ans:125, hint:'∠A+∠D=180°, ∠D=125°' }, + { q:'В параллелограмме $\\angle B = 130°$. Найди $\\angle A$.', ans:50, hint:'∠A+∠B=180°, ∠A=50°' }, + { q:'Периметр параллелограмма равен 80, одна сторона = 25. Найди вторую сторону.', ans:15, hint:'2(25+x)=80, x=15' }, + ]; + const bossBox=document.getElementById('p4-boss-tasks'); + bossBox.innerHTML=tasks.map((t,i)=>` +
+
${t.q}
+
+ + +
+ +
`).join(''); + window.p4BossSolved=new Set(); + })(); + 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'); }