diff --git a/backend/src/db/migrations/037_physics_8_hub.sql b/backend/src/db/migrations/037_physics_8_hub.sql
new file mode 100644
index 0000000..879d7b6
--- /dev/null
+++ b/backend/src/db/migrations/037_physics_8_hub.sql
@@ -0,0 +1,45 @@
+-- Physics 8 hub migration.
+-- Rebuilds physics-8 as a full 3-chapter + lab textbook in the style of physics-10:
+-- physics-8 (hub, html_path = physics_8_hub.html)
+-- physics-8-ch1 (Тепловые явления, §§1–11) → physics_8_ch1.html
+-- physics-8-ch2 (Электромагнитные явления, §§12–31) → physics_8_ch2.html
+-- physics-8-ch3 (Световые явления, §§32–40) → physics_8_ch3.html
+-- physics-8-lab (Лабораторный практикум, 7 ЛР) → physics_8_lab.html
+--
+-- Replaces the old legacy children created in migration 015
+-- (physics-8-thermal / physics-8-electro / physics-8-optics), which pointed
+-- to monolithic legacy files. Author left empty per project policy.
+
+-- 1. Remove legacy children (HTML files are kept on disk as backup, just unlinked from DB).
+DELETE FROM textbooks WHERE slug IN ('physics-8-thermal', 'physics-8-electro', 'physics-8-optics');
+
+-- 2. Update the parent physics-8 hub row.
+UPDATE textbooks
+SET
+ author = '',
+ para_count = 47,
+ html_path = 'physics_8_hub.html',
+ description = 'Полный курс физики 8 класса: тепловые явления (§§1–11), электромагнитные явления (§§12–31), световые явления (§§32–40), 7 виртуальных лабораторных работ.',
+ color = 'violet'
+WHERE slug = 'physics-8';
+
+-- 3. Insert the 4 new children.
+INSERT INTO textbooks
+ (slug, subject, grade, title, author, description, html_path, para_count, color, sort_order, is_active, parent_slug)
+VALUES
+ ('physics-8-ch1', 'physics', 8, 'Физика 8 · Тепловые явления',
+ '',
+ '§§1–11: внутренняя энергия, теплопроводность, конвекция, излучение, удельная теплоёмкость, плавление, кипение.',
+ 'physics_8_ch1.html', 11, 'red', 1, 1, 'physics-8'),
+ ('physics-8-ch2', 'physics', 8, 'Физика 8 · Электромагнитные явления',
+ '',
+ '§§12–31: электризация, ток, закон Ома, последовательное и параллельное соединения, мощность тока, постоянные магниты, электромагнит.',
+ 'physics_8_ch2.html', 20, 'amber', 2, 1, 'physics-8'),
+ ('physics-8-ch3', 'physics', 8, 'Физика 8 · Световые явления',
+ '',
+ '§§32–40: прямолинейное распространение света, отражение, преломление, линзы, построение изображений, глаз и очки.',
+ 'physics_8_ch3.html', 9, 'cyan', 3, 1, 'physics-8'),
+ ('physics-8-lab', 'physics', 8, 'Физика 8 · Лабораторный практикум',
+ '',
+ '7 виртуальных лабораторных работ: теплообмен, удельная теплоёмкость, простейшая цепь, последовательное и параллельное соединения, работа и мощность, отражение света.',
+ 'physics_8_lab.html', 7, 'emerald', 4, 1, 'physics-8');
diff --git a/frontend/js/optics.js b/frontend/js/optics.js
new file mode 100644
index 0000000..1c550f5
--- /dev/null
+++ b/frontend/js/optics.js
@@ -0,0 +1,284 @@
+// optics.js — модуль хелперов геометрической оптики для учебника Физика 8
+// Экспорт в window.OPTICS = { ... }
+(function(){
+'use strict';
+
+// === Палитра ===
+const COLOR = {
+ ray: '#fbbf24',
+ rayIncident:'#0891b2',
+ rayReflected:'#10b981',
+ rayRefracted:'#a855f7',
+ normal: '#94a3b8',
+ lensConv: '#22c55e',
+ lensDiv: '#f97316',
+ mirror: '#475569',
+ hatch: '#94a3b8',
+ axis: '#cbd5e1',
+ focus: '#1d4ed8',
+ imageReal: '#7c3aed',
+ imageVirtual:'#a78bfa'
+};
+
+// === Стрелка-наконечник (внутренний помощник) ===
+function arrowHead(x, y, ux, uy, size, color){
+ const w = size * 0.55;
+ const px = -uy, py = ux;
+ const bx = x - ux*size, by = y - uy*size;
+ const lx = bx + px*w, ly = by + py*w;
+ const rx = bx - px*w, ry = by - py*w;
+ return ` `;
+}
+
+// === Луч (линия + стрелка посередине) ===
+// dashed: true → пунктир (для виртуальных продолжений)
+function ray(x1, y1, x2, y2, color, dashed){
+ color = color || COLOR.ray;
+ const dx = x2 - x1, dy = y2 - y1;
+ const len = Math.sqrt(dx*dx + dy*dy);
+ if (len < 1e-6) return '';
+ const ux = dx/len, uy = dy/len;
+ const dash = dashed ? ' stroke-dasharray="6 4"' : '';
+ let s = '';
+ s += ` `;
+ // Стрелка-наконечник в точке (x2,y2)
+ if (!dashed) s += arrowHead(x2, y2, ux, uy, 9, color);
+ return s;
+}
+
+// === Падающий, отражённый, преломлённый лучи + нормаль ===
+// На границе двух сред (горизонтальной) с нормалью вверх
+function refractRay(x0, y0, angleInDeg, n1, n2, len){
+ // angleInDeg — угол падения от нормали (в градусах)
+ // Возвращает SVG: падающий луч (сверху-слева к (x0,y0)) + нормаль + отражённый + преломлённый
+ len = len || 80;
+ const a1 = angleInDeg * Math.PI / 180;
+ const sinA2 = (n1/n2) * Math.sin(a1);
+ const tir = Math.abs(sinA2) > 1; // полное внутреннее отражение
+ const a2 = tir ? 0 : Math.asin(sinA2);
+
+ let s = '';
+ // Граница
+ s += ` `;
+ // Нормаль (вверх и вниз пунктиром)
+ s += ` `;
+ // Падающий луч (приходит сверху-слева)
+ const xi = x0 - len*Math.sin(a1), yi = y0 - len*Math.cos(a1);
+ s += ray(xi, yi, x0, y0, COLOR.rayIncident);
+ // Отражённый луч (вверх-вправо)
+ const xr = x0 + len*Math.sin(a1), yr = y0 - len*Math.cos(a1);
+ s += ray(x0, y0, xr, yr, COLOR.rayReflected);
+ // Преломлённый луч (вниз)
+ if (!tir){
+ const xt = x0 + len*Math.sin(a2), yt = y0 + len*Math.cos(a2);
+ s += ray(x0, y0, xt, yt, COLOR.rayRefracted);
+ }
+ return { svg: s, a1: a1, a2: a2, tir: tir };
+}
+
+// === Отражение от плоского зеркала ===
+// Зеркало горизонтальное на y = y0
+function reflectRay(x0, y0, angleInDeg, len){
+ len = len || 80;
+ const a = angleInDeg * Math.PI / 180;
+ let s = '';
+ // Зеркало
+ s += ` `;
+ // Штриховка с обратной стороны
+ for (let i = -len; i <= len; i += 8){
+ s += ` `;
+ }
+ // Нормаль
+ s += ` `;
+ // Падающий
+ const xi = x0 - len*Math.sin(a), yi = y0 - len*Math.cos(a);
+ s += ray(xi, yi, x0, y0, COLOR.rayIncident);
+ // Отражённый
+ const xr = x0 + len*Math.sin(a), yr = y0 - len*Math.cos(a);
+ s += ray(x0, y0, xr, yr, COLOR.rayReflected);
+ return s;
+}
+
+// === Плоское зеркало (отдельный элемент) ===
+function mirrorPlane(x, y, len, angleDeg){
+ angleDeg = angleDeg || 0;
+ const a = angleDeg * Math.PI / 180;
+ const ca = Math.cos(a), sa = Math.sin(a);
+ const x1 = x - len/2*ca, y1 = y - len/2*sa;
+ const x2 = x + len/2*ca, y2 = y + len/2*sa;
+ const nx = -sa, ny = ca; // нормаль "наружу"
+ let s = ` `;
+ // Штриховка с тыльной стороны
+ for (let t = -len/2 + 3; t <= len/2; t += 8){
+ const bx = x + t*ca, by = y + t*sa;
+ s += ` `;
+ }
+ return s;
+}
+
+// === Сферическое зеркало (вогнутое/выпуклое) ===
+// kind: 'concave' (вогнутое — фокусирует) | 'convex' (выпуклое — рассеивает)
+function mirrorSpherical(cx, cy, R, kind, halfH){
+ halfH = halfH || R * 0.6;
+ const sign = (kind === 'convex') ? -1 : 1;
+ // Дуга
+ const x1 = cx - sign*R*0.15, y1 = cy - halfH;
+ const x2 = cx - sign*R*0.15, y2 = cy + halfH;
+ const sweep = sign > 0 ? 0 : 1;
+ let s = ` `;
+ // Главная оптическая ось
+ s += ` `;
+ return s;
+}
+
+// === Тонкая линза ===
+// kind: 'converging' (двусторонне-выпуклая, |) | 'diverging' (двусторонне-вогнутая, |)
+// Возвращает SVG с осью, фокусами F и 2F
+function thinLens(cx, cy, halfH, F, kind){
+ halfH = halfH || 70;
+ F = F || 80;
+ const color = (kind === 'diverging') ? COLOR.lensDiv : COLOR.lensConv;
+ let s = '';
+ // Главная оптическая ось
+ s += ` `;
+ // Линза — вертикальный овал
+ s += ` `;
+ if (kind === 'diverging'){
+ // Стрелки наружу (рассеивающая)
+ s += arrowHead(cx, cy - halfH, 0, -1, 10, color);
+ s += arrowHead(cx, cy + halfH, 0, 1, 10, color);
+ } else {
+ // Стрелки внутрь (собирающая) — вершины на оси
+ s += arrowHead(cx - 6, cy - halfH + 8, -0.6, -0.8, 10, color);
+ s += arrowHead(cx + 6, cy - halfH + 8, 0.6, -0.8, 10, color);
+ s += arrowHead(cx - 6, cy + halfH - 8, -0.6, 0.8, 10, color);
+ s += arrowHead(cx + 6, cy + halfH - 8, 0.6, 0.8, 10, color);
+ }
+ // Фокусы F и 2F
+ s += ` `;
+ s += ` `;
+ s += `F `;
+ s += `F `;
+ s += ` `;
+ s += ` `;
+ s += `2F `;
+ s += `2F `;
+ return s;
+}
+
+// === Построение изображения в тонкой линзе ===
+// F — фокусное расстояние (положительное для собирающей, отрицательное для рассеивающей)
+// d — расстояние от предмета до линзы (положительное)
+// h — высота предмета (положительная)
+// Возвращает { f: расстояние до изображения, h2: высота, virtual: bool, kind: 'real'|'virtual' }
+function buildLensImage(F, d, h){
+ // 1/F = 1/d + 1/f → f = d·F / (d - F)
+ if (Math.abs(d - F) < 1e-6){
+ return { f: Infinity, h2: -Infinity, virtual: false, kind: 'infinity' };
+ }
+ const f = d * F / (d - F);
+ const h2 = -h * f / d; // увеличение: h2/h = -f/d
+ const virtual = (F > 0) ? (d < F) : true; // для рассеивающей всегда мнимое
+ return { f: f, h2: h2, virtual: virtual, kind: virtual ? 'virtual' : 'real' };
+}
+
+// === Три "золотых" луча для построения изображения ===
+// Возвращает SVG трёх лучей: через центр, параллельно оси, через передний фокус.
+// objX, objY — координата предмета (вершина стрелки)
+// lensX, lensY — центр линзы
+// F (px) — фокусное расстояние (в пикселях)
+function goldenRays(objX, objY, lensX, lensY, F){
+ let s = '';
+ const dx = lensX - objX;
+ const dy = lensY - objY;
+ // Луч 1: параллельно оси → проходит через F с другой стороны
+ const y1At = objY; // приходит на линзу на высоте objY
+ s += ray(objX, y1At, lensX, y1At, COLOR.rayIncident);
+ s += ray(lensX, y1At, lensX + 2.5*F, lensY + (y1At - lensY) * (-2.5*F)/(F * (objY < lensY ? 1 : -1)), COLOR.rayIncident);
+ // Луч 2: через центр — продолжается без преломления
+ s += ray(objX, objY, lensX + dx, lensY + dy, COLOR.rayReflected);
+ // Луч 3: через передний фокус → выходит параллельно оси
+ // (вычислим точку пересечения с линзой)
+ const slope = (lensY - objY) / (objX - (lensX - F));
+ const yAtLens = lensY - slope * F; // упрощённо
+ s += ray(objX, objY, lensX, yAtLens, COLOR.rayRefracted);
+ s += ray(lensX, yAtLens, lensX + 2*F, yAtLens, COLOR.rayRefracted);
+ return s;
+}
+
+// === Глаз (упрощённая схема) ===
+// accommodation: 0..1, где 0 — расслабленный (дальний предмет), 1 — напряжённый (близкий)
+function eyeDiagram(cx, cy, R, accommodation){
+ accommodation = accommodation || 0;
+ let s = '';
+ // Глазное яблоко
+ s += ` `;
+ // Роговица — выпуклость спереди (слева)
+ s += ` `;
+ // Хрусталик — эллипс изнутри, форма зависит от accommodation
+ const lensHalfH = R * 0.45;
+ const lensW = R * (0.10 + 0.10 * accommodation); // толще при напряжении
+ s += ` `;
+ // Сетчатка — задняя часть
+ s += ` `;
+ // Зрительный нерв
+ s += ` `;
+ return s;
+}
+
+// === Источник света / предмет ===
+// kind: 'point' (точечный звезда) | 'arrow' (вертикальная стрелка-предмет)
+function lightObject(x, y, h, kind){
+ kind = kind || 'arrow';
+ if (kind === 'point'){
+ let s = ` `;
+ // Лучики
+ for (let i = 0; i < 8; i++){
+ const a = i * Math.PI / 4;
+ const x1 = x + 8*Math.cos(a), y1 = y + 8*Math.sin(a);
+ const x2 = x + 13*Math.cos(a), y2 = y + 13*Math.sin(a);
+ s += ` `;
+ }
+ return s;
+ }
+ // Стрелка-предмет: основание на оси (y), вершина на (y - h)
+ const tipY = y - h;
+ const color = '#0f172a';
+ let s = ` `;
+ s += arrowHead(x, tipY, 0, -1, 9, color);
+ return s;
+}
+
+// === Тень и полутень ===
+// Источник в (sx, sy), непрозрачный объект — отрезок [ox-or .. ox+or] на высоте oy.
+// Возвращает SVG полупрозрачных треугольников тени/полутени, падающих на экран y = screenY.
+function shadowTriangle(sx, sy, ox, oy, or, screenY){
+ // Касательные от источника к краям объекта дают полутень.
+ // Лучи через центр объекта дают полную тень.
+ // Простейшая реализация для точечного источника: только тень.
+ const dy = screenY - sy;
+ const k = dy / (oy - sy);
+ const x1 = sx + (ox - or - sx) * k;
+ const x2 = sx + (ox + or - sx) * k;
+ let s = '';
+ s += ` `;
+ return s;
+}
+
+// === Экспорт ===
+window.OPTICS = {
+ COLOR: COLOR,
+ ray: ray,
+ refractRay: refractRay,
+ reflectRay: reflectRay,
+ mirrorPlane: mirrorPlane,
+ mirrorSpherical: mirrorSpherical,
+ thinLens: thinLens,
+ buildLensImage: buildLensImage,
+ goldenRays: goldenRays,
+ eyeDiagram: eyeDiagram,
+ lightObject: lightObject,
+ shadowTriangle: shadowTriangle
+};
+
+})();
diff --git a/frontend/js/phys.js b/frontend/js/phys.js
index ccca6d9..9e596b8 100644
--- a/frontend/js/phys.js
+++ b/frontend/js/phys.js
@@ -225,8 +225,158 @@ function paToAtm(p) { return p / 101325; }
function litersToM3(V) { return V / 1000; }
function m3ToLiters(V) { return V * 1000; }
+// === Расширения для Физики 8 (тепловые явления) ===
+
+// === Цвет по температуре: 240° (синий) → 0° (красный) ===
+function tempColor(t, tMin, tMax) {
+ const u = Math.max(0, Math.min(1, (t - tMin) / (tMax - tMin)));
+ const hue = 240 * (1 - u);
+ return `hsl(${hue.toFixed(0)},72%,52%)`;
+}
+
+// === Термометр (вертикальная шкала, столбик ртути по температуре) ===
+function thermometer(x, y, h, tMin, tMax, tValue) {
+ // x, y — верх корпуса; h — высота столбика
+ const reservoirR = 11;
+ const tubeW = 8;
+ const u = Math.max(0, Math.min(1, (tValue - tMin) / (tMax - tMin)));
+ const fillH = h * u;
+ const color = tempColor(tValue, tMin, tMax);
+ let s = '';
+ // Корпус (стекло)
+ s += ` `;
+ // Столбик ртути
+ s += ` `;
+ // Резервуар
+ s += ` `;
+ // Деления (5)
+ for (let i = 0; i <= 5; i++) {
+ const ty = y + h * i / 5;
+ const tv = tMax - (tMax - tMin) * i / 5;
+ s += ` `;
+ s += `${tv.toFixed(0)} `;
+ }
+ // Подпись текущего значения
+ s += `${tValue.toFixed(0)} °C `;
+ return s;
+}
+
+// === Калориметр-стакан с жидкостью ===
+function calorimeter(x, y, w, h, fillFrac, liquidColor) {
+ fillFrac = Math.max(0, Math.min(1, fillFrac || 0.6));
+ liquidColor = liquidColor || '#60a5fa';
+ const wall = 4;
+ const innerH = h - wall;
+ const liqH = innerH * fillFrac;
+ let s = '';
+ // Внешний контур
+ s += ` `;
+ // Жидкость
+ s += ` `;
+ // Мениск
+ s += ` `;
+ return s;
+}
+
+// === Симуляция теплопроводности по стержню (одномерное уравнение тепла) ===
+// Возвращает объект с .step(dt), .render(x, y, w, h), .reset(), .setTHot(t), .setTCold(t)
+function createHeatBar(opts) {
+ opts = opts || {};
+ const N = opts.N || 30;
+ const tHot = opts.tHot != null ? opts.tHot : 200;
+ const tCold = opts.tCold != null ? opts.tCold : 0;
+ const alpha = opts.alpha || 0.25; // коэф. диффузии (отн. ед.)
+ const T = new Array(N);
+ for (let i = 0; i < N; i++) T[i] = tCold;
+ return {
+ N: N, alpha: alpha, T: T,
+ _tHot: tHot, _tCold: tCold,
+ setTHot(v) { this._tHot = v; },
+ setTCold(v) { this._tCold = v; },
+ reset() {
+ for (let i = 0; i < this.N; i++) this.T[i] = this._tCold;
+ },
+ step(dt) {
+ // Конечно-разностное уравнение теплопроводности с граничными условиями Дирихле.
+ const Tnew = new Array(this.N);
+ Tnew[0] = this._tHot;
+ Tnew[this.N - 1] = this._tCold;
+ for (let i = 1; i < this.N - 1; i++) {
+ Tnew[i] = this.T[i] + this.alpha * dt * (this.T[i-1] - 2*this.T[i] + this.T[i+1]);
+ }
+ this.T = Tnew;
+ },
+ render(x, y, w, h) {
+ const segW = w / this.N;
+ const tMin = Math.min(this._tCold, this._tHot);
+ const tMax = Math.max(this._tCold, this._tHot);
+ let s = '';
+ for (let i = 0; i < this.N; i++) {
+ const c = tempColor(this.T[i], tMin, tMax);
+ s += ` `;
+ }
+ // Контур стержня
+ s += ` `;
+ return s;
+ }
+ };
+}
+
+// === График фазовых переходов T(t) с горизонтальными плато ===
+// points: массив сегментов [{tStart, tEnd, Tstart, Tend, label?}]
+// W, H, pad — размеры графика; tMaxAll, TminAll, TmaxAll — диапазоны
+function phaseGraphTT(W, H, pad, points, tMaxAll, TminAll, TmaxAll) {
+ const toX = t => pad + (W - 2*pad) * t / tMaxAll;
+ const toY = T => H - pad - (H - 2*pad) * (T - TminAll) / (TmaxAll - TminAll);
+ let s = '';
+ // Оси
+ s += ` `;
+ s += ` `;
+ s += `t `;
+ s += `T,°C `;
+ // Сегменты
+ let d = '';
+ let first = true;
+ for (const seg of points) {
+ if (first) { d += `M ${toX(seg.tStart).toFixed(1)} ${toY(seg.Tstart).toFixed(1)} `; first = false; }
+ d += `L ${toX(seg.tEnd).toFixed(1)} ${toY(seg.Tend).toFixed(1)} `;
+ }
+ s += ` `;
+ // Подписи сегментов
+ for (const seg of points) {
+ if (seg.label) {
+ const mx = (toX(seg.tStart) + toX(seg.tEnd)) / 2;
+ const my = (toY(seg.Tstart) + toY(seg.Tend)) / 2 - 8;
+ s += `${seg.label} `;
+ }
+ }
+ return { svg: s, toX: toX, toY: toY };
+}
+
+// === Электронные хелперы для электрических задач ===
+// Параллельное и последовательное сопротивление
+function Rseries() {
+ let R = 0;
+ for (let i = 0; i < arguments.length; i++) R += arguments[i];
+ return R;
+}
+function Rparallel() {
+ let inv = 0;
+ for (let i = 0; i < arguments.length; i++) {
+ if (arguments[i] > 0) inv += 1 / arguments[i];
+ }
+ return inv > 0 ? 1 / inv : Infinity;
+}
+
// === Экспорт ===
window.PHYS = {
+ tempColor: tempColor,
+ thermometer: thermometer,
+ calorimeter: calorimeter,
+ createHeatBar: createHeatBar,
+ phaseGraphTT: phaseGraphTT,
+ Rseries: Rseries,
+ Rparallel: Rparallel,
drawArrow: drawArrow,
fieldLinesPointCharge: fieldLinesPointCharge,
chargeMark: chargeMark,
diff --git a/frontend/textbooks/physics_8_ch1.html b/frontend/textbooks/physics_8_ch1.html
new file mode 100644
index 0000000..b62fc53
--- /dev/null
+++ b/frontend/textbooks/physics_8_ch1.html
@@ -0,0 +1,668 @@
+
+
+
+
+
+
+
+Физика 8 · Глава 1 · «Тепловые явления»
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Физика 8 · Глава 1
+
Внутренняя энергия · теплопередача · фазовые переходы
+
+
+
+
+
+
+
+
+
+ Тепловые явления — как энергия переходит между телами
+ Внутренняя энергия зависит от температуры тела. Тепло передаётся теплопроводностью, конвекцией и излучением. При нагревании, плавлении и кипении нужно разное количество теплоты.
+
+
Начать § 1
+
+
Прогресс по главе
+
+
0%
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/textbooks/physics_8_ch2.html b/frontend/textbooks/physics_8_ch2.html
new file mode 100644
index 0000000..186eae0
--- /dev/null
+++ b/frontend/textbooks/physics_8_ch2.html
@@ -0,0 +1,731 @@
+
+
+
+
+
+
+
+Физика 8 · Глава 2 · «Электромагнитные явления»
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Физика 8 · Глава 2
+
Электризация · ток · закон Ома · магнитное поле
+
+
+
+
+
+
+
+
+
+ Электромагнитные явления — от заряда до магнита
+ Заряды притягиваются и отталкиваются, образуют электрическое поле. По проводнику течёт ток, и закон Ома связывает $U$, $I$, $R$. У постоянных магнитов и проводников с током есть магнитное поле.
+
+
Начать § 12
+
+
Прогресс по главе
+
+
0%
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/textbooks/physics_8_ch3.html b/frontend/textbooks/physics_8_ch3.html
new file mode 100644
index 0000000..2539333
--- /dev/null
+++ b/frontend/textbooks/physics_8_ch3.html
@@ -0,0 +1,654 @@
+
+
+
+
+
+
+
+Физика 8 · Глава 3 · «Световые явления»
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Физика 8 · Глава 3
+
Свет · отражение · преломление · линзы · глаз
+
+
+
+
+
+
+
+
+
+ Световые явления — геометрическая оптика
+ Свет распространяется прямолинейно со скоростью $c = 3 \cdot 10^8$ м/с. Закон отражения и закон преломления (Снеллиуса) объясняют поведение пучков света. Линзы строят изображения; глаз — это оптическая система.
+
+
Начать § 32
+
+
Прогресс по главе
+
+
0%
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/textbooks/physics_8_hub.html b/frontend/textbooks/physics_8_hub.html
new file mode 100644
index 0000000..e7ce44c
--- /dev/null
+++ b/frontend/textbooks/physics_8_hub.html
@@ -0,0 +1,856 @@
+
+
+
+
+
+
+
+
+Физика 8 класс — учебник
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Физика — 8 класс
+
Полный курс физики 8 класса: тепловые явления, электромагнитные явления, световые явления, лабораторный практикум
+
+
+
+
+
+
+
+
+ f
+
+
Общий прогресс по курсу
+
Загрузка...
+
+
+ 0 XP
+
+
+
+
+
+
+
Q
+
Глава 1
+
Тепловые явления
+
§1–§11 + Финал
+
+
+
Внутренняя энергия, теплопроводность, конвекция, излучение, удельная теплоёмкость, плавление и кристаллизация, испарение и кипение.
+
+
+
+
+
+
+
+
I
+
Глава 2
+
Электромагнитные явления
+
§12–§31 + Финал
+
+
+
Электризация, электрическое поле, ток и источники, закон Ома, последовательное и параллельное соединения, мощность тока, магнитное поле, электромагнит.
+
+
+
+
+
+
+
+
F
+
Глава 3
+
Световые явления
+
§32–§40 + Финал
+
+
+
Источники света, прямолинейное распространение, отражение, преломление, линзы и построение изображений, глаз как оптическая система, очки.
+
+
+
+
+
+
+
+
ЛР
+
Лаборатория
+
Лабораторный практикум
+
7 виртуальных ЛР
+
+
+
7 виртуальных лабораторных работ: теплообмен, удельная теплоёмкость, простейшая цепь, последовательное и параллельное соединения, работа и мощность тока, отражение света.
+
+
+
+
+
+
+
+
+
+
+
+
Финал курса
+
Босс-проверка по всему курсу
+
Шпаргалка курса и 10 интегрированных боссов по всем 3 главам. Победи всех — получи «Магистр физики 8» и +150 XP.
+
+
+
+
+
+
+
+
+
+
+
+ Гл. 1
+ Тепловые явления
+
+
+ $Q = cm\Delta T$ — нагрев / охлаждение
+ $Q = qm$ — сгорание топлива
+ $Q = \lambda m$ — плавление
+ $Q = L m$ — парообразование
+ Теплопередача: проводность, конвекция, излучение
+
+
+
+
+ Гл. 2
+ Электромагнитные
+
+
+ $q = Ne$, $e = 1{,}6 \cdot 10^{-19}$ Кл
+ $A = qU$, $U = A/q$
+ $I = q/t$, $I = U/R$ — закон Ома
+ $R = \rho l / S$
+ Последов.: $R = R_1+R_2$, $U = U_1+U_2$
+ Паралл.: $1/R = 1/R_1 + 1/R_2$
+ $P = UI$, $A = UIt$, $Q = I^2 Rt$
+
+
+
+
+ Гл. 3
+ Световые явления
+
+
+ $c = 3 \cdot 10^8$ м/с
+ Закон отражения: $\alpha = \beta$
+ Закон Снеллиуса: $\dfrac{\sin\alpha}{\sin\beta} = n$
+ $D = 1/F$ (дптр)
+ $\dfrac{1}{F} = \dfrac{1}{d} + \dfrac{1}{f}$ (тонкая линза)
+ Близо-: $D < 0$; дально-: $D > 0$
+
+
+
+
+
+
+ 10 интегрированных боссов
+
+
+
+
Боссов побеждено: 0 / 10
+
+
+
+
+
+
+
+
+
Курс Физика 8 пройден!
+
Вы прошли всю итоговую проверку курса. +150 XP, ачивка «Магистр физики 8» получена.
+
+
+ К каталогу учебников
+
+
+
+
+
+
+
+
+
+
+
Магистр физики 8
+
Прочитайте все 40 параграфов и выполните все 7 лабораторных работ, чтобы получить достижение
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/textbooks/physics_8_lab.html b/frontend/textbooks/physics_8_lab.html
new file mode 100644
index 0000000..f688231
--- /dev/null
+++ b/frontend/textbooks/physics_8_lab.html
@@ -0,0 +1,634 @@
+
+
+
+
+
+
+
+Физика 8 · Лабораторный практикум
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Физика 8 · Лабораторный практикум
+
7 виртуальных лабораторных работ
+
+
+
+
+
+
+
+
+
+ Лабораторный практикум 8 класса
+ 7 виртуальных лабораторных работ по тепловым явлениям, электрическим цепям и оптике. Каждая работа — это симуляция эксперимента + измерения + расчёт + автоматический отчёт.
+
+
Начать ЛР 1
+
+
Прогресс по главе
+
+
0%
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+