From ac10ebdd210a7620d384b38bd2186301e166d232 Mon Sep 17 00:00:00 2001 From: Maxim Dolgolyov Date: Thu, 28 May 2026 20:33:48 +0300 Subject: [PATCH] =?UTF-8?q?feat(geom8):=20Wave=205=20=E2=80=94=20=D1=84?= =?UTF-8?q?=D0=B8=D0=BD=D0=B0=D0=BB=20=D0=93=D0=BB=D0=B0=D0=B2=D1=8B=204?= =?UTF-8?q?=20(=D0=9F=D0=9E=D0=A1=D0=9B=D0=95=D0=94=D0=9D=D0=98=D0=99=20?= =?UTF-8?q?=D0=BF=D0=B0=D1=80=D0=B0=D0=B3=D1=80=D0=B0=D1=84=20=D0=93=D0=B5?= =?UTF-8?q?=D0=BE=D0=BC=D0=B5=D1=82=D1=80=D0=B8=D0=B8=208!)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Часть 1: 16 mini-cards со SVG-иконками и формулами в KaTeX для всех §1-§16 (касательные, дуги, вписанные углы, произведения). Часть 2: интерактивная карта связей (SVG 620×360): центральный узел 'ОКРУЖНОСТЬ' → 3 ветви (Касательные §1-7, Углы §8-14, Отрезки §15-16). Кликабельные узлы с формулами. Часть 3: 7 интегрированных боссов (по 10 XP): Босс 1 (§1+§3): R=5, OP=13 → PT=12, периметр=34 Босс 2 (§9+§11): диаметр AB, ∠CAB=35° → ∠ACB=90°, ∠ABC=55° Босс 3 (§10+§13): хорды, дуги 70°/50° → ∠P=60°, ∠ADC=35° Босс 4 (§14): две секущие, дуги 100°/40° → ∠P=30° Босс 5 (§15): PA=4 PB=9 PC=6 → PD=6 Босс 6 (§16): PT=8 AB=12 → PA=4, PB=16 Босс 7 (§7): R₁=6 R₂=2 d=10 → ℓ=√84≈9.17 Часть 4: финальная плашка с confetti + achievement 'Мастер окружностей Главы 4' + 50 XP бонус + переход к /textbooks. File: 6712 → 7381 LOC. ГЛАВА 4 ПОЛНОСТЬЮ ЗАВЕРШЕНА. 🎉 ВСЯ ГЕОМЕТРИЯ 8 ЗАВЕРШЕНА: Глава 1 (Многоугольники, 16§+финал): 5560 LOC Глава 2 (Площади, 15§+финал): 7144 LOC Глава 3 (Подобие, 9§+финал): 4709 LOC Глава 4 (Окружности, 16§+финал): 7381 LOC Итого: 56 параграфов + 4 финала = 60 разделов, 24,794 LOC. Co-Authored-By: Claude Opus 4.7 (1M context) --- frontend/textbooks/geometry_8_ch4.html | 667 ++++++++++++++++++++++++- 1 file changed, 665 insertions(+), 2 deletions(-) diff --git a/frontend/textbooks/geometry_8_ch4.html b/frontend/textbooks/geometry_8_ch4.html index 32880e2..fee5bb4 100644 --- a/frontend/textbooks/geometry_8_ch4.html +++ b/frontend/textbooks/geometry_8_ch4.html @@ -359,7 +359,7 @@ const PARAS=[ function buildParaSelector(){const g=document.getElementById('psel-grid');g.innerHTML='';PARAS.forEach(p=>{const card=document.createElement('div');card.className='psel-card'+(p.final?' final':'');card.dataset.id=p.id;card.dataset.progCard=p.id;card.innerHTML=`
${p.num}
${p.name}
`;card.addEventListener('click',()=>goTo(p.id));g.appendChild(card);});} const BUILT=new Set(); -const BUILDERS={p1:()=>buildP1(),p2:()=>buildP2(),p3:()=>buildP3(),p4:()=>buildP4(),p5:()=>buildP5(),p6:()=>buildP6(),p7:()=>buildP7(),p8:()=>buildP8(),p9:()=>buildP9(),p10:()=>buildP10(),p11:()=>buildP11(),p12:()=>buildP12(),p13:()=>buildP13(),p14:()=>buildP14(),p15:()=>buildP15(),p16:()=>buildP16(),final4:()=>buildFinal4stub()}; +const BUILDERS={p1:()=>buildP1(),p2:()=>buildP2(),p3:()=>buildP3(),p4:()=>buildP4(),p5:()=>buildP5(),p6:()=>buildP6(),p7:()=>buildP7(),p8:()=>buildP8(),p9:()=>buildP9(),p10:()=>buildP10(),p11:()=>buildP11(),p12:()=>buildP12(),p13:()=>buildP13(),p14:()=>buildP14(),p15:()=>buildP15(),p16:()=>buildP16(),final4:()=>buildFinal4()}; function ensureBuilt(id){if(BUILT.has(id))return;const fn=BUILDERS[id];if(fn){fn();BUILT.add(id);}} function goTo(id){STATE.current=id;ensureBuilt(id);document.querySelectorAll('.sec').forEach(s=>s.classList.remove('active'));const el=document.getElementById('sec-'+id);if(el)el.classList.add('active');document.querySelectorAll('.psel-card').forEach(c=>c.classList.toggle('active',c.dataset.id===id));buildSidebar(id);window.scrollTo({top:0,behavior:'smooth'});if((STATE.progress[id]||0)<10)bumpProgress(id,10);if(window.renderMathInElement)setTimeout(()=>renderMath(el),0);setTimeout(()=>{try{wrapGlossary(el);}catch(e){}},60);markLastPara(id);} @@ -6712,7 +6712,670 @@ function buildP16(){ if(window.renderMathInElement) try{renderMath(cont);}catch(e){} })(); } -function buildFinal4stub(){ document.getElementById('final4-body').innerHTML='

Финал главы 4 — Волна 1: боссы и итоги появятся в следующем обновлении.

'+secNav('p16',null); } +function buildFinal4(){ + const box = document.getElementById('final4-body'); + let html = ''; + + /* === ЧАСТЬ 1: Итоговая шпаргалка === */ + html += `
+
+
+ +
+
Итоговая шпаргалка · Вся Глава 4 «Окружности»
+
+
+
+ +
+
§1 Признак касательной
+
+ + + + + + + R + t + +
+

$t \\perp R \\Leftrightarrow d = R$

+

касательная ⊥ радиусу

+
+
+
+ +
+
§2 Свойство касательной
+
+

$OT \\perp t,\\; OT = R$

+

расстояние $d(O,t) = R$

+

перпендикуляр из центра

+
+
+ +
+
§3 Касательные из точки
+
+ + + + + + + + A + T1 + T2 + +
+

$AT_1 = AT_2$

+

равны, $OA$ — биссектриса

+
+
+
+ +
+
§4 Построение касательной
+
+

окружность на $OA$ как диаметре

+

точки пересечения $T_1, T_2$

+

$\\angle OT_1A = 90°$ (Фалес)

+
+
+ +
+
§5 Окружность в угол
+
+

центр на биссектрисе угла

+

$R = d(O, \\ \\ \text{стор})$

+

вписана в угол

+
+
+ +
+
§6 Два круга: 5 случаев
+
+ + + + + + + O1 + O2 + +
+

$d > R_1{+}R_2$: нет точек

+

$d = R_1{+}R_2$: вн. касание

+

5 взаим. расположений

+
+
+
+ +
+
§7 Общая касательная
+
+

внешняя: $\\ell = \\sqrt{d^2-(R_1-R_2)^2}$

+

внутренняя: $\\ell = \\sqrt{d^2-(R_1+R_2)^2}$

+

$d$ — расст. между центрами

+
+
+ +
+
§8 Центральный и дуга
+
+ + + + + + + O + A + B + + +
+

$\\angle AOB$ — центр. угол

+

дуга $\\smile AB = \\angle AOB$

+
+
+
+ +
+
§9 Вписанный угол
+
+ + + + + + + + C + A + B + +
+

$\\angle ACB = \\dfrac{1}{2}\\angle AOB$

+

= ½ центрального

+
+
+
+ +
+
§10 Углы на одну дугу
+
+

$\\angle ACB = \\angle ADB$

+

$C, D$ на одной стороне от $AB$

+

вписанные углы равны

+
+
+ +
+
§11 Угол на диаметр
+
+ + + + + + + + + + A + B + C + +
+

$\\angle ACB = 90°$

+

$AB$ — диаметр

+
+
+
+ +
+
§12 Угол касат. и хорды
+
+

$\\angle(t, AB) = \\dfrac{1}{2}\\smile AB$

+

= ½ дуга, стянутой хордой

+
+
+ +
+
§13 Угол двух хорд
+
+

$\\angle P = \\dfrac{1}{2}(\\smile AC + \\smile BD)$

+

хорды пересекаются внутри

+
+
+ +
+
§14 Угол двух секущих
+
+

$\\angle P = \\dfrac{1}{2}|\\smile AC - \\smile BD|$

+

секущие из внешней точки

+
+
+ +
+
§15 Произведение хорд
+
+ + + + + + P + A + B + C + D + +
+

$PA \\cdot PB = PC \\cdot PD$

+

хорды AB, CD пересеч. в P

+
+
+
+ +
+
§16 Касательная и секущая
+
+ + + + + + + P + T + A B + +
+

$PT^2 = PA \\cdot PB$

+

T — точка касания

+
+
+
+ +
+
+
`; + + /* === ЧАСТЬ 2: Интерактивная карта связей === */ + html += `
+
КАРТА СВЯЗЕЙ
Окружность: касательные, углы, произведения отрезков
+
Нажми на узел, чтобы увидеть формулу и способ применения.
+
+
Нажми на узел в схеме выше
+
`; + + /* === ЧАСТЬ 3: 7 боссов === */ + html += `
+
+ 7 БОССОВ ГЛАВЫ 4 +
Интегрированные задачи
+
+
Каждая задача объединяет 2–3 темы главы. +10 XP за каждого побеждённого босса. Победи всех семерых — получишь +50 XP и достижение «Мастер окружностей Главы 4»!
+
+
`; + + /* === ЧАСТЬ 4: Финальная плашка === */ + html += ``; + + html += `
+ +
`; + + html += secNav('p16', null); + box.innerHTML = html; + + /* === JS: Карта связей SVG === */ + (function(){ + const W = 620, H = 360; + const nodes = [ + { id:'circ', x:310, y:30, rx:64, label:'ОКРУЖНОСТЬ', + props:'Центральная тема главы 4. Окружность радиуса $R$ с центром $O$ — множество точек, равноудалённых от $O$.' }, + { id:'tang', x:100, y:120, rx:60, label:'Касательные §1–7', + props:'§1–7: касательная $\\perp$ радиусу в точке касания; из внешней точки равны два отрезка касательных; 5 взаимных расположений окружностей; $\\ell = \\sqrt{d^2-(R_1{\\pm}R_2)^2}$.' }, + { id:'angl', x:310, y:120, rx:60, label:'Углы §8–14', + props:'§8–14: центральный угол = дуга; вписанный = ½ центрального; углы на одну дугу равны; угол на диаметр = 90°; угол (касательная, хорда) = ½ дуга; угол двух хорд = ½(дуга₁+дуга₂); угол двух секущих = ½|дуга₁−дуга₂|.' }, + { id:'prod', x:510, y:120, rx:60, label:'Отрезки §15–16', + props:'§15: хорды $PA\\cdot PB = PC\\cdot PD$. §16: касательная и секущая $PT^2 = PA\\cdot PB$. Оба факта доказываются через подобие треугольников.' }, + { id:'t13', x:80, y:230, rx:52, label:'§3 Равные касат.', + props:'§3: из внешней точки $A$ отрезки касательных равны: $AT_1 = AT_2$. Прямая $OA$ является биссектрисой угла $T_1AT_2$.' }, + { id:'t67', x:220, y:230, rx:52, label:'§6–7 Два круга', + props:'§6–7: 5 случаев взаимного расположения; длина внешней общей касательной $\\ell = \\sqrt{d^2-(R_1-R_2)^2}$, внутренней $\\ell = \\sqrt{d^2-(R_1+R_2)^2}$.' }, + { id:'t911', x:380, y:230, rx:52, label:'§9–11 Вписанный', + props:'§9: вписанный угол = ½ центрального. §10: вписанные на одну дугу равны. §11: вписанный угол, опирающийся на диаметр, равен 90°.' }, + { id:'t1214', x:530, y:230, rx:52, label:'§12–14 Угол и дуга', + props:'§12: угол между касательной и хордой = ½ дуга. §13: угол между двумя хордами = ½(дуга₁+дуга₂). §14: угол между двумя секущими из внешней точки = ½|дуга₁−дуга₂|.' }, + { id:'t15', x:200, y:320, rx:52, label:'§15 Хорды', + props:'§15: если хорды $AB$ и $CD$ пересекаются в точке $P$ внутри окружности, то $PA\\cdot PB = PC\\cdot PD$. Доказывается через подобие $\\triangle PAC\\sim\\triangle PDB$.' }, + { id:'t16', x:420, y:320, rx:52, label:'§16 Касат.+секущая', + props:'§16: если из точки $P$ проведены касательная $PT$ и секущая $PAB$, то $PT^2 = PA\\cdot PB$. Следствие подобия $\\triangle PTA\\sim\\triangle PBT$.' }, + ]; + const edges = [ + ['circ','tang'],['circ','angl'],['circ','prod'], + ['tang','t13'],['tang','t67'], + ['angl','t911'],['angl','t1214'], + ['prod','t15'],['prod','t16'], + ]; + let sel = null; + function draw(selId){ + const colors = { circ:'#0891b2', tang:'#0e7490', angl:'#0284c7', prod:'#0369a1', + t13:'#06b6d4', t67:'#0891b2', t911:'#2563eb', t1214:'#7c3aed', + t15:'#0369a1', t16:'#0891b2' }; + let s = ``; + s += ``; + edges.forEach(([a,b])=>{ + const na=nodes.find(n=>n.id===a), nb=nodes.find(n=>n.id===b); + if(!na||!nb) return; + const dx=nb.x-na.x, dy=nb.y-na.y, len=Math.sqrt(dx*dx+dy*dy); + if(len<1) return; + const sy_r=na.rx*0.50; + const sx=na.x+dx/len*na.rx, sy2=na.y+dy/len*sy_r; + const ex=nb.x-dx/len*(nb.rx+7), ey=nb.y-dy/len*(nb.rx*0.50+7); + const isAct = selId===a||selId===b; + s += ``; + }); + nodes.forEach(n=>{ + const isS = selId===n.id; + const col = colors[n.id] || '#0891b2'; + const ry = n.rx * 0.50; + s += ``; + const words = n.label.split(' '); + const line1 = words.slice(0,2).join(' '), line2 = words.slice(2).join(' '); + const tc = isS ? '#fff' : col; + if(line2){ + s += `${line1}`; + s += `${line2}`; + } else { + s += `${line1}`; + } + }); + s += ''; + document.getElementById('final4-map-svg').innerHTML = s; + document.getElementById('final4-map-svg').querySelector('svg').addEventListener('click', function(e){ + const el = e.target.closest('[data-nid]'); + if(!el) return; + const nid = el.dataset.nid; + sel = (sel===nid) ? null : nid; + const nd = nodes.find(n=>n.id===nid); + if(sel && nd){ document.getElementById('final4-map-info').innerHTML = '' + nd.label + ': ' + nd.props; renderMath(document.getElementById('final4-map-info')); } + else document.getElementById('final4-map-info').textContent = 'Нажми на узел в схеме выше'; + draw(sel); + }); + } + draw(null); + })(); + + /* === JS: 7 боссов === */ + (function(){ + const bosses = [ + { + n: 1, + title: 'Две касательные из точки', + color: '#0891b2', + svg: ` + + + + + + + + + + + + O + P + T1 + T2 + R=5 + |OP|=13 + `, + cond: 'Из точки $P$ к окружности с центром $O$ и радиусом $R = 5$ проведены две касательные $PT_1$ и $PT_2$. $|OP| = 13$. (§1, §3)', + parts: [ + { label: 'Найди длину касательной $PT_1$ (в единицах).', ans: 12, hint: '$OT_1 \\perp PT_1$, теорема Пифагора: $PT_1 = \\sqrt{OP^2 - R^2} = \\sqrt{169-25} = \\sqrt{144} = 12$' }, + { label: 'Найди периметр четырёхугольника $OT_1PT_2$.', ans: 34, hint: '$P = PT_1 + OT_1 + PT_2 + OT_2 = 12+5+12+5 = 34$. По §3: $PT_1=PT_2=12$.' }, + ], + }, + { + n: 2, + title: 'Вписанный угол и диаметр', + color: '#0284c7', + svg: ` + + + + + + + + + + + A + B + C + O + 35° + AB — диаметр + `, + cond: 'В окружности $AB$ — диаметр, $C$ — точка на окружности. $\\angle CAB = 35°$. (§9, §11)', + parts: [ + { label: 'Найди $\\angle ACB$ (в градусах).', ans: 90, hint: '$\\angle ACB = 90°$ — вписанный угол, опирающийся на диаметр $AB$ (§11).' }, + { label: 'Найди $\\angle ABC$ (в градусах).', ans: 55, hint: '$\\angle ACB = 90°$, $\\angle CAB = 35°$, $\\angle ABC = 180° - 90° - 35° = 55°$.' }, + ], + }, + { + n: 3, + title: 'Вписанные углы + пересечение хорд', + color: '#7c3aed', + svg: ` + + + + + + + + + + A + C + B + D + P + ⌢AC=70° + ⌢BD=50° + `, + cond: 'В окружности хорды $AB$ и $CD$ пересекаются в точке $P$. Дуга $\\smile AC = 70°$, дуга $\\smile BD = 50°$. (§10, §13)', + parts: [ + { label: 'Найди угол при пересечении хорд в точке $P$ (в градусах).', ans: 60, hint: '$\\angle APD = \\dfrac{1}{2}(\\smile AC + \\smile BD) = \\dfrac{1}{2}(70+50) = 60°$ (§13).' }, + { label: 'Найди $\\angle ADC$ — вписанный угол, опирающийся на дугу $AC$ (в градусах).', ans: 35, hint: '$\\angle ADC = \\dfrac{1}{2}\\smile AC = \\dfrac{1}{2}\\cdot 70° = 35°$ (§10).' }, + ], + }, + { + n: 4, + title: 'Две секущие из внешней точки', + color: '#0369a1', + svg: ` + + + + + + + + + + P + B + A + D + C + + ? + ⌢AC=100° + ⌢BD=40° + `, + cond: 'Из внешней точки $P$ проведены две секущие $PAC$ и $PBD$. Дуга $\\smile AC = 100°$, дуга $\\smile BD = 40°$. (§14)', + parts: [ + { label: 'Найди угол $\\angle APB$ при точке $P$ (в градусах).', ans: 30, hint: '$\\angle P = \\dfrac{1}{2}|\\smile AC - \\smile BD| = \\dfrac{1}{2}|100-40| = 30°$ (§14).' }, + ], + }, + { + n: 5, + title: 'Произведение отрезков хорд', + color: '#059669', + svg: ` + + + + + + + + + + A + B + C + D + P + PA=4 + PB=9 + PC=6 + PD=? + `, + cond: 'В окружности хорды $AB$ и $CD$ пересекаются в точке $P$. $PA = 4$, $PB = 9$, $PC = 6$. (§15)', + parts: [ + { label: 'Найди $PD$.', ans: 6, hint: '$PA \\cdot PB = PC \\cdot PD \\Rightarrow PD = \\dfrac{PA \\cdot PB}{PC} = \\dfrac{4 \\cdot 9}{6} = 6$.' }, + ], + }, + { + n: 6, + title: 'Касательная и секущая', + color: '#d97706', + svg: ` + + + + + + + + + P + T + A + B + PT=8 + AB=12 + PA=? + `, + cond: 'Из точки $P$ проведены касательная $PT$ и секущая $PAB$. $PT = 8$, $AB = 12$. (§16)', + parts: [ + { label: 'Найди $PA$ (внешний отрезок секущей). Подсказка: $PA(PA+12) = 64$.', ans: 4, hint: '$PT^2 = PA\\cdot PB$, $PB = PA+12$. Уравнение: $PA^2+12PA-64=0$. Корень: $PA = \\dfrac{-12+\\sqrt{144+256}}{2} = \\dfrac{-12+20}{2} = 4$.' }, + { label: 'Найди $PB$.', ans: 16, hint: '$PB = PA + AB = 4+12 = 16$. Проверка: $8^2 = 4\\cdot 16 = 64$ — верно.' }, + ], + }, + { + n: 7, + title: 'Общая касательная двух окружностей', + color: '#6d28d9', + svg: ` + + + + + + + + + O1 + O2 + R1=6 + R2=2 + d=10 + ℓ=? + T1 + T2 + `, + cond: 'Две окружности с $R_1 = 6$, $R_2 = 2$. Расстояние между центрами $d = 10$. Найди длину общей внешней касательной. (§7)', + parts: [ + { label: 'Найди $\\ell = \\sqrt{d^2-(R_1-R_2)^2}$. Введи результат (округли до 2 знаков).', ans: 9.17, tol: 0.05, hint: '$\\ell = \\sqrt{10^2 - (6-2)^2} = \\sqrt{100-16} = \\sqrt{84} \\approx 9{,}17$.' }, + ], + }, + ]; + + window.final4BossSolved = new Set(); + const bossBox = document.getElementById('final4-bosses'); + bossBox.innerHTML = bosses.map(b => { + const partsHtml = b.parts.map((p,pi) => { + return `
+
${p.label}
+
+ + + +
+ +
`; + }).join(''); + + const svgHtml = b.svg ? `
${b.svg}
` : ''; + + return `
+
+ БОСС ${b.n} + ${b.title} + +
+
${b.cond}
+ ${svgHtml} + ${partsHtml} +
`; + }).join(''); + + function checkPart(bi, pi){ + const boss = bosses[bi]; + const part = boss.parts[pi]; + const inp = bossBox.querySelector('.final4-boss-inp[data-b="'+bi+'"][data-p="'+pi+'"]'); + const fb = bossBox.querySelector('.final4-boss-fb[data-b="'+bi+'"][data-p="'+pi+'"]'); + const ok = bossBox.querySelector('.final4-boss-ok[data-b="'+bi+'"][data-p="'+pi+'"]'); + if(!inp) return; + const val = parseFloat(inp.value); + const tol = part.tol !== undefined ? part.tol : 0; + if(Math.abs(val - part.ans) <= tol){ + feedback(fb, true, 'Верно! ' + (part.hint ? '
' + part.hint + '' : '')); + inp.disabled = true; + const btn = bossBox.querySelector('.final4-boss-check[data-b="'+bi+'"][data-p="'+pi+'"]'); + if(btn) btn.disabled = true; + if(ok) ok.style.display = 'inline'; + const allDone = boss.parts.every((_,pj) => { + const el = bossBox.querySelector('.final4-boss-inp[data-b="'+bi+'"][data-p="'+pj+'"]'); + return el && el.disabled; + }); + if(allDone && !window.final4BossSolved.has(bi)){ + window.final4BossSolved.add(bi); + addXp(10, 'final4-boss-' + (bi+1)); + const xpBadge = document.getElementById('final4-boss-xp-' + bi); + if(xpBadge) xpBadge.style.display = 'inline'; + bumpProgress('final4', 8); + if(window.final4BossSolved.size === bosses.length){ + setTimeout(function(){ + confetti(); + if(!STATE.achievements.has('final4-master')){ + STATE.achievements.set('final4-master', 'Мастер окружностей Главы 4'); + saveProgress(); + const pop = document.getElementById('ach-popup'); + if(pop){ document.getElementById('ach-text').textContent = 'Мастер окружностей Главы 4!'; pop.classList.add('show'); setTimeout(function(){ pop.classList.remove('show'); }, 4000); } + } + addXp(50, 'final4-all-bosses'); + bumpProgress('final4', 20); + const fin = document.getElementById('final4-finish'); + if(fin) fin.style.display = 'block'; + }, 500); + } + } + } else { + feedback(fb, false, 'Неверно. Подсказка: ' + part.hint); + } + } + + bossBox.querySelectorAll('.final4-boss-check').forEach(function(btn){ + btn.addEventListener('click', function(){ checkPart(+btn.dataset.b, +btn.dataset.p); }); + }); + bossBox.querySelectorAll('.final4-boss-inp').forEach(function(inp){ + inp.addEventListener('keydown', function(e){ if(e.key==='Enter'){ var btn=bossBox.querySelector('.final4-boss-check[data-b="'+inp.dataset.b+'"][data-p="'+inp.dataset.p+'"]'); if(btn)btn.click(); } }); + }); + })(); + + renderMath(box); +}