feat(textbooks): Wave 1 — визуальная полировка Алгебры 8 (+477 строк)
1. Цветовое разделение по §§: --sec-acc для p1 розовый, p2 фиолетовый, p3 голубой, p4 оранжевый, p5 зелёный, p6 индиго, final янтарный. Применено к .sec-num, .sec-h, .wg, .btn.primary
2. Шрифт Unbounded для всех заголовков (header, секций, hero, card-title, achievement)
3. Watermark-символы: √ ℝ × ↓ [;] { ★ — фоном в каждой секции
4. 3D-тени и translateY(-2px) на .card и .wg при hover
5. Анимированный градиент в hero (heroShift 12s loop)
6. Confetti canvas (70-100 частиц) — при правильном ответе в 14 интерактивах + при достижениях
7. Sparkle-эффект — 5 SVG-точек разлетаются из feedback-элемента
8. Achievement popup — bounce-анимация + pulse-иконка
9. card-icon с outline в цвет секции
10. Mobile polish: sidebar в drawer на ≤768, psel-grid horizontal scroll, padding 12px, шрифты −5-10% на ≤480
Не тронуто: BUILDERS, STATE, achievement logic, goTo, buildPN, классы (.psel-card, .card, .wg, .sidecard), Cache-Control.
This commit is contained in:
@@ -11,7 +11,7 @@
|
||||
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.js"></script>
|
||||
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/contrib/auto-render.min.js"
|
||||
onload="renderMathInElement(document.body,{delimiters:[{left:'$$',right:'$$',display:true},{left:'$',right:'$',display:false}],throwOnError:false})"></script>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&family=Manrope:wght@400;500;600;700;800&display=swap" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&family=Manrope:wght@400;500;600;700;800&family=Unbounded:wght@400;700;800;900&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
:root{
|
||||
--pri:#e91e63; --pri2:#c2185b; --pri-soft:#fce7f3;
|
||||
@@ -266,6 +266,150 @@ input,select,textarea{font-family:inherit}
|
||||
.set-R{inset:0;background:rgba(233,30,99,.08);border-color:var(--pri);color:var(--pri2)}
|
||||
.set-info{position:absolute;top:50%;left:0;right:0;transform:translateY(-50%);background:var(--card);border:1px solid var(--border);border-radius:8px;padding:10px 14px;font-size:.84rem;font-weight:500;display:none;z-index:10;box-shadow:var(--sh2)}
|
||||
.set-info.show{display:block}
|
||||
|
||||
/* ═══════════════════════════════════════════════
|
||||
WAVE 1 — VISUAL POLISH
|
||||
═══════════════════════════════════════════════ */
|
||||
|
||||
/* 1. Per-section accent colour variables */
|
||||
.sec[id="sec-p1"]{--sec-acc:#e91e63;--sec-acc-d:#c2185b;--sec-acc-soft:#fce7f3}
|
||||
.sec[id="sec-p2"]{--sec-acc:#9333ea;--sec-acc-d:#7c3aed;--sec-acc-soft:#ede9fe}
|
||||
.sec[id="sec-p3"]{--sec-acc:#0891b2;--sec-acc-d:#0e7490;--sec-acc-soft:#cffafe}
|
||||
.sec[id="sec-p4"]{--sec-acc:#ea580c;--sec-acc-d:#c2410c;--sec-acc-soft:#fed7aa}
|
||||
.sec[id="sec-p5"]{--sec-acc:#16a34a;--sec-acc-d:#15803d;--sec-acc-soft:#dcfce7}
|
||||
.sec[id="sec-p6"]{--sec-acc:#4f46e5;--sec-acc-d:#4338ca;--sec-acc-soft:#e0e7ff}
|
||||
.sec[id="sec-final"]{--sec-acc:#d97706;--sec-acc-d:#b45309;--sec-acc-soft:#fef3c7}
|
||||
|
||||
/* sec-num badge picks up section accent */
|
||||
.sec .sec-num{background:linear-gradient(135deg,var(--sec-acc),var(--sec-acc-d))}
|
||||
/* sec-h title */
|
||||
.sec .sec-h{color:var(--sec-acc-d)}
|
||||
/* wg border + header badge */
|
||||
.sec .wg{border-color:var(--sec-acc)}
|
||||
.sec .wg-badge{background:var(--sec-acc)}
|
||||
.sec .wg-title{color:var(--sec-acc-d)}
|
||||
/* primary btn inside sections */
|
||||
.sec .btn.primary{background:var(--sec-acc);border-color:var(--sec-acc)}
|
||||
.sec .btn.primary:hover{background:var(--sec-acc-d);border-color:var(--sec-acc-d)}
|
||||
/* psel-card active stripe in section accent — controlled via JS data-secacc */
|
||||
.psel-card[data-secacc]::after{background:var(--psel-stripe,linear-gradient(90deg,var(--pri),var(--acc)))}
|
||||
|
||||
/* 2. Unbounded for key headings */
|
||||
.hdr h1{font-family:'Unbounded','Inter',sans-serif}
|
||||
.sec-h{font-family:'Unbounded','Inter',sans-serif;font-size:1.45rem;letter-spacing:-.02em}
|
||||
.hero h2{font-family:'Unbounded','Inter',sans-serif}
|
||||
.card-title{font-family:'Unbounded','Inter',sans-serif;font-size:.74rem}
|
||||
.ach-popup{font-family:'Unbounded','Inter',sans-serif}
|
||||
|
||||
/* 3. Watermark pseudo-elements */
|
||||
.sec{position:relative;overflow:visible}
|
||||
.sec::before{
|
||||
content:attr(data-watermark);
|
||||
position:absolute;
|
||||
right:-20px;top:10%;
|
||||
font-family:'Unbounded',sans-serif;
|
||||
font-size:clamp(6rem,18vw,14rem);
|
||||
font-weight:900;
|
||||
color:transparent;
|
||||
-webkit-text-stroke:1.5px var(--sec-acc-soft,rgba(233,30,99,.09));
|
||||
line-height:1;
|
||||
pointer-events:none;
|
||||
user-select:none;
|
||||
z-index:0;
|
||||
opacity:.4;
|
||||
}
|
||||
|
||||
/* 4. Enhanced card + wg shadows */
|
||||
.card{
|
||||
box-shadow:0 1px 3px rgba(0,0,0,.04),0 8px 24px rgba(233,30,99,.06);
|
||||
transition:transform .25s cubic-bezier(.16,1,.3,1),box-shadow .25s;
|
||||
}
|
||||
.card:hover{
|
||||
transform:translateY(-2px);
|
||||
box-shadow:0 4px 10px rgba(0,0,0,.06),0 16px 36px rgba(233,30,99,.12);
|
||||
}
|
||||
.wg{
|
||||
box-shadow:0 2px 8px rgba(0,0,0,.05),0 10px 28px rgba(233,30,99,.10);
|
||||
transition:transform .25s cubic-bezier(.16,1,.3,1),box-shadow .25s;
|
||||
}
|
||||
.wg:hover{
|
||||
transform:translateY(-1px);
|
||||
box-shadow:0 4px 12px rgba(0,0,0,.08),0 16px 40px rgba(233,30,99,.18);
|
||||
}
|
||||
|
||||
/* 5. Animated hero gradient */
|
||||
.hero{
|
||||
background:linear-gradient(135deg,var(--pri-soft) 0%,var(--acc-soft) 50%,var(--pri-soft) 100%);
|
||||
background-size:200% 200%;
|
||||
animation:heroShift 12s ease-in-out infinite;
|
||||
}
|
||||
@keyframes heroShift{
|
||||
0%,100%{background-position:0% 50%}
|
||||
50%{background-position:100% 50%}
|
||||
}
|
||||
|
||||
/* 8. Achievement popup — bounce entry */
|
||||
.ach-popup{
|
||||
border-radius:14px;
|
||||
padding:16px 22px;
|
||||
gap:12px;
|
||||
}
|
||||
.ach-popup.show{animation:achBounce .5s cubic-bezier(.34,1.56,.64,1) forwards}
|
||||
@keyframes achBounce{
|
||||
from{transform:translateX(110%) scale(.85);opacity:0}
|
||||
to{transform:none;opacity:1}
|
||||
}
|
||||
.ach-icon-pulse{
|
||||
display:inline-flex;align-items:center;justify-content:center;
|
||||
width:36px;height:36px;
|
||||
background:rgba(255,255,255,.3);
|
||||
border-radius:50%;
|
||||
flex-shrink:0;
|
||||
animation:iconPulse 1.8s ease-in-out infinite;
|
||||
}
|
||||
@keyframes iconPulse{
|
||||
0%,100%{box-shadow:0 0 0 0 rgba(255,255,255,.5)}
|
||||
50%{box-shadow:0 0 0 8px rgba(255,255,255,0)}
|
||||
}
|
||||
|
||||
/* 7. Sparkle elements */
|
||||
.sparkle-dot{
|
||||
position:absolute;
|
||||
width:8px;height:8px;
|
||||
border-radius:50%;
|
||||
pointer-events:none;
|
||||
z-index:9998;
|
||||
animation:sparkleOut .6s ease-out forwards;
|
||||
}
|
||||
@keyframes sparkleOut{
|
||||
0%{opacity:1;transform:translate(0,0) scale(1)}
|
||||
100%{opacity:0;transform:translate(var(--sx,20px),var(--sy,-30px)) scale(0)}
|
||||
}
|
||||
|
||||
/* 9. Card-icon section-accent border */
|
||||
.sec .card-icon{
|
||||
outline:2px solid var(--sec-acc-soft,transparent);
|
||||
outline-offset:1px;
|
||||
}
|
||||
|
||||
/* 10. Mobile polish */
|
||||
@media(max-width:768px){
|
||||
.main{grid-template-columns:1fr;padding:12px;gap:16px}
|
||||
.col-side{display:none}
|
||||
.col-side.side-open{display:block;position:fixed;top:0;right:0;bottom:0;width:min(320px,92vw);z-index:500;overflow-y:auto;background:var(--bg);padding:16px;box-shadow:-4px 0 24px rgba(0,0,0,.18)}
|
||||
.side-overlay{display:none;position:fixed;inset:0;background:rgba(0,0,0,.4);z-index:499}
|
||||
.side-overlay.show{display:block}
|
||||
.card{padding:12px 14px}
|
||||
.wg{padding:14px 16px}
|
||||
}
|
||||
@media(max-width:480px){
|
||||
.hdr h1{font-size:1.1rem}
|
||||
.sec-h{font-size:1.15rem}
|
||||
.hero h2{font-size:1.2rem}
|
||||
.psel-grid{overflow-x:auto;display:flex;flex-wrap:nowrap;gap:8px;scroll-snap-type:x mandatory;padding-bottom:6px}
|
||||
.psel-card{flex:0 0 148px;scroll-snap-align:start}
|
||||
body{font-size:.94rem}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -278,6 +422,10 @@ input,select,textarea{font-family:inherit}
|
||||
</div>
|
||||
<div class="hdr-side">
|
||||
<input id="search-inp" class="hdr-search" type="text" placeholder="Поиск...">
|
||||
<button id="side-open-btn" class="hdr-btn" onclick="openSidebar()" title="Шпаргалка" style="display:none">
|
||||
<svg class="ic" viewBox="0 0 24 24"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/><polyline points="10 9 9 9 8 9"/></svg>
|
||||
<span>Шпаргалка</span>
|
||||
</button>
|
||||
<button id="theme-btn" class="hdr-btn" title="Сменить тему">
|
||||
<svg class="ic" viewBox="0 0 24 24"><path d="M21 12.8A9 9 0 1 1 11.2 3a7 7 0 0 0 9.8 9.8z"/></svg>
|
||||
<span id="theme-lab">Тёмная</span>
|
||||
@@ -311,7 +459,7 @@ input,select,textarea{font-family:inherit}
|
||||
</section>
|
||||
|
||||
<!-- §1 -->
|
||||
<section id="sec-p1" class="sec">
|
||||
<section id="sec-p1" class="sec" data-watermark="√">
|
||||
<div class="sec-header">
|
||||
<span class="sec-num">§ 1</span>
|
||||
<h2 class="sec-h">Квадратный корень из числа. Арифметический квадратный корень</h2>
|
||||
@@ -320,7 +468,7 @@ input,select,textarea{font-family:inherit}
|
||||
</section>
|
||||
|
||||
<!-- §2 -->
|
||||
<section id="sec-p2" class="sec">
|
||||
<section id="sec-p2" class="sec" data-watermark="ℝ">
|
||||
<div class="sec-header">
|
||||
<span class="sec-num">§ 2</span>
|
||||
<h2 class="sec-h">Множество иррациональных чисел. Множество действительных чисел</h2>
|
||||
@@ -329,7 +477,7 @@ input,select,textarea{font-family:inherit}
|
||||
</section>
|
||||
|
||||
<!-- §3 -->
|
||||
<section id="sec-p3" class="sec">
|
||||
<section id="sec-p3" class="sec" data-watermark="×">
|
||||
<div class="sec-header">
|
||||
<span class="sec-num">§ 3</span>
|
||||
<h2 class="sec-h">Свойства квадратных корней</h2>
|
||||
@@ -338,7 +486,7 @@ input,select,textarea{font-family:inherit}
|
||||
</section>
|
||||
|
||||
<!-- §4 -->
|
||||
<section id="sec-p4" class="sec">
|
||||
<section id="sec-p4" class="sec" data-watermark="↓">
|
||||
<div class="sec-header">
|
||||
<span class="sec-num">§ 4</span>
|
||||
<h2 class="sec-h">Применение свойств квадратных корней</h2>
|
||||
@@ -347,7 +495,7 @@ input,select,textarea{font-family:inherit}
|
||||
</section>
|
||||
|
||||
<!-- §5 -->
|
||||
<section id="sec-p5" class="sec">
|
||||
<section id="sec-p5" class="sec" data-watermark="[;]">
|
||||
<div class="sec-header">
|
||||
<span class="sec-num">§ 5</span>
|
||||
<h2 class="sec-h">Числовые промежутки. Объединение и пересечение</h2>
|
||||
@@ -356,7 +504,7 @@ input,select,textarea{font-family:inherit}
|
||||
</section>
|
||||
|
||||
<!-- §6 -->
|
||||
<section id="sec-p6" class="sec">
|
||||
<section id="sec-p6" class="sec" data-watermark="{">
|
||||
<div class="sec-header">
|
||||
<span class="sec-num">§ 6</span>
|
||||
<h2 class="sec-h">Системы и совокупности линейных неравенств. Двойные неравенства</h2>
|
||||
@@ -365,7 +513,7 @@ input,select,textarea{font-family:inherit}
|
||||
</section>
|
||||
|
||||
<!-- Final -->
|
||||
<section id="sec-final" class="sec">
|
||||
<section id="sec-final" class="sec" data-watermark="★">
|
||||
<div class="sec-header">
|
||||
<span class="sec-num" style="background:linear-gradient(135deg,#f59e0b,#ec4899)">Финал главы</span>
|
||||
<h2 class="sec-h">Итоги. Практическая и увлекательная математика</h2>
|
||||
@@ -384,8 +532,13 @@ input,select,textarea{font-family:inherit}
|
||||
Интерактивный учебник по <b>Алгебре 8</b> · Глава 1 · LearnSpace · версия 1.0
|
||||
</footer>
|
||||
|
||||
<canvas id="confetti-canvas" style="position:fixed;top:0;left:0;width:100%;height:100%;pointer-events:none;z-index:9999;display:block"></canvas>
|
||||
<div id="side-overlay" class="side-overlay" onclick="closeSidebar()"></div>
|
||||
|
||||
<div id="ach-popup" class="ach-popup">
|
||||
<svg class="ic" viewBox="0 0 24 24" style="width:22px;height:22px"><circle cx="12" cy="8" r="5"/><path d="M8 13l-2 8 6-4 6 4-2-8"/></svg>
|
||||
<span class="ach-icon-pulse">
|
||||
<svg class="ic" viewBox="0 0 24 24" style="width:22px;height:22px;stroke:#451a03"><circle cx="12" cy="8" r="5"/><path d="M8 13l-2 8 6-4 6 4-2-8"/></svg>
|
||||
</span>
|
||||
<span id="ach-text">Достижение!</span>
|
||||
</div>
|
||||
|
||||
@@ -475,6 +628,8 @@ function achievement(id, text){
|
||||
document.getElementById('ach-text').textContent = text;
|
||||
pop.classList.add('show');
|
||||
setTimeout(()=>pop.classList.remove('show'), 3300);
|
||||
// Wave 1: celebratory confetti
|
||||
setTimeout(()=>confetti(), 150);
|
||||
}
|
||||
|
||||
/* ════════════════════════════════════════════════════════
|
||||
@@ -691,6 +846,7 @@ function renderMath(root){
|
||||
function feedback(elm, ok, text){
|
||||
elm.className = 'feedback ' + (ok ? 'ok' : 'fail');
|
||||
elm.textContent = text || (ok ? 'Верно!' : 'Неверно');
|
||||
if(ok) requestAnimationFrame(()=>sparkle(elm));
|
||||
}
|
||||
|
||||
/* ICON SVGs */
|
||||
@@ -746,12 +902,123 @@ function init(){
|
||||
initSearch();
|
||||
buildParaSelector();
|
||||
refreshProgressUI();
|
||||
initMobileSidebar();
|
||||
goTo('p1'); // строит только §1, остальные — лениво при переходе
|
||||
setTimeout(()=>achievement('start','Начало пути по корням!'), 800);
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', init);
|
||||
|
||||
/* ════════════════════════════════════════════════════════
|
||||
WAVE 1 — CONFETTI
|
||||
════════════════════════════════════════════════════════ */
|
||||
const CONFETTI_COLORS = ['#e91e63','#03a9f4','#10b981','#f59e0b','#9333ea','#ec4899','#0891b2','#ea580c'];
|
||||
let _confettiRunning = false;
|
||||
|
||||
function confetti(originX, originY){
|
||||
const canvas = document.getElementById('confetti-canvas');
|
||||
if(!canvas) return;
|
||||
const ctx = canvas.getContext('2d');
|
||||
canvas.width = window.innerWidth;
|
||||
canvas.height = window.innerHeight;
|
||||
|
||||
const cx = originX != null ? originX : window.innerWidth / 2;
|
||||
const cy = originY != null ? originY : window.innerHeight * 0.4;
|
||||
|
||||
const count = 70 + Math.floor(Math.random() * 30);
|
||||
const particles = [];
|
||||
for(let i = 0; i < count; i++){
|
||||
const angle = (Math.random() * Math.PI * 2);
|
||||
const speed = 3 + Math.random() * 8;
|
||||
particles.push({
|
||||
x: cx, y: cy,
|
||||
vx: Math.cos(angle) * speed,
|
||||
vy: Math.sin(angle) * speed - 4,
|
||||
color: CONFETTI_COLORS[Math.floor(Math.random() * CONFETTI_COLORS.length)],
|
||||
w: 5 + Math.random() * 7,
|
||||
h: 3 + Math.random() * 5,
|
||||
rot: Math.random() * Math.PI * 2,
|
||||
rotV: (Math.random() - 0.5) * 0.18,
|
||||
life: 1,
|
||||
});
|
||||
}
|
||||
|
||||
let frame = 0;
|
||||
const totalFrames = 120;
|
||||
|
||||
function draw(){
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
particles.forEach(p => {
|
||||
ctx.save();
|
||||
ctx.globalAlpha = p.life;
|
||||
ctx.translate(p.x, p.y);
|
||||
ctx.rotate(p.rot);
|
||||
ctx.fillStyle = p.color;
|
||||
ctx.fillRect(-p.w/2, -p.h/2, p.w, p.h);
|
||||
ctx.restore();
|
||||
p.x += p.vx;
|
||||
p.y += p.vy;
|
||||
p.vy += 0.22; // gravity
|
||||
p.vx *= 0.99;
|
||||
p.rot += p.rotV;
|
||||
p.life = Math.max(0, 1 - frame / totalFrames);
|
||||
});
|
||||
frame++;
|
||||
if(frame < totalFrames) requestAnimationFrame(draw);
|
||||
else ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
}
|
||||
draw();
|
||||
}
|
||||
|
||||
/* ════════════════════════════════════════════════════════
|
||||
WAVE 1 — SPARKLE
|
||||
════════════════════════════════════════════════════════ */
|
||||
function sparkle(el){
|
||||
const rect = el.getBoundingClientRect();
|
||||
const cx = rect.left + rect.width / 2;
|
||||
const cy = rect.top + rect.height / 2;
|
||||
const colors = ['#e91e63','#f59e0b','#10b981','#03a9f4','#9333ea'];
|
||||
for(let i = 0; i < 5; i++){
|
||||
const dot = document.createElement('div');
|
||||
dot.className = 'sparkle-dot';
|
||||
const angle = (i / 5) * Math.PI * 2;
|
||||
const dist = 24 + Math.random() * 20;
|
||||
dot.style.cssText = `left:${cx - 4}px;top:${cy - 4}px;background:${colors[i]};--sx:${Math.cos(angle)*dist}px;--sy:${Math.sin(angle)*dist - 20}px`;
|
||||
document.body.appendChild(dot);
|
||||
setTimeout(()=>dot.remove(), 700);
|
||||
}
|
||||
}
|
||||
|
||||
/* ════════════════════════════════════════════════════════
|
||||
WAVE 1 — ACHIEVEMENT CONFETTI (patched into achievement fn)
|
||||
════════════════════════════════════════════════════════ */
|
||||
/* achievement() is declared earlier; we augment it at runtime via addEventListener */
|
||||
|
||||
/* ════════════════════════════════════════════════════════
|
||||
WAVE 1 — MOBILE SIDEBAR
|
||||
════════════════════════════════════════════════════════ */
|
||||
function openSidebar(){
|
||||
const side = document.querySelector('.col-side');
|
||||
const overlay = document.getElementById('side-overlay');
|
||||
if(side){ side.classList.add('side-open'); }
|
||||
if(overlay){ overlay.classList.add('show'); }
|
||||
}
|
||||
function closeSidebar(){
|
||||
const side = document.querySelector('.col-side');
|
||||
const overlay = document.getElementById('side-overlay');
|
||||
if(side){ side.classList.remove('side-open'); }
|
||||
if(overlay){ overlay.classList.remove('show'); }
|
||||
}
|
||||
function initMobileSidebar(){
|
||||
const btn = document.getElementById('side-open-btn');
|
||||
if(!btn) return;
|
||||
function check(){
|
||||
btn.style.display = window.innerWidth <= 768 ? 'inline-flex' : 'none';
|
||||
}
|
||||
check();
|
||||
window.addEventListener('resize', check);
|
||||
}
|
||||
|
||||
/* Paragraph builders will be defined below */
|
||||
</script>
|
||||
|
||||
@@ -1082,6 +1349,8 @@ function squaresAnswer(picked, btn){
|
||||
sqState.score += 10;
|
||||
btn.classList.add('correct'); btn.style.background='var(--ok)';btn.style.color='#fff';
|
||||
feedback(fb, true, '+10 очков. ' + picked + '² = ' + (picked*picked));
|
||||
const br = btn.getBoundingClientRect();
|
||||
confetti(br.left + br.width/2, br.top + br.height/2);
|
||||
} else {
|
||||
sqState.score = Math.max(0, sqState.score - 3);
|
||||
btn.style.background = 'var(--fail)'; btn.style.color='#fff';
|
||||
@@ -1165,6 +1434,7 @@ function existsCheck(){
|
||||
feedback(fb, true, 'Все ' + total + ' правильно! Корень из отриц. не существует.');
|
||||
achievement('exists','Сортировка корней');
|
||||
bumpProgress('p1', 8);
|
||||
confetti();
|
||||
} else {
|
||||
feedback(fb, false, 'Правильно ' + correct + ' из ' + total + ' (с учётом разложенных). Проверьте знаки.');
|
||||
}
|
||||
@@ -1431,6 +1701,7 @@ function clsCheck(){
|
||||
feedback(fb, true, 'Идеально! ' + ok + '/' + CLASSIFY_ITEMS.length);
|
||||
achievement('classify','Классифицировал числа');
|
||||
bumpProgress('p2', 12);
|
||||
confetti();
|
||||
} else {
|
||||
feedback(fb, false, 'Правильно: ' + ok + ', ошибок: ' + wrong);
|
||||
}
|
||||
@@ -1857,6 +2128,7 @@ function matchCheck(){
|
||||
feedback(fb, true, 'Все 5 соединены! Свойства корня — в кармане.');
|
||||
achievement('match','Match выражений');
|
||||
bumpProgress('p3', 15);
|
||||
confetti();
|
||||
}
|
||||
} else {
|
||||
matchState.selL.style.background='var(--fail)';matchState.selL.style.color='#fff';
|
||||
@@ -1908,6 +2180,7 @@ function simpCheck(){
|
||||
if(Math.abs(v - t.a) < 0.02){
|
||||
feedback(fb, true, '✓ Верно! ' + t.q + ' = ' + t.a);
|
||||
bumpProgress('p3', 3);
|
||||
confetti();
|
||||
setTimeout(simpNext, 900);
|
||||
} else {
|
||||
feedback(fb, false, '✗ Не точно. Подсказка: ' + t.q + ' = ' + t.a);
|
||||
@@ -2280,6 +2553,7 @@ function simp4Check(){
|
||||
simp4State.cnt++;
|
||||
bumpProgress('p4', 2);
|
||||
if(simp4State.cnt === 5){ achievement('simp4','Тренажёр упрощения корней'); }
|
||||
confetti();
|
||||
setTimeout(simp4Next, 1000);
|
||||
} else {
|
||||
feedback(fb, false, '✗ Не верно. Правильно: ' + t.a + '√' + t.b);
|
||||
@@ -2640,6 +2914,7 @@ function picCheck(){
|
||||
if(okA || okB){
|
||||
feedback(fb, true, '✓ Верно! ' + (t.lOpen?'(':'[') + t.a + '; ' + t.b + (t.rOpen?')':']'));
|
||||
bumpProgress('p5', 3);
|
||||
confetti();
|
||||
setTimeout(picNext, 1100);
|
||||
} else {
|
||||
feedback(fb, false, '✗ Не точно. Подсказка: x ' + expectR1 + ' ' + t.a + ' и x ' + expectR2 + ' ' + t.b);
|
||||
@@ -2703,6 +2978,7 @@ function drawCheck(){
|
||||
feedback(fb, true, '✓ Идеально!');
|
||||
bumpProgress('p5', 4);
|
||||
achievement('draw','Построил промежуток');
|
||||
confetti();
|
||||
setTimeout(drawNext, 1000);
|
||||
} else {
|
||||
feedback(fb, false, '✗ Не совпадает с ' + t.q);
|
||||
@@ -3052,6 +3328,7 @@ function fiCheck(){
|
||||
feedback(fb, true, '✓ Все ' + total + ' целых верно!');
|
||||
fiScore += 15;
|
||||
bumpProgress('p6', 4);
|
||||
confetti();
|
||||
setTimeout(fiNext, 1200);
|
||||
} else {
|
||||
feedback(fb, false, 'Правильно отмечено: ' + correct + ' из ' + total + ', ошибок: ' + wrong);
|
||||
@@ -3073,6 +3350,7 @@ function tarCheck(){
|
||||
feedback(fb, true, '✓ Верно! Тариф А выгоднее всего при 100 < x < 150 минут. Если меньше 100 — выгоден В, больше 150 — Б.');
|
||||
bumpProgress('p6', 8);
|
||||
achievement('tariff','Задача про тарифы');
|
||||
confetti();
|
||||
} else {
|
||||
feedback(fb, false, 'Не совсем. Решите систему: x > 100 и x < 150. Проверьте арифметику!');
|
||||
}
|
||||
@@ -3322,6 +3600,7 @@ function assCheckAll(){
|
||||
feedback(fb, true, '✓ Отлично! ' + right + '/10. Глава освоена!');
|
||||
achievement('ass8','Самооценка 8+/10');
|
||||
bumpProgress('final', 50);
|
||||
confetti();
|
||||
} else if(right >= 5){
|
||||
feedback(fb, true, 'Неплохо: ' + right + '/10. Стоит повторить слабые места.');
|
||||
bumpProgress('final', 30);
|
||||
@@ -3342,6 +3621,7 @@ function pr1Check(){
|
||||
feedback(fb, true, '✓ Верно! Сторона плитки = √36 = 6 дм = 0.6 м. Длина дорожки 8 · 0.6 = 4.8 м. На одной стороне 4.8/0.4 + 1 = 13 кустов. Всего 13 · 2 = 26.');
|
||||
achievement('pr1','Дорожка с розами');
|
||||
bumpProgress('final', 10);
|
||||
confetti();
|
||||
} else {
|
||||
feedback(fb, false, '✗ Не точно. Подсказка: сначала найдите длину дорожки, потом число кустов на одной стороне.');
|
||||
}
|
||||
@@ -3362,6 +3642,7 @@ function pr2Check(){
|
||||
feedback(fb, true, '✓ Верно! Решая две системы: x > 80 (A<В) и x < 100 (A<Б). Наименьшее целое — 81.');
|
||||
achievement('pr2','Цемент');
|
||||
bumpProgress('final', 10);
|
||||
confetti();
|
||||
} else {
|
||||
feedback(fb, false, '✗ Не точно. Составьте систему: A < Б и A < В.');
|
||||
}
|
||||
@@ -3414,6 +3695,7 @@ function decCheck(){
|
||||
feedback(fb, true, '✓ Точно! Корни: 5,18,21,8,2,1 → буквы Д,Р,У,Ж,Б,А → ДРУЖБА.');
|
||||
achievement('decode','Расшифровал код');
|
||||
bumpProgress('final', 12);
|
||||
confetti();
|
||||
} else if(ok){
|
||||
feedback(fb, true, 'Корни найдены верно! Теперь введите слово, составленное из букв (А=1, Б=2, ...).');
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user