diff --git a/backend/tests/math6-page.test.js b/backend/tests/math6-page.test.js index 2691e8b..b8c973f 100644 --- a/backend/tests/math6-page.test.js +++ b/backend/tests/math6-page.test.js @@ -85,6 +85,27 @@ test('ch5: координатная плоскость — интерактив assert.deepEqual(errors, [], 'нет ошибок: ' + errors.join(' | ')); }); +test('ch6: наглядная геометрия — интерактивы §1–§5 + финал', async () => { + const { doc, errors } = await loadDom('math_6_ch6.html'); + const win = doc.defaultView; + assert.ok(doc.querySelector('#p1-fig svg') && doc.querySelector('#p1-q'), 'тела §1'); + win.goTo('p2'); await wait(80); + assert.ok(doc.querySelector('#p2-r') && doc.querySelector('#p2-fig svg circle'), 'окружность §2'); + assert.ok(doc.querySelector('#p2-out').textContent.indexOf('=') >= 0, 'формулы C, S §2'); + win.goTo('p3'); await wait(80); + assert.ok(doc.querySelector('#p3-fig svg polygon'), 'треугольник §3'); + assert.ok(doc.querySelectorAll('#p3-iv1 [data-v]').length === 3, 'виды по сторонам §3'); + win.goTo('p4'); await wait(80); + assert.ok(doc.querySelector('#p4-fig svg'), 'плоскость симметрии §4'); + win.goTo('p5'); await wait(80); + assert.ok(doc.querySelector('#p5-fig svg'), 'плоскость симметрии §5'); + win.goTo('final'); await wait(80); + assert.ok(doc.querySelector('#fin-go'), 'арена боссов §6'); + win.bumpProgress('final', 100); await wait(20); + assert.ok(win.M6STATE.achievements.has('ch6_done'), 'достижение «Глава 6 пройдена»'); + assert.deepEqual(errors, [], 'нет ошибок: ' + errors.join(' | ')); +}); + test('hub: 6 карточек глав', async () => { const { doc, errors } = await loadDom('math_6_hub.html'); assert.deepEqual(errors, [], 'нет ошибок: ' + errors.join(' | ')); diff --git a/frontend/textbooks/math_6_ch6.html b/frontend/textbooks/math_6_ch6.html index c887969..be68448 100644 --- a/frontend/textbooks/math_6_ch6.html +++ b/frontend/textbooks/math_6_ch6.html @@ -92,6 +92,377 @@ window.M6 = { sidebars: {}, tips: [], glossary: [], builders: {}, footer: 'Интерактивный учебник «Математика 6» · Глава 6 · Наглядная геометрия · LearnSpace' }; + +/* ===================== ВСПОМОГАТЕЛЬНОЕ ===================== */ +function _ri(a,b){ return a + Math.floor(Math.random()*(b-a+1)); } +function _pick(a){ return a[_ri(0,a.length-1)]; } +function _kf(x){ return String(x).replace('.','{,}'); } +function _round(n,d){ var p=Math.pow(10,d); return Math.round(n*p)/p; } +var PI=3.14; +function svgWrap(w,h,inner){ return '
'+inner+'
'; } + +/* тела */ +var SOLIDS={ + cube:'', + prism:'', + pyramid:'', + cylinder:'', + cone:'' +}; +var SOLID_NAME={cube:'Куб',prism:'Треугольная призма',pyramid:'Пирамида',cylinder:'Цилиндр',cone:'Конус'}; +var SOLID_FEV={cube:[6,12,8],prism:[5,9,6],pyramid:[5,8,5]}; +var NETS={ + cube:'', + pyramid:'', + cylinder:'' +}; + +/* треугольники: классификация по координатам (svg, y вниз) */ +function triClass(A,B,C){ + function d(P,Q){ return Math.hypot(P.x-Q.x,P.y-Q.y); } + var c=d(A,B), a=d(B,C), b=d(C,A); /* a против A, b против B, c против C */ + var arr=[a,b,c].slice().sort(function(x,y){return x-y;}); var eq=function(u,v){return Math.abs(u-v)<6;}; + var side = (eq(a,b)&&eq(b,c))?'равносторонний':((eq(a,b)||eq(b,c)||eq(a,c))?'равнобедренный':'разносторонний'); + var mx=arr[2], rest=arr[0]*arr[0]+arr[1]*arr[1]-arr[2]*arr[2]; + var angle = Math.abs(rest)<60?'прямоугольный':(rest>0?'остроугольный':'тупоугольный'); + /* вершина наибольшего угла = против наибольшей стороны */ + var rv=null; if(angle==='прямоугольный'){ if(mx===a)rv=A; else if(mx===b)rv=B; else rv=C; } + /* равные стороны для штрихов */ + var ticks=[]; + if(side==='равносторонний'){ ticks=[[A,B,1],[B,C,1],[C,A,1]]; } + else if(side==='равнобедренный'){ if(eq(a,b)){ticks=[[B,C,2],[C,A,2]];} else if(eq(b,c)){ticks=[[C,A,2],[A,B,2]];} else {ticks=[[A,B,2],[B,C,2]];} } + return {side:side, angle:angle, ticks:ticks, rv:rv}; +} +function drawTri(A,B,C,info,color){ + color=color||'#d97706'; + var s=''; + (info.ticks||[]).forEach(function(t){ var P=t[0],Q=t[1],n=t[2]; var mx=(P.x+Q.x)/2,my=(P.y+Q.y)/2,dx=Q.x-P.x,dy=Q.y-P.y,L=Math.hypot(dx,dy)||1,ux=dx/L,uy=dy/L,nx=-uy,ny=ux; + for(var k=0;k'; } }); + if(info.rv){ var V=info.rv, o1=(V===A?B:A), o2=(V===C?B:C); var u1x=(o1.x-V.x),u1y=(o1.y-V.y),L1=Math.hypot(u1x,u1y)||1; u1x/=L1;u1y/=L1; var u2x=(o2.x-V.x),u2y=(o2.y-V.y),L2=Math.hypot(u2x,u2y)||1; u2x/=L2;u2y/=L2; var m=12; s+=''; } + return s; +} +var TRIS=[ + [{x:100,y:55},{x:45,y:150},{x:155,y:150}], /* равносторонний остроуг. */ + [{x:100,y:30},{x:60,y:150},{x:140,y:150}], /* равнобедренный остроуг. */ + [{x:50,y:50},{x:50,y:150},{x:150,y:150}], /* прямоуг. равнобедр. */ + [{x:40,y:40},{x:40,y:150},{x:160,y:150}], /* прямоуг. разносторонний */ + [{x:20,y:60},{x:60,y:150},{x:190,y:150}], /* тупоуг. разносторонний */ + [{x:70,y:35},{x:30,y:150},{x:175,y:135}] /* разносторонний остроуг. */ +]; + +/* ===================== § 1. ТЕЛА И РАЗВЁРТКИ ===================== */ +function buildP1(){ + var box=document.getElementById('p1-body'); var h=''; + h+=makeCard('theory','Тела в пространстве','1.1', + '

Окружающие предметы имеют форму геометрических тел: коробка — это прямоугольный параллелепипед (частный случай — куб), палатка — призма, египетские сооружения — пирамида, банка — цилиндр, рожок мороженого — конус.

' + +'

У многогранников есть грани (плоские стороны), рёбра (линии стыка граней) и вершины (точки стыка рёбер).

' + +'
' + +['cube','prism','pyramid','cylinder','cone'].map(function(k){ return '
'+svgWrap(140,120,SOLIDS[k])+'
'+SOLID_NAME[k]+'
'; }).join('')+'
'); + h+=makeCard('theory','Развёртка тела','1.2', + '

Развёртка — это фигура на плоскости, из которой можно склеить тело. У куба развёртка состоит из 6 квадратов, у цилиндра — из прямоугольника и двух кругов.

' + +'
'+svgWrap(160,160,NETS.cube)+svgWrap(160,160,NETS.cylinder)+'
'); + h+='
Интерактив 1
Грани, рёбра, вершины
' + +'
Посмотри на многогранник и ответь, сколько у него граней, рёбер или вершин.
' + +'
Вопрос 1 / 6Очки: 0 / 6
' + +'
' + +'
' + +'
'; + h+='
Интерактив 2
Какое тело из развёртки?
' + +'
Определи, какое тело сложится из показанной развёртки.
' + +'
Вопрос 1 / 4Очки: 0 / 4
' + +'
' + +'
' + +'
'; + h+=secNav(null,'p2')+readBtn('p1'); + box.innerHTML=h; renderMath(box); + + (function(){ + var i=0,score=0,cur=null, polys=['cube','prism','pyramid'], lbl=['граней','рёбер','вершин']; + function gen(){ var k=_pick(polys), j=_ri(0,2); cur={k:k, j:j, ans:SOLID_FEV[k][j]}; } + function show(){ if(i>=6){ document.getElementById('p1-fig').innerHTML=''; document.getElementById('p1-q').innerHTML='Готово! Результат: '+score+' / 6'; if(score>=5){addXp(15,'p1-iv1');bumpProgress('p1',30);}else if(score>=3){addXp(8,'p1-iv1');bumpProgress('p1',16);} return; } + gen(); document.getElementById('p1-i').textContent=i+1; + document.getElementById('p1-fig').innerHTML=svgWrap(140,120,SOLIDS[cur.k]); + document.getElementById('p1-q').innerHTML='Сколько '+lbl[cur.j]+' у тела «'+SOLID_NAME[cur.k]+'»?'; + document.getElementById('p1-a').value=''; document.getElementById('p1-fb').style.display='none'; } + function go(){ if(i>=6)return; var fb=document.getElementById('p1-fb'), v=parseInt(document.getElementById('p1-a').value,10); + if(isNaN(v)){ feedback(fb,false,'Введи число.'); return; } + if(v===cur.ans){ score++; feedback(fb,true,'✓ Верно: '+cur.ans+'.'); } else feedback(fb,false,'✗ Нет. У «'+SOLID_NAME[cur.k]+'» '+cur.ans+' '+lbl[cur.j]+'.'); + document.getElementById('p1-s').textContent=score; i++; setTimeout(show,1300); } + document.getElementById('p1-go').addEventListener('click',go); + document.getElementById('p1-a').addEventListener('keydown',function(e){ if(e.key==='Enter')go(); }); show(); + })(); + + (function(){ + var i=0,score=0,cur=null, keys=['cube','pyramid','cylinder']; + function gen(){ cur=_pick(keys); } + function show(){ if(i>=4){ document.getElementById('p1-dfig').innerHTML=''; document.getElementById('p1-dopts').innerHTML=''; if(score>=3){addXp(15,'p1-iv2');bumpProgress('p1',30);}else if(score>=2){addXp(8,'p1-iv2');bumpProgress('p1',16);} return; } + gen(); document.getElementById('p1-di').textContent=i+1; + document.getElementById('p1-dfig').innerHTML=svgWrap(160,160,NETS[cur]); + var opts=['cube','pyramid','cylinder','cone']; for(var j=opts.length-1;j>0;j--){var k=_ri(0,j),t=opts[j];opts[j]=opts[k];opts[k]=t;} + document.getElementById('p1-dopts').innerHTML=opts.map(function(o){ return ''; }).join(''); + document.querySelectorAll('#p1-dopts [data-o]').forEach(function(b){ b.addEventListener('click',function(){ ans(b.getAttribute('data-o')); }); }); + document.getElementById('p1-dfb').style.display='none'; } + function ans(o){ if(i>=4)return; var fb=document.getElementById('p1-dfb'); + if(o===cur){ score++; feedback(fb,true,'✓ Верно — '+SOLID_NAME[cur]+'.'); } else feedback(fb,false,'✗ Нет. Это развёртка «'+SOLID_NAME[cur]+'».'); + document.getElementById('p1-ds').textContent=score; i++; setTimeout(show,1300); } + show(); + })(); +} + +/* ===================== § 2. ОКРУЖНОСТЬ. КРУГ ===================== */ +function buildP2(){ + var box=document.getElementById('p2-body'); var h=''; + h+=makeCard('theory','Окружность и круг','2.1', + '

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

' + +'

Радиус $r$ — расстояние от центра до окружности; диаметр $d=2r$.

'); + h+=makeCard('rule','Длина окружности и площадь круга','2.2', + '

Длина окружности: $C = 2\\pi r = \\pi d$. Площадь круга: $S = \\pi r^2$.

' + +'

Число $\\pi \\approx 3{,}14$ — отношение длины окружности к диаметру (одинаково для любой окружности).

'); + h+='
Интерактив 1
Радиус, длина, площадь
' + +'
Двигай радиус — смотри, как меняются длина окружности и площадь круга ($\\pi=3{,}14$).
' + +'
' + +'
'; + h+='
Интерактив 2
Тренажёр: вычисли C или S
' + +'
Используй $\\pi=3{,}14$. Ответ — число.
' + +'
Задача 1 / 6Очки: 0 / 6
' + +'
' + +'
' + +'
'; + h+=secNav('p1','p3')+readBtn('p2'); + box.innerHTML=h; renderMath(box); + + (function(){ + var sl=document.getElementById('p2-r'), fig=document.getElementById('p2-fig'), out=document.getElementById('p2-out'); + function render(){ var r=+sl.value; document.getElementById('p2-rv').textContent=r; + var rpx=10+r*11, cx=110, cy=85; + fig.innerHTML=svgWrap(220,170,'r='+r+''); + out.innerHTML='
$C = 2\\pi r = 2\\cdot 3{,}14\\cdot '+r+' = '+_kf(_round(2*PI*r,2))+'$
' + +'
$S = \\pi r^2 = 3{,}14\\cdot '+r+'^2 = '+_kf(_round(PI*r*r,2))+'$
'; renderMath(out); } + sl.oninput=render; render(); + })(); + + (function(){ + var i=0,score=0,cur=null; + function gen(){ var r=_ri(2,10), what=_pick(['C','S']); cur={r:r, what:what, ans:what==='C'?_round(2*PI*r,2):_round(PI*r*r,2)}; } + function show(){ if(i>=6){ document.getElementById('p2-q').innerHTML='Готово! Результат: '+score+' / 6'; if(score>=5){addXp(15,'p2-iv2');bumpProgress('p2',30);}else if(score>=3){addXp(8,'p2-iv2');bumpProgress('p2',16);} return; } + gen(); document.getElementById('p2-i').textContent=i+1; + document.getElementById('p2-q').innerHTML=(cur.what==='C'?'Найди длину окружности $C$':'Найди площадь круга $S$')+' при $r='+cur.r+'$ ($\\pi=3{,}14$).'; renderMath(document.getElementById('p2-q')); + document.getElementById('p2-a').value=''; document.getElementById('p2-fb').style.display='none'; } + function go(){ if(i>=6)return; var fb=document.getElementById('p2-fb'), v=parseFloat(document.getElementById('p2-a').value.replace(',','.').trim()); + if(isNaN(v)){ feedback(fb,false,'Введи число.'); return; } + if(Math.abs(v-cur.ans)<0.011){ score++; feedback(fb,true,'✓ Верно: $'+_kf(cur.ans)+'$.'); } else feedback(fb,false,'✗ Нет. Правильно: $'+_kf(cur.ans)+'$.'); + document.getElementById('p2-s').textContent=score; i++; setTimeout(show,1300); } + document.getElementById('p2-go').addEventListener('click',go); + document.getElementById('p2-a').addEventListener('keydown',function(e){ if(e.key==='Enter')go(); }); show(); + })(); +} + +/* ===================== § 3. ВИДЫ ТРЕУГОЛЬНИКОВ ===================== */ +function buildP3(){ + var box=document.getElementById('p3-body'); var h=''; + h+=makeCard('rule','По сторонам','3.1', + '

Разносторонний — все стороны разные. Равнобедренный — две стороны равны. Равносторонний — все три стороны равны (равные стороны отмечают одинаковыми штрихами).

'); + h+=makeCard('rule','По углам','3.2', + '

Остроугольный — все углы острые ($<90°$). Прямоугольный — есть прямой угол ($=90°$). Тупоугольный — есть тупой угол ($>90°$).

'); + h+='
Интерактив 1
Вид по сторонам
' + +'
Определи вид треугольника по сторонам (штрихи отмечают равные стороны).
' + +'
Вопрос 1 / 5Очки: 0 / 5
' + +'
' + +'
' + +'
'; + h+='
Интерактив 2
Вид по углам
' + +'
Определи вид треугольника по его углам.
' + +'
Вопрос 1 / 5Очки: 0 / 5
' + +'
' + +'
' + +'
'; + h+=secNav('p2','p4')+readBtn('p3'); + box.innerHTML=h; renderMath(box); + + (function(){ + var i=0,score=0,cur=null; + function gen(){ var t=_pick(TRIS), info=triClass(t[0],t[1],t[2]); cur={t:t,info:info}; } + function show(){ if(i>=5){ document.getElementById('p3-fig').innerHTML='Готово! '+score+' / 5'; if(score>=4){addXp(15,'p3-iv1');bumpProgress('p3',30);}else if(score>=2){addXp(8,'p3-iv1');bumpProgress('p3',16);} return; } + gen(); document.getElementById('p3-i').textContent=i+1; + document.getElementById('p3-fig').innerHTML=svgWrap(210,180,drawTri(cur.t[0],cur.t[1],cur.t[2],cur.info)); + document.getElementById('p3-fb').style.display='none'; } + function ans(v){ if(i>=5)return; var fb=document.getElementById('p3-fb'); + if(v===cur.info.side){ score++; feedback(fb,true,'✓ Верно — '+cur.info.side+'.'); } else feedback(fb,false,'✗ Нет. Это '+cur.info.side+' треугольник.'); + document.getElementById('p3-s').textContent=score; i++; setTimeout(show,1300); } + document.querySelectorAll('#p3-iv1 [data-v]').forEach(function(b){ b.addEventListener('click',function(){ ans(b.getAttribute('data-v')); }); }); show(); + })(); + + (function(){ + var i=0,score=0,cur=null; + function gen(){ var t=_pick(TRIS), info=triClass(t[0],t[1],t[2]); cur={t:t,info:info}; } + function show(){ if(i>=5){ document.getElementById('p3-afig').innerHTML='Готово! '+score+' / 5'; if(score>=4){addXp(15,'p3-iv2');bumpProgress('p3',30);}else if(score>=2){addXp(8,'p3-iv2');bumpProgress('p3',16);} return; } + gen(); document.getElementById('p3-ai').textContent=i+1; + document.getElementById('p3-afig').innerHTML=svgWrap(210,180,drawTri(cur.t[0],cur.t[1],cur.t[2],{ticks:[],rv:cur.info.rv})); + document.getElementById('p3-afb').style.display='none'; } + function ans(a){ if(i>=5)return; var fb=document.getElementById('p3-afb'); + if(a===cur.info.angle){ score++; feedback(fb,true,'✓ Верно — '+cur.info.angle+'.'); } else feedback(fb,false,'✗ Нет. Это '+cur.info.angle+' треугольник.'); + document.getElementById('p3-as').textContent=score; i++; setTimeout(show,1300); } + document.querySelectorAll('#p3-iv2 [data-a]').forEach(function(b){ b.addEventListener('click',function(){ ans(b.getAttribute('data-a')); }); }); show(); + })(); +} + +/* ===================== § 4. СИММЕТРИЯ ОТНОСИТЕЛЬНО ТОЧКИ ===================== */ +function buildP4(){ + var box=document.getElementById('p4-body'); var h=''; + h+=makeCard('theory','Центральная симметрия','4.1', + '

Точки $A$ и $A\'$ симметричны относительно точки $O$, если $O$ — середина отрезка $AA\'$. Точка $O$ — центр симметрии.

' + +'

Координаты образа: если $A(x;\\,y)$ и центр $O(a;\\,b)$, то $A\'(2a-x;\\;2b-y)$. Относительно начала координат: $A(x;y)\\to A\'(-x;-y)$.

'); + h+='
Интерактив 1
Построй образ точки
' + +'
Найди координаты точки $A\'$, симметричной $A$ относительно центра $O$.
' + +'
Задача 1 / 5Очки: 0 / 5
' + +'
' + +'
$x\'=$ $y\'=$
' + +'
'; + h+=secNav('p3','p5')+readBtn('p4'); + box.innerHTML=h; renderMath(box); + + (function(){ + var i=0,score=0,cur=null; + function gen(){ var ax=_ri(-4,4),ay=_ri(-4,4),ox=_ri(-2,2),oy=_ri(-2,2); cur={ax:ax,ay:ay,ox:ox,oy:oy,rx:2*ox-ax,ry:2*oy-ay}; } + function show(){ if(i>=5){ document.getElementById('p4-fig').innerHTML=''; document.getElementById('p4-q').innerHTML='Готово! '+score+' / 5'; if(score>=4){addXp(15,'p4-iv1');bumpProgress('p4',35);}else if(score>=2){addXp(8,'p4-iv1');bumpProgress('p4',18);} return; } + gen(); document.getElementById('p4-i').textContent=i+1; + document.getElementById('p4-fig').innerHTML=Math6.plane({size:320,points:[{x:cur.ax,y:cur.ay,label:'A',color:'#d97706'},{x:cur.ox,y:cur.oy,label:'O',color:'#0891b2'}]}); + document.getElementById('p4-q').innerHTML='$A('+cur.ax+';\\,'+cur.ay+')$, центр $O('+cur.ox+';\\,'+cur.oy+')$. Найди $A\''+'$.'; renderMath(document.getElementById('p4-q')); + document.getElementById('p4-x').value=''; document.getElementById('p4-y').value=''; document.getElementById('p4-fb').style.display='none'; } + function go(){ if(i>=5)return; var fb=document.getElementById('p4-fb'), x=parseInt(document.getElementById('p4-x').value,10), y=parseInt(document.getElementById('p4-y').value,10); + if(isNaN(x)||isNaN(y)){ feedback(fb,false,'Введи обе координаты.'); return; } + if(x===cur.rx&&y===cur.ry){ score++; feedback(fb,true,'✓ Верно: $A\'('+cur.rx+';\\,'+cur.ry+')$.'); } else feedback(fb,false,'✗ Нет. $A\'(2\\cdot'+cur.ox+'-'+cur.ax+';\\,\\ldots)=('+cur.rx+';\\,'+cur.ry+')$.'); + document.getElementById('p4-s').textContent=score; i++; setTimeout(show,1500); } + document.getElementById('p4-go').addEventListener('click',go); + document.getElementById('p4-y').addEventListener('keydown',function(e){ if(e.key==='Enter')go(); }); show(); + })(); +} + +/* ===================== § 5. СИММЕТРИЯ ОТНОСИТЕЛЬНО ПРЯМОЙ ===================== */ +function buildP5(){ + var box=document.getElementById('p5-body'); var h=''; + h+=makeCard('theory','Осевая симметрия','5.1', + '

Точки $A$ и $A\'$ симметричны относительно прямой (оси), если эта прямая — серединный перпендикуляр отрезка $AA\'$: она проходит через середину $AA\'$ под прямым углом.

' + +'

Относительно оси $Oy$: $A(x;\\,y)\\to A\'(-x;\\,y)$. Относительно оси $Ox$: $A(x;\\,y)\\to A\'(x;\\,-y)$.

'); + h+='
Интерактив 1
Зеркало относительно оси
' + +'
Найди координаты точки, симметричной $A$ относительно указанной оси.
' + +'
Задача 1 / 6Очки: 0 / 6
' + +'
' + +'
$x\'=$ $y\'=$
' + +'
'; + h+=secNav('p4','final')+readBtn('p5'); + box.innerHTML=h; renderMath(box); + + (function(){ + var i=0,score=0,cur=null; + function gen(){ var ax=_pick([-4,-3,-2,-1,1,2,3,4]),ay=_pick([-4,-3,-2,-1,1,2,3,4]),axis=_pick(['Oy','Ox']); cur={ax:ax,ay:ay,axis:axis,rx:axis==='Oy'?-ax:ax,ry:axis==='Oy'?ay:-ay}; } + function show(){ if(i>=6){ document.getElementById('p5-fig').innerHTML=''; document.getElementById('p5-q').innerHTML='Готово! '+score+' / 6'; if(score>=5){addXp(15,'p5-iv1');bumpProgress('p5',35);}else if(score>=3){addXp(8,'p5-iv1');bumpProgress('p5',18);} return; } + gen(); document.getElementById('p5-i').textContent=i+1; + document.getElementById('p5-fig').innerHTML=Math6.plane({size:320,points:[{x:cur.ax,y:cur.ay,label:'A',color:'#d97706'}]}); + document.getElementById('p5-q').innerHTML='$A('+cur.ax+';\\,'+cur.ay+')$. Найди образ при симметрии относительно оси $'+cur.axis+'$.'; renderMath(document.getElementById('p5-q')); + document.getElementById('p5-x').value=''; document.getElementById('p5-y').value=''; document.getElementById('p5-fb').style.display='none'; } + function go(){ if(i>=6)return; var fb=document.getElementById('p5-fb'), x=parseInt(document.getElementById('p5-x').value,10), y=parseInt(document.getElementById('p5-y').value,10); + if(isNaN(x)||isNaN(y)){ feedback(fb,false,'Введи обе координаты.'); return; } + if(x===cur.rx&&y===cur.ry){ score++; feedback(fb,true,'✓ Верно: $A\'('+cur.rx+';\\,'+cur.ry+')$.'); } else feedback(fb,false,'✗ Нет. Относительно $'+cur.axis+'$: $A\'('+cur.rx+';\\,'+cur.ry+')$.'); + document.getElementById('p5-s').textContent=score; i++; setTimeout(show,1500); } + document.getElementById('p5-go').addEventListener('click',go); + document.getElementById('p5-y').addEventListener('keydown',function(e){ if(e.key==='Enter')go(); }); show(); + })(); +} + +/* ===================== ФИНАЛ ГЛАВЫ — БОССЫ ===================== */ +function buildFinal(){ + var box=document.getElementById('final-body'); var h=''; + h+=makeCard('theory','Финал главы 6','★','

Пять боссов проверят тела, окружность и круг, треугольники и симметрию. Победи всех!

'); + h+='
Боссы
Сразись с главой 6
' + +'
' + +'
Босс 1 / 5Побеждено: 0 / 5
' + +'
' + +'
' + +'
' + +'
'; + h+=secNav('p5',null)+readBtn('final','Завершить главу 6 (+10 XP)'); + box.innerHTML=h; renderMath(box); + + (function(){ + var bosses=[ + function(){ var k=_pick(['cube','prism','pyramid']), j=_ri(0,2), lbl=['граней','рёбер','вершин']; return {name:'Хранитель Тел', fig:svgWrap(140,120,SOLIDS[k]), q:'Сколько '+lbl[j]+' у тела «'+SOLID_NAME[k]+'»?', ans:SOLID_FEV[k][j]}; }, + function(){ var r=_ri(2,8); return {name:'Окружность', fig:'', q:'Найди длину окружности $C=2\\pi r$ при $r='+r+'$ ($\\pi=3{,}14$).', ans:_round(2*PI*r,2)}; }, + function(){ var r=_ri(2,7); return {name:'Площадь Круга', fig:'', q:'Найди площадь круга $S=\\pi r^2$ при $r='+r+'$ ($\\pi=3{,}14$).', ans:_round(PI*r*r,2)}; }, + function(){ var ax=_ri(-4,4),ay=_ri(-4,4); return {name:'Центр Симметрии', fig:Math6.plane({size:280,points:[{x:ax,y:ay,label:'A',color:'#d97706'}]}), q:'Точка $A('+ax+';\\,'+ay+')$. Найди абсциссу точки, симметричной $A$ относительно начала координат.', ans:-ax}; }, + function(){ var ax=_pick([-4,-3,-2,-1,1,2,3,4]),ay=_ri(-4,4); return {name:'Зеркало', fig:'', q:'Точка $A('+ax+';\\,'+ay+')$. Найди абсциссу образа при симметрии относительно оси $Oy$.', ans:-ax}; } + ]; + var i=0,score=0,cur=null,done=false; + function show(){ if(i>=5){ done=true; document.getElementById('fin-name').textContent=''; document.getElementById('fin-fig').innerHTML=''; document.getElementById('fin-q').innerHTML=(score>=4?'Победа! Глава 6 пройдена. ':'Бой окончен. ')+'Побеждено боссов: '+score+' / 5.'; document.getElementById('fin-hp').style.width=(score>=4?0:40)+'%'; + if(score>=4){ addXp(40,'final'); bumpProgress('final',100); if(window.confetti)try{confetti();}catch(e){} } else bumpProgress('final',60); return; } + cur=bosses[i](); document.getElementById('fin-i').textContent=i+1; document.getElementById('fin-s').textContent=score; + document.getElementById('fin-name').textContent='Босс '+(i+1)+': '+cur.name; + document.getElementById('fin-hp').style.width=(100-i*20)+'%'; + document.getElementById('fin-fig').innerHTML=cur.fig||''; + document.getElementById('fin-q').innerHTML=cur.q; renderMath(document.getElementById('fin-q')); + document.getElementById('fin-a').value=''; document.getElementById('fin-fb').style.display='none'; } + function go(){ if(done||i>=5)return; var fb=document.getElementById('fin-fb'), v=parseFloat(document.getElementById('fin-a').value.replace(',','.').trim()); + if(isNaN(v)){ feedback(fb,false,'Введи число.'); return; } + if(Math.abs(v-cur.ans)<0.011){ score++; feedback(fb,true,'✓ Босс повержен! Ответ '+_kf(cur.ans)+'.'); } else feedback(fb,false,'✗ Босс устоял. Верно: '+_kf(cur.ans)+'.'); + document.getElementById('fin-s').textContent=score; i++; setTimeout(show,1400); } + document.getElementById('fin-go').addEventListener('click',go); + document.getElementById('fin-a').addEventListener('keydown',function(e){ if(e.key==='Enter')go(); }); show(); + })(); +} + +/* ===================== ДАННЫЕ ===================== */ +var SIDEBARS = { + p1:{ title:'Шпаргалка § 1', rows:[ + ['Грань','плоская сторона тела'], + ['Ребро','линия стыка граней'], + ['Вершина','точка стыка рёбер'], + ['Куб','6 граней, 12 рёбер, 8 вершин'], + ['Развёртка','фигура, из которой склеивают тело'] ]}, + p2:{ title:'Шпаргалка § 2', rows:[ + ['Радиус','$r$ — центр→окружность'], + ['Диаметр','$d=2r$'], + ['Длина окружности','$C=2\\pi r=\\pi d$'], + ['Площадь круга','$S=\\pi r^2$'], + ['$\\pi$','$\\approx 3{,}14$'] ]}, + p3:{ title:'Шпаргалка § 3', rows:[ + ['По сторонам','разносторонний / равнобедренный / равносторонний'], + ['По углам','остро- / прямо- / тупоугольный'], + ['Прямоугольный','есть угол $90°$'], + ['Тупоугольный','есть угол $>90°$'] ]}, + p4:{ title:'Шпаргалка § 4', rows:[ + ['Центр. симметрия','$O$ — середина $AA\'$'], + ['Образ','$A\'(2a-x;\\,2b-y)$'], + ['Относ. нуля','$A(x;y)\\to A\'(-x;-y)$'] ]}, + p5:{ title:'Шпаргалка § 5', rows:[ + ['Осевая симметрия','ось — серединный перпендикуляр $AA\'$'], + ['Относ. $Oy$','$(x;y)\\to(-x;y)$'], + ['Относ. $Ox$','$(x;y)\\to(x;-y)$'] ]}, + final:{ title:'Финал главы 6', rows:[ + ['5 боссов','тела, окружность, круг, симметрия'], + ['Победа','4 из 5 и больше'], + ['Награда','+40 XP и достижение «Глава 6 пройдена»'] ]} +}; +var TIPS = [ + { sec:'p1', html:'Грани — это «стенки», рёбра — «края», вершины — «уголки». У куба: 6 стенок, 12 краёв, 8 уголков.' }, + { sec:'p2', html:'Сначала реши, что ищешь: длину ($C=2\\pi r$) или площадь ($S=\\pi r^2$). Не путай $r$ и $d=2r$.' }, + { sec:'p3', html:'Вид по сторонам и вид по углам — разные классификации. Равнобедренный может быть и остро-, и прямо-, и тупоугольным.' }, + { sec:'p4', html:'Центр симметрии — это середина. Координаты образа: удвой координаты центра и вычти координаты точки: $2a-x$.' }, + { sec:'p5', html:'Относительно оси $Oy$ меняется знак $x$; относительно оси $Ox$ — знак $y$. Вторая координата остаётся прежней.' } +]; +var GLOSSARY = [ + { term:'грань', def:'Плоская сторона многогранника.', sec:'p1', aliases:['грань','грани','граней','гранью'] }, + { term:'ребро', def:'Линия, по которой пересекаются две грани.', sec:'p1', aliases:['ребро','ребра','рёбра','рёбер'] }, + { term:'вершина', def:'Точка, в которой сходятся рёбра.', sec:'p1', aliases:['вершина','вершины','вершин','вершиной'] }, + { term:'развёртка', def:'Фигура на плоскости, из которой можно склеить тело.', sec:'p1', aliases:['развёртка','развёртки','развёрток','развёртку'] }, + { term:'окружность', def:'Замкнутая линия, все точки которой равноудалены от центра.', sec:'p2', aliases:['окружность','окружности','окружностью'] }, + { term:'круг', def:'Часть плоскости, ограниченная окружностью.', sec:'p2', aliases:['круг','круга','круге','кругом'] }, + { term:'радиус', def:'Расстояние от центра до окружности; $d=2r$.', sec:'p2', aliases:['радиус','радиуса','радиусе','радиусом'] }, + { term:'диаметр', def:'Отрезок через центр; $d=2r$.', sec:'p2', aliases:['диаметр','диаметра','диаметре','диаметром'] }, + { term:'центральная симметрия', def:'Симметрия относительно точки $O$ — середины $AA\'$.', sec:'p4', aliases:['центральная симметрия','центральной симметрии','центр симметрии','центра симметрии'] }, + { term:'осевая симметрия', def:'Симметрия относительно прямой — серединного перпендикуляра $AA\'$.', sec:'p5', aliases:['осевая симметрия','осевой симметрии','ось симметрии','оси симметрии'] } +]; +var BUILDERS = { p1:buildP1, p2:buildP2, p3:buildP3, p4:buildP4, p5:buildP5, final:buildFinal }; +Object.assign(window.M6, { sidebars:SIDEBARS, tips:TIPS, glossary:GLOSSARY, builders:BUILDERS });