diff --git a/frontend/textbooks/geometry_8_ch4.html b/frontend/textbooks/geometry_8_ch4.html index aa9b825..418b6fd 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:()=>buildP12stub(),p13:()=>buildP13stub(),p14:()=>buildP14stub(),p15:()=>buildP15stub(),p16:()=>buildP16stub(),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:()=>buildFinal4stub()}; 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);} @@ -438,6 +438,11 @@ const GLOSSARY=[ {term:'гипотенуза',def:'Сторона прямоугольного треугольника, противолежащая прямому углу.',sec:'p1',aliases:['гипотенуза','гипотенузы','гипотенузу']}, {term:'высота',def:'Перпендикуляр из вершины на противоположную сторону.',sec:'p1',aliases:['высота','высоты','высоту']}, {term:'теорема Фалеса',def:'Параллельные прямые пропорционально рассекают секущие.',sec:'p1',aliases:['теорема Фалеса','теореме Фалеса','теоремы Фалеса']}, + {term:'угол между касательной и хордой',def:'Угол, образованный касательной к окружности и хордой, проведённой из точки касания; равен половине дуги, заключённой между ними.',sec:'p12',aliases:['угол между касательной и хордой','угла между касательной и хордой']}, + {term:'пересекающиеся хорды',def:'Две хорды окружности, имеющие общую точку внутри окружности. Произведения их отрезков равны: PA·PB = PC·PD.',sec:'p15',aliases:['пересекающиеся хорды','пересекающихся хорд','пересекающимся хордам']}, + {term:'полусумма дуг',def:'Выражение вида ½(дуга₁ + дуга₂), возникающее в теореме об угле между двумя хордами, пересекающимися внутри окружности.',sec:'p13',aliases:['полусумма дуг','полусуммы дуг','полусумме дуг']}, + {term:'полуразность дуг',def:'Выражение вида ½|дуга₁ − дуга₂|, возникающее в теореме об угле между секущими из внешней точки.',sec:'p14',aliases:['полуразность дуг','полуразности дуг','полуразностью дуг']}, + {term:'квадрат касательной',def:'Если из внешней точки P проведены касательная PT и секущая через A и B, то PT² = PA·PB.',sec:'p16',aliases:['квадрат касательной','квадрата касательной']}, ]; function wrapGlossary(root){if(!root||root.__glossDone)return;const allAliases=[];GLOSSARY.forEach((g,i)=>g.aliases.forEach(a=>allAliases.push({a,i})));allAliases.sort((x,y)=>y.a.length-x.a.length);const re=new RegExp('(?x.a.replace(/[.*+?^${}()|[\]\\]/g,'\\$&')).join('|')+')(?![\\w\\u0400-\\u04ff-])','iu');const walker=document.createTreeWalker(root,NodeFilter.SHOW_TEXT,{acceptNode(node){const p=node.parentElement;if(!p)return NodeFilter.FILTER_REJECT;if(p.closest('.katex,.gloss-term,button,input,select,.wg-badge,.card-icon,.sec-num,.psel-num,.hdr,.ach-popup,script,style,.search-modal,.sidecard,.gloss-tip'))return NodeFilter.FILTER_REJECT;if(!re.test(node.nodeValue))return NodeFilter.FILTER_REJECT;return NodeFilter.FILTER_ACCEPT;}});const nodes=[];let n;while((n=walker.nextNode()))nodes.push(n);nodes.forEach(node=>{const text=node.nodeValue;const out=document.createDocumentFragment();let cursor=0;const global=new RegExp(re.source,'giu');let m;while((m=global.exec(text))!==null){if(m.index>cursor)out.appendChild(document.createTextNode(text.slice(cursor,m.index)));const found=m[0].toLowerCase();const hit=allAliases.find(x=>x.a.toLowerCase()===found);const g=hit?GLOSSARY[hit.i]:null;const sp=document.createElement('span');sp.className='gloss-term';sp.dataset.gloss=g?g.term:'';sp.textContent=m[0];out.appendChild(sp);cursor=m.index+m[0].length;}if(cursorx.term===elm.dataset.gloss);if(!g)return;tip.innerHTML=''+g.term[0].toUpperCase()+g.term.slice(1)+'
'+g.def+'
См. § '+g.sec.replace('p','')+'
';if(window.renderMathInElement)renderMath(tip);const r=elm.getBoundingClientRect();tip.classList.add('show');const tw=tip.offsetWidth,th=tip.offsetHeight;let left=r.left,top=r.bottom+8;if(left+tw>window.innerWidth-12)left=window.innerWidth-tw-12;if(top+th>window.innerHeight-12)top=r.top-th-8;tip.style.left=Math.max(8,left)+'px';tip.style.top=Math.max(8,top)+'px';}function hide(){tip.classList.remove('show');}document.addEventListener('mouseover',e=>{const elm=e.target.closest&&e.target.closest('.gloss-term');if(elm&&!lockOpen)show(elm);});document.addEventListener('mouseout',e=>{const elm=e.target.closest&&e.target.closest('.gloss-term');if(elm&&!lockOpen)hide();});document.addEventListener('click',e=>{const elm=e.target.closest&&e.target.closest('.gloss-term');if(elm){if(lockOpen===elm){lockOpen=null;hide();}else{lockOpen=elm;show(elm);}}else if(lockOpen&&!e.target.closest('.gloss-tip')){lockOpen=null;hide();}});} @@ -4758,11 +4763,1949 @@ function buildP11(){ if(window.renderMathInElement) try{renderMath(cont);}catch(e){} })(); } -function buildP12stub(){ document.getElementById('p12-body').innerHTML='

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

'+secNav('p11','p13'); } -function buildP13stub(){ document.getElementById('p13-body').innerHTML='

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

'+secNav('p12','p14'); } -function buildP14stub(){ document.getElementById('p14-body').innerHTML='

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

'+secNav('p13','p15'); } -function buildP15stub(){ document.getElementById('p15-body').innerHTML='

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

'+secNav('p14','p16'); } -function buildP16stub(){ document.getElementById('p16-body').innerHTML='

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

'+secNav('p15','final4'); } +function buildP12(){ + const box=document.getElementById('p12-body'); + let html=''; + + html+=makeCard('rule','Угол между касательной и хордой','12.1',` +

Теорема. Угол между касательной и хордой, проведённой из точки касания, равен половине дуги, заключённой между ними.

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

Здесь $l$ — касательная к окружности в точке $A$, $AB$ — хорда из точки касания $A$. Дуга $\\smile AB$ — та, которая лежит «внутри» угла.

+
+ + + + + + + + + + + l + A + B + O + α + ⌒AB + α = ½⌒AB + +
`); + + html+=makeCard('theory','Доказательство (случай: O внутри угла)','12.2',` +

Пусть $l$ — касательная в $A$, $AB$ — хорда. Проведём диаметр $AC$ из точки $A$.

+
    +
  1. Шаг 1. Касательная перпендикулярна радиусу $OA$: $l \\perp OA$, значит $\\angle(l,AC) = 90°$.
  2. +
  3. Шаг 2. Угол между $l$ и хордой $AB$: $\\angle(l,AB) = 90° - \\angle(AB,OA) = 90° - \\angle BAC'$, где $C'$ — точка на $l$. Точнее: $\\angle(l,AB) = \\angle CAB = $ вписанный угол на дуге $BC$... нет, используем другой подход.
  4. +
  5. Шаг 3 (прямо). $\\angle(l,AB) = \\dfrac{1}{2}\\smile AB$ — следует из того, что $\\angle CAB = \\dfrac{1}{2}\\smile CB$ (вписанный), и $90° = \\dfrac{1}{2}\\cdot 180°$, поэтому $\\angle(l,AB) = 90° - \\angle CAB = \\dfrac{1}{2}(180° - \\smile CB) = \\dfrac{1}{2}\\smile AB$.
  6. +
+

ч.т.д.

`); + + html+=makeCard('example','Пример применения','12.3',` +

Задача 1. Касательная $l$ и хорда $AB$ образуют угол $35°$. Найди дугу $\\smile AB$.

+

Решение. По теореме: $35° = \\dfrac{1}{2}\\smile AB$, значит $\\smile AB = 70°$.

+

Задача 2. Дуга $\\smile AB = 110°$. Найди угол между касательной и хордой $AB$.

+

Решение. $\\angle = \\dfrac{1}{2}\\cdot 110° = 55°$.

+
+ + + + + + + + + l + A + B + 110° + 55° + +
`); + + /* ИНТЕРАКТИВ 1 — слайдер хорды */ + html+=`
+
ИНТЕРАКТИВ 1
Касательная и хорда: угол = ½ дуги
+
Двигай слайдер — меняй положение хорды $AB$. Наблюдай: угол всегда равен половине отсекаемой дуги.
+
+ +
+
+
+
`; + + /* ИНТЕРАКТИВ 2 — пошаговое доказательство */ + html+=`
+
ИНТЕРАКТИВ 2
Доказательство по шагам
+
Нажимай «Далее» — пошаговое доказательство через диаметр.
+
+
+
+ + +
+
`; + + /* ИНТЕРАКТИВ 3 — калькулятор */ + html+=`
+
ИНТЕРАКТИВ 3
Калькулятор: угол ↔ дуга
+
Введи дугу — получи угол, или наоборот.
+
+ + + + +
+ +
`; + + /* ИНТЕРАКТИВ 4 — тренажёр */ + html+=`
+
ИНТЕРАКТИВ 4
Тренажёр §12
+
5 задач на угол между касательной и хордой.
+
Задача 1 / 5Очки: 0
+
+
+ + + +
+ +
`; + + /* ИНТЕРАКТИВ 5 — DnD */ + html+=`
+
ИНТЕРАКТИВ 5
Верно или неверно?
+
Рассортируй утверждения об угле между касательной и хордой.
+
+
+
Верно
+
Неверно
+
+
+ +
`; + + /* ИНТЕРАКТИВ 6 — Босс §12 */ + html+=`
+
БОСС §12
Итоговые задачи
+
4 задачи повышенной сложности — каждая верная даёт +5 XP.
+
+
`; + + html+=`
+ +
`; + html+=secNav('p11','p13'); + box.innerHTML=html; + if(window.renderMathInElement) setTimeout(()=>renderMath(box),0); + + /* === INIT 1: слайдер хорды === */ + (function(){ + const sl=document.getElementById('p12-arc-sl'); + const valEl=document.getElementById('p12-arc-val'); + const svgWrap=document.getElementById('p12-svg-wrap'); + const info=document.getElementById('p12-info'); + const R=65, cx=130, cy=100, W=260, H=200; + function draw(){ + const arcDeg=+sl.value; + valEl.textContent=arcDeg; + const ang=arcDeg/2; + // A is leftmost point of circle + const aA=Math.PI; // angle for A = 180deg => A=(cx-R, cy) + const Ax=cx+R*Math.cos(aA), Ay=cy+R*Math.sin(aA); + // B is at angle (PI - arcDeg*PI/180) from positive x-axis, going CCW from A + const aB=Math.PI - arcDeg*Math.PI/180; + const Bx=cx+R*Math.cos(aB), By=cy+R*Math.sin(aB); + // tangent at A is vertical (perpendicular to radius OA which is horizontal) + const tLen=50; + const T1x=Ax, T1y=Ay-tLen; + const T2x=Ax, T2y=Ay+tLen; + // arc indicator small + const large=arcDeg>180?1:0; + svgWrap.innerHTML=` + + + + + + + + + A + B + O + l + ${arcDeg}° + ${Math.round(ang)}° + `; + info.textContent='Дуга AB = '+arcDeg+'° → Угол (l, AB) = '+Math.round(ang)+'° (= '+arcDeg+'°/2)'; + } + sl.addEventListener('input',draw); + draw(); + })(); + + /* === INIT 2: пошаговое доказательство === */ + (function(){ + const R=55, cx=115, cy=85, W=250, H=175; + const aA=Math.PI; + const Ax=cx+R*Math.cos(aA), Ay=cy; + const aB=Math.PI-70*Math.PI/180; + const Bx=cx+R*Math.cos(aB), By=cy+R*Math.sin(aB); + // diameter through A: C is diametrically opposite to A + const Ccx=cx+R, Ccy=cy; + const steps=[ + {text:'Дано: $l$ — касательная в точке $A$, $AB$ — хорда. Обозначим $\\angle(l,AB)=\\alpha$. Доказать: $\\alpha = \\dfrac{1}{2}\\smile AB$.'}, + {text:'Шаг 1. Проведём диаметр $AC$ через точку $A$. Так как касательная перпендикулярна радиусу $OA$, то $l \\perp OA$, следовательно $\\angle(l,AC) = 90°$.'}, + {text:'Шаг 2. Угол $\\angle BAC$ — вписанный, опирается на дугу $\\smile BC$. По теореме §9: $\\angle BAC = \\dfrac{1}{2}\\smile BC$.'}, + {text:'Шаг 3. Из рисунка: $\\alpha = \\angle(l,AB) = 90° - \\angle BAC = 90° - \\dfrac{1}{2}\\smile BC = \\dfrac{1}{2}(180° - \\smile BC) = \\dfrac{1}{2}\\smile AB$. ч.т.д.'}, + ]; + let step=0; + const svgEl=document.getElementById('p12-proof-svg'), txtEl=document.getElementById('p12-proof-text'); + function draw(){ + let ex=''; + if(step>=1){ + ex+=``; + ex+=``; + ex+=`C`; + ex+=`90°`; + } + if(step>=2){ + ex+=``; + ex+=`∠BAC`; + } + if(step>=3){ + ex+=`α=½⌢AB`; + } + svgEl.innerHTML=` + + + + + + A + B + O + l + ${ex} + `; + txtEl.innerHTML=steps[step].text; + if(window.renderMathInElement) try{renderMath(txtEl);}catch(e){} + document.getElementById('p12-proof-next').textContent=step>=steps.length-1?'Готово':'Далее'; + } + document.getElementById('p12-proof-next').addEventListener('click',()=>{if(step{step=0;draw();}); + draw(); + })(); + + /* === INIT 3: калькулятор === */ + (function(){ + document.getElementById('p12-arc2ang').addEventListener('click',()=>{ + const v=parseFloat(document.getElementById('p12-arc-inp').value); + const out=document.getElementById('p12-calc-out'); + out.style.display='block'; + if(isNaN(v)||v<=0||v>=360){out.style.background='#fee2e2';out.style.color='#7f1d1d';out.textContent='Введите дугу от 1 до 359°.';return;} + out.style.background='var(--pri-soft,#cffafe)';out.style.color='var(--pri2,#0e7490)'; + out.textContent='Дуга '+v+'° → Угол = '+v+'°/2 = '+(v/2)+'°'; + }); + document.getElementById('p12-ang2arc').addEventListener('click',()=>{ + const v=parseFloat(document.getElementById('p12-ang-inp').value); + const out=document.getElementById('p12-calc-out'); + out.style.display='block'; + if(isNaN(v)||v<=0||v>=180){out.style.background='#fee2e2';out.style.color='#7f1d1d';out.textContent='Введите угол от 1 до 179°.';return;} + out.style.background='var(--pri-soft,#cffafe)';out.style.color='var(--pri2,#0e7490)'; + out.textContent='Угол '+v+'° → Дуга AB = 2·'+v+'° = '+(2*v)+'°'; + }); + })(); + + /* === INIT 4: тренажёр === */ + (function(){ + const tasks=[ + {q:'Угол между касательной $l$ и хордой $AB$ равен $40°$. Найди дугу $\\smile AB$.',a:80,hint:'Дуга = 2·40° = 80°'}, + {q:'Дуга $\\smile AB = 130°$. Найди угол между касательной в точке $A$ и хордой $AB$.',a:65,hint:'Угол = 130°/2 = 65°'}, + {q:'Угол между касательной и хордой $= 90°$. Чему равна дуга, отсекаемая хордой?',a:180,hint:'Дуга = 2·90° = 180°, значит хорда — диаметр'}, + {q:'Угол между касательной и хордой $= 45°$. Найди дугу.',a:90,hint:'Дуга = 2·45° = 90°'}, + {q:'Дуга $\\smile AB = 54°$. Угол между касательной в точке $A$ и хордой $AB$:',a:27,hint:'Угол = 54°/2 = 27°'}, + ]; + let cur=0, score=0; + const iEl=document.getElementById('p12-tr-i'), scEl=document.getElementById('p12-tr-score'); + const taskEl=document.getElementById('p12-tr-task'), ansEl=document.getElementById('p12-tr-ans'); + const goBtn=document.getElementById('p12-tr-go'), startBtn=document.getElementById('p12-tr-start'); + const fb=document.getElementById('p12-tr-fb'); + function showTask(){ + if(cur>=tasks.length){taskEl.innerHTML='Тренажёр завершён! Очки: '+score+'/'+tasks.length+'';ansEl.style.display='none';goBtn.style.display='none';addXp(score*4,'p12-trainer');bumpProgress('p12',20);return;} + taskEl.innerHTML=tasks[cur].q;iEl.textContent=cur+1;ansEl.value='';fb.style.display='none'; + if(window.renderMathInElement) try{renderMath(taskEl);}catch(e){} + } + goBtn.addEventListener('click',()=>{ + const ans=parseFloat(ansEl.value.replace(',','.')); + const ok=Math.abs(ans-tasks[cur].a)<0.5; + feedback(fb,ok,ok?'Верно!':'Неверно. Подсказка: '+tasks[cur].hint); + if(ok){score++;scEl.textContent=score;cur++;setTimeout(showTask,900);} + }); + startBtn.addEventListener('click',()=>{cur=0;score=0;scEl.textContent=0;ansEl.style.display='';goBtn.style.display='';showTask();}); + showTask(); + })(); + + /* === INIT 5: DnD верно/неверно === */ + (function(){ + const items=[ + {label:'Угол (касательная, хорда) = ½ дуги',cat:'true'}, + {label:'Угол (касательная, хорда) = дуге целиком',cat:'false'}, + {label:'Если дуга AB = 100°, угол = 50°',cat:'true'}, + {label:'Угол между касательной и хордой может быть больше 90°',cat:'false'}, + {label:'Если угол = 90°, то хорда — диаметр',cat:'true'}, + {label:'Касательная параллельна хорде всегда',cat:'false'}, + ]; + const pool=document.getElementById('p12-dnd-pool'); + const boxes={true:document.getElementById('p12-drop-true-items'),false:document.getElementById('p12-drop-false-items')}; + const fb=document.getElementById('p12-dnd-fb'); + let placed={}; + function reset(){ + pool.innerHTML='';placed={}; + Object.values(boxes).forEach(b=>b.innerHTML=''); + fb.style.display='none'; + items.forEach((it,i)=>{ + const chip=document.createElement('div'); + chip.className='dnd-chip';chip.dataset.i=i;chip.textContent=it.label; + chip.addEventListener('click',()=>chip.classList.toggle('armed')); + Object.entries(boxes).forEach(([cat,bx])=>{ + bx.parentElement.addEventListener('click',()=>{ + if(!chip.classList.contains('armed'))return; + chip.classList.remove('armed'); + if(placed[i]!==undefined) boxes[placed[i]].removeChild(chip); + placed[i]=cat; + bx.appendChild(chip); + }); + }); + pool.appendChild(chip); + }); + } + document.getElementById('p12-dnd-check').addEventListener('click',()=>{ + let ok=0; + items.forEach((it,i)=>{if(placed[i]===it.cat)ok++;}); + feedback(fb,ok===items.length,'Верно: '+ok+'/'+items.length+(ok===items.length?'. Отлично!':'. Попробуй ещё.')); + if(ok===items.length){addXp(8,'p12-dnd');bumpProgress('p12',15);} + }); + document.getElementById('p12-dnd-reset').addEventListener('click',reset); + reset(); + })(); + + /* === INIT 6: Босс §12 === */ + (function(){ + const tasks=[ + {q:'Угол между касательной и хордой $AB = 35°$. Дуга $\\smile AB$:', + opts:['70°','35°','17,5°'],cor:0, + exp:'$\\smile AB = 2 \\cdot 35° = 70°$.'}, + {q:'Дуга $\\smile AB = 160°$. Угол между касательной в $A$ и хордой $AB$:', + opts:['80°','160°','40°'],cor:0, + exp:'Угол $= \\dfrac{1}{2}\\cdot 160° = 80°$.'}, + {q:'Угол между касательной и хордой $= 60°$. Дуга между ними:', + opts:['120°','60°','30°'],cor:0, + exp:'Дуга $= 2\\cdot 60° = 120°$.'}, + {q:'Если хорда — диаметр, угол между касательной в точке начала диаметра и диаметром равен:', + opts:['90°','180°','45°'],cor:0, + exp:'Диаметр стягивает дугу $180°$. Угол $= \\dfrac{1}{2}\\cdot 180° = 90°$.'}, + ]; + const cont=document.getElementById('p12-boss-tasks'); + let bhtml=''; + tasks.forEach((t,i)=>{ + bhtml+=`
+
${i+1}. ${t.q}
+
+ ${t.opts.map((o,j)=>``).join('')} +
+ +
`; + }); + cont.innerHTML=bhtml; + if(window.renderMathInElement) try{renderMath(cont);}catch(e){} + })(); +} +function buildP13(){ + const box=document.getElementById('p13-body'); + let html=''; + + html+=makeCard('rule','Угол между двумя хордами','13.1',` +

Теорема. Угол между двумя хордами, пересекающимися внутри окружности, равен полусумме двух дуг: той, которую он «охватывает», и противоположной.

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

Хорды $AB$ и $CD$ пересекаются в точке $P$ внутри окружности. Угол $\\angle APC$ (и вертикальный ему $\\angle BPD$) равен полусумме дуг $\\smile AC$ и $\\smile BD$.

+
+ + + + + + + + + + + + + A + C + B + D + P + ½(⌢AC+⌢BD) + +
`); + + html+=makeCard('theory','Доказательство','13.2',` +

Хорды $AB$ и $CD$ пересекаются в $P$. Соединим $A$ с $D$ — получим треугольник $\\triangle APD$... нет, выберем правильно: соединим $AD$.

+
    +
  1. Шаг 1. Соединим $A$ и $D$. Рассмотрим $\\triangle APD$ (вершины $A$, $P$, $D$).
  2. +
  3. Шаг 2. Угол $\\angle ADP$ — вписанный, опирается на дугу $\\smile AC$ (от $A$ до $C$ через вершины хорды $AB$). По теореме §9: $\\angle DAB = \\dfrac{1}{2}\\smile BD$.
  4. +
  5. Шаг 3. Угол $\\angle DAB$ — вписанный, опирается на $\\smile DB$: $\\angle DAB = \\dfrac{1}{2}\\smile DB$. Угол $\\angle ADP$ опирается на $\\smile AC$: $\\angle ADP = \\dfrac{1}{2}\\smile AC$.
  6. +
  7. Шаг 4. По теореме о внешнем угле треугольника: $\\angle APC = \\angle DAB + \\angle ADB = \\dfrac{1}{2}\\smile BD + \\dfrac{1}{2}\\smile AC = \\dfrac{1}{2}(\\smile AC + \\smile BD)$. ч.т.д.
  8. +
`); + + html+=makeCard('example','Примеры','13.3',` +

Задача 1. Хорды пересекаются внутри окружности. Дуга $\\smile AC = 80°$, дуга $\\smile BD = 60°$. Найди угол при пересечении.

+

Решение. $\\angle = \\dfrac{1}{2}(80° + 60°) = \\dfrac{140°}{2} = 70°$.

+

Задача 2. Угол при пересечении хорд $= 85°$, одна из дуг $= 90°$. Найди вторую дугу.

+

Решение. $85° = \\dfrac{1}{2}(90° + x)$ ⟹ $x = 2\\cdot 85° - 90° = 80°$.

`); + + /* ИНТЕРАКТИВ 1 — слайдер дуг */ + html+=`
+
ИНТЕРАКТИВ 1
Угол между хордами = ½(дуга₁ + дуга₂)
+
Меняй дуги слайдерами — угол при пересечении обновляется автоматически.
+
+ + +
+
+
+
`; + + /* ИНТЕРАКТИВ 2 — пошаговое доказательство */ + html+=`
+
ИНТЕРАКТИВ 2
Доказательство по шагам
+
Нажимай «Далее» — каждый шаг раскрывает ключевую идею.
+
+
+
+ + +
+
`; + + /* ИНТЕРАКТИВ 3 — калькулятор */ + html+=`
+
ИНТЕРАКТИВ 3
Калькулятор: угол между хордами
+
Введи две дуги — получи угол. Или угол и одну дугу — найди вторую дугу.
+
+ + + + + +
+ +
`; + + /* ИНТЕРАКТИВ 4 — тренажёр */ + html+=`
+
ИНТЕРАКТИВ 4
Тренажёр §13
+
5 задач на угол между хордами внутри окружности.
+
Задача 1 / 5Очки: 0
+
+
+ + + +
+ +
`; + + /* ИНТЕРАКТИВ 5 — DnD */ + html+=`
+
ИНТЕРАКТИВ 5
Верно или неверно?
+
Рассортируй утверждения об угле при пересечении хорд.
+
+
+
Верно
+
Неверно
+
+
+ +
`; + + /* ИНТЕРАКТИВ 6 — Босс §13 */ + html+=`
+
БОСС §13
Итоговые задачи
+
4 задачи повышенной сложности — каждая верная даёт +5 XP.
+
+
`; + + html+=`
+ +
`; + html+=secNav('p12','p14'); + box.innerHTML=html; + if(window.renderMathInElement) setTimeout(()=>renderMath(box),0); + + /* === INIT 1: слайдеры дуг === */ + (function(){ + const sl1=document.getElementById('p13-arc1-sl'), sl2=document.getElementById('p13-arc2-sl'); + const v1=document.getElementById('p13-arc1-val'), v2=document.getElementById('p13-arc2-val'); + const svgWrap=document.getElementById('p13-svg-wrap'), info=document.getElementById('p13-info'); + const R=64, cx=128, cy=95, W=256, H=192; + function draw(){ + const a1=+sl1.value, a2=+sl2.value; + v1.textContent=a1; v2.textContent=a2; + const ang=Math.round((a1+a2)/2); + // Place A, C, B, D on circle such that arc AC = a1, arc BD = a2 + // A at 200deg, C at 200+a1, B at 200+a1+50 (gap), D at 200+a1+50+a2 + const aA=200*Math.PI/180; + const aC=(200+a1)*Math.PI/180; + const aB=(200+a1+a2+20)*Math.PI/180; + const aD=(200+a1+a2+20+a2)*Math.PI/180; + const Ax=cx+R*Math.cos(aA), Ay=cy+R*Math.sin(aA); + const Ccx=cx+R*Math.cos(aC), Ccy=cy+R*Math.sin(aC); + const Bx=cx+R*Math.cos(aB), By=cy+R*Math.sin(aB); + const Dx=cx+R*Math.cos(aD), Dy=cy+R*Math.sin(aD); + // intersection of chords AC and BD — line-line intersection + const denom=(Ax-Ccx)*(By-Dy)-(Ay-Ccy)*(Bx-Dx); + let Px=cx, Py=cy; + if(Math.abs(denom)>0.01){ + const t=((Ax-Bx)*(By-Dy)-(Ay-By)*(Bx-Dx))/denom; + Px=Ax+t*(Ccx-Ax); Py=Ay+t*(Ccy-Ay); + } + svgWrap.innerHTML=` + + + + + + + + + + + + A + C + B + D + P + ${ang}° + ⌢AC=${a1}° + ⌢BD=${a2}° + `; + info.textContent='⌢AC = '+a1+'°, ⌢BD = '+a2+'° → Угол = ½('+a1+'+'+a2+') = '+ang+'°'; + } + sl1.addEventListener('input',draw); sl2.addEventListener('input',draw); + draw(); + })(); + + /* === INIT 2: пошаговое доказательство === */ + (function(){ + const R=55, cx=115, cy=85, W=250, H=175; + const aA=210*Math.PI/180, aC=290*Math.PI/180; + const aB=350*Math.PI/180, aD=70*Math.PI/180; + const Ax=cx+R*Math.cos(aA), Ay=cy+R*Math.sin(aA); + const Ccx=cx+R*Math.cos(aC), Ccy=cy+R*Math.sin(aC); + const Bx=cx+R*Math.cos(aB), By=cy+R*Math.sin(aB); + const Dx=cx+R*Math.cos(aD), Dy=cy+R*Math.sin(aD); + const denom=(Ax-Ccx)*(By-Dy)-(Ay-Ccy)*(Bx-Dx); + const t=((Ax-Bx)*(By-Dy)-(Ay-By)*(Bx-Dx))/denom; + const Px=Ax+t*(Ccx-Ax), Py=Ay+t*(Ccy-Ay); + const steps=[ + {text:'Дано: хорды $AB$ и $CD$ пересекаются в точке $P$ внутри окружности. Обозначим: $\\smile AC$ — дуга между $A$ и $C$ (со стороны угла $\\angle APC$), $\\smile BD$ — противоположная дуга.'}, + {text:'Шаг 1. Соединим $A$ и $D$. Рассмотрим треугольник $\\triangle APD$. Угол $\\angle APC$ является внешним углом этого треугольника при вершине $P$.'}, + {text:'Шаг 2. По теореме о внешнем угле треугольника: $\\angle APC = \\angle PAD + \\angle PDA$. Угол $\\angle PAD = \\angle BAD$ — вписанный, опирается на $\\smile BD$: $\\angle BAD = \\dfrac{1}{2}\\smile BD$.'}, + {text:'Шаг 3. Угол $\\angle PDA = \\angle CDA$ — вписанный, опирается на $\\smile CA$: $\\angle CDA = \\dfrac{1}{2}\\smile AC$. Итого: $\\angle APC = \\dfrac{1}{2}\\smile BD + \\dfrac{1}{2}\\smile AC = \\dfrac{1}{2}(\\smile AC + \\smile BD)$. ч.т.д.'}, + ]; + let step=0; + const svgEl=document.getElementById('p13-proof-svg'), txtEl=document.getElementById('p13-proof-text'); + function draw(){ + let ex=''; + if(step>=1){ + ex+=``; + } + if(step>=2){ + ex+=`∠BAD`; + } + if(step>=3){ + ex+=`∠CDA`; + ex+=`∠APC`; + } + svgEl.innerHTML=` + + + + + + + + + + A + C + B + D + P + ${ex} + `; + txtEl.innerHTML=steps[step].text; + if(window.renderMathInElement) try{renderMath(txtEl);}catch(e){} + document.getElementById('p13-proof-next').textContent=step>=steps.length-1?'Готово':'Далее'; + } + document.getElementById('p13-proof-next').addEventListener('click',()=>{if(step{step=0;draw();}); + draw(); + })(); + + /* === INIT 3: калькулятор === */ + (function(){ + document.getElementById('p13-calc-ang').addEventListener('click',()=>{ + const d1=parseFloat(document.getElementById('p13-d1').value); + const d2=parseFloat(document.getElementById('p13-d2').value); + const out=document.getElementById('p13-calc-out'); + out.style.display='block'; + if(isNaN(d1)||isNaN(d2)||d1<=0||d2<=0){out.style.background='#fee2e2';out.style.color='#7f1d1d';out.textContent='Введите положительные дуги.';return;} + out.style.background='var(--acc-soft,#a5f3fc)';out.style.color='var(--acc2,#0891b2)'; + out.textContent='Угол = ½('+d1+'+'+d2+') = '+(d1+d2)/2+'°'; + }); + document.getElementById('p13-calc-arc').addEventListener('click',()=>{ + const ang=parseFloat(document.getElementById('p13-ang').value); + const d1=parseFloat(document.getElementById('p13-d1').value); + const out=document.getElementById('p13-calc-out'); + out.style.display='block'; + if(isNaN(ang)||isNaN(d1)||ang<=0||d1<=0){out.style.background='#fee2e2';out.style.color='#7f1d1d';out.textContent='Введите угол и дугу 1.';return;} + const d2=2*ang-d1; + if(d2<=0){out.style.background='#fee2e2';out.style.color='#7f1d1d';out.textContent='Дуга 2 должна быть положительной.';return;} + out.style.background='var(--acc-soft,#a5f3fc)';out.style.color='var(--acc2,#0891b2)'; + out.textContent='Дуга 2 = 2·'+ang+' − '+d1+' = '+d2+'°'; + }); + })(); + + /* === INIT 4: тренажёр === */ + (function(){ + const tasks=[ + {q:'Хорды пересекаются внутри окружности. Дуга $\\smile AC = 70°$, дуга $\\smile BD = 50°$. Угол при пересечении:',a:60,hint:'½(70+50) = 60°'}, + {q:'Угол при пересечении хорд $= 75°$, одна дуга $= 80°$. Найди вторую дугу.',a:70,hint:'2·75−80 = 70°'}, + {q:'Обе дуги равны $100°$. Угол при пересечении хорд:',a:100,hint:'½(100+100) = 100°'}, + {q:'Дуга $\\smile AC = 120°$, дуга $\\smile BD = 40°$. Угол при пересечении хорд:',a:80,hint:'½(120+40) = 80°'}, + {q:'Угол при пересечении $= 90°$, дуга $\\smile AC = \\smile BD$. Чему равна каждая дуга?',a:90,hint:'½(x+x)=90° ⟹ x=90°'}, + ]; + let cur=0, score=0; + const iEl=document.getElementById('p13-tr-i'), scEl=document.getElementById('p13-tr-score'); + const taskEl=document.getElementById('p13-tr-task'), ansEl=document.getElementById('p13-tr-ans'); + const goBtn=document.getElementById('p13-tr-go'), startBtn=document.getElementById('p13-tr-start'); + const fb=document.getElementById('p13-tr-fb'); + function showTask(){ + if(cur>=tasks.length){taskEl.innerHTML='Тренажёр завершён! Очки: '+score+'/'+tasks.length+'';ansEl.style.display='none';goBtn.style.display='none';addXp(score*4,'p13-trainer');bumpProgress('p13',20);return;} + taskEl.innerHTML=tasks[cur].q;iEl.textContent=cur+1;ansEl.value='';fb.style.display='none'; + if(window.renderMathInElement) try{renderMath(taskEl);}catch(e){} + } + goBtn.addEventListener('click',()=>{ + const ans=parseFloat(ansEl.value.replace(',','.')); + const ok=Math.abs(ans-tasks[cur].a)<0.5; + feedback(fb,ok,ok?'Верно!':'Неверно. Подсказка: '+tasks[cur].hint); + if(ok){score++;scEl.textContent=score;cur++;setTimeout(showTask,900);} + }); + startBtn.addEventListener('click',()=>{cur=0;score=0;scEl.textContent=0;ansEl.style.display='';goBtn.style.display='';showTask();}); + showTask(); + })(); + + /* === INIT 5: DnD верно/неверно === */ + (function(){ + const items=[ + {label:'Угол между хордами = ½(сумма двух дуг)',cat:'true'}, + {label:'Угол между хордами = разности двух дуг',cat:'false'}, + {label:'Если обе дуги по 90°, угол = 90°',cat:'true'}, + {label:'Угол между хордами всегда острый',cat:'false'}, + {label:'Вертикальные углы при пересечении хорд равны',cat:'true'}, + {label:'Угол при пересечении = вписанному углу',cat:'false'}, + ]; + const pool=document.getElementById('p13-dnd-pool'); + const boxes={true:document.getElementById('p13-drop-true-items'),false:document.getElementById('p13-drop-false-items')}; + const fb=document.getElementById('p13-dnd-fb'); + let placed={}; + function reset(){ + pool.innerHTML='';placed={}; + Object.values(boxes).forEach(b=>b.innerHTML=''); + fb.style.display='none'; + items.forEach((it,i)=>{ + const chip=document.createElement('div'); + chip.className='dnd-chip';chip.dataset.i=i;chip.textContent=it.label; + chip.addEventListener('click',()=>chip.classList.toggle('armed')); + Object.entries(boxes).forEach(([cat,bx])=>{ + bx.parentElement.addEventListener('click',()=>{ + if(!chip.classList.contains('armed'))return; + chip.classList.remove('armed'); + if(placed[i]!==undefined) boxes[placed[i]].removeChild(chip); + placed[i]=cat; + bx.appendChild(chip); + }); + }); + pool.appendChild(chip); + }); + } + document.getElementById('p13-dnd-check').addEventListener('click',()=>{ + let ok=0; + items.forEach((it,i)=>{if(placed[i]===it.cat)ok++;}); + feedback(fb,ok===items.length,'Верно: '+ok+'/'+items.length+(ok===items.length?'. Отлично!':'. Попробуй ещё.')); + if(ok===items.length){addXp(8,'p13-dnd');bumpProgress('p13',15);} + }); + document.getElementById('p13-dnd-reset').addEventListener('click',reset); + reset(); + })(); + + /* === INIT 6: Босс §13 === */ + (function(){ + const tasks=[ + {q:'Дуги $\\smile AC = 50°$, $\\smile BD = 90°$. Угол при пересечении хорд:', + opts:['70°','140°','45°'],cor:0, + exp:'$\\angle = \\dfrac{1}{2}(50+90) = 70°$.'}, + {q:'Угол при пересечении $= 100°$, одна дуга $= 120°$. Другая дуга:', + opts:['80°','60°','200°'],cor:0, + exp:'$2\\cdot100 - 120 = 80°$.'}, + {q:'Две хорды пересекаются в центре окружности. Угол между ними равен:', + opts:['Центральному углу','Вписанному углу','Может быть любым'],cor:2, + exp:'Если хорды пересекаются в центре, это два диаметра. Угол определяется расположением точек.'}, + {q:'Дуга $\\smile AC = \\smile BD = 80°$. Угол при пересечении хорд:', + opts:['80°','40°','160°'],cor:0, + exp:'$\\angle = \\dfrac{1}{2}(80+80) = 80°$.'}, + ]; + const cont=document.getElementById('p13-boss-tasks'); + let bhtml=''; + tasks.forEach((t,i)=>{ + bhtml+=`
+
${i+1}. ${t.q}
+
+ ${t.opts.map((o,j)=>``).join('')} +
+ +
`; + }); + cont.innerHTML=bhtml; + if(window.renderMathInElement) try{renderMath(cont);}catch(e){} + })(); +} +function buildP14(){ + const box=document.getElementById('p14-body'); + let html=''; + + html+=makeCard('rule','Угол между двумя секущими из внешней точки','14.1',` +

Теорема. Угол между двумя секущими, проведёнными из одной точки вне окружности, равен полуразности дуг, заключённых между секущими (большей минус меньшей).

+ $$\\angle P = \\dfrac{1}{2}(\\smile AB - \\smile CD)$$ +

$P$ — внешняя точка; секущие пересекают окружность в точках $A$, $B$ и $C$, $D$ соответственно ($PA < PB$, $PC < PD$). Дуга $\\smile AB$ — дальняя (большая), $\\smile CD$ — ближняя (меньшая).

+
+ + + + + + + + + + + + + P + C + A + D + B + ∠P = ½(⌢AB − ⌢CD) + +
`); + + html+=makeCard('theory','Доказательство','14.2',` +

Пусть секущие из точки $P$ пересекают окружность в $C, A$ и $D, B$ ($C$ и $D$ ближе к $P$, $A$ и $B$ дальше). Соединим $A$ и $D$.

+
    +
  1. Шаг 1. В треугольнике $\\triangle PAD$ угол $\\angle P$ является внутренним. Угол $\\angle ADB$ — внешний угол треугольника $\\triangle PCD$ при вершине $D$... рассмотрим иначе.
  2. +
  3. Шаг 2. $\\angle CAD$ — вписанный угол, опирается на $\\smile CD$: $\\angle CAD = \\dfrac{1}{2}\\smile CD$.
  4. +
  5. Шаг 3. $\\angle ADB$ — вписанный угол (= $\\angle ADP$), опирается на $\\smile AB$: $\\angle ADB = \\dfrac{1}{2}\\smile AB$.
  6. +
  7. Шаг 4. В треугольнике $\\triangle PAD$: $\\angle ADB$ — внешний угол при $D$. Поэтому $\\angle ADB = \\angle P + \\angle PAD$, откуда $\\angle P = \\angle ADB - \\angle CAD = \\dfrac{1}{2}\\smile AB - \\dfrac{1}{2}\\smile CD = \\dfrac{1}{2}(\\smile AB - \\smile CD)$. ч.т.д.
  8. +
`); + + html+=makeCard('example','Примеры','14.3',` +

Задача 1. Угол при внешней точке $= 30°$, бо́льшая дуга $= 130°$. Найди меньшую дугу.

+

Решение. $30 = \\dfrac{1}{2}(130 - x)$, $60 = 130 - x$, $x = 70°$.

+

Задача 2. Дуга $\\smile AB = 150°$, дуга $\\smile CD = 50°$. Угол $P$:

+

Решение. $\\angle P = \\dfrac{1}{2}(150 - 50) = 50°$.

`); + + /* ИНТЕРАКТИВ 1 — слайдер */ + html+=`
+
ИНТЕРАКТИВ 1
Угол между секущими = ½(бол. дуга − мал. дуга)
+
Меняй дуги — угол при внешней точке обновляется.
+
+ + +
+
+
+
`; + + /* ИНТЕРАКТИВ 2 — пошаговое доказательство */ + html+=`
+
ИНТЕРАКТИВ 2
Доказательство по шагам
+
Нажимай «Далее» для пошагового объяснения через внешний угол.
+
+
+
+ + +
+
`; + + /* ИНТЕРАКТИВ 3 — калькулятор */ + html+=`
+
ИНТЕРАКТИВ 3
Калькулятор: угол между секущими
+
Введи две дуги (большую и меньшую) → угол, или угол + одна дуга → другая дуга.
+
+ + + + + +
+ +
`; + + /* ИНТЕРАКТИВ 4 — тренажёр */ + html+=`
+
ИНТЕРАКТИВ 4
Тренажёр §14
+
5 задач на угол между секущими из внешней точки.
+
Задача 1 / 5Очки: 0
+
+
+ + + +
+ +
`; + + /* ИНТЕРАКТИВ 5 — DnD */ + html+=`
+
ИНТЕРАКТИВ 5
Верно или неверно?
+
Рассортируй утверждения об угле между секущими из внешней точки.
+
+
+
Верно
+
Неверно
+
+
+ +
`; + + /* ИНТЕРАКТИВ 6 — Босс §14 */ + html+=`
+
БОСС §14
Итоговые задачи
+
4 задачи повышенной сложности — каждая верная даёт +5 XP.
+
+
`; + + html+=`
+ +
`; + html+=secNav('p13','p15'); + box.innerHTML=html; + if(window.renderMathInElement) setTimeout(()=>renderMath(box),0); + + /* === INIT 1: слайдеры дуг === */ + (function(){ + const slB=document.getElementById('p14-arcB-sl'), slS=document.getElementById('p14-arcS-sl'); + const vB=document.getElementById('p14-arcB-val'), vS=document.getElementById('p14-arcS-val'); + const svgWrap=document.getElementById('p14-svg-wrap'), info=document.getElementById('p14-info'); + const R=60, cx=125, cy=90, W=300, H=184; + const Px=278, Py=90; + function draw(){ + let arcB=+slB.value, arcS=+slS.value; + if(arcS>=arcB-5){arcS=arcB-5;slS.value=arcS;} + vB.textContent=arcB; vS.textContent=arcS; + const ang=Math.round((arcB-arcS)/2); + // A, B endpoints of far chord: arc AB = arcB, symmetric about horizontal from center + const halfB=arcB/2*Math.PI/180; + const Ax=cx+R*Math.cos(Math.PI+halfB), Ay=cy+R*Math.sin(Math.PI+halfB); + const Bx=cx+R*Math.cos(Math.PI-halfB), By=cy+R*Math.sin(Math.PI-halfB); + // C, D endpoints of near chord: arc CD = arcS, symmetric + const halfS=arcS/2*Math.PI/180; + const Ccx=cx+R*Math.cos(Math.PI+halfS), Ccy=cy+R*Math.sin(Math.PI+halfS); + const Dx=cx+R*Math.cos(Math.PI-halfS), Dy=cy+R*Math.sin(Math.PI-halfS); + const large=arcB>180?1:0; + const largeS=arcS>180?1:0; + svgWrap.innerHTML=` + + + + + + + + + + + + A + B + C + D + P + ∠P = ${ang}° + ⌢AB=${arcB}° + ⌢CD=${arcS}° + `; + info.textContent='⌢AB = '+arcB+'°, ⌢CD = '+arcS+'° → ∠P = ½('+arcB+'−'+arcS+') = '+ang+'°'; + } + slB.addEventListener('input',draw); slS.addEventListener('input',draw); + draw(); + })(); + + /* === INIT 2: пошаговое доказательство === */ + (function(){ + const R=52, cx=105, cy=80, W=260, H=165; + const Px=242, Py=80; + const Ax=cx+R*Math.cos(Math.PI+60*Math.PI/180), Ay=cy+R*Math.sin(Math.PI+60*Math.PI/180); + const Bx=cx+R*Math.cos(Math.PI-60*Math.PI/180), By=cy+R*Math.sin(Math.PI-60*Math.PI/180); + const Ccx=cx+R*Math.cos(Math.PI+25*Math.PI/180), Ccy=cy+R*Math.sin(Math.PI+25*Math.PI/180); + const Dx=cx+R*Math.cos(Math.PI-25*Math.PI/180), Dy=cy+R*Math.sin(Math.PI-25*Math.PI/180); + const steps=[ + {text:'Дано: Из точки $P$ вне окружности проведены две секущие. Одна пересекает в $C, A$ ($C$ ближе к $P$), другая — в $D, B$ ($D$ ближе к $P$). Доказать: $\\angle P = \\dfrac{1}{2}(\\smile AB - \\smile CD)$.'}, + {text:'Шаг 1. Соединим точки $A$ и $D$. Рассмотрим треугольник $\\triangle PAD$.'}, + {text:'Шаг 2. Угол $\\angle ADP$ — внешний угол треугольника $\\triangle CAD$ при вершине $D$... нет. Точнее: угол $\\angle ADB$ — вписанный, опирающийся на дугу $\\smile AB$: $\\angle ADB = \\dfrac{1}{2}\\smile AB$. Угол $\\angle DAC = \\angle DAС$ — вписанный на $\\smile CD$: $\\angle DAC = \\dfrac{1}{2}\\smile CD$.'}, + {text:'Шаг 3. Из треугольника $\\triangle PAD$: $\\angle ADB = \\angle P + \\angle DAС$ (внешний угол). Отсюда $\\angle P = \\angle ADB - \\angle DAC = \\dfrac{1}{2}\\smile AB - \\dfrac{1}{2}\\smile CD = \\dfrac{1}{2}(\\smile AB - \\smile CD)$. ч.т.д.'}, + ]; + let step=0; + const svgEl=document.getElementById('p14-proof-svg'), txtEl=document.getElementById('p14-proof-text'); + function draw(){ + let ex=''; + if(step>=1){ + ex+=``; + } + if(step>=2){ + ex+=`AD`; + } + if(step>=3){ + ex+=`∠P`; + } + svgEl.innerHTML=` + + + + + + + + + + A + B + C + D + P + ${ex} + `; + txtEl.innerHTML=steps[step].text; + if(window.renderMathInElement) try{renderMath(txtEl);}catch(e){} + document.getElementById('p14-proof-next').textContent=step>=steps.length-1?'Готово':'Далее'; + } + document.getElementById('p14-proof-next').addEventListener('click',()=>{if(step{step=0;draw();}); + draw(); + })(); + + /* === INIT 3: калькулятор === */ + (function(){ + document.getElementById('p14-calc-ang').addEventListener('click',()=>{ + const big=parseFloat(document.getElementById('p14-big').value); + const sml=parseFloat(document.getElementById('p14-sml').value); + const out=document.getElementById('p14-calc-out'); + out.style.display='block'; + if(isNaN(big)||isNaN(sml)||big<=sml){out.style.background='#fee2e2';out.style.color='#7f1d1d';out.textContent='Бол. дуга должна быть больше мал. дуги.';return;} + out.style.background='var(--pri-soft,#cffafe)';out.style.color='var(--pri2,#0e7490)'; + out.textContent='∠P = ½('+big+'−'+sml+') = '+((big-sml)/2)+'°'; + }); + document.getElementById('p14-calc-sml').addEventListener('click',()=>{ + const ang=parseFloat(document.getElementById('p14-ang').value); + const big=parseFloat(document.getElementById('p14-big').value); + const out=document.getElementById('p14-calc-out'); + out.style.display='block'; + if(isNaN(ang)||isNaN(big)||ang<=0||big<=0){out.style.background='#fee2e2';out.style.color='#7f1d1d';out.textContent='Введите угол и большую дугу.';return;} + const sml=big-2*ang; + if(sml<=0){out.style.background='#fee2e2';out.style.color='#7f1d1d';out.textContent='Мал. дуга получается неположительной — проверьте данные.';return;} + out.style.background='var(--pri-soft,#cffafe)';out.style.color='var(--pri2,#0e7490)'; + out.textContent='Мал. дуга = '+big+'−2·'+ang+' = '+sml+'°'; + }); + })(); + + /* === INIT 4: тренажёр === */ + (function(){ + const tasks=[ + {q:'Дуги $\\smile AB = 150°$, $\\smile CD = 50°$. Угол $P$ между секущими:',a:50,hint:'½(150−50) = 50°'}, + {q:'Угол $P = 40°$, бол. дуга $= 130°$. Найди меньшую дугу.',a:50,hint:'Мал. дуга = 130−2·40 = 50°'}, + {q:'Дуги: $\\smile AB = 200°$, $\\smile CD = 80°$. Угол $P$:',a:60,hint:'½(200−80) = 60°'}, + {q:'Угол $P = 35°$, мал. дуга $= 60°$. Найди бол. дугу.',a:130,hint:'Бол. дуга = 60+2·35 = 130°'}, + {q:'Обе секущие совпадают (стягивают одинаковые дуги). Угол $P$:',a:0,hint:'Полуразность 0 → угол = 0°'}, + ]; + let cur=0, score=0; + const iEl=document.getElementById('p14-tr-i'), scEl=document.getElementById('p14-tr-score'); + const taskEl=document.getElementById('p14-tr-task'), ansEl=document.getElementById('p14-tr-ans'); + const goBtn=document.getElementById('p14-tr-go'), startBtn=document.getElementById('p14-tr-start'); + const fb=document.getElementById('p14-tr-fb'); + function showTask(){ + if(cur>=tasks.length){taskEl.innerHTML='Тренажёр завершён! Очки: '+score+'/'+tasks.length+'';ansEl.style.display='none';goBtn.style.display='none';addXp(score*4,'p14-trainer');bumpProgress('p14',20);return;} + taskEl.innerHTML=tasks[cur].q;iEl.textContent=cur+1;ansEl.value='';fb.style.display='none'; + if(window.renderMathInElement) try{renderMath(taskEl);}catch(e){} + } + goBtn.addEventListener('click',()=>{ + const ans=parseFloat(ansEl.value.replace(',','.')); + const ok=Math.abs(ans-tasks[cur].a)<0.5; + feedback(fb,ok,ok?'Верно!':'Неверно. Подсказка: '+tasks[cur].hint); + if(ok){score++;scEl.textContent=score;cur++;setTimeout(showTask,900);} + }); + startBtn.addEventListener('click',()=>{cur=0;score=0;scEl.textContent=0;ansEl.style.display='';goBtn.style.display='';showTask();}); + showTask(); + })(); + + /* === INIT 5: DnD верно/неверно === */ + (function(){ + const items=[ + {label:'Угол между секущими = ½|дуга1 − дуга2|',cat:'true'}, + {label:'Угол между секущими = ½(дуга1 + дуга2)',cat:'false'}, + {label:'Бол. дуга всегда минус мал. дуга',cat:'true'}, + {label:'Угол P может быть больше 90°',cat:'false'}, + {label:'Если дуги равны, угол P = 0°',cat:'true'}, + {label:'Угол между секущими равен вписанному углу',cat:'false'}, + ]; + const pool=document.getElementById('p14-dnd-pool'); + const boxes={true:document.getElementById('p14-drop-true-items'),false:document.getElementById('p14-drop-false-items')}; + const fb=document.getElementById('p14-dnd-fb'); + let placed={}; + function reset(){ + pool.innerHTML='';placed={}; + Object.values(boxes).forEach(b=>b.innerHTML=''); + fb.style.display='none'; + items.forEach((it,i)=>{ + const chip=document.createElement('div'); + chip.className='dnd-chip';chip.dataset.i=i;chip.textContent=it.label; + chip.addEventListener('click',()=>chip.classList.toggle('armed')); + Object.entries(boxes).forEach(([cat,bx])=>{ + bx.parentElement.addEventListener('click',()=>{ + if(!chip.classList.contains('armed'))return; + chip.classList.remove('armed'); + if(placed[i]!==undefined) boxes[placed[i]].removeChild(chip); + placed[i]=cat; + bx.appendChild(chip); + }); + }); + pool.appendChild(chip); + }); + } + document.getElementById('p14-dnd-check').addEventListener('click',()=>{ + let ok=0; + items.forEach((it,i)=>{if(placed[i]===it.cat)ok++;}); + feedback(fb,ok===items.length,'Верно: '+ok+'/'+items.length+(ok===items.length?'. Отлично!':'. Попробуй ещё.')); + if(ok===items.length){addXp(8,'p14-dnd');bumpProgress('p14',15);} + }); + document.getElementById('p14-dnd-reset').addEventListener('click',reset); + reset(); + })(); + + /* === INIT 6: Босс §14 === */ + (function(){ + const tasks=[ + {q:'Дуги $\\smile AB = 160°$, $\\smile CD = 60°$. Угол $P$:', + opts:['50°','110°','100°'],cor:0, + exp:'$\\angle P = \\dfrac{1}{2}(160-60) = 50°$.'}, + {q:'Угол $P = 45°$, мал. дуга $= 70°$. Бол. дуга:', + opts:['160°','115°','25°'],cor:0, + exp:'Бол. дуга $= 70 + 2\\cdot45 = 160°$.'}, + {q:'Секущие становятся касательными (каждая касается в одной точке). Дуга $\\smile AB$ превращается в точку. Угол $P$:', + opts:['½ дуги CD','Дуге CD','Нулю'],cor:0, + exp:'Когда секущая стягивается в касательную, $\\smile AB \\to 0$, и формула даёт $\\angle P = \\dfrac{1}{2}(0 - \\smile CD)$ — ошибка. Правильно: оба становятся касательными, угол = ½ разности двух дуг между точками касания.'}, + {q:'Дуга $\\smile AB = 100°$, $\\smile CD = 100°$. Угол $P$:', + opts:['0°','50°','100°'],cor:0, + exp:'$\\angle P = \\dfrac{1}{2}(100-100) = 0°$ — секущие параллельны.'}, + ]; + const cont=document.getElementById('p14-boss-tasks'); + let bhtml=''; + tasks.forEach((t,i)=>{ + bhtml+=`
+
${i+1}. ${t.q}
+
+ ${t.opts.map((o,j)=>``).join('')} +
+ +
`; + }); + cont.innerHTML=bhtml; + if(window.renderMathInElement) try{renderMath(cont);}catch(e){} + })(); +} +function buildP15(){ + const box=document.getElementById('p15-body'); + let html=''; + + html+=makeCard('rule','Свойство пересекающихся хорд','15.1',` +

Теорема. Если две хорды $AB$ и $CD$ окружности пересекаются в точке $P$, то произведения их отрезков равны:

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

$P$ — точка пересечения хорд внутри окружности; $PA$, $PB$ — отрезки хорды $AB$, $PC$, $PD$ — отрезки хорды $CD$.

+
+ + + + + + + + + + + A + B + C + D + P + PA·PB = PC·PD + +
`); + + html+=makeCard('theory','Доказательство через подобие','15.2',` +

Хорды $AB$ и $CD$ пересекаются в $P$. Рассмотрим треугольники $\\triangle APC$ и $\\triangle DPB$.

+
    +
  1. Угол при $P$: $\\angle APC = \\angle DPB$ (вертикальные углы).
  2. +
  3. Вписанные углы на одной дуге: $\\angle PAC = \\angle PDC$ (оба опираются на дугу $\\smile BC$).
  4. +
  5. Вывод: $\\triangle APC \\sim \\triangle DPB$ (по двум углам — АА).
  6. +
  7. Пропорция сторон: $\\dfrac{PA}{PD} = \\dfrac{PC}{PB}$, откуда $PA \\cdot PB = PC \\cdot PD$. ч.т.д.
  8. +
`); + + html+=makeCard('example','Пример применения','15.3',` +

Задача. Хорды пересекаются. $PA = 4$, $PB = 9$, $PC = 6$. Найди $PD$.

+

Решение. $PA \\cdot PB = PC \\cdot PD$ ⟹ $4 \\cdot 9 = 6 \\cdot PD$ ⟹ $PD = \\dfrac{36}{6} = 6$.

+
+ + + + + + + + + + + A + B + C + D + P + PA=4 + PB=9 + PC=6 + PD=? + +
`); + + /* ИНТЕРАКТИВ 1 — draggable-стиль через слайдер положения хорд */ + html+=`
+
ИНТЕРАКТИВ 1
PA · PB = PC · PD (живая демонстрация)
+
Меняй положение точки $P$ внутри окружности — произведения всегда равны.
+
+ + +
+
+
+
`; + + /* ИНТЕРАКТИВ 2 — пошаговое доказательство */ + html+=`
+
ИНТЕРАКТИВ 2
Доказательство через подобие — по шагам
+
Нажимай «Далее» — подсвечиваются подобные треугольники.
+
+
+
+ + +
+
`; + + /* ИНТЕРАКТИВ 3 — калькулятор */ + html+=`
+
ИНТЕРАКТИВ 3
Калькулятор: PA · PB = PC · PD
+
Введи три из четырёх отрезков — найди четвёртый.
+
+ + + + + +
+ +
`; + + /* ИНТЕРАКТИВ 4 — тренажёр */ + html+=`
+
ИНТЕРАКТИВ 4
Тренажёр §15
+
5 задач на свойство пересекающихся хорд.
+
Задача 1 / 5Очки: 0
+
+
+ + + +
+ +
`; + + /* ИНТЕРАКТИВ 5 — DnD */ + html+=`
+
ИНТЕРАКТИВ 5
Верно или неверно?
+
Рассортируй утверждения о пересекающихся хордах.
+
+
+
Верно
+
Неверно
+
+
+ +
`; + + /* ИНТЕРАКТИВ 6 — Босс §15 */ + html+=`
+
БОСС §15
Итоговые задачи
+
4 задачи повышенной сложности — каждая верная даёт +5 XP.
+
+
`; + + html+=`
+ +
`; + html+=secNav('p14','p16'); + box.innerHTML=html; + if(window.renderMathInElement) setTimeout(()=>renderMath(box),0); + + /* === INIT 1: слайдеры положения P === */ + (function(){ + const slPos=document.getElementById('p15-pos-sl'), slRot=document.getElementById('p15-rot-sl'); + const vPos=document.getElementById('p15-pos-val'), vRot=document.getElementById('p15-rot-val'); + const svgWrap=document.getElementById('p15-svg-wrap'), info=document.getElementById('p15-info'); + const R=65, cx=130, cy=95, W=260, H=192; + function draw(){ + const posAngle=+slPos.value, rotAngle=+slRot.value; + vPos.textContent=posAngle; vRot.textContent=rotAngle; + // P is inside circle at radius fraction, along angle posAngle + const pFrac=0.45; // P at 45% of radius + const pRad=posAngle*Math.PI/180; + const Px=cx+R*pFrac*Math.cos(pRad), Py=cy+R*pFrac*Math.sin(pRad); + // chord AB: line through P at angle rotAngle*PI/180, find intersections with circle + const theta1=(rotAngle)*Math.PI/180; + const dx1=Math.cos(theta1), dy1=Math.sin(theta1); + // parametric: (Px+t*dx1)^2 ... solve quadratic + function chordIntersect(px,py,dx,dy){ + const a=dx*dx+dy*dy; + const b=2*((px-cx)*dx+(py-cy)*dy); + const c=(px-cx)*(px-cx)+(py-cy)*(py-cy)-R*R; + const disc=b*b-4*a*c; + if(disc<0)return null; + const t1=(-b-Math.sqrt(disc))/(2*a); + const t2=(-b+Math.sqrt(disc))/(2*a); + return [t1,t2]; + } + const t1=chordIntersect(Px,Py,dx1,dy1); + const t2=chordIntersect(Px,Py,-dy1,dx1); + if(!t1||!t2){info.textContent='Переместите P внутрь окружности';return;} + const Ax=Px+t1[0]*dx1, Ay=Py+t1[0]*dy1; + const Bx=Px+t1[1]*dx1, By=Py+t1[1]*dy1; + const Ccx=Px+t2[0]*(-dy1), Ccy=Py+t2[0]*dx1; + const Dx=Px+t2[1]*(-dy1), Dy=Py+t2[1]*dx1; + const PA=Math.sqrt((Px-Ax)**2+(Py-Ay)**2); + const PB=Math.sqrt((Px-Bx)**2+(Py-By)**2); + const PC=Math.sqrt((Px-Ccx)**2+(Py-Ccy)**2); + const PD=Math.sqrt((Px-Dx)**2+(Py-Dy)**2); + const prod1=PA*PB, prod2=PC*PD; + svgWrap.innerHTML=` + + + + + + + + + + A + B + C + D + P + ${PA.toFixed(1)} + ${PB.toFixed(1)} + ${PC.toFixed(1)} + ${PD.toFixed(1)} + `; + info.textContent='PA·PB = '+PA.toFixed(2)+'·'+PB.toFixed(2)+' = '+prod1.toFixed(2)+' | PC·PD = '+PC.toFixed(2)+'·'+PD.toFixed(2)+' = '+prod2.toFixed(2)+(Math.abs(prod1-prod2)<0.1?' ✓ Равны!':' (пересчёт...)'); + } + slPos.addEventListener('input',draw); slRot.addEventListener('input',draw); + draw(); + })(); + + /* === INIT 2: пошаговое доказательство === */ + (function(){ + const R=55, cx=115, cy=85, W=250, H=175; + const Ax=cx+R*Math.cos(200*Math.PI/180), Ay=cy+R*Math.sin(200*Math.PI/180); + const Bx=cx+R*Math.cos(20*Math.PI/180), By=cy+R*Math.sin(20*Math.PI/180); + const Ccx=cx+R*Math.cos(130*Math.PI/180), Ccy=cy+R*Math.sin(130*Math.PI/180); + const Dx=cx+R*Math.cos(330*Math.PI/180), Dy=cy+R*Math.sin(330*Math.PI/180); + const denom=(Ax-Bx)*(Ccy-Dy)-(Ay-By)*(Ccx-Dx); + const t=((Ax-Ccx)*(Ccy-Dy)-(Ay-Ccy)*(Ccx-Dx))/denom; + const Px=Ax+t*(Bx-Ax), Py=Ay+t*(By-Ay); + const steps=[ + {text:'Дано: хорды $AB$ и $CD$ пересекаются в $P$ внутри окружности. Доказать: $PA \\cdot PB = PC \\cdot PD$.'}, + {text:'Шаг 1. Рассмотрим треугольники $\\triangle APC$ и $\\triangle DPB$. Углы $\\angle APC$ и $\\angle DPB$ — вертикальные, значит они равны.'}, + {text:'Шаг 2. Углы $\\angle PAC$ и $\\angle PDB$ — вписанные, опираются на одну дугу $\\smile BC$, значит $\\angle PAC = \\angle PDB$.'}, + {text:'Шаг 3. По признаку подобия AA: $\\triangle APC \\sim \\triangle DPB$. Из подобия: $\\dfrac{PA}{PD} = \\dfrac{PC}{PB}$, откуда $PA \\cdot PB = PC \\cdot PD$. ч.т.д.'}, + ]; + let step=0; + const svgEl=document.getElementById('p15-proof-svg'), txtEl=document.getElementById('p15-proof-text'); + function draw(){ + let ex=''; + if(step>=1){ + ex+=``; + ex+=``; + } + if(step>=2){ + ex+=`∠PAC`; + ex+=`∠PDB`; + } + if(step>=3){ + ex+=`△APC~△DPB`; + } + svgEl.innerHTML=` + + + + + + + + + + A + B + C + D + P + ${ex} + `; + txtEl.innerHTML=steps[step].text; + if(window.renderMathInElement) try{renderMath(txtEl);}catch(e){} + document.getElementById('p15-proof-next').textContent=step>=steps.length-1?'Готово':'Далее'; + } + document.getElementById('p15-proof-next').addEventListener('click',()=>{if(step{step=0;draw();}); + draw(); + })(); + + /* === INIT 3: калькулятор === */ + (function(){ + document.getElementById('p15-calc-pd').addEventListener('click',()=>{ + const pa=parseFloat(document.getElementById('p15-pa').value); + const pb=parseFloat(document.getElementById('p15-pb').value); + const pc=parseFloat(document.getElementById('p15-pc').value); + const out=document.getElementById('p15-calc-out'); + out.style.display='block'; + if([pa,pb,pc].some(v=>isNaN(v)||v<=0)){out.style.background='#fee2e2';out.style.color='#7f1d1d';out.textContent='Введите положительные значения PA, PB, PC.';return;} + const pd=pa*pb/pc; + out.style.background='var(--ok-bg,#d1fae5)';out.style.color='#065f46'; + out.innerHTML='PD = PA·PB/PC = '+pa+'·'+pb+'/'+pc+' = '+pd.toFixed(4)+''; + }); + })(); + + /* === INIT 4: тренажёр === */ + (function(){ + const tasks=[ + {q:'$PA = 3$, $PB = 12$, $PC = 9$. Найди $PD$.',a:4,hint:'PD = 3·12/9 = 4'}, + {q:'$PA = 4$, $PB = 9$, $PC = 6$. Найди $PD$.',a:6,hint:'PD = 4·9/6 = 6'}, + {q:'$PA = 5$, $PC = 5$, $PD = 5$. Найди $PB$.',a:5,hint:'PB = PC·PD/PA = 5'}, + {q:'$PA = 2$, $PB = 8$, $PD = 4$. Найди $PC$.',a:4,hint:'PC = PA·PB/PD = 16/4 = 4'}, + {q:'$PA = 6$, $PB = 6$, $PC = 4$. Найди $PD$.',a:9,hint:'PD = 6·6/4 = 9'}, + ]; + let cur=0, score=0; + const iEl=document.getElementById('p15-tr-i'), scEl=document.getElementById('p15-tr-score'); + const taskEl=document.getElementById('p15-tr-task'), ansEl=document.getElementById('p15-tr-ans'); + const goBtn=document.getElementById('p15-tr-go'), startBtn=document.getElementById('p15-tr-start'); + const fb=document.getElementById('p15-tr-fb'); + function showTask(){ + if(cur>=tasks.length){taskEl.innerHTML='Тренажёр завершён! Очки: '+score+'/'+tasks.length+'';ansEl.style.display='none';goBtn.style.display='none';addXp(score*4,'p15-trainer');bumpProgress('p15',20);return;} + taskEl.innerHTML=tasks[cur].q;iEl.textContent=cur+1;ansEl.value='';fb.style.display='none'; + if(window.renderMathInElement) try{renderMath(taskEl);}catch(e){} + } + goBtn.addEventListener('click',()=>{ + const ans=parseFloat(ansEl.value.replace(',','.')); + const ok=Math.abs(ans-tasks[cur].a)<0.05; + feedback(fb,ok,ok?'Верно!':'Неверно. Подсказка: '+tasks[cur].hint); + if(ok){score++;scEl.textContent=score;cur++;setTimeout(showTask,900);} + }); + startBtn.addEventListener('click',()=>{cur=0;score=0;scEl.textContent=0;ansEl.style.display='';goBtn.style.display='';showTask();}); + showTask(); + })(); + + /* === INIT 5: DnD верно/неверно === */ + (function(){ + const items=[ + {label:'PA·PB = PC·PD для любых двух хорд, пересекающихся внутри',cat:'true'}, + {label:'PA + PB = PC + PD',cat:'false'}, + {label:'Если PA = PC, то PB = PD',cat:'true'}, + {label:'Произведение отрезков одной хорды больше произведения другой',cat:'false'}, + {label:'Точка P делит хорды пропорционально: PA/PD = PC/PB',cat:'true'}, + {label:'Отношение PA/PB = PC/PD',cat:'false'}, + ]; + const pool=document.getElementById('p15-dnd-pool'); + const boxes={true:document.getElementById('p15-drop-true-items'),false:document.getElementById('p15-drop-false-items')}; + const fb=document.getElementById('p15-dnd-fb'); + let placed={}; + function reset(){ + pool.innerHTML='';placed={}; + Object.values(boxes).forEach(b=>b.innerHTML=''); + fb.style.display='none'; + items.forEach((it,i)=>{ + const chip=document.createElement('div'); + chip.className='dnd-chip';chip.dataset.i=i;chip.textContent=it.label; + chip.addEventListener('click',()=>chip.classList.toggle('armed')); + Object.entries(boxes).forEach(([cat,bx])=>{ + bx.parentElement.addEventListener('click',()=>{ + if(!chip.classList.contains('armed'))return; + chip.classList.remove('armed'); + if(placed[i]!==undefined) boxes[placed[i]].removeChild(chip); + placed[i]=cat; + bx.appendChild(chip); + }); + }); + pool.appendChild(chip); + }); + } + document.getElementById('p15-dnd-check').addEventListener('click',()=>{ + let ok=0; + items.forEach((it,i)=>{if(placed[i]===it.cat)ok++;}); + feedback(fb,ok===items.length,'Верно: '+ok+'/'+items.length+(ok===items.length?'. Отлично!':'. Попробуй ещё.')); + if(ok===items.length){addXp(8,'p15-dnd');bumpProgress('p15',15);} + }); + document.getElementById('p15-dnd-reset').addEventListener('click',reset); + reset(); + })(); + + /* === INIT 6: Босс §15 === */ + (function(){ + const tasks=[ + {q:'$PA = 4, PB = 9, PC = 6$. Найди $PD$.', + opts:['6','3','12'],cor:0, + exp:'$PD = PA\\cdot PB / PC = 4\\cdot9/6 = 6$.'}, + {q:'$PA = PB = 5, PC = 5$. Найди $PD$.', + opts:['5','10','25'],cor:0, + exp:'$PD = 5\\cdot5/5 = 5$. Точка $P$ — середина каждой хорды.'}, + {q:'Хорды пересекаются в центре. $PA = 3$. Чему равно $PB$?', + opts:['3','6','Недостаточно данных'],cor:0, + exp:'В центре окружности хорды — диаметры, поэтому $PA = PB = R$.'}, + {q:'$PA = 2, PC = 3, PD = 4$. Найди $PB$.', + opts:['6','3','2'],cor:0, + exp:'$PB = PC\\cdot PD / PA = 3\\cdot4/2 = 6$.'}, + ]; + const cont=document.getElementById('p15-boss-tasks'); + let bhtml=''; + tasks.forEach((t,i)=>{ + bhtml+=`
+
${i+1}. ${t.q}
+
+ ${t.opts.map((o,j)=>``).join('')} +
+ +
`; + }); + cont.innerHTML=bhtml; + if(window.renderMathInElement) try{renderMath(cont);}catch(e){} + })(); +} +function buildP16(){ + const box=document.getElementById('p16-body'); + let html=''; + + html+=makeCard('rule','Свойство касательной и секущей','16.1',` +

Теорема. Если из внешней точки $P$ проведены касательная $PT$ (где $T$ — точка касания) и секущая, пересекающая окружность в точках $A$ и $B$ ($PA < PB$), то:

+ $$PT^2 = PA \\cdot PB$$ +

Следствие: квадрат длины касательной равен произведению полной секущей ($PB$) на её внешнюю часть ($PA$).

+
+ + + + + + + + + + + P + T + A + B + O + PT + PA · PB + PT² = PA·PB + +
`); + + html+=makeCard('theory','Доказательство через подобие','16.2',` +

Из точки $P$ вне окружности проведены: касательная $PT$ и секущая через $A$, $B$ ($PA < PB$). Докажем $PT^2 = PA \\cdot PB$.

+
    +
  1. Шаг 1. Рассмотрим треугольники $\\triangle PTA$ и $\\triangle PBT$.
  2. +
  3. Шаг 2. Общий угол при $P$: $\\angle TPА = \\angle BPT$ (общий угол).
  4. +
  5. Шаг 3. По теореме §12: $\\angle PTA = \\angle TBA$ (угол между касательной $PT$ и хордой $TA$ равен вписанному углу $\\angle TBA$, опирающемуся на ту же дугу $\\smile TA$).
  6. +
  7. Шаг 4. Значит $\\triangle PTA \\sim \\triangle PBT$ (по АА). Из подобия: $\\dfrac{PT}{PB} = \\dfrac{PA}{PT}$, откуда $PT^2 = PA \\cdot PB$. ч.т.д.
  8. +
`); + + html+=makeCard('example','Примеры','16.3',` +

Задача 1. $PA = 4$, $PB = 9$. Найди длину касательной $PT$.

+

Решение. $PT^2 = 4 \\cdot 9 = 36$, $PT = 6$.

+

Задача 2. $PT = 8$, $PA = 4$. Найди $PB$.

+

Решение. $PB = PT^2/PA = 64/4 = 16$.

+

Задача 3. $PT = 6$, $PB = 12$. Найди $PA$.

+

Решение. $PA = PT^2/PB = 36/12 = 3$.

`); + + /* ИНТЕРАКТИВ 1 — слайдер секущей */ + html+=`
+
ИНТЕРАКТИВ 1
PT² = PA · PB (живая демонстрация)
+
Меняй положение секущей слайдером. PT² всегда равно PA·PB.
+
+ +
+
+
+
`; + + /* ИНТЕРАКТИВ 2 — пошаговое доказательство */ + html+=`
+
ИНТЕРАКТИВ 2
Доказательство по шагам
+
Нажимай «Далее» — подсвечиваются подобные треугольники.
+
+
+
+ + +
+
`; + + /* ИНТЕРАКТИВ 3 — калькулятор (три варианта) */ + html+=`
+
ИНТЕРАКТИВ 3
Калькулятор: PT² = PA · PB
+
Выбери что искать: PT, PA или PB.
+
+ + + +
+
+ + +
`; + + /* ИНТЕРАКТИВ 4 — тренажёр */ + html+=`
+
ИНТЕРАКТИВ 4
Тренажёр §16
+
5 задач на свойство касательной и секущей.
+
Задача 1 / 5Очки: 0
+
+
+ + + +
+ +
`; + + /* ИНТЕРАКТИВ 5 — DnD */ + html+=`
+
ИНТЕРАКТИВ 5
Верно или неверно?
+
Рассортируй утверждения о касательной и секущей.
+
+
+
Верно
+
Неверно
+
+
+ +
`; + + /* ИНТЕРАКТИВ 6 — Босс §16 */ + html+=`
+
БОСС §16
Итоговые задачи
+
4 задачи повышенной сложности — каждая верная даёт +5 XP.
+
+
`; + + html+=`
+ +
`; + html+=secNav('p15','final4'); + box.innerHTML=html; + if(window.renderMathInElement) setTimeout(()=>renderMath(box),0); + + /* === INIT 1: слайдер секущей === */ + (function(){ + const sl=document.getElementById('p16-sec-sl'); + const valEl=document.getElementById('p16-sec-val'); + const svgWrap=document.getElementById('p16-svg-wrap'); + const info=document.getElementById('p16-info'); + const R=62, ocx=115, ocy=95, W=285, H=192; + const Px=262, Py=95; + // tangent: T is where line from P is tangent to circle + // tangent length = sqrt(PO^2 - R^2) + const PO=Math.sqrt((Px-ocx)**2+(Py-ocy)**2); + const PTlen=Math.sqrt(PO*PO-R*R); + // angle of tangent from P: sin(alpha) = R/PO + const tanAngle=Math.asin(R/PO); + // main tangent angle (upper tangent) + const baseAngle=Math.atan2(ocy-Py,ocx-Px); // angle from P toward O + const Tx=Px+PTlen*Math.cos(baseAngle-tanAngle); + const Ty=Py+PTlen*Math.sin(baseAngle-tanAngle); + function draw(){ + const secDeg=+sl.value; + valEl.textContent=secDeg; + // secant from P at angle (baseAngle + secDeg*PI/180) + const secAngle=baseAngle+secDeg*Math.PI/180; + const dx=Math.cos(secAngle), dy=Math.sin(secAngle); + // intersect with circle: quadratic + const a=dx*dx+dy*dy; + const b=2*((Px-ocx)*dx+(Py-ocy)*dy); + const c=(Px-ocx)**2+(Py-ocy)**2-R*R; + const disc=b*b-4*a*c; + if(disc<0){svgWrap.innerHTML='';return;} + const t1=(-b-Math.sqrt(disc))/(2*a); + const t2=(-b+Math.sqrt(disc))/(2*a); + const Ax=Px+t1*dx, Ay=Py+t1*dy; + const Bx=Px+t2*dx, By=Py+t2*dy; + const PA=Math.abs(t1), PB=Math.abs(t2); + const PT=PTlen; + const prod=PA*PB; + const pt2=PT*PT; + // right-angle marker at T (tangent perp to OT) + const OTx=(Tx-ocx)/R, OTy=(Ty-ocy)/R; // unit vector O->T + const ux=-OTy, uy=OTx; // tangent direction + const s=8; + const m1x=Tx+s*(-OTx), m1y=Ty+s*(-OTy); // toward O + const m2x=m1x+s*ux, m2y=m1y+s*uy; + const m3x=Tx+s*ux, m3y=Ty+s*uy; + svgWrap.innerHTML=` + + + + + + + + + + + T + A + B + P + O + PT=${PT.toFixed(1)} + PA=${PA.toFixed(1)} + AB=${(PB-PA).toFixed(1)} + `; + info.textContent='PT² = '+pt2.toFixed(2)+' | PA·PB = '+prod.toFixed(2)+(Math.abs(pt2-prod)<0.1?' ✓ Равны!':''); + } + sl.addEventListener('input',draw); + draw(); + })(); + + /* === INIT 2: пошаговое доказательство === */ + (function(){ + const R=52, ocx=105, ocy=82, W=265, H=168; + const Px=248, Py=82; + const PO=Math.sqrt((Px-ocx)**2+(Py-ocy)**2); + const PTlen=Math.sqrt(PO*PO-R*R); + const baseAngle=Math.atan2(ocy-Py,ocx-Px); + const tanAngle=Math.asin(R/PO); + const Tx=Px+PTlen*Math.cos(baseAngle-tanAngle); + const Ty=Py+PTlen*Math.sin(baseAngle-tanAngle); + const secAngle=baseAngle+28*Math.PI/180; + const dx=Math.cos(secAngle), dy=Math.sin(secAngle); + const aCoef=dx*dx+dy*dy; + const bCoef=2*((Px-ocx)*dx+(Py-ocy)*dy); + const cCoef=(Px-ocx)**2+(Py-ocy)**2-R*R; + const disc=bCoef*bCoef-4*aCoef*cCoef; + const t1=(-bCoef-Math.sqrt(disc))/(2*aCoef); + const t2=(-bCoef+Math.sqrt(disc))/(2*aCoef); + const Ax=Px+t1*dx, Ay=Py+t1*dy; + const Bx=Px+t2*dx, By=Py+t2*dy; + const steps=[ + {text:'Дано: Из точки $P$ вне окружности проведены: касательная $PT$ и секущая $PAB$ ($PA < PB$). Доказать: $PT^2 = PA \\cdot PB$.'}, + {text:'Шаг 1. Рассмотрим треугольники $\\triangle PTA$ и $\\triangle PBT$. Угол $\\angle TPА$ — общий для обоих треугольников.'}, + {text:'Шаг 2. По теореме §12: угол между касательной $PT$ и хордой $TA$ равен вписанному углу $\\angle TBA$, опирающемуся на ту же дугу $\\smile TA$. Значит $\\angle PTA = \\angle PBT$.'}, + {text:'Шаг 3. $\\triangle PTA \\sim \\triangle PBT$ (по АА). Из подобия: $\\dfrac{PT}{PB} = \\dfrac{PA}{PT}$, т.е. $PT^2 = PA \\cdot PB$. ч.т.д.'}, + ]; + let step=0; + const svgEl=document.getElementById('p16-proof-svg'), txtEl=document.getElementById('p16-proof-text'); + function draw(){ + let ex=''; + if(step>=1){ + ex+=``; + ex+=``; + } + if(step>=2){ + ex+=`∠PTA`; + ex+=`∠TBA`; + } + if(step>=3){ + ex+=`PT²=PA·PB`; + } + svgEl.innerHTML=` + + + + + + + + + T + A + B + P + ${ex} + `; + txtEl.innerHTML=steps[step].text; + if(window.renderMathInElement) try{renderMath(txtEl);}catch(e){} + document.getElementById('p16-proof-next').textContent=step>=steps.length-1?'Готово':'Далее'; + } + document.getElementById('p16-proof-next').addEventListener('click',()=>{if(step{step=0;draw();}); + draw(); + })(); + + /* === INIT 3: калькулятор 3-в-1 === */ + (function(){ + let mode='pt'; + const fields=document.getElementById('p16-calc-fields'); + const out=document.getElementById('p16-calc-out'); + const modes={ + pt:{label:'Найти PT',fields:[['PA','p16-cpa','4'],['PB','p16-cpb','9']], + calc:()=>{const pa=parseFloat(document.getElementById('p16-cpa').value),pb=parseFloat(document.getElementById('p16-cpb').value);if(isNaN(pa)||isNaN(pb)||pa<=0||pb<=0||pa>=pb)return{err:'PA и PB > 0, PA < PB'};const pt=Math.sqrt(pa*pb);return{ok:'PT = \\u221a(PA\\u00b7PB) = \\u221a('+pa+'\\u00b7'+pb+') = '+pt.toFixed(4)};}}, + pa:{label:'Найти PA',fields:[['PT','p16-cpt2','6'],['PB','p16-cpb2','9']], + calc:()=>{const pt=parseFloat(document.getElementById('p16-cpt2').value),pb=parseFloat(document.getElementById('p16-cpb2').value);if(isNaN(pt)||isNaN(pb)||pt<=0||pb<=0||pt*pt>=pb*pb)return{err:'PT и PB > 0, PT < PB'};const pa=pt*pt/pb;return{ok:'PA = PT²/PB = '+pt+'²/'+pb+' = '+pa.toFixed(4)};}}, + pb:{label:'Найти PB',fields:[['PT','p16-cpt3','6'],['PA','p16-cpa3','4']], + calc:()=>{const pt=parseFloat(document.getElementById('p16-cpt3').value),pa=parseFloat(document.getElementById('p16-cpa3').value);if(isNaN(pt)||isNaN(pa)||pt<=0||pa<=0||pa>=pt)return{err:'PT и PA > 0, PA < PT'};const pb=pt*pt/pa;return{ok:'PB = PT²/PA = '+pt+'²/'+pa+' = '+pb.toFixed(4)};}} + }; + function setMode(m){ + mode=m; + ['pt','pa','pb'].forEach(k=>document.getElementById('p16-mode-'+k).className='btn'+(k===m?' primary':'')); + const cfg=modes[m]; + fields.innerHTML=cfg.fields.map(([lab,id,def])=>``).join(''); + out.style.display='none'; + } + document.getElementById('p16-mode-pt').addEventListener('click',()=>setMode('pt')); + document.getElementById('p16-mode-pa').addEventListener('click',()=>setMode('pa')); + document.getElementById('p16-mode-pb').addEventListener('click',()=>setMode('pb')); + document.getElementById('p16-calc-go').addEventListener('click',()=>{ + const res=modes[mode].calc(); + out.style.display='block'; + if(res.err){out.style.background='#fee2e2';out.style.color='#7f1d1d';out.textContent=res.err;} + else{out.style.background='#ede9fe';out.style.color='#5b21b6';out.textContent=res.ok;} + }); + setMode('pt'); + })(); + + /* === INIT 4: тренажёр === */ + (function(){ + const tasks=[ + {q:'$PA = 4$, $PB = 9$. Найди $PT$.',a:6,hint:'PT = √(4·9) = √36 = 6'}, + {q:'$PT = 8$, $PA = 4$. Найди $PB$.',a:16,hint:'PB = 64/4 = 16'}, + {q:'$PT = 6$, $PB = 12$. Найди $PA$.',a:3,hint:'PA = 36/12 = 3'}, + {q:'$PA = 3$, $PB = 12$. Найди $PT$.',a:6,hint:'PT = √(3·12) = √36 = 6'}, + {q:'$PT = 10$, $PA = 5$. Найди $PB$.',a:20,hint:'PB = 100/5 = 20'}, + ]; + let cur=0, score=0; + const iEl=document.getElementById('p16-tr-i'), scEl=document.getElementById('p16-tr-score'); + const taskEl=document.getElementById('p16-tr-task'), ansEl=document.getElementById('p16-tr-ans'); + const goBtn=document.getElementById('p16-tr-go'), startBtn=document.getElementById('p16-tr-start'); + const fb=document.getElementById('p16-tr-fb'); + function showTask(){ + if(cur>=tasks.length){taskEl.innerHTML='Тренажёр завершён! Очки: '+score+'/'+tasks.length+'';ansEl.style.display='none';goBtn.style.display='none';addXp(score*4,'p16-trainer');bumpProgress('p16',20);return;} + taskEl.innerHTML=tasks[cur].q;iEl.textContent=cur+1;ansEl.value='';fb.style.display='none'; + if(window.renderMathInElement) try{renderMath(taskEl);}catch(e){} + } + goBtn.addEventListener('click',()=>{ + const ans=parseFloat(ansEl.value.replace(',','.')); + const ok=Math.abs(ans-tasks[cur].a)<0.05; + feedback(fb,ok,ok?'Верно!':'Неверно. Подсказка: '+tasks[cur].hint); + if(ok){score++;scEl.textContent=score;cur++;setTimeout(showTask,900);} + }); + startBtn.addEventListener('click',()=>{cur=0;score=0;scEl.textContent=0;ansEl.style.display='';goBtn.style.display='';showTask();}); + showTask(); + })(); + + /* === INIT 5: DnD верно/неверно === */ + (function(){ + const items=[ + {label:'PT² = PA·PB',cat:'true'}, + {label:'PT = PA + PB',cat:'false'}, + {label:'PT — среднее геометрическое PA и PB',cat:'true'}, + {label:'PT всегда больше PA и PB',cat:'false'}, + {label:'Если PA = PB, то PA = PB = PT (точка P — на окружности)',cat:'false'}, + {label:'Квадрат касательной = полная секущая × внешняя часть',cat:'true'}, + ]; + const pool=document.getElementById('p16-dnd-pool'); + const boxes={true:document.getElementById('p16-drop-true-items'),false:document.getElementById('p16-drop-false-items')}; + const fb=document.getElementById('p16-dnd-fb'); + let placed={}; + function reset(){ + pool.innerHTML='';placed={}; + Object.values(boxes).forEach(b=>b.innerHTML=''); + fb.style.display='none'; + items.forEach((it,i)=>{ + const chip=document.createElement('div'); + chip.className='dnd-chip';chip.dataset.i=i;chip.textContent=it.label; + chip.addEventListener('click',()=>chip.classList.toggle('armed')); + Object.entries(boxes).forEach(([cat,bx])=>{ + bx.parentElement.addEventListener('click',()=>{ + if(!chip.classList.contains('armed'))return; + chip.classList.remove('armed'); + if(placed[i]!==undefined) boxes[placed[i]].removeChild(chip); + placed[i]=cat; + bx.appendChild(chip); + }); + }); + pool.appendChild(chip); + }); + } + document.getElementById('p16-dnd-check').addEventListener('click',()=>{ + let ok=0; + items.forEach((it,i)=>{if(placed[i]===it.cat)ok++;}); + feedback(fb,ok===items.length,'Верно: '+ok+'/'+items.length+(ok===items.length?'. Отлично!':'. Попробуй ещё.')); + if(ok===items.length){addXp(8,'p16-dnd');bumpProgress('p16',15);} + }); + document.getElementById('p16-dnd-reset').addEventListener('click',reset); + reset(); + })(); + + /* === INIT 6: Босс §16 === */ + (function(){ + const tasks=[ + {q:'$PA = 4, PB = 16$. Длина касательной $PT$:', + opts:['8','64','4'],cor:0, + exp:'$PT = \\sqrt{4\\cdot16} = \\sqrt{64} = 8$.'}, + {q:'$PT = 6, PB = 9$. Найди $PA$.', + opts:['4','3','2'],cor:0, + exp:'$PA = PT^2/PB = 36/9 = 4$.'}, + {q:'$PT = 5, PA = 5$. Найди $PB$.', + opts:['5','10','25'],cor:0, + exp:'$PB = PT^2/PA = 25/5 = 5$. Значит $PA = PB$ — секущая проходит через центр (диаметр).'}, + {q:'$PA = 3, AB = 5$ (хорда). Найди $PT$.', + opts:['$\\sqrt{24}$','$\\sqrt{15}$','$\\sqrt{8}$'],cor:0, + exp:'$PB = PA + AB = 3+5 = 8$. $PT = \\sqrt{3\\cdot8} = \\sqrt{24} = 2\\sqrt{6}$.'}, + ]; + const cont=document.getElementById('p16-boss-tasks'); + let bhtml=''; + tasks.forEach((t,i)=>{ + bhtml+=`
+
${i+1}. ${t.q}
+
+ ${t.opts.map((o,j)=>``).join('')} +
+ +
`; + }); + cont.innerHTML=bhtml; + if(window.renderMathInElement) try{renderMath(cont);}catch(e){} + })(); +} function buildFinal4stub(){ document.getElementById('final4-body').innerHTML='

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

'+secNav('p16',null); }