// Генератор physics_9_hub.html на основе physics_10_hub.html // Палитра: blue (вместо amber у Phys 10), 5 глав, заголовки/описания Физики 9. 'use strict'; const fs = require('fs'); const path = require('path'); const SRC = path.join(__dirname, '..', '..', 'frontend', 'textbooks', 'physics_10_hub.html'); const DST = path.join(__dirname, '..', '..', 'frontend', 'textbooks', 'physics_9_hub.html'); let h = fs.readFileSync(SRC, 'utf8'); // === 1. Primary palette: amber (#ca8a04 / #fde047) → blue (#2563eb / #60a5fa) === h = h.replace( /:root\{[\s\S]*?--sh-h:0 12px 36px rgba\(202,138,4,\.18\);[\s\S]*?\}/, `:root{ --bg:#eff6ff; --card:#fff; --text:#0f172a; --muted:#475569; --border:#bfdbfe; --pri:#2563eb; --pri-d:#1d4ed8; --pri-soft:#dbeafe; --ch1:#2563eb; --ch1-d:#1d4ed8; --ch2:#059669; --ch2-d:#047857; --ch3:#7c3aed; --ch3-d:#6d28d9; --ch4:#db2777; --ch4-d:#be185d; --ch5:#0891b2; --ch5-d:#0e7490; --sh:0 4px 16px rgba(37,99,235,.10); --sh-h:0 12px 36px rgba(37,99,235,.18); }`); h = h.replace( /html\.dark\{[\s\S]*?--pri-soft:rgba\(202,138,4,\.16\);[\s\S]*?\}/, `html.dark{ --bg:#0a1428; --card:#102137; --text:#dbeafe; --muted:#93c5fd; --border:#1e3a5f; --pri-soft:rgba(37,99,235,.16); }`); // === 2. Header gradient: amber → blue === h = h.replace( /\.hdr\{position:relative;background:linear-gradient\(110deg,#713f12 0%,#ca8a04 55%,#fde047 100%\)[^}]*\}/, `.hdr{position:relative;background:linear-gradient(110deg,#1e3a8a 0%,#2563eb 55%,#60a5fa 100%);color:#fff;padding:32px 24px 28px;overflow:hidden;border-bottom:2px solid rgba(219,234,254,.18)}`); h = h.replace(/rgba\(254,243,199,\.12\)/g, 'rgba(219,234,254,.12)'); h = h.replace(/rgba\(254,243,199,\.18\)/g, 'rgba(219,234,254,.18)'); // === 3. po-icon gradient + po-bar/po-fill === h = h.replace( /\.po-icon\{[^}]*background:linear-gradient\(135deg,#ca8a04,#fde047\)[^}]*\}/, `.po-icon{width:46px;height:46px;border-radius:12px;background:linear-gradient(135deg,#2563eb,#60a5fa);color:#fff;display:flex;align-items:center;justify-content:center;flex-shrink:0;font-family:'Outfit',sans-serif;font-size:1.4rem;font-weight:900;font-style:italic}`); h = h.replace(/\.po-bar\{height:8px;background:rgba\(202,138,4,\.14\)/, '.po-bar{height:8px;background:rgba(37,99,235,.14)'); h = h.replace(/\.po-fill\{height:100%;background:linear-gradient\(90deg,var\(--pri\),#fde047\)/, '.po-fill{height:100%;background:linear-gradient(90deg,var(--pri),#60a5fa)'); h = h.replace(/\.po-xp\{[^}]*background:linear-gradient\(135deg,#f59e0b,var\(--pri\)\)[^}]*\}/, ".po-xp{display:inline-flex;align-items:center;gap:6px;padding:6px 14px;background:linear-gradient(135deg,#3b82f6,var(--pri));color:#fff;border-radius:99px;font-size:.8rem;font-weight:800;font-family:'Unbounded',sans-serif;letter-spacing:.02em;box-shadow:0 4px 12px rgba(37,99,235,.24)}"); // === 4. Final-head gradient === h = h.replace( /\.final-head\{padding:18px 22px;background:linear-gradient\(135deg,#713f12 0%,#ca8a04 55%,#f59e0b 100%\)/, '.final-head{padding:18px 22px;background:linear-gradient(135deg,#1e3a8a 0%,#2563eb 55%,#3b82f6 100%)'); // === 5. Title + H1 + subtitle === h = h.replace(/Физика 10 класс — учебник<\/title>/, '<title>Физика 9 класс — учебник'); h = h.replace(/

Физика — 10 класс<\/h1>/, '

Физика — 9 класс

'); h = h.replace( /
Полный курс физики 10 класса:[^<]+<\/div>/, '
Полный курс механики: кинематика, динамика, статика, законы сохранения, 12 лабораторных работ
' ); // === 6. localStorage keys + API endpoint === h = h.replace(/physics10_theme/g, 'physics9_theme'); h = h.replace(/physics10_xp/g, 'physics9_xp'); h = h.replace(/physics10_course_master/g, 'physics9_course_master'); h = h.replace(/physics10_course_bosses/g, 'physics9_course_bosses'); h = h.replace(/physics10-master/g, 'physics9-master'); h = h.replace(/'\/api\/textbooks\/physics-10\/children'/, "'/api/textbooks/physics-9/children'"); // === 7. Заменяем блок с 6 главами целиком на блок с 5 главами === const chBlock = `
v
Глава 1
Основы кинематики
§1–§14
Механическое движение, относительность, векторы, путь и перемещение, равномерное и равноускоренное движение, движение по окружности.
Прогресс0%
Открыть главу
F
Глава 2
Основы динамики
§15–§24
Законы Ньютона, масса, закон Гука, силы трения, движение под силой тяжести, всемирное тяготение, вес и невесомость.
Прогресс0%
Открыть главу
M
Глава 3
Основы статики
§25–§30
Условия равновесия, момент силы, рычаги, блоки, наклонная плоскость, КПД, центр тяжести, закон Архимеда.
Прогресс0%
Открыть главу
p·E
Глава 4
Законы сохранения
§31–§36
Импульс тела, закон сохранения импульса, реактивное движение, работа, мощность, кинетическая и потенциальная энергия, закон сохранения энергии.
Прогресс0%
Открыть главу
Δt
Глава 5
Лабораторный практикум
ЛР 1–12
12 лабораторных работ: погрешности, ускорение, окружность, закон Гука, трение, брошенное тело, рычаг, блоки, наклонная плоскость, Архимед, импульс, энергия.
Прогресс0%
Открыть главу
`; // Replace the entire ... block (6 cards → 5 cards) h = h.replace(/\s*\s*/, chBlock); // === 8. final cta + master text === h = h.replace(/
Курс Физика 10 пройден!<\/div>/, '
Курс Физика 9 пройден!
'); h = h.replace(/«Магистр физики 10»/g, '«Магистр физики 9»'); h = h.replace(/Магистр физики 10/g, 'Магистр физики 9'); // final-head-sub h = h.replace( /
Шпаргалка курса и интегрированные боссы по всем 6 главам\. В разработке \(Phase 7\)\.<\/div>/, '
Шпаргалка курса и интегрированные боссы по всем 5 главам. В разработке (Phase 7).
' ); // fin-placeholder: 37 → 36, 6 → 5 h = h.replace( /Итоговая шпаргалка по всем 37 параграфам и 8–10 интегрированных боссов появятся в Phase 7 \(после завершения всех 6 глав\)\./, 'Итоговая шпаргалка по всем 36 параграфам и 8–10 интегрированных боссов появятся в Phase 7 (после завершения всех 5 глав).' ); // Footer h = h.replace(/Интерактивный учебник «Физика — 10 класс»/, 'Интерактивный учебник «Физика — 9 класс»'); // Achievement strip h = h.replace(/Прочитайте все 37 параграфов курса, чтобы получить достижение/, 'Прочитайте все 36 параграфов курса, чтобы получить достижение'); h = h.replace(/Вы прочитали весь курс физики 10 класса\./, 'Вы прочитали весь курс физики 9 класса.'); // === 9. TOTAL + CH_PARA + CH_IDX === h = h.replace(/var TOTAL = 37;[\s\S]*?var CH_IDX = \{[\s\S]*?\};/, `var TOTAL = 36; var CH_PARA = { 'physics-9-ch1': 14, 'physics-9-ch2': 10, 'physics-9-ch3': 6, 'physics-9-ch4': 6, 'physics-9-ch5': 12, }; var CH_IDX = { 'physics-9-ch1': 1, 'physics-9-ch2': 2, 'physics-9-ch3': 3, 'physics-9-ch4': 4, 'physics-9-ch5': 5, };`); // === 10. Chapter grid: 6 cards → 5 cards (2-1-2 на широких экранах смотрится лучше при 5) === // Оставим CSS как есть — repeat(3,1fr) на >=1000px и repeat(2,1fr) на >=680px. // 5 карточек выстроятся как 3+2 (или 2+2+1). Это нормально. fs.writeFileSync(DST, h); console.log('OK hub →', DST, 'bytes:', h.length); // Sanity: parse inline scripts const scriptMatches = [...h.matchAll(/