diff --git a/backend/tests/math5-page.test.js b/backend/tests/math5-page.test.js index b166d9e..3500727 100644 --- a/backend/tests/math5-page.test.js +++ b/backend/tests/math5-page.test.js @@ -106,6 +106,12 @@ test('ch1: §1 «как решать задачу», §2 «разрядная т assert.ok(doc.querySelector('#p8-iv2 #p8-xa'), '§8: «найди неизвестное»'); win.goTo('p9'); await wait(80); assert.ok(doc.querySelector('#p9-fig svg circle'), '§9: прямоугольник из точек'); + win.goTo('p10'); await wait(80); + assert.ok(doc.querySelector('#p10-fig svg rect'), '§10: квадрат из клеток'); + win.goTo('p11'); await wait(80); + assert.ok(doc.querySelector('#p11-fig svg circle'), '§11: точки-группы с остатком'); + win.goTo('p12'); await wait(80); + assert.ok(doc.querySelector('#p12-fig'), '§12: делители-чипсы (НОД)'); win.goTo('final'); await wait(80); assert.ok(doc.querySelector('#fin-go'), 'финал: арена боссов'); win.bumpProgress('final', 100); await wait(20); diff --git a/frontend/textbooks/math_5_ch1.html b/frontend/textbooks/math_5_ch1.html index cf34185..f632a6d 100644 --- a/frontend/textbooks/math_5_ch1.html +++ b/frontend/textbooks/math_5_ch1.html @@ -832,6 +832,223 @@ function buildP9(){ })(); } +/* ===================== § 10. СТЕПЕНЬ ЧИСЛА ===================== */ +function buildP10(){ + var box=document.getElementById('p10-body'); var h=''; + h+=makeCard('oral','Где это в жизни','10.0', + '

Степень прячется там, где что-то многократно повторяется. Площадь квадратного ковра со стороной $3$ м — это $3^2=9$ м². Объём кубика со стороной $2$ см — $2^3=8$ см³. А если каждый день репост видят вдвое больше людей — рост идёт степенями двойки.

'); + h+=makeCard('theory','Что такое степень','10.1', + '

Степенью числа $a$ с натуральным показателем $n$ называют произведение $n$ одинаковых множителей $a$:

' + +'

$a^n=\\underbrace{a\\cdot a\\cdot \\ldots \\cdot a}_{n}$.   Здесь $a$ — основание, $n$ — показатель.

' + +'

$a^2$ читают «$a$ в квадрате», $a^3$ — «$a$ в кубе». Принято $a^1=a$.

'); + h+=makeCard('example','Примеры','10.2', + '

$2^3=2\\cdot2\\cdot2=8$.   $5^2=25$.   $10^4=10\\,000$.   $1^{100}=1$.

'); + h+=makeCard('example','Разбор по шагам','10.3', + '

Вычислим $2^4$.

' + +'
    ' + +'
  1. Показатель $4$ — берём $4$ множителя: $2\\cdot2\\cdot2\\cdot2$.
  2. ' + +'
  3. $2\\cdot2=4$, затем $4\\cdot2=8$, затем $8\\cdot2=16$.
  4. ' + +'
  5. Ответ: $2^4=16$.
  6. ' + +'
'); + h+=makeCard('theory','А знаешь ли ты?','10.4', + '

По легенде, изобретатель шахмат попросил у правителя «всего лишь» зёрнышко за первую клетку, $2$ за вторую, $4$ за третью и так далее — удваивая. На $64$-й клетке вышло $2^{63}$ зёрен — больше, чем во всех амбарах мира! Вот как быстро растут степени двойки.

'); + h+='
Интерактив 1
Квадрат числа
' + +'
Клетки образуют квадрат со стороной $a$. Сколько всего клеток ($a^2$)?
' + +'
Вопрос 1 / 5Очки: 0 / 5
' + +'
' + +'
' + +'
'; + h+='
Интерактив 2
Вычисли степень
' + +'
Вычисли значение степени.
' + +'
Пример 1 / 6Очки: 0 / 6
' + +'
' + +'
' + +'
'; + h+=secNav('p9','p11')+readBtn('p10'); + box.innerHTML=h; renderMath(box); + + (function(){ + var i=0,score=0,cur=null; + function sqSVG(a){ var u=Math.min(26,Math.floor(150/a)),x0=4,W=x0*2+a*u; var s=''; + for(var r=0;r'; + return s+''; } + function gen(){ cur=_ri(2,9); } + function show(){ if(i>=5){ document.getElementById('p10-fig').innerHTML='Готово! '+score+' / 5'; if(score>=4){addXp(15,'p10-iv1');bumpProgress('p10',30);}else if(score>=2){addXp(8,'p10-iv1');bumpProgress('p10',16);} return; } + gen(); document.getElementById('p10-i').textContent=i+1; + document.getElementById('p10-fig').innerHTML=sqSVG(cur)+'
сторона '+cur+', значит '+cur+'2
'; + document.getElementById('p10-a').value=''; document.getElementById('p10-fb').style.display='none'; } + function go(){ if(i>=5)return; var fb=document.getElementById('p10-fb'), a=parseInt(document.getElementById('p10-a').value,10); + if(isNaN(a)){ feedback(fb,false,'Введи число.'); return; } + if(a===cur*cur){ score++; feedback(fb,true,'✓ Верно! $'+cur+'^2='+(cur*cur)+'$.'); renderMath(fb); } else { feedback(fb,false,'✗ Нет. $'+cur+'^2='+(cur*cur)+'$.'); renderMath(fb); } + document.getElementById('p10-s').textContent=score; i++; setTimeout(show,1200); } + document.getElementById('p10-go').addEventListener('click',go); + document.getElementById('p10-a').addEventListener('keydown',function(e){ if(e.key==='Enter')go(); }); + show(); + })(); + + (function(){ + var i=0,score=0,cur=null; + function gen(){ var a=_ri(2,7), n=_pick([2,2,3,3,4]); if(a>=6)n=_pick([2,3]); cur={a:a,n:n,ans:Math.pow(a,n)}; } + function show(){ if(i>=6){ document.getElementById('p10-pq').innerHTML='Готово! '+score+' / 6'; if(score>=5){addXp(15,'p10-iv2');bumpProgress('p10',30);}else if(score>=3){addXp(8,'p10-iv2');bumpProgress('p10',16);} return; } + gen(); document.getElementById('p10-pi').textContent=i+1; + document.getElementById('p10-pq').innerHTML='Вычисли $'+cur.a+'^{'+cur.n+'}$'; renderMath(document.getElementById('p10-pq')); + document.getElementById('p10-pa').value=''; document.getElementById('p10-pfb').style.display='none'; } + function go(){ if(i>=6)return; var fb=document.getElementById('p10-pfb'), a=parseInt(document.getElementById('p10-pa').value,10); + if(isNaN(a)){ feedback(fb,false,'Введи число.'); return; } + if(a===cur.ans){ score++; feedback(fb,true,'✓ Верно! Ответ '+cur.ans+'.'); } else feedback(fb,false,'✗ Нет. Правильно: '+cur.ans+'.'); + document.getElementById('p10-ps').textContent=score; i++; setTimeout(show,1200); } + document.getElementById('p10-pgo').addEventListener('click',go); + document.getElementById('p10-pa').addEventListener('keydown',function(e){ if(e.key==='Enter')go(); }); + show(); + })(); +} + +/* ===================== § 11. ДЕЛЕНИЕ С ОСТАТКОМ ===================== */ +function buildP11(){ + var box=document.getElementById('p11-body'); var h=''; + h+=makeCard('oral','Где это в жизни','11.0', + '

Разделить $25$ конфет на $4$ детей поровну не получится — по $6$ и ещё одна лишняя. Эта «лишняя» — остаток. Деление с остатком повсюду: дни недели, страницы по тетрадям, ученики по командам.

'); + h+=makeCard('rule','Деление с остатком','11.1', + '

Разделить $a$ на $b$ с остатком — значит найти такие числа $q$ и $r$, что

' + +'

$a = b\\cdot q + r$,   где $0\\le r < b$.

' + +'

$q$ — неполное частное, $r$ — остаток. Остаток всегда меньше делителя.

'); + h+=makeCard('example','Примеры','11.2', + '

$47:5=9$ (ост. $2$), ведь $5\\cdot9+2=47$.   $30:6=5$ (ост. $0$) — делится нацело.

'); + h+=makeCard('example','Разбор по шагам','11.3', + '

Разделим $47$ на $5$ с остатком.

' + +'
    ' + +'
  1. Ищем наибольшее число «пятёрок» в $47$: $5\\cdot9=45$, а $5\\cdot10=50$ — уже много.
  2. ' + +'
  3. Значит неполное частное $q=9$.
  4. ' + +'
  5. Остаток: $47-45=2$. Проверяем: $2<5$. Верно.
  6. ' + +'
  7. Ответ: $47=5\\cdot9+2$.
  8. ' + +'
'); + h+=makeCard('theory','А знаешь ли ты?','11.4', + '

Часы — это деление с остатком! Если сейчас $10$ часов, то через $5$ часов будет не $15$, а $3$ часа: $15:12=1$ (ост. $3$). Математики называют такой счёт «арифметикой остатков», и на ней держится вся компьютерная защита данных.

'); + h+='
Интерактив 1
Найди остаток
' + +'
Точки раскладывают по $b$ в ряд. Сколько точек останется в неполном ряду?
' + +'
Вопрос 1 / 6Очки: 0 / 6
' + +'
' + +'
' + +'
'; + h+='
Интерактив 2
Неполное частное
' + +'
Найди неполное частное $q$ (сколько целых раз делитель помещается в делимом).
' + +'
Вопрос 1 / 5Очки: 0 / 5
' + +'
' + +'
' + +'
'; + h+=secNav('p10','p12')+readBtn('p11'); + box.innerHTML=h; renderMath(box); + + (function(){ + var i=0,score=0,cur=null; + function dotsSVG(a,b){ var u=15,x0=6,cols=b,rows=Math.ceil(a/b),W=x0*2+cols*u,H=x0*2+rows*u; var s='',k=0; + for(var r=0;r=a)break; var rem=k>=a-(a%b||b)&&(a%b)!==0&&r===rows-1; s+=''; k++; } return s+''; } + function gen(){ var b=_ri(3,7), q=_ri(3,8), r=_ri(1,b-1); cur={a:b*q+r,b:b,r:r}; } + function show(){ if(i>=6){ document.getElementById('p11-fig').innerHTML='Готово! '+score+' / 6'; if(score>=5){addXp(15,'p11-iv1');bumpProgress('p11',30);}else if(score>=3){addXp(8,'p11-iv1');bumpProgress('p11',16);} return; } + gen(); document.getElementById('p11-i').textContent=i+1; + document.getElementById('p11-fig').innerHTML=dotsSVG(cur.a,cur.b)+'
'+cur.a+' точек по '+cur.b+' в ряд
'; + document.getElementById('p11-a').value=''; document.getElementById('p11-fb').style.display='none'; } + function go(){ if(i>=6)return; var fb=document.getElementById('p11-fb'), a=parseInt(document.getElementById('p11-a').value,10); + if(isNaN(a)){ feedback(fb,false,'Введи число.'); return; } + if(a===cur.r){ score++; feedback(fb,true,'✓ Верно! Остаток '+cur.r+' (красные точки).'); } else feedback(fb,false,'✗ Нет. Остаток '+cur.r+'.'); + document.getElementById('p11-s').textContent=score; i++; setTimeout(show,1300); } + document.getElementById('p11-go').addEventListener('click',go); + document.getElementById('p11-a').addEventListener('keydown',function(e){ if(e.key==='Enter')go(); }); + show(); + })(); + + (function(){ + var i=0,score=0,cur=null; + function gen(){ var b=_ri(3,12), q=_ri(4,15), r=_ri(0,b-1); cur={a:b*q+r,b:b,q:q}; } + function show(){ if(i>=5){ document.getElementById('p11-qq').innerHTML='Готово! '+score+' / 5'; if(score>=4){addXp(15,'p11-iv2');bumpProgress('p11',30);}else if(score>=2){addXp(8,'p11-iv2');bumpProgress('p11',16);} return; } + gen(); document.getElementById('p11-qi').textContent=i+1; + document.getElementById('p11-qq').innerHTML='Раздели $'+cur.a+'$ на $'+cur.b+'$ с остатком. Чему равно неполное частное?'; renderMath(document.getElementById('p11-qq')); + document.getElementById('p11-qa').value=''; document.getElementById('p11-qfb').style.display='none'; } + function go(){ if(i>=5)return; var fb=document.getElementById('p11-qfb'), a=parseInt(document.getElementById('p11-qa').value,10); + if(isNaN(a)){ feedback(fb,false,'Введи число.'); return; } + if(a===cur.q){ score++; feedback(fb,true,'✓ Верно! '+cur.a+'='+cur.b+'·'+cur.q+'+'+(cur.a-cur.b*cur.q)+'.'); } else feedback(fb,false,'✗ Нет. Неполное частное '+cur.q+'.'); + document.getElementById('p11-qs').textContent=score; i++; setTimeout(show,1300); } + document.getElementById('p11-qgo').addEventListener('click',go); + document.getElementById('p11-qa').addEventListener('keydown',function(e){ if(e.key==='Enter')go(); }); + show(); + })(); +} + +/* ===================== § 12. ДЕЛИТЕЛИ И КРАТНЫЕ. НОД И НОК ===================== */ +function buildP12(){ + var box=document.getElementById('p12-body'); var h=''; + h+=makeCard('oral','Где это в жизни','12.0', + '

Чтобы рассадить $24$ ученика за столы поровну, нужны делители числа $24$. Чтобы два светофора, мигающие через $4$ и $6$ секунд, мигнули одновременно, ищут общее кратное. Эти понятия — основа всей работы с дробями.

'); + h+=makeCard('theory','Делители и кратные','12.1', + '

Делитель числа $a$ — число, на которое $a$ делится нацело. Делители $12$: $1,2,3,4,6,12$.

' + +'

Кратное числа $a$ — число, которое делится на $a$ нацело. Кратные $4$: $4,8,12,16,\\dots$

'); + h+=makeCard('rule','НОД и НОК','12.2', + '

НОД (наибольший общий делитель) — самое большое число, на которое делятся оба числа.

' + +'

НОК (наименьшее общее кратное) — самое маленькое число, которое делится на каждое из них.

' + +'

Полезно: $\\text{НОД}(a,b)\\cdot\\text{НОК}(a,b)=a\\cdot b$.

'); + h+=makeCard('example','Разбор по шагам','12.3', + '

Найдём НОД$(12,18)$ и НОК$(12,18)$.

' + +'
    ' + +'
  1. Делители $12$: $1,2,3,4,6,12$. Делители $18$: $1,2,3,6,9,18$.
  2. ' + +'
  3. Общие: $1,2,3,6$. Наибольший — $6$. Значит НОД$=6$.
  4. ' + +'
  5. НОК: кратные $18$: $18,36,54,\\dots$; $36$ делится на $12$. Значит НОК$=36$.
  6. ' + +'
  7. Проверка: $6\\cdot36=216=12\\cdot18$. Верно!
  8. ' + +'
'); + h+=makeCard('theory','А знаешь ли ты?','12.4', + '

Быстрый способ найти НОД придумал ещё Евклид $2300$ лет назад: большее число заменяют остатком от деления на меньшее — и так, пока остаток не станет нулём. Это один из древнейших алгоритмов, и он до сих пор работает в компьютерах!

'); + h+='
Интерактив 1
Найди НОД
' + +'
Общие делители подсвечены. Введи наибольший из них (НОД).
' + +'
Вопрос 1 / 5Очки: 0 / 5
' + +'
' + +'
' + +'
'; + h+='
Интерактив 2
Найди НОК
' + +'
Найди наименьшее общее кратное двух чисел.
' + +'
Вопрос 1 / 5Очки: 0 / 5
' + +'
' + +'
' + +'
'; + h+=secNav('p11','p13')+readBtn('p12'); + box.innerHTML=h; renderMath(box); + + function divisors(n){ var d=[]; for(var k=1;k<=n;k++)if(n%k===0)d.push(k); return d; } + function gcd(a,b){ while(b){ var t=b; b=a%b; a=t; } return a; } + + (function(){ + var i=0,score=0,cur=null; + function gen(){ var pairs=[[12,18],[8,12],[16,24],[15,20],[18,24],[14,21],[20,30],[9,12]]; cur=_pick(pairs); cur=cur.slice(); cur.g=gcd(cur[0],cur[1]); } + function chips(n,common){ var ds=divisors(n),s='
Делители '+n+': '; ds.forEach(function(d){ var hot=common.indexOf(d)>=0; s+=''+d+''; }); return s+'
'; } + function show(){ if(i>=5){ document.getElementById('p12-fig').innerHTML='Готово! '+score+' / 5'; if(score>=4){addXp(15,'p12-iv1');bumpProgress('p12',30);}else if(score>=2){addXp(8,'p12-iv1');bumpProgress('p12',16);} return; } + gen(); document.getElementById('p12-i').textContent=i+1; + var common=divisors(cur[0]).filter(function(d){ return cur[1]%d===0; }); + document.getElementById('p12-fig').innerHTML=chips(cur[0],common)+chips(cur[1],common); + document.getElementById('p12-a').value=''; document.getElementById('p12-fb').style.display='none'; } + function go(){ if(i>=5)return; var fb=document.getElementById('p12-fb'), a=parseInt(document.getElementById('p12-a').value,10); + if(isNaN(a)){ feedback(fb,false,'Введи число.'); return; } + if(a===cur.g){ score++; feedback(fb,true,'✓ Верно! НОД('+cur[0]+','+cur[1]+')='+cur.g+'.'); } else feedback(fb,false,'✗ Нет. НОД='+cur.g+' (наибольший общий делитель).'); + document.getElementById('p12-s').textContent=score; i++; setTimeout(show,1300); } + document.getElementById('p12-go').addEventListener('click',go); + document.getElementById('p12-a').addEventListener('keydown',function(e){ if(e.key==='Enter')go(); }); + show(); + })(); + + (function(){ + var i=0,score=0,cur=null; + function gen(){ var pairs=[[4,6],[6,9],[8,12],[3,5],[10,15],[4,10],[6,8],[9,12]]; var p=_pick(pairs); cur={a:p[0],b:p[1],ans:p[0]*p[1]/gcd(p[0],p[1])}; } + function show(){ if(i>=5){ document.getElementById('p12-kq').innerHTML='Готово! '+score+' / 5'; if(score>=4){addXp(15,'p12-iv2');bumpProgress('p12',30);}else if(score>=2){addXp(8,'p12-iv2');bumpProgress('p12',16);} return; } + gen(); document.getElementById('p12-ki').textContent=i+1; + document.getElementById('p12-kq').innerHTML='Найди НОК$('+cur.a+';\\,'+cur.b+')$'; renderMath(document.getElementById('p12-kq')); + document.getElementById('p12-ka').value=''; document.getElementById('p12-kfb').style.display='none'; } + function go(){ if(i>=5)return; var fb=document.getElementById('p12-kfb'), a=parseInt(document.getElementById('p12-ka').value,10); + if(isNaN(a)){ feedback(fb,false,'Введи число.'); return; } + if(a===cur.ans){ score++; feedback(fb,true,'✓ Верно! НОК='+cur.ans+'.'); } else feedback(fb,false,'✗ Нет. НОК('+cur.a+','+cur.b+')='+cur.ans+'.'); + document.getElementById('p12-ks').textContent=score; i++; setTimeout(show,1300); } + document.getElementById('p12-kgo').addEventListener('click',go); + document.getElementById('p12-ka').addEventListener('keydown',function(e){ if(e.key==='Enter')go(); }); + show(); + })(); +} + /* ===================== ДАННЫЕ САЙДБАРА / ГЛОССАРИЯ ===================== */ var SIDEBARS = { p1:{ title:'Шпаргалка § 1', rows:[ @@ -880,6 +1097,21 @@ var SIDEBARS = { ['Деление','обратно умножению'], ['Проверка','частное · делитель = делимое'], ['Распределит.','$a(b+c)=ab+ac$'] ]}, + p10:{ title:'Шпаргалка § 10', rows:[ + ['Степень','$a^n=a\\cdot a\\cdots a$ ($n$ раз)'], + ['Основание','$a$ — что умножаем'], + ['Показатель','$n$ — сколько множителей'], + ['$a^2$ / $a^3$','квадрат / куб'] ]}, + p11:{ title:'Шпаргалка § 11', rows:[ + ['Формула','$a=b\\cdot q+r$'], + ['$q$','неполное частное'], + ['$r$','остаток, всегда $r