«Решить треугольник» — значит найти все его стороны и углы. Какие случаи бывают:
+
+
3 стороны $(a,b,c)$: углы — по теореме косинусов; площадь — по Герону.
+
2 стороны и угол между ними $(a, b, C)$: 3-я сторона — по теореме косинусов; остальные углы — по теореме синусов; площадь $S = \\tfrac{1}{2}ab\\sin C$.
+
1 сторона и 2 угла $(a, A, B)$: 3-й угол $C = 180° - A - B$; остальные стороны — по теореме синусов.
+
2 стороны и угол не между ними: может быть 0, 1 или 2 решения (неоднозначный случай).
+
+
Пример. $a = 5$, $b = 7$, угол между ними $C = 60°$.
Задай стороны $a, b, c$ ползунками. Если они удовлетворяют неравенству треугольника, увидишь треугольник; площадь, углы и радиусы вычисляются автоматически.
+
+
+
+
+
+
+
+
+
+
`;
+
+ /* IV2 — Калькулятор Герона */
+ html += `
+
ИНТЕРАКТИВ 2
Калькулятор Герона
+
Введи длины трёх сторон — программа найдёт площадь по формуле Герона.
+
+
+
+
+
+
+
+
+
`;
+
+ /* IV3 — Какой случай / какой метод? */
+ html += `
+
ИНТЕРАКТИВ 3
Какой метод применим?
+
Дано — какой инструмент быстрее всего приведёт к ответу? Выбери из четырёх.
+
Задача 1 / 6Очки: 0 / 6
+
+
+
+
+
+
+
+
+
`;
+
+ /* IV4 — Тренажёр */
+ html += `
+
ИНТЕРАКТИВ 4
Тренажёр Герона
+
Реши задачу и введи площадь (округляй до 2 знаков после запятой).
+
Задача 1 / 6Очки: 0 / 6
+
+
+ $S =$
+
+
+
+
+
+
`;
+
+ html += readButton('p12');
+ html += secNav('p11', 'final3');
+
+ box.innerHTML = html;
+ renderMath(box);
+
+ /* IV1 — Slider 3-х сторон */
+ (function(){
+ const sA=document.getElementById('p12-iv1-a');
+ const sB=document.getElementById('p12-iv1-b');
+ const sC=document.getElementById('p12-iv1-c');
+ const lA=document.getElementById('p12-iv1-aval');
+ const lB=document.getElementById('p12-iv1-bval');
+ const lC=document.getElementById('p12-iv1-cval');
+ const svg=document.getElementById('p12-iv1-svg');
+ const out=document.getElementById('p12-iv1-out');
+ const seen=new Set();
+ function draw(){
+ const a=+sA.value, b=+sB.value, c=+sC.value;
+ lA.textContent=a; lB.textContent=b; lC.textContent=c;
+ // Неравенство треугольника
+ if(a+b<=c || a+c<=b || b+c<=a){
+ svg.innerHTML=''
+ +'Невозможный треугольник'
+ +'Сумма двух сторон должна быть больше третьей';
+ out.innerHTML='Неравенство треугольника не выполнено: $a + b > c$, $a + c > b$, $b + c > a$.';
+ renderMath(out);
+ return;
+ }
+ // Построение треугольника: A в начале, B = (c, 0); C находим по теореме косинусов через cos A
+ const cosA=(b*b+c*c-a*a)/(2*b*c);
+ const sinA=Math.sqrt(Math.max(0,1-cosA*cosA));
+ // в локальных координатах: A=(0,0), B=(c,0), C=(b*cosA, b*sinA)
+ const Ax=0, Ay=0, Bx=c, By=0, Cx=b*cosA, Cy=b*sinA;
+ // масштабируем в SVG 420×320 с полем 40
+ const minX=Math.min(Ax,Bx,Cx), maxX=Math.max(Ax,Bx,Cx);
+ const minY=Math.min(Ay,Cy), maxY=Math.max(By,Cy);
+ const W=420, H=320, pad=46;
+ const sx=(W-2*pad)/(maxX-minX||1), sy=(H-2*pad)/(maxY-minY||1);
+ const s_=Math.min(sx,sy);
+ function T(X,Y){ return {x: pad+(X-minX)*s_, y: H-pad-(Y-minY)*s_}; }
+ const Av=T(Ax,Ay), Bv=T(Bx,By), Cv=T(Cx,Cy);
+ // углы
+ const cosB_=(a*a+c*c-b*b)/(2*a*c); const cosC_=(a*a+b*b-c*c)/(2*a*b);
+ const Aang=Math.acos(Math.max(-1,Math.min(1,cosA)))*180/Math.PI;
+ const Bang=Math.acos(Math.max(-1,Math.min(1,cosB_)))*180/Math.PI;
+ const Cang=Math.acos(Math.max(-1,Math.min(1,cosC_)))*180/Math.PI;
+ const p=(a+b+c)/2;
+ const S=Math.sqrt(Math.max(0,p*(p-a)*(p-b)*(p-c)));
+ const R=(a*b*c)/(4*S||1e-9);
+ const r=S/(p||1e-9);
+ const mA=0.5*Math.sqrt(2*b*b+2*c*c-a*a);
+ const mB=0.5*Math.sqrt(2*a*a+2*c*c-b*b);
+ const mC=0.5*Math.sqrt(2*a*a+2*b*b-c*c);
+ let s='';
+ s += '';
+ s += '';
+ // подписи сторон
+ const midAB={x:(Av.x+Bv.x)/2, y:(Av.y+Bv.y)/2};
+ const midAC={x:(Av.x+Cv.x)/2, y:(Av.y+Cv.y)/2};
+ const midBC={x:(Bv.x+Cv.x)/2, y:(Bv.y+Cv.y)/2};
+ s += 'c = '+c+'';
+ s += 'b = '+b+'';
+ s += 'a = '+a+'';
+ // вершины с подписями
+ [['A',Av,-14,18],['B',Bv,14,18],['C',Cv,0,-10]].forEach(([n,P,dx,dy])=>{
+ s += '';
+ s += ''+n+'';
+ });
+ svg.innerHTML=s;
+ out.innerHTML = 'Полупериметр: $p = '+p.toFixed(2)+'$ · Площадь (Герон): $S \\approx '+S.toFixed(2)+'$ '
+ + 'Углы: $A \\approx '+Aang.toFixed(1)+'°$, $B \\approx '+Bang.toFixed(1)+'°$, $C \\approx '+Cang.toFixed(1)+'°$ '
+ + 'Радиусы: $R \\approx '+R.toFixed(2)+'$, $r \\approx '+r.toFixed(2)+'$ '
+ + 'Медианы: $m_a \\approx '+mA.toFixed(2)+'$, $m_b \\approx '+mB.toFixed(2)+'$, $m_c \\approx '+mC.toFixed(2)+'$';
+ renderMath(out);
+ seen.add(a+'|'+b+'|'+c);
+ if(seen.size>=4 && !seen.has('done')){ addXp(10,'p12-iv1'); bumpProgress('p12',15); seen.add('done'); }
+ }
+ [sA,sB,sC].forEach(s=>s.addEventListener('input', draw));
+ draw();
+ })();
+
+ /* IV2 — Калькулятор Герона */
+ (function(){
+ const aI=document.getElementById('p12-iv2-a');
+ const bI=document.getElementById('p12-iv2-b');
+ const cI=document.getElementById('p12-iv2-c');
+ const go=document.getElementById('p12-iv2-go');
+ const out=document.getElementById('p12-iv2-out');
+ const fb=document.getElementById('p12-iv2-fb');
+ let solved=0;
+ go.addEventListener('click', ()=>{
+ const a=parseFloat(aI.value), b=parseFloat(bI.value), c=parseFloat(cI.value);
+ if(!isFinite(a)||!isFinite(b)||!isFinite(c)){ feedback(fb,false,'✗ Введи все значения.'); return; }
+ if(a<=0||b<=0||c<=0){ feedback(fb,false,'✗ Стороны должны быть положительными.'); return; }
+ if(a+b<=c||a+c<=b||b+c<=a){ feedback(fb,false,'✗ Неравенство треугольника не выполняется.'); return; }
+ const p=(a+b+c)/2;
+ const inner=p*(p-a)*(p-b)*(p-c);
+ const S=Math.sqrt(Math.max(0,inner));
+ out.innerHTML = '$p = \\dfrac{a+b+c}{2} = \\dfrac{'+a+'+'+b+'+'+c+'}{2} = '+p.toFixed(2)+'$ '
+ + '$S = \\sqrt{p(p-a)(p-b)(p-c)} = \\sqrt{'+p.toFixed(2)+' \\cdot '+(p-a).toFixed(2)+' \\cdot '+(p-b).toFixed(2)+' \\cdot '+(p-c).toFixed(2)+'}$ '
+ + '$S = \\sqrt{'+inner.toFixed(3)+'} \\approx '+S.toFixed(3)+'$';
+ renderMath(out);
+ feedback(fb,true,'✓ Площадь найдена.');
+ solved++;
+ if(solved===1){ addXp(10,'p12-iv2'); bumpProgress('p12',10); }
+ });
+ })();
+
+ /* IV3 — Какой метод? */
+ (function(){
+ const Q=[
+ {t:'Известны три стороны треугольника. Найти его площадь.', a:'heron'},
+ {t:'Известны две стороны и угол между ними. Найти площадь.', a:'sab'},
+ {t:'Известны три стороны. Найти один из углов.', a:'cos'},
+ {t:'Известны сторона и противолежащий ей угол. Найти радиус описанной окружности.', a:'sin'},
+ {t:'Известны два угла и одна сторона. Найти другую сторону.', a:'sin'},
+ {t:'Известны две стороны и угол между ними. Найти третью сторону.', a:'cos'}
+ ];
+ const explain={
+ heron:'$S = \\sqrt{p(p-a)(p-b)(p-c)}$ — площадь без углов и высот.',
+ cos:'$a^2 = b^2+c^2-2bc\\cos A$ — связывает 3 стороны и угол.',
+ sin:'$\\dfrac{a}{\\sin A} = 2R$ — пара (сторона; противолежащий угол).',
+ sab:'$S = \\tfrac{1}{2}ab\\sin C$ — площадь через две стороны и угол между ними.'
+ };
+ const labels={heron:'формула Герона', cos:'теорема косинусов', sin:'теорема синусов', sab:'$S = \\tfrac{1}{2}ab\\sin C$'};
+ const qBox=document.getElementById('p12-iv3-q');
+ const iEl=document.getElementById('p12-iv3-i');
+ const sEl=document.getElementById('p12-iv3-s');
+ const fb=document.getElementById('p12-iv3-fb');
+ const btns=document.querySelectorAll('#p12-iv3 button[data-ans]');
+ let i=0, score=0, done=false;
+ function show(){
+ if(i>=Q.length){
+ qBox.innerHTML='Завершено! Очки: '+score+' / '+Q.length;
+ if(!done){ done=true; addXp(15,'p12-iv3'); bumpProgress('p12',25); if(score===Q.length) achievement('p12_done'); }
+ btns.forEach(b=>b.disabled=true);
+ return;
+ }
+ qBox.innerHTML=Q[i].t; renderMath(qBox);
+ iEl.textContent=(i+1); sEl.textContent=score;
+ fb.style.display='none';
+ }
+ btns.forEach(b=>b.addEventListener('click', ()=>{
+ const ok = b.dataset.ans===Q[i].a;
+ if(ok) score++;
+ feedback(fb, ok, ok?('✓ Верно! '+explain[Q[i].a]):('✗ Правильно: '+labels[Q[i].a]+'. '+explain[Q[i].a]));
+ i++;
+ setTimeout(show, 1100);
+ }));
+ show();
+ })();
+
+ /* IV4 — Тренажёр Герона */
+ (function(){
+ const Q=[
+ {t:'Треугольник со сторонами $3, 4, 5$. Найди площадь $S$.', a:6, tol:0.02},
+ {t:'Треугольник со сторонами $5, 5, 6$. Найди площадь $S$.', a:12, tol:0.02},
+ {t:'Треугольник со сторонами $7, 8, 9$. Найди площадь $S$.', a:26.83, tol:0.05},
+ {t:'Треугольник со сторонами $6, 8, 10$. Найди площадь $S$.', a:24, tol:0.02},
+ {t:'Треугольник со сторонами $13, 14, 15$. Найди площадь $S$.', a:84, tol:0.05},
+ {t:'Стороны $a = 4$, $b = 6$, угол между ними $C = 90°$. Найди $S$.', a:12, tol:0.02}
+ ];
+ const qBox=document.getElementById('p12-iv4-q');
+ const ans=document.getElementById('p12-iv4-ans');
+ const go=document.getElementById('p12-iv4-go');
+ const reset=document.getElementById('p12-iv4-start');
+ const iEl=document.getElementById('p12-iv4-i');
+ const sEl=document.getElementById('p12-iv4-s');
+ const fb=document.getElementById('p12-iv4-fb');
+ let i=0, score=0, done=false;
+ function show(){
+ if(i>=Q.length){
+ qBox.innerHTML='Финиш! Очки: '+score+' / '+Q.length;
+ if(!done){ done=true; addXp(15,'p12-iv4'); bumpProgress('p12',25); }
+ go.disabled=true; ans.disabled=true;
+ return;
+ }
+ qBox.innerHTML=Q[i].t; renderMath(qBox);
+ iEl.textContent=(i+1); sEl.textContent=score;
+ ans.value=''; fb.style.display='none'; go.disabled=false; ans.disabled=false;
+ }
+ go.addEventListener('click', ()=>{
+ const v=parseFloat((ans.value||'').replace(',', '.'));
+ if(!isFinite(v)){ feedback(fb,false,'✗ Введи число.'); return; }
+ const tol=Q[i].tol||0.05;
+ const ok=Math.abs(v-Q[i].a)<=tol;
+ if(ok) score++;
+ feedback(fb, ok, ok?'✓ Верно!':'✗ Правильный ответ: $'+Q[i].a+'$');
+ i++;
+ setTimeout(show, 1000);
+ });
+ reset.addEventListener('click', ()=>{ i=0; score=0; done=false; show(); });
+ show();
+ })();
+
+ wireReadBtn('p12');
+}
function buildFinal3(){
- const body = document.getElementById('final3-body');
+ const box = document.getElementById('final3-body');
let html = '';
- html += makeCard('theory', 'Финал главы 3', '★', `
-
Итоговый раздел главы «Теоремы синусов и косинусов» будет добавлен в следующих обновлениях.
-
Раздел Phase 7.
`);
- html += readButton('final3');
+
+ /* Часть А — Шпаргалка главы (3 mini-карточки) */
+ html += `
+
+
${ICONS.theory}
+
Шпаргалка главы 3
+
Итог
+
+
+
Главные формулы главы «Теоремы синусов и косинусов» — в одном месте. Просмотри перед боссами!
$a^2 = b^2 + c^2 - 2bc\\cos A$ — обобщение Пифагора. По 3 сторонам — любой угол; по 2 сторонам и углу — 3-я сторона.
+
+
+
+
+ § 12 · Формула Герона
+
+
$S = \\sqrt{p(p-a)(p-b)(p-c)}$, где $p = \\dfrac{a+b+c}{2}$ — полупериметр. Площадь по трём сторонам.
+
+
+
+
`;
+
+ /* Часть Б — 5 боссов */
+ html += `
+
+
${ICONS.rule}
+
Боссы главы 3
+
5
+
+
+
5 интегрированных задач — каждая комбинирует темы §§10–12. За каждого побеждённого босса — +10 XP и +18% к прогрессу. Победишь всех — +50 XP бонус и ачивка «Магистр треугольников»!
+
+
`;
+
+ html += '';
+
+ html += `
+
Прогресс по боссам
+
0 / 5 боссов побеждено
+
+
+
+
+
+
+
Магистр треугольников
+
+
Глава 3 пройдена! Все 5 боссов повержены. +50 XP бонус.