From b29b395a968cef73943dbf52114a41b7f3ca24a3 Mon Sep 17 00:00:00 2001 From: Maxim Dolgolyov Date: Sat, 30 May 2026 17:39:36 +0300 Subject: [PATCH] =?UTF-8?q?feat(biochem):=20=D0=A4=D0=B0=D0=B7=D0=B0=204?= =?UTF-8?q?=20(4.1-4.3)=20=E2=80=94=20=D0=BF=D1=83=D1=82=D0=B8=20=D0=BC?= =?UTF-8?q?=D0=B5=D1=82=D0=B0=D0=B1=D0=BE=D0=BB=D0=B8=D0=B7=D0=BC=D0=B0=20?= =?UTF-8?q?=D0=B8=D0=B7=20=D0=91=D0=94=20(API),=20=D1=85=D0=B0=D1=80=D0=B4?= =?UTF-8?q?=D0=BA=D0=BE=D0=B4=20=D1=83=D0=B1=D1=80=D0=B0=D0=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Перенос данных путей из ~700 строк инлайн-объекта PATHWAYS в biochem-pathways.html в БД. Document-подход: каждый путь — самодостаточный документ data_json (граф узлов/рёбер + шаги с квизами); путь всегда читается целиком, реляционных запросов нет — нормализация не нужна. - migration 045_bio_pathways: таблица bio_pathways(slug, name, color, ord, data_json). - backend/scripts/biochem_pathways_data.js: данные 4 путей (извлечены из инлайн- объекта, теперь самодостаточный источник правды). - seed_biochem_pathways.js: идемпотентный upsert по slug. - biochemController.getPathways + GET /biochem/pathways (карта slug->данные). - js/api.js: biochemGetPathways. - biochem-pathways.html: инлайн PATHWAYS (-238 строк) заменён на загрузку из API в init (loadPathways); форма данных идентична — рендер не изменён. Проверено: API отдаёт 4 пути в форме фронта, сидер идемпотентен. Co-Authored-By: Claude Opus 4.8 (1M context) --- backend/scripts/biochem_pathways_data.js | 1290 +++++++++++++++++ backend/scripts/seed_biochem_pathways.js | 42 + backend/src/controllers/biochemController.js | 10 +- .../src/db/migrations/045_bio_pathways.sql | 15 + backend/src/routes/biochem.js | 1 + frontend/biochem-pathways.html | 251 +--- js/api.js | 3 +- 7 files changed, 1372 insertions(+), 240 deletions(-) create mode 100644 backend/scripts/biochem_pathways_data.js create mode 100644 backend/scripts/seed_biochem_pathways.js create mode 100644 backend/src/db/migrations/045_bio_pathways.sql diff --git a/backend/scripts/biochem_pathways_data.js b/backend/scripts/biochem_pathways_data.js new file mode 100644 index 0000000..576b8c5 --- /dev/null +++ b/backend/scripts/biochem_pathways_data.js @@ -0,0 +1,1290 @@ +'use strict'; +// Данные метаболических путей (источник для seed_biochem_pathways.js). +// Извлечены из инлайн-объекта PATHWAYS biochem-pathways.html — теперь самодостаточный источник. +module.exports = { + "glycolysis": { + "name": "Гликолиз", + "color": "#f59e0b", + "colorRgb": "245,158,11", + "desc": "10 реакций расщепления глюкозы до пирувата. Происходит в цитоплазме. Выход: 2 АТФ (нетто), 2 НАДН, 2 пируват.", + "stats": [ + { + "label": "−2 АТФ +4 АТФ", + "cls": "atp" + }, + { + "label": "2 НАДН", + "cls": "nadh" + } + ], + "legend": [ + { + "color": "#f59e0b", + "type": "circle", + "label": "Метаболит" + }, + { + "color": "#f59e0b", + "type": "line", + "label": "Реакция" + }, + { + "color": "#f59e0b88", + "type": "circle-sm", + "label": "Кофактор (АТФ/НАД)" + } + ], + "nodes": [ + { + "id": "glc", + "label": "Глюкоза", + "formula": "C₆H₁₂O₆", + "x": 400, + "y": 60, + "role": "substrate", + "desc": "Исходный субстрат гликолиза. 6-углеродный сахар, главный источник энергии клетки.", + "props": [] + }, + { + "id": "g6p", + "label": "Глюкозо-6-Ф", + "formula": "C₆H₁₃O₉P", + "x": 400, + "y": 145, + "role": "inter", + "desc": "Глюкозо-6-фосфат. Образуется при фосфорилировании глюкозы за счёт АТФ. Удерживает молекулу в клетке.", + "props": [ + "−1 АТФ" + ] + }, + { + "id": "f6p", + "label": "Фруктозо-6-Ф", + "formula": "C₆H₁₃O₉P", + "x": 400, + "y": 225, + "role": "inter", + "desc": "Изомер глюкозо-6-фосфата. Образуется при изомеризации ферментом фосфоглюкоизомеразой.", + "props": [] + }, + { + "id": "f16bp", + "label": "Фруктозо-1,6-бФ", + "formula": "C₆H₁₄O₁₂P₂", + "x": 400, + "y": 310, + "role": "key", + "desc": "Фруктозо-1,6-бисфосфат — ключевой регуляторный метаболит. Образование катализирует фосфофруктокиназа-1 (ФФК-1).", + "props": [ + "−1 АТФ", + "Контроль скорости" + ] + }, + { + "id": "dhap", + "label": "ДГАФ", + "formula": "C₃H₇O₆P", + "x": 260, + "y": 395, + "role": "inter", + "desc": "Дигидроксиацетонфосфат — один из двух триозофосфатов при расщеплении фруктозо-1,6-бисфосфата. Быстро конвертируется в ГАФ.", + "props": [] + }, + { + "id": "gap", + "label": "ГАФ", + "formula": "C₃H₇O₆P", + "x": 540, + "y": 395, + "role": "inter", + "desc": "Глицеральдегид-3-фосфат (ГАФ) — непосредственный субстрат следующих реакций. Оба триозофосфата канализируются через ГАФ.", + "props": [] + }, + { + "id": "bpg", + "label": "1,3-бФГ", + "formula": "C₃H₈O₁₀P₂", + "x": 540, + "y": 480, + "role": "inter", + "desc": "1,3-бисфосфоглицерат. Образуется при окислении ГАФ, сопряжённом с восстановлением НАД⁺ в НАДН.", + "props": [ + "2 НАДН" + ] + }, + { + "id": "pg3", + "label": "3-ФГК", + "formula": "C₃H₇O₇P", + "x": 540, + "y": 560, + "role": "inter", + "desc": "3-фосфоглицерат. Образуется при субстратном фосфорилировании АДФ АТФ ферментом фосфоглицераткиназой.", + "props": [ + "+2 АТФ" + ] + }, + { + "id": "pg2", + "label": "2-ФГК", + "formula": "C₃H₇O₇P", + "x": 540, + "y": 635, + "role": "inter", + "desc": "2-фосфоглицерат. Образуется при перемещении фосфатной группы с 3 на 2 положение.", + "props": [] + }, + { + "id": "pep", + "label": "ФЕП", + "formula": "C₃H₅O₆P", + "x": 540, + "y": 710, + "role": "inter", + "desc": "Фосфоенолпируват (ФЕП) — высокоэнергетический промежуточный продукт. Образуется при дегидратации 2-ФГК.", + "props": [] + }, + { + "id": "pyr", + "label": "Пируват", + "formula": "C₃H₄O₃", + "x": 400, + "y": 795, + "role": "product", + "desc": "Конечный продукт гликолиза. В аэробных условиях переходит в ацетил-КоА (цикл Кребса). В анаэробных лактат или этанол.", + "props": [ + "+2 АТФ", + "2 молекулы" + ] + } + ], + "edges": [ + { + "from": "glc", + "to": "g6p", + "enzyme": "Гексокиназа", + "co": "-АТФ", + "curveX": 0 + }, + { + "from": "g6p", + "to": "f6p", + "enzyme": "ФГИ", + "curveX": 0 + }, + { + "from": "f6p", + "to": "f16bp", + "enzyme": "ФФК-1", + "co": "-АТФ", + "curveX": 0 + }, + { + "from": "f16bp", + "to": "dhap", + "enzyme": "Альдолаза", + "curveX": 0 + }, + { + "from": "f16bp", + "to": "gap", + "enzyme": "Альдолаза", + "curveX": 0 + }, + { + "from": "dhap", + "to": "gap", + "enzyme": "ТФИ", + "curveX": 0 + }, + { + "from": "gap", + "to": "bpg", + "enzyme": "ГАФДГ", + "co": "+НАДН", + "curveX": 0 + }, + { + "from": "bpg", + "to": "pg3", + "enzyme": "ФГК", + "co": "+АТФ", + "curveX": 0 + }, + { + "from": "pg3", + "to": "pg2", + "enzyme": "Фосфоглицератмутаза", + "curveX": 0 + }, + { + "from": "pg2", + "to": "pep", + "enzyme": "Енолаза", + "curveX": 0 + }, + { + "from": "pep", + "to": "pyr", + "enzyme": "Пируваткиназа", + "co": "+АТФ", + "curveX": 0 + } + ], + "steps": [ + { + "title": "Фосфорилирование глюкозы", + "mol": "g6p", + "desc": "Гексокиназа катализирует перенос фосфатной группы с АТФ на глюкозу, образуя глюкозо-6-фосфат (Г6Ф). Реакция необратима и «ловит» глюкозу в клетке.", + "energy": [ + { + "label": "-1 АТФ", + "cls": "atp-used" + } + ], + "quiz": { + "q": "Зачем глюкозу фосфорилируют в первой реакции?", + "opts": [ + "Для выхода из клетки", + "Чтобы удержать глюкозу в клетке", + "Для образования НАДН", + "Для расщепления кольца" + ], + "ans": 1 + } + }, + { + "title": "Изомеризация", + "mol": "f6p", + "desc": "Фосфоглюкоизомераза превращает Г6Ф в фруктозо-6-фосфат (Ф6Ф). Реакция обратима и перестраивает альдозный сахар в кетозный.", + "energy": [], + "quiz": { + "q": "Какой фермент катализирует изомеризацию Г6Ф Ф6Ф?", + "opts": [ + "Гексокиназа", + "Альдолаза", + "Фосфоглюкоизомераза", + "Пируваткиназа" + ], + "ans": 2 + } + }, + { + "title": "Ключевой контрольный шаг", + "mol": "f16bp", + "desc": "Фосфофруктокиназа-1 (ФФК-1) фосфорилирует Ф6Ф фруктозо-1,6-бисфосфат. Это необратимая реакция — главный регуляторный пункт гликолиза. АТФ ингибирует, АМФ/АДФ активирует.", + "energy": [ + { + "label": "-1 АТФ", + "cls": "atp-used" + } + ], + "quiz": { + "q": "Что является главным аллостерическим активатором ФФК-1?", + "opts": [ + "АТФ", + "АМФ", + "НАДН", + "Пируват" + ], + "ans": 1 + } + }, + { + "title": "Расщепление на триозы", + "mol": "gap", + "desc": "Альдолаза расщепляет фруктозо-1,6-бисфосфат на два триозофосфата: ДГАФ и ГАФ (глицеральдегид-3-фосфат). Триозофосфатизомераза быстро конвертирует ДГАФ ГАФ.", + "energy": [], + "quiz": { + "q": "Сколько молекул ГАФ образуется из одной глюкозы?", + "opts": [ + "1", + "2", + "3", + "4" + ], + "ans": 1 + } + }, + { + "title": "Окислительное фосфорилирование", + "mol": "bpg", + "desc": "ГАФДГ окисляет ГАФ и присоединяет неорганический фосфат 1,3-бисфосфоглицерат. Сопряжено с восстановлением НАД⁺ НАДН. Реакция субстратного фосфорилирования.", + "energy": [ + { + "label": "+2 НАДН", + "cls": "nadh" + } + ], + "quiz": { + "q": "Чем восстанавливается НАД⁺ в этой реакции?", + "opts": [ + "ГАФ", + "Пируват", + "ДГАФ", + "АТФ" + ], + "ans": 0 + } + }, + { + "title": "Первая выработка АТФ", + "mol": "pg3", + "desc": "Фосфоглицераткиназа переносит фосфат с 1,3-бФГ на АДФ АТФ. Это субстратное фосфорилирование — первый синтез АТФ в гликолизе. С каждой глюкозы получаем 2 АТФ.", + "energy": [ + { + "label": "+2 АТФ", + "cls": "atp-prod" + } + ], + "quiz": { + "q": "Как называется тип синтеза АТФ в этой реакции?", + "opts": [ + "Окислительное фосфорилирование", + "Субстратное фосфорилирование", + "Фотофосфорилирование", + "Трансфосфорилирование" + ], + "ans": 1 + } + }, + { + "title": "Мутация фосфатной группы", + "mol": "pg2", + "desc": "Фосфоглицератмутаза перемещает фосфатную группу с 3-го на 2-е углеродное положение, подготавливая молекулу к дегидратации.", + "energy": [], + "quiz": { + "q": "Какой продукт образуется из 3-ФГК под действием мутазы?", + "opts": [ + "ФЕП", + "2-ФГК", + "Пируват", + "1,3-бФГ" + ], + "ans": 1 + } + }, + { + "title": "Образование ФЕП", + "mol": "pep", + "desc": "Енолаза катализирует дегидратацию 2-фосфоглицерата фосфоенолпируват (ФЕП). ФЕП — высокоэнергетический соединение с большой отрицательной ΔG° гидролиза фосфата.", + "energy": [], + "quiz": { + "q": "Почему ФЕП называют «высокоэнергетическим»?", + "opts": [ + "Содержит много атомов С", + "Большая ΔG° гидролиза фосфатной связи", + "Растворяется в жирах", + "Содержит двойную связь" + ], + "ans": 1 + } + }, + { + "title": "Финальная реакция — пируват", + "mol": "pyr", + "desc": "Пируваткиназа переносит фосфат с ФЕП на АДФ АТФ + пируват. Необратимая реакция. Итог: из 1 глюкозы 2 пирувата, 2 НАДН, +2 АТФ нетто.", + "energy": [ + { + "label": "+2 АТФ", + "cls": "atp-prod" + }, + { + "label": "2 пируват", + "cls": "co2" + } + ], + "quiz": { + "q": "Каков нетто-выход АТФ на 1 молекулу глюкозы в гликолизе?", + "opts": [ + "1", + "2", + "4", + "36" + ], + "ans": 1 + } + } + ] + }, + "krebs": { + "name": "Цикл Кребса", + "color": "#06b6d4", + "colorRgb": "6,182,212", + "desc": "8 реакций окисления ацетил-КоА. Происходит в матриксе митохондрий. Выход на 1 оборот: 3 НАДН, 1 ФАДН₂, 1 ГТФ, 2 СО₂.", + "stats": [ + { + "label": "3 НАДН / оборот", + "cls": "nadh" + }, + { + "label": "2 CO₂", + "cls": "co2" + }, + { + "label": "1 ГТФ", + "cls": "atp" + } + ], + "legend": [ + { + "color": "#06b6d4", + "type": "circle", + "label": "Промежуточный метаболит" + }, + { + "color": "#06b6d4", + "type": "line", + "label": "Реакция цикла" + } + ], + "nodes": [ + { + "id": "acetcoa", + "label": "Ацетил-КоА", + "formula": "CH₃CO-SCoA", + "x": 440, + "y": 80, + "role": "substrate", + "desc": "Активированный ацетат. Образуется из пирувата (гликолиз), жирных кислот (β-окисление) и аминокислот.", + "props": [ + "Входит в цикл" + ] + }, + { + "id": "oaa", + "label": "ОАА", + "formula": "C₄H₄O₅", + "x": 260, + "y": 140, + "role": "key", + "desc": "Оксалоацетат — акцептор ацетил-КоА. Регенерируется в каждом обороте цикла. Ключевой анаплеротический метаболит.", + "props": [ + "Акцептор" + ] + }, + { + "id": "cit", + "label": "Цитрат", + "formula": "C₆H₈O₇", + "x": 160, + "y": 260, + "role": "inter", + "desc": "Цитрат — первый продукт цикла. Синтезируется цитратсинтазой из ацетил-КоА и ОАА.", + "props": [] + }, + { + "id": "isocit", + "label": "Изоцитрат", + "formula": "C₆H₈O₇", + "x": 120, + "y": 390, + "role": "inter", + "desc": "Изоцитрат — изомер цитрата. Субстрат изоцитратдегидрогеназы — ключевого регуляторного фермента.", + "props": [] + }, + { + "id": "akg", + "label": "α-КГ", + "formula": "C₅H₆O₅", + "x": 160, + "y": 520, + "role": "inter", + "desc": "α-кетоглутарат (α-КГ). Образуется при окислительном декарбоксилировании изоцитрата. Выделяется CO₂.", + "props": [ + "−CO₂", + "+НАДН" + ] + }, + { + "id": "succoa", + "label": "Сукцинил-КоА", + "formula": "C₅H₆O₃S", + "x": 300, + "y": 620, + "role": "inter", + "desc": "Сукцинил-КоА — высокоэнергетический тиоэфир. Образуется при окислительном декарбоксилировании α-КГ.", + "props": [ + "+НАДН", + "+ГТФ", + "-CO₂" + ] + }, + { + "id": "succ", + "label": "Сукцинат", + "formula": "C₄H₆O₄", + "x": 480, + "y": 620, + "role": "inter", + "desc": "Сукцинат. Окисляется сукцинатдегидрогеназой (СДГ) — единственным мембранным ферментом цикла.", + "props": [ + "+ФАДН₂" + ] + }, + { + "id": "fum", + "label": "Фумарат", + "formula": "C₄H₄O₄", + "x": 620, + "y": 520, + "role": "inter", + "desc": "Фумарат — транс-изомер. Образуется при окислении сукцината. Гидратируется фумаразой.", + "props": [] + }, + { + "id": "mal", + "label": "Малат", + "formula": "C₄H₆O₅", + "x": 660, + "y": 390, + "role": "inter", + "desc": "Малат (яблочная кислота). Образуется при гидратации фумарата. Окисляется малатдегидрогеназой.", + "props": [ + "+НАДН" + ] + } + ], + "edges": [ + { + "from": "acetcoa", + "to": "cit", + "enzyme": "Цитратсинтаза", + "co": "+ОАА", + "curveX": 0 + }, + { + "from": "oaa", + "to": "cit", + "enzyme": "", + "curveX": 0 + }, + { + "from": "cit", + "to": "isocit", + "enzyme": "Аконитаза", + "curveX": 0 + }, + { + "from": "isocit", + "to": "akg", + "enzyme": "ИзоцитратДГ", + "co": "+НАДН,-CO₂", + "curveX": 0 + }, + { + "from": "akg", + "to": "succoa", + "enzyme": "α-КГДГ-комплекс", + "co": "+НАДН,-CO₂", + "curveX": 0 + }, + { + "from": "succoa", + "to": "succ", + "enzyme": "Сукцинил-КоА-синтетаза", + "co": "+ГТФ", + "curveX": 0 + }, + { + "from": "succ", + "to": "fum", + "enzyme": "Сукцинатдегидрогеназа", + "co": "+ФАДН₂", + "curveX": 0 + }, + { + "from": "fum", + "to": "mal", + "enzyme": "Фумараза", + "curveX": 0 + }, + { + "from": "mal", + "to": "oaa", + "enzyme": "МалатДГ", + "co": "+НАДН", + "curveX": 0 + } + ], + "steps": [ + { + "title": "Конденсация с ОАА", + "mol": "cit", + "desc": "Цитратсинтаза присоединяет ацетил-КоА (2C) к оксалоацетату (4C) цитрат (6C). Это необратимая реакция, запускающая цикл.", + "energy": [], + "quiz": { + "q": "Сколько углеродов в цитрате?", + "opts": [ + "2", + "4", + "6", + "8" + ], + "ans": 2 + } + }, + { + "title": "Изомеризация цитрата", + "mol": "isocit", + "desc": "Аконитаза через промежуточный цис-аконитат превращает цитрат в изоцитрат. Реакция обратима, равновесие сдвинуто в сторону цитрата.", + "energy": [], + "quiz": { + "q": "Какой фермент изомеризует цитрат?", + "opts": [ + "Фумараза", + "Аконитаза", + "Малатдегидрогеназа", + "Цитратсинтаза" + ], + "ans": 1 + } + }, + { + "title": "Первое окислительное декарбоксилирование", + "mol": "akg", + "desc": "Изоцитратдегидрогеназа окисляет изоцитрат α-кетоглутарат с выделением CO₂ и НАДН. Ключевой регуляторный шаг — активируется изоцитратом, ингибируется НАДН.", + "energy": [ + { + "label": "+НАДН", + "cls": "nadh" + }, + { + "label": "-CO₂", + "cls": "co2" + } + ], + "quiz": { + "q": "Сколько углеродов в α-кетоглутарате?", + "opts": [ + "2", + "4", + "5", + "6" + ], + "ans": 2 + } + }, + { + "title": "Второе окислительное декарбоксилирование", + "mol": "succoa", + "desc": "α-кетоглутаратдегидрогеназный комплекс (аналог ПДК) окисляет α-КГ сукцинил-КоА. Выделяется ещё одна CO₂ и НАДН.", + "energy": [ + { + "label": "+НАДН", + "cls": "nadh" + }, + { + "label": "-CO₂", + "cls": "co2" + } + ], + "quiz": { + "q": "Чем структурно похож α-КГДК на пируватдегидрогеназный комплекс?", + "opts": [ + "Использует ФАДН₂", + "Механизм окислительного декарбоксилирования с КоА", + "Находится в цитоплазме", + "Требует витамин К" + ], + "ans": 1 + } + }, + { + "title": "Субстратное фосфорилирование", + "mol": "succ", + "desc": "Сукцинил-КоА-синтетаза расщепляет тиоэфирную связь сукцинил-КоА, сопрягая это с синтезом ГТФ (или АТФ). Единственная реакция субстратного фосфорилирования в цикле.", + "energy": [ + { + "label": "+ГТФ", + "cls": "atp-prod" + } + ], + "quiz": { + "q": "Что синтезируется при реакции сукцинил-КоА-синтетазы?", + "opts": [ + "НАДН", + "ФАДН₂", + "ГТФ", + "CO₂" + ], + "ans": 2 + } + }, + { + "title": "Окисление сукцината", + "mol": "fum", + "desc": "Сукцинатдегидрогеназа (комплекс II дыхательной цепи) окисляет сукцинат фумарат, восстанавливая ФАД ФАДН₂.", + "energy": [ + { + "label": "+ФАДН₂", + "cls": "fadh2" + } + ], + "quiz": { + "q": "К какому комплексу дыхательной цепи относится СДГ?", + "opts": [ + "Комплекс I", + "Комплекс II", + "Комплекс III", + "АТФ-синтаза" + ], + "ans": 1 + } + }, + { + "title": "Гидратация фумарата", + "mol": "mal", + "desc": "Фумараза присоединяет воду к фумарату L-малат. Реакция стереоспецифична — образуется только L-изомер.", + "energy": [], + "quiz": { + "q": "Что присоединяется к фумарату в этой реакции?", + "opts": [ + "CO₂", + "АТФ", + "H₂O", + "НАДН" + ], + "ans": 2 + } + }, + { + "title": "Регенерация ОАА", + "mol": "oaa", + "desc": "Малатдегидрогеназа окисляет малат оксалоацетат с образованием НАДН. Регенерируется акцептор для следующего оборота цикла.", + "energy": [ + { + "label": "+НАДН", + "cls": "nadh" + } + ], + "quiz": { + "q": "Сколько оборотов цикла Кребса нужно на 1 молекулу глюкозы?", + "opts": [ + "1", + "2", + "4", + "10" + ], + "ans": 1 + } + } + ] + }, + "oxidation": { + "name": "β-Окисление", + "color": "#fb923c", + "colorRgb": "251,146,60", + "desc": "Повторяющиеся циклы окисления жирных кислот в митохондриях. Каждый цикл отщепляет 2C в виде ацетил-КоА и выделяет 1 НАДН + 1 ФАДН₂.", + "stats": [ + { + "label": "+НАДН / цикл", + "cls": "nadh" + }, + { + "label": "+ФАДН₂", + "cls": "nadh" + }, + { + "label": "+Ацетил-КоА", + "cls": "atp" + } + ], + "legend": [ + { + "color": "#fb923c", + "type": "circle", + "label": "Промежуточный продукт" + }, + { + "color": "#fb923c", + "type": "line", + "label": "Реакция β-окисления" + } + ], + "nodes": [ + { + "id": "fac", + "label": "Жирная к-та", + "formula": "R-COOH", + "x": 400, + "y": 60, + "role": "substrate", + "desc": "Свободная жирная кислота (напр. пальмитиновая C₁₆). Активируется в ацил-КоА перед входом в митохондрии.", + "props": [] + }, + { + "id": "acylcoa", + "label": "Ацил-КоА", + "formula": "R-CO-SCoA", + "x": 400, + "y": 150, + "role": "key", + "desc": "Активированная жирная кислота. Образуется при участии ацил-КоА-синтетазы за счёт АТФ (АМФ+PPi). Не проходит через мембрану — транспортируется как карнитиновый эфир.", + "props": [ + "-АТФ (АМФ)" + ] + }, + { + "id": "enoylcoa", + "label": "Транс-еноил-КоА", + "formula": "R-CH=CH-CO-SCoA", + "x": 400, + "y": 250, + "role": "inter", + "desc": "Транс-Δ²-еноил-КоА. Образуется при ФАД-зависимом окислении ацил-КоА ацил-КоА-дегидрогеназой.", + "props": [ + "+ФАДН₂" + ] + }, + { + "id": "hydroxy", + "label": "L-β-гидрокси-КоА", + "formula": "R-CHOH-CH₂-CO-SCoA", + "x": 400, + "y": 345, + "role": "inter", + "desc": "L-β-гидроксиацил-КоА. Образуется при гидратации двойной связи еноил-КоА гидратазой.", + "props": [] + }, + { + "id": "ketoacoa", + "label": "β-кето-КоА", + "formula": "R-CO-CH₂-CO-SCoA", + "x": 400, + "y": 440, + "role": "inter", + "desc": "β-кетоацил-КоА. Образуется при НАД⁺-зависимом окислении L-β-гидроксиацил-КоА.", + "props": [ + "+НАДН" + ] + }, + { + "id": "newacyl", + "label": "Ацил-КоА (−2C)", + "formula": "R'—CO-SCoA", + "x": 240, + "y": 540, + "role": "inter", + "desc": "Укороченный на 2 углерода ацил-КоА. Возвращается на начало цикла β-окисления.", + "props": [ + "Следующий цикл" + ] + }, + { + "id": "acetcoa2", + "label": "Ацетил-КоА", + "formula": "CH₃CO-SCoA", + "x": 560, + "y": 540, + "role": "product", + "desc": "Ацетил-КоА — входит в цикл Кребса. Из пальмитиновой кислоты (C₁₆) образуется 8 ацетил-КоА за 7 циклов β-окисления.", + "props": [ + " Цикл Кребса" + ] + } + ], + "edges": [ + { + "from": "fac", + "to": "acylcoa", + "enzyme": "Ацил-КоА-синтетаза", + "co": "-АТФ", + "curveX": 0 + }, + { + "from": "acylcoa", + "to": "enoylcoa", + "enzyme": "Ацил-КоА-ДГ", + "co": "+ФАДН₂", + "curveX": 0 + }, + { + "from": "enoylcoa", + "to": "hydroxy", + "enzyme": "Еноил-КоА-гидратаза", + "curveX": 0 + }, + { + "from": "hydroxy", + "to": "ketoacoa", + "enzyme": "L-3-гидроксиацил-КоА-ДГ", + "co": "+НАДН", + "curveX": 0 + }, + { + "from": "ketoacoa", + "to": "newacyl", + "enzyme": "Тиолаза", + "curveX": 0 + }, + { + "from": "ketoacoa", + "to": "acetcoa2", + "enzyme": "Тиолаза", + "curveX": 0 + }, + { + "from": "newacyl", + "to": "acylcoa", + "enzyme": "Повтор цикла", + "curveX": -60 + } + ], + "steps": [ + { + "title": "Активация жирной кислоты", + "mol": "acylcoa", + "desc": "Ацил-КоА-синтетаза присоединяет КоА к жирной кислоте, образуя ацил-КоА. Расходуется АТФ (АМФ+PPi, что эквивалентно 2 АТФ). Это происходит в цитоплазме.", + "energy": [ + { + "label": "-2 АТФ", + "cls": "atp-used" + } + ], + "quiz": { + "q": "Где происходит активация жирной кислоты в ацил-КоА?", + "opts": [ + "В митохондриях", + "В ядре", + "В цитоплазме", + "В рибосомах" + ], + "ans": 2 + } + }, + { + "title": "ФАД-зависимое окисление", + "mol": "enoylcoa", + "desc": "Ацил-КоА-дегидрогеназа окисляет ацил-КоА, вводя двойную связь между α и β углеродами транс-Δ²-еноил-КоА. ФАД восстанавливается до ФАДН₂.", + "energy": [ + { + "label": "+ФАДН₂", + "cls": "fadh2" + } + ], + "quiz": { + "q": "Какой кофактор восстанавливается в первой реакции β-окисления?", + "opts": [ + "НАД⁺", + "ФАД", + "ГТФ", + "КоА" + ], + "ans": 1 + } + }, + { + "title": "Гидратация двойной связи", + "mol": "hydroxy", + "desc": "Еноил-КоА-гидратаза присоединяет воду по двойной связи L-β-гидроксиацил-КоА. Реакция стереоспецифична.", + "energy": [], + "quiz": { + "q": "Что присоединяется в реакции гидратации еноил-КоА?", + "opts": [ + "CO₂", + "O₂", + "H₂O", + "НАД⁺" + ], + "ans": 2 + } + }, + { + "title": "НАД⁺-зависимое окисление", + "mol": "ketoacoa", + "desc": "L-3-гидроксиацил-КоА-дегидрогеназа окисляет гидроксильную группу кетогруппу, восстанавливая НАД⁺ НАДН.", + "energy": [ + { + "label": "+НАДН", + "cls": "nadh" + } + ], + "quiz": { + "q": "Какая группа окисляется в этой реакции?", + "opts": [ + "Карбоксильная", + "Аминогруппа", + "Гидроксильная", + "Метильная" + ], + "ans": 2 + } + }, + { + "title": "Тиолитическое расщепление", + "mol": "acetcoa2", + "desc": "Тиолаза расщепляет β-кетоацил-КоА присоединением КоА ацетил-КоА (2C) + укороченный ацил-КоА. Цикл повторяется.", + "energy": [ + { + "label": "+Ацетил-КоА", + "cls": "atp-prod" + } + ], + "quiz": { + "q": "Сколько ацетил-КоА образуется из пальмитиновой кислоты (C16)?", + "opts": [ + "4", + "6", + "7", + "8" + ], + "ans": 3 + } + } + ] + }, + "synthesis": { + "name": "Синтез белка", + "color": "#a78bfa", + "colorRgb": "167,139,250", + "desc": "Трансляция — считывание мРНК рибосомой и полимеризация аминокислот в полипептидную цепь.", + "stats": [ + { + "label": "~2 ГТФ / аминокислота", + "cls": "atp" + }, + { + "label": "мРНК белок", + "cls": "nadh" + } + ], + "legend": [ + { + "color": "#a78bfa", + "type": "circle", + "label": "Участник трансляции" + }, + { + "color": "#a78bfa", + "type": "line", + "label": "Этап синтеза" + } + ], + "nodes": [ + { + "id": "mrna", + "label": "мРНК", + "formula": "5′-AUG…-3′", + "x": 400, + "y": 60, + "role": "substrate", + "desc": "Матричная РНК — несёт генетическую информацию от ДНК к рибосоме в виде кодонов (триплетов нуклеотидов).", + "props": [ + "Матрица" + ] + }, + { + "id": "ribosome", + "label": "Рибосома", + "formula": "60S+40S", + "x": 400, + "y": 160, + "role": "key", + "desc": "Эукариотическая рибосома (80S). Состоит из малой (40S) и большой (60S) субъединиц. Имеет 3 сайта: A (аминоацильный), P (пептидильный), E (выход).", + "props": [ + "A-P-E сайты" + ] + }, + { + "id": "trna", + "label": "аминоацил-тРНК", + "formula": "aa-tRNA", + "x": 230, + "y": 260, + "role": "inter", + "desc": "тРНК с присоединённой аминокислотой. Распознаёт кодон мРНК через антикодон. Доставляется в A-сайт в комплексе с EF-Tu·ГТФ.", + "props": [ + "-2 ГТФ" + ] + }, + { + "id": "peptide", + "label": "Растущая цепь", + "formula": "...aa-aa-aa", + "x": 560, + "y": 260, + "role": "inter", + "desc": "Нарастающая полипептидная цепь в P-сайте. Пептидилтрансфераза (23S rRNA) катализирует образование пептидной связи.", + "props": [ + "P-сайт" + ] + }, + { + "id": "peptbond", + "label": "Пептидная связь", + "formula": "—CO—NH—", + "x": 400, + "y": 360, + "role": "inter", + "desc": "Образование пептидной связи катализируется рибозимом (23S rRNA) — пептидилтрансферазой. Выделяется тРНК из P-сайта.", + "props": [] + }, + { + "id": "translo", + "label": "Транслокация", + "formula": "EF-G·ГТФ", + "x": 400, + "y": 460, + "role": "inter", + "desc": "Фактор EF-G (с ГТФ) сдвигает рибосому на 1 кодон (3 нт) в направлении 5′3′. Освобождается Е-сайт. Расходуется ГТФ.", + "props": [ + "-1 ГТФ" + ] + }, + { + "id": "protein", + "label": "Белок", + "formula": "[полипептид]", + "x": 400, + "y": 560, + "role": "product", + "desc": "Готовый полипептид. Освобождается при встрече со стоп-кодоном (UAA, UAG, UGA) при участии факторов высвобождения RF1/RF2.", + "props": [ + "Готовый продукт" + ] + } + ], + "edges": [ + { + "from": "mrna", + "to": "ribosome", + "enzyme": "Инициация (eIF)", + "curveX": 0 + }, + { + "from": "ribosome", + "to": "trna", + "enzyme": "Декодирование", + "curveX": 0 + }, + { + "from": "trna", + "to": "peptbond", + "enzyme": "Пептидилтрансфераза", + "curveX": 0 + }, + { + "from": "peptide", + "to": "peptbond", + "enzyme": "", + "curveX": 0 + }, + { + "from": "peptbond", + "to": "translo", + "enzyme": "EF-G·ГТФ", + "curveX": 0 + }, + { + "from": "translo", + "to": "protein", + "enzyme": "Терминация (RF)", + "curveX": 0 + }, + { + "from": "translo", + "to": "ribosome", + "enzyme": "Следующий кодон", + "curveX": -70 + } + ], + "steps": [ + { + "title": "Инициация", + "mol": "ribosome", + "desc": "Малая субъединица рибосомы распознаёт 5′-кэп мРНК при помощи факторов инициации (eIF4E/4G). Инициаторная Met-тРНК занимает P-сайт. Присоединяется большая субъединица.", + "energy": [ + { + "label": "-3 ГТФ", + "cls": "atp-used" + } + ], + "quiz": { + "q": "Какой сайт занимает инициаторная Met-тРНК?", + "opts": [ + "A-сайт", + "P-сайт", + "E-сайт", + "Все три" + ], + "ans": 1 + } + }, + { + "title": "Элонгация — доставка аа-тРНК", + "mol": "trna", + "desc": "EF-Tu·ГТФ доставляет аминоацил-тРНК в A-сайт. При правильном спаривании кодон–антикодон ГТФ гидролизуется, EF-Tu·ГДФ уходит.", + "energy": [ + { + "label": "-1 ГТФ", + "cls": "atp-used" + } + ], + "quiz": { + "q": "Какой фактор доставляет аа-тРНК в А-сайт?", + "opts": [ + "EF-G", + "EF-Tu", + "eIF2", + "RF1" + ], + "ans": 1 + } + }, + { + "title": "Пептидная связь", + "mol": "peptbond", + "desc": "Пептидилтрансфераза переносит пептидильную группу с P-сайта на аминогруппу в A-сайте, образуя пептидную связь. Энергия — из гидролиза аминоацильной связи тРНК.", + "energy": [], + "quiz": { + "q": "Что катализирует образование пептидной связи?", + "opts": [ + "Белковый фермент", + "23S rRNA (рибозим)", + "ДНК-полимераза", + "АТФ-синтаза" + ], + "ans": 1 + } + }, + { + "title": "Транслокация", + "mol": "translo", + "desc": "EF-G·ГТФ сдвигает рибосому на 3 нуклеотида по мРНК. Цепь с тРНК перемещается из A P, пустая тРНК из P E и уходит. Расходуется ГТФ.", + "energy": [ + { + "label": "-1 ГТФ", + "cls": "atp-used" + } + ], + "quiz": { + "q": "На сколько нуклеотидов сдвигается рибосома при транслокации?", + "opts": [ + "1", + "2", + "3", + "4" + ], + "ans": 2 + } + }, + { + "title": "Терминация и высвобождение", + "mol": "protein", + "desc": "Стоп-кодон (UAA/UAG/UGA) распознаётся факторами высвобождения RF1/RF2. Пептидилтрансфераза гидролизует связь пептид-тРНК белок освобождается. Рибосома диссоциирует.", + "energy": [], + "quiz": { + "q": "Сколько стоп-кодонов существует?", + "opts": [ + "1", + "2", + "3", + "4" + ], + "ans": 2 + } + } + ] + } +}; diff --git a/backend/scripts/seed_biochem_pathways.js b/backend/scripts/seed_biochem_pathways.js new file mode 100644 index 0000000..a16580c --- /dev/null +++ b/backend/scripts/seed_biochem_pathways.js @@ -0,0 +1,42 @@ +'use strict'; +/* + * Сид метаболических путей в bio_pathways. + * Источник данных — backend/scripts/data/biochem_pathways.json (изначально + * извлечён из инлайн-объекта PATHWAYS; теперь это самодостаточный источник + * правды, не зависящий от фронта). Каждый путь — документ data_json. + * Идемпотентно (upsert по slug): повторный запуск синхронизирует данные. + * + * Запуск: node backend/scripts/seed_biochem_pathways.js + */ +const db = require('../src/db/db'); +const P = require('./biochem_pathways_data'); + +const upsert = db.prepare(`INSERT INTO bio_pathways (slug, name, color, ord, data_json) + VALUES (@slug, @name, @color, @ord, @data_json) + ON CONFLICT(slug) DO UPDATE SET + name=excluded.name, color=excluded.color, ord=excluded.ord, data_json=excluded.data_json`); + +const slugs = Object.keys(P); +let n = 0; +db.exec('BEGIN'); +try { + slugs.forEach((slug, idx) => { + const p = P[slug]; + upsert.run({ + slug, + name: p.name || slug, + color: p.color || '#9B5DE5', + ord: idx, + data_json: JSON.stringify(p), + }); + n++; + }); + db.exec('COMMIT'); +} catch (e) { + db.exec('ROLLBACK'); + throw e; +} + +console.log(`biochem pathways seed: ${n} путь(ей) — ${slugs.join(', ')}`); +console.log('в БД:', db.prepare('SELECT slug, name, LENGTH(data_json) AS bytes FROM bio_pathways ORDER BY ord').all() + .map(r => `${r.slug}(${r.bytes}b)`).join(' ')); diff --git a/backend/src/controllers/biochemController.js b/backend/src/controllers/biochemController.js index f8bfb96..9ac3eed 100644 --- a/backend/src/controllers/biochemController.js +++ b/backend/src/controllers/biochemController.js @@ -321,6 +321,14 @@ function deleteSaved(req, res) { res.json({ ok: true }); } +/* ── GET /api/biochem/pathways — все пути из БД (карта slug → данные) ──── */ +const stmtsPathways = db.prepare('SELECT slug, data_json FROM bio_pathways ORDER BY ord'); +function getPathways(_req, res) { + const out = {}; + for (const r of stmtsPathways.all()) out[r.slug] = tryParse(r.data_json, {}); + res.json(out); +} + /* ── Прогресс прохождения путей (Learn-режим) ────────────────────────── */ const PATHWAY_XP = 80; const stmtsPath = { @@ -369,7 +377,7 @@ module.exports = { getElements, getMolecules, getMolecule, validate, getReactions, getChallenges, solveChallenge, getSaved, saveMolecule, deleteSaved, - getPathwayProgress, savePathwayProgress, + getPathways, getPathwayProgress, savePathwayProgress, // экспортируется для тестов структурной проверки structuralMatch, canonicalHash, }; diff --git a/backend/src/db/migrations/045_bio_pathways.sql b/backend/src/db/migrations/045_bio_pathways.sql new file mode 100644 index 0000000..a704bac --- /dev/null +++ b/backend/src/db/migrations/045_bio_pathways.sql @@ -0,0 +1,15 @@ +-- 045_bio_pathways.sql +-- Метаболические пути как данные (вместо ~700 строк хардкода в +-- biochem-pathways.html). Каждый путь — самодостаточный документ (граф узлов +-- и рёбер + шаги Learn-режима с квизами) в data_json; страница грузит их через +-- API. Document-подход выбран намеренно: путь всегда читается целиком, +-- реляционных запросов к узлам/рёбрам нет. + +CREATE TABLE IF NOT EXISTS bio_pathways ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + slug TEXT NOT NULL UNIQUE, + name TEXT NOT NULL, + color TEXT NOT NULL DEFAULT '#9B5DE5', + ord INTEGER NOT NULL DEFAULT 0, + data_json TEXT NOT NULL DEFAULT '{}' +); diff --git a/backend/src/routes/biochem.js b/backend/src/routes/biochem.js index ea65f2f..38ace09 100644 --- a/backend/src/routes/biochem.js +++ b/backend/src/routes/biochem.js @@ -14,6 +14,7 @@ router.post('/challenges/:id/solve', c.solveChallenge); router.get('/saved', c.getSaved); router.post('/saved', c.saveMolecule); router.delete('/saved/:id', c.deleteSaved); +router.get('/pathways', c.getPathways); router.get('/pathways/progress', c.getPathwayProgress); router.post('/pathways/progress', c.savePathwayProgress); diff --git a/frontend/biochem-pathways.html b/frontend/biochem-pathways.html index ac61b70..7e20a35 100644 --- a/frontend/biochem-pathways.html +++ b/frontend/biochem-pathways.html @@ -475,244 +475,7 @@ // ═══════════════════════════════════════════════════════ // PATHWAY DATA // ═══════════════════════════════════════════════════════ -const PATHWAYS = { - glycolysis: { - name: 'Гликолиз', - color: '#f59e0b', - colorRgb: '245,158,11', - desc: '10 реакций расщепления глюкозы до пирувата. Происходит в цитоплазме. Выход: 2 АТФ (нетто), 2 НАДН, 2 пируват.', - stats: [ - { label: '−2 АТФ +4 АТФ', cls: 'atp' }, - { label: '2 НАДН', cls: 'nadh' }, - ], - legend: [ - { color: '#f59e0b', type: 'circle', label: 'Метаболит' }, - { color: '#f59e0b', type: 'line', label: 'Реакция' }, - { color: '#f59e0b88', type: 'circle-sm', label: 'Кофактор (АТФ/НАД)' }, - ], - // nodes: id, label, formula, x, y, role - nodes: [ - { id:'glc', label:'Глюкоза', formula:'C₆H₁₂O₆', x:400, y:60, role:'substrate', desc:'Исходный субстрат гликолиза. 6-углеродный сахар, главный источник энергии клетки.', props:[] }, - { id:'g6p', label:'Глюкозо-6-Ф', formula:'C₆H₁₃O₉P', x:400, y:145, role:'inter', desc:'Глюкозо-6-фосфат. Образуется при фосфорилировании глюкозы за счёт АТФ. Удерживает молекулу в клетке.', props:['−1 АТФ'] }, - { id:'f6p', label:'Фруктозо-6-Ф',formula:'C₆H₁₃O₉P', x:400, y:225, role:'inter', desc:'Изомер глюкозо-6-фосфата. Образуется при изомеризации ферментом фосфоглюкоизомеразой.', props:[] }, - { id:'f16bp', label:'Фруктозо-1,6-бФ',formula:'C₆H₁₄O₁₂P₂', x:400, y:310, role:'key', desc:'Фруктозо-1,6-бисфосфат — ключевой регуляторный метаболит. Образование катализирует фосфофруктокиназа-1 (ФФК-1).', props:['−1 АТФ', 'Контроль скорости'] }, - { id:'dhap', label:'ДГАФ', formula:'C₃H₇O₆P', x:260, y:395, role:'inter', desc:'Дигидроксиацетонфосфат — один из двух триозофосфатов при расщеплении фруктозо-1,6-бисфосфата. Быстро конвертируется в ГАФ.', props:[] }, - { id:'gap', label:'ГАФ', formula:'C₃H₇O₆P', x:540, y:395, role:'inter', desc:'Глицеральдегид-3-фосфат (ГАФ) — непосредственный субстрат следующих реакций. Оба триозофосфата канализируются через ГАФ.', props:[] }, - { id:'bpg', label:'1,3-бФГ', formula:'C₃H₈O₁₀P₂',x:540, y:480, role:'inter', desc:'1,3-бисфосфоглицерат. Образуется при окислении ГАФ, сопряжённом с восстановлением НАД⁺ в НАДН.', props:['2 НАДН'] }, - { id:'pg3', label:'3-ФГК', formula:'C₃H₇O₇P', x:540, y:560, role:'inter', desc:'3-фосфоглицерат. Образуется при субстратном фосфорилировании АДФ АТФ ферментом фосфоглицераткиназой.', props:['+2 АТФ'] }, - { id:'pg2', label:'2-ФГК', formula:'C₃H₇O₇P', x:540, y:635, role:'inter', desc:'2-фосфоглицерат. Образуется при перемещении фосфатной группы с 3 на 2 положение.', props:[] }, - { id:'pep', label:'ФЕП', formula:'C₃H₅O₆P', x:540, y:710, role:'inter', desc:'Фосфоенолпируват (ФЕП) — высокоэнергетический промежуточный продукт. Образуется при дегидратации 2-ФГК.', props:[] }, - { id:'pyr', label:'Пируват', formula:'C₃H₄O₃', x:400, y:795, role:'product', desc:'Конечный продукт гликолиза. В аэробных условиях переходит в ацетил-КоА (цикл Кребса). В анаэробных лактат или этанол.', props:['+2 АТФ', '2 молекулы'] }, - ], - edges: [ - { from:'glc', to:'g6p', enzyme:'Гексокиназа', co:'-АТФ', curveX:0 }, - { from:'g6p', to:'f6p', enzyme:'ФГИ', curveX:0 }, - { from:'f6p', to:'f16bp', enzyme:'ФФК-1', co:'-АТФ', curveX:0 }, - { from:'f16bp',to:'dhap', enzyme:'Альдолаза', curveX:0 }, - { from:'f16bp',to:'gap', enzyme:'Альдолаза', curveX:0 }, - { from:'dhap', to:'gap', enzyme:'ТФИ', curveX:0 }, - { from:'gap', to:'bpg', enzyme:'ГАФДГ', co:'+НАДН', curveX:0 }, - { from:'bpg', to:'pg3', enzyme:'ФГК', co:'+АТФ', curveX:0 }, - { from:'pg3', to:'pg2', enzyme:'Фосфоглицератмутаза', curveX:0 }, - { from:'pg2', to:'pep', enzyme:'Енолаза', curveX:0 }, - { from:'pep', to:'pyr', enzyme:'Пируваткиназа', co:'+АТФ', curveX:0 }, - ], - steps: [ - { - title:'Фосфорилирование глюкозы', - mol:'g6p', - desc:'Гексокиназа катализирует перенос фосфатной группы с АТФ на глюкозу, образуя глюкозо-6-фосфат (Г6Ф). Реакция необратима и «ловит» глюкозу в клетке.', - energy:[{label:'-1 АТФ', cls:'atp-used'}], - quiz:{ q:'Зачем глюкозу фосфорилируют в первой реакции?', opts:['Для выхода из клетки','Чтобы удержать глюкозу в клетке','Для образования НАДН','Для расщепления кольца'], ans:1 } - }, - { - title:'Изомеризация', - mol:'f6p', - desc:'Фосфоглюкоизомераза превращает Г6Ф в фруктозо-6-фосфат (Ф6Ф). Реакция обратима и перестраивает альдозный сахар в кетозный.', - energy:[], - quiz:{ q:'Какой фермент катализирует изомеризацию Г6Ф Ф6Ф?', opts:['Гексокиназа','Альдолаза','Фосфоглюкоизомераза','Пируваткиназа'], ans:2 } - }, - { - title:'Ключевой контрольный шаг', - mol:'f16bp', - desc:'Фосфофруктокиназа-1 (ФФК-1) фосфорилирует Ф6Ф фруктозо-1,6-бисфосфат. Это необратимая реакция — главный регуляторный пункт гликолиза. АТФ ингибирует, АМФ/АДФ активирует.', - energy:[{label:'-1 АТФ', cls:'atp-used'}], - quiz:{ q:'Что является главным аллостерическим активатором ФФК-1?', opts:['АТФ','АМФ','НАДН','Пируват'], ans:1 } - }, - { - title:'Расщепление на триозы', - mol:'gap', - desc:'Альдолаза расщепляет фруктозо-1,6-бисфосфат на два триозофосфата: ДГАФ и ГАФ (глицеральдегид-3-фосфат). Триозофосфатизомераза быстро конвертирует ДГАФ ГАФ.', - energy:[], - quiz:{ q:'Сколько молекул ГАФ образуется из одной глюкозы?', opts:['1','2','3','4'], ans:1 } - }, - { - title:'Окислительное фосфорилирование', - mol:'bpg', - desc:'ГАФДГ окисляет ГАФ и присоединяет неорганический фосфат 1,3-бисфосфоглицерат. Сопряжено с восстановлением НАД⁺ НАДН. Реакция субстратного фосфорилирования.', - energy:[{label:'+2 НАДН', cls:'nadh'}], - quiz:{ q:'Чем восстанавливается НАД⁺ в этой реакции?', opts:['ГАФ','Пируват','ДГАФ','АТФ'], ans:0 } - }, - { - title:'Первая выработка АТФ', - mol:'pg3', - desc:'Фосфоглицераткиназа переносит фосфат с 1,3-бФГ на АДФ АТФ. Это субстратное фосфорилирование — первый синтез АТФ в гликолизе. С каждой глюкозы получаем 2 АТФ.', - energy:[{label:'+2 АТФ', cls:'atp-prod'}], - quiz:{ q:'Как называется тип синтеза АТФ в этой реакции?', opts:['Окислительное фосфорилирование','Субстратное фосфорилирование','Фотофосфорилирование','Трансфосфорилирование'], ans:1 } - }, - { - title:'Мутация фосфатной группы', - mol:'pg2', - desc:'Фосфоглицератмутаза перемещает фосфатную группу с 3-го на 2-е углеродное положение, подготавливая молекулу к дегидратации.', - energy:[], - quiz:{ q:'Какой продукт образуется из 3-ФГК под действием мутазы?', opts:['ФЕП','2-ФГК','Пируват','1,3-бФГ'], ans:1 } - }, - { - title:'Образование ФЕП', - mol:'pep', - desc:'Енолаза катализирует дегидратацию 2-фосфоглицерата фосфоенолпируват (ФЕП). ФЕП — высокоэнергетический соединение с большой отрицательной ΔG° гидролиза фосфата.', - energy:[], - quiz:{ q:'Почему ФЕП называют «высокоэнергетическим»?', opts:['Содержит много атомов С','Большая ΔG° гидролиза фосфатной связи','Растворяется в жирах','Содержит двойную связь'], ans:1 } - }, - { - title:'Финальная реакция — пируват', - mol:'pyr', - desc:'Пируваткиназа переносит фосфат с ФЕП на АДФ АТФ + пируват. Необратимая реакция. Итог: из 1 глюкозы 2 пирувата, 2 НАДН, +2 АТФ нетто.', - energy:[{label:'+2 АТФ', cls:'atp-prod'},{label:'2 пируват', cls:'co2'}], - quiz:{ q:'Каков нетто-выход АТФ на 1 молекулу глюкозы в гликолизе?', opts:['1','2','4','36'], ans:1 } - }, - ] - }, - - krebs: { - name: 'Цикл Кребса', - color: '#06b6d4', - colorRgb: '6,182,212', - desc: '8 реакций окисления ацетил-КоА. Происходит в матриксе митохондрий. Выход на 1 оборот: 3 НАДН, 1 ФАДН₂, 1 ГТФ, 2 СО₂.', - stats: [ - { label: '3 НАДН / оборот', cls: 'nadh' }, - { label: '2 CO₂', cls: 'co2' }, - { label: '1 ГТФ', cls: 'atp' }, - ], - legend: [ - { color: '#06b6d4', type: 'circle', label: 'Промежуточный метаболит' }, - { color: '#06b6d4', type: 'line', label: 'Реакция цикла' }, - ], - nodes: [ - { id:'acetcoa', label:'Ацетил-КоА', formula:'CH₃CO-SCoA',x:440, y:80, role:'substrate', desc:'Активированный ацетат. Образуется из пирувата (гликолиз), жирных кислот (β-окисление) и аминокислот.', props:['Входит в цикл'] }, - { id:'oaa', label:'ОАА', formula:'C₄H₄O₅', x:260, y:140, role:'key', desc:'Оксалоацетат — акцептор ацетил-КоА. Регенерируется в каждом обороте цикла. Ключевой анаплеротический метаболит.', props:['Акцептор'] }, - { id:'cit', label:'Цитрат', formula:'C₆H₈O₇', x:160, y:260, role:'inter', desc:'Цитрат — первый продукт цикла. Синтезируется цитратсинтазой из ацетил-КоА и ОАА.', props:[] }, - { id:'isocit', label:'Изоцитрат', formula:'C₆H₈O₇', x:120, y:390, role:'inter', desc:'Изоцитрат — изомер цитрата. Субстрат изоцитратдегидрогеназы — ключевого регуляторного фермента.', props:[] }, - { id:'akg', label:'α-КГ', formula:'C₅H₆O₅', x:160, y:520, role:'inter', desc:'α-кетоглутарат (α-КГ). Образуется при окислительном декарбоксилировании изоцитрата. Выделяется CO₂.', props:['−CO₂','+НАДН'] }, - { id:'succoa', label:'Сукцинил-КоА',formula:'C₅H₆O₃S', x:300, y:620, role:'inter', desc:'Сукцинил-КоА — высокоэнергетический тиоэфир. Образуется при окислительном декарбоксилировании α-КГ.', props:['+НАДН','+ГТФ','-CO₂'] }, - { id:'succ', label:'Сукцинат', formula:'C₄H₆O₄', x:480, y:620, role:'inter', desc:'Сукцинат. Окисляется сукцинатдегидрогеназой (СДГ) — единственным мембранным ферментом цикла.', props:['+ФАДН₂'] }, - { id:'fum', label:'Фумарат', formula:'C₄H₄O₄', x:620, y:520, role:'inter', desc:'Фумарат — транс-изомер. Образуется при окислении сукцината. Гидратируется фумаразой.', props:[] }, - { id:'mal', label:'Малат', formula:'C₄H₆O₅', x:660, y:390, role:'inter', desc:'Малат (яблочная кислота). Образуется при гидратации фумарата. Окисляется малатдегидрогеназой.', props:['+НАДН'] }, - ], - edges: [ - { from:'acetcoa',to:'cit', enzyme:'Цитратсинтаза', co:'+ОАА', curveX:0 }, - { from:'oaa', to:'cit', enzyme:'', curveX:0 }, - { from:'cit', to:'isocit', enzyme:'Аконитаза', curveX:0 }, - { from:'isocit', to:'akg', enzyme:'ИзоцитратДГ', co:'+НАДН,-CO₂', curveX:0 }, - { from:'akg', to:'succoa', enzyme:'α-КГДГ-комплекс', co:'+НАДН,-CO₂', curveX:0 }, - { from:'succoa', to:'succ', enzyme:'Сукцинил-КоА-синтетаза', co:'+ГТФ', curveX:0 }, - { from:'succ', to:'fum', enzyme:'Сукцинатдегидрогеназа', co:'+ФАДН₂', curveX:0 }, - { from:'fum', to:'mal', enzyme:'Фумараза', curveX:0 }, - { from:'mal', to:'oaa', enzyme:'МалатДГ', co:'+НАДН', curveX:0 }, - ], - steps: [ - { title:'Конденсация с ОАА', mol:'cit', desc:'Цитратсинтаза присоединяет ацетил-КоА (2C) к оксалоацетату (4C) цитрат (6C). Это необратимая реакция, запускающая цикл.', energy:[], quiz:{q:'Сколько углеродов в цитрате?', opts:['2','4','6','8'], ans:2} }, - { title:'Изомеризация цитрата', mol:'isocit', desc:'Аконитаза через промежуточный цис-аконитат превращает цитрат в изоцитрат. Реакция обратима, равновесие сдвинуто в сторону цитрата.', energy:[], quiz:{q:'Какой фермент изомеризует цитрат?', opts:['Фумараза','Аконитаза','Малатдегидрогеназа','Цитратсинтаза'], ans:1} }, - { title:'Первое окислительное декарбоксилирование', mol:'akg', desc:'Изоцитратдегидрогеназа окисляет изоцитрат α-кетоглутарат с выделением CO₂ и НАДН. Ключевой регуляторный шаг — активируется изоцитратом, ингибируется НАДН.', energy:[{label:'+НАДН',cls:'nadh'},{label:'-CO₂',cls:'co2'}], quiz:{q:'Сколько углеродов в α-кетоглутарате?', opts:['2','4','5','6'], ans:2} }, - { title:'Второе окислительное декарбоксилирование', mol:'succoa', desc:'α-кетоглутаратдегидрогеназный комплекс (аналог ПДК) окисляет α-КГ сукцинил-КоА. Выделяется ещё одна CO₂ и НАДН.', energy:[{label:'+НАДН',cls:'nadh'},{label:'-CO₂',cls:'co2'}], quiz:{q:'Чем структурно похож α-КГДК на пируватдегидрогеназный комплекс?', opts:['Использует ФАДН₂','Механизм окислительного декарбоксилирования с КоА','Находится в цитоплазме','Требует витамин К'], ans:1} }, - { title:'Субстратное фосфорилирование', mol:'succ', desc:'Сукцинил-КоА-синтетаза расщепляет тиоэфирную связь сукцинил-КоА, сопрягая это с синтезом ГТФ (или АТФ). Единственная реакция субстратного фосфорилирования в цикле.', energy:[{label:'+ГТФ',cls:'atp-prod'}], quiz:{q:'Что синтезируется при реакции сукцинил-КоА-синтетазы?', opts:['НАДН','ФАДН₂','ГТФ','CO₂'], ans:2} }, - { title:'Окисление сукцината', mol:'fum', desc:'Сукцинатдегидрогеназа (комплекс II дыхательной цепи) окисляет сукцинат фумарат, восстанавливая ФАД ФАДН₂.', energy:[{label:'+ФАДН₂',cls:'fadh2'}], quiz:{q:'К какому комплексу дыхательной цепи относится СДГ?', opts:['Комплекс I','Комплекс II','Комплекс III','АТФ-синтаза'], ans:1} }, - { title:'Гидратация фумарата', mol:'mal', desc:'Фумараза присоединяет воду к фумарату L-малат. Реакция стереоспецифична — образуется только L-изомер.', energy:[], quiz:{q:'Что присоединяется к фумарату в этой реакции?', opts:['CO₂','АТФ','H₂O','НАДН'], ans:2} }, - { title:'Регенерация ОАА', mol:'oaa', desc:'Малатдегидрогеназа окисляет малат оксалоацетат с образованием НАДН. Регенерируется акцептор для следующего оборота цикла.', energy:[{label:'+НАДН',cls:'nadh'}], quiz:{q:'Сколько оборотов цикла Кребса нужно на 1 молекулу глюкозы?', opts:['1','2','4','10'], ans:1} }, - ] - }, - - oxidation: { - name: 'β-Окисление', - color: '#fb923c', - colorRgb: '251,146,60', - desc: 'Повторяющиеся циклы окисления жирных кислот в митохондриях. Каждый цикл отщепляет 2C в виде ацетил-КоА и выделяет 1 НАДН + 1 ФАДН₂.', - stats: [ - { label: '+НАДН / цикл', cls: 'nadh' }, - { label: '+ФАДН₂', cls: 'nadh' }, - { label: '+Ацетил-КоА', cls: 'atp' }, - ], - legend: [ - { color: '#fb923c', type: 'circle', label: 'Промежуточный продукт' }, - { color: '#fb923c', type: 'line', label: 'Реакция β-окисления' }, - ], - nodes: [ - { id:'fac', label:'Жирная к-та',formula:'R-COOH', x:400, y:60, role:'substrate', desc:'Свободная жирная кислота (напр. пальмитиновая C₁₆). Активируется в ацил-КоА перед входом в митохондрии.', props:[] }, - { id:'acylcoa', label:'Ацил-КоА', formula:'R-CO-SCoA', x:400, y:150, role:'key', desc:'Активированная жирная кислота. Образуется при участии ацил-КоА-синтетазы за счёт АТФ (АМФ+PPi). Не проходит через мембрану — транспортируется как карнитиновый эфир.', props:['-АТФ (АМФ)'] }, - { id:'enoylcoa',label:'Транс-еноил-КоА',formula:'R-CH=CH-CO-SCoA',x:400,y:250,role:'inter',desc:'Транс-Δ²-еноил-КоА. Образуется при ФАД-зависимом окислении ацил-КоА ацил-КоА-дегидрогеназой.', props:['+ФАДН₂'] }, - { id:'hydroxy', label:'L-β-гидрокси-КоА',formula:'R-CHOH-CH₂-CO-SCoA',x:400,y:345,role:'inter',desc:'L-β-гидроксиацил-КоА. Образуется при гидратации двойной связи еноил-КоА гидратазой.', props:[] }, - { id:'ketoacoa',label:'β-кето-КоА', formula:'R-CO-CH₂-CO-SCoA',x:400,y:440,role:'inter',desc:'β-кетоацил-КоА. Образуется при НАД⁺-зависимом окислении L-β-гидроксиацил-КоА.', props:['+НАДН'] }, - { id:'newacyl', label:'Ацил-КоА (−2C)',formula:'R\'—CO-SCoA', x:240, y:540, role:'inter', desc:'Укороченный на 2 углерода ацил-КоА. Возвращается на начало цикла β-окисления.', props:['Следующий цикл'] }, - { id:'acetcoa2',label:'Ацетил-КоА', formula:'CH₃CO-SCoA', x:560, y:540, role:'product', desc:'Ацетил-КоА — входит в цикл Кребса. Из пальмитиновой кислоты (C₁₆) образуется 8 ацетил-КоА за 7 циклов β-окисления.', props:[' Цикл Кребса'] }, - ], - edges: [ - { from:'fac', to:'acylcoa', enzyme:'Ацил-КоА-синтетаза', co:'-АТФ', curveX:0 }, - { from:'acylcoa', to:'enoylcoa', enzyme:'Ацил-КоА-ДГ', co:'+ФАДН₂', curveX:0 }, - { from:'enoylcoa',to:'hydroxy', enzyme:'Еноил-КоА-гидратаза', curveX:0 }, - { from:'hydroxy', to:'ketoacoa', enzyme:'L-3-гидроксиацил-КоА-ДГ', co:'+НАДН', curveX:0 }, - { from:'ketoacoa',to:'newacyl', enzyme:'Тиолаза', curveX:0 }, - { from:'ketoacoa',to:'acetcoa2', enzyme:'Тиолаза', curveX:0 }, - { from:'newacyl', to:'acylcoa', enzyme:'Повтор цикла', curveX:-60 }, - ], - steps: [ - { title:'Активация жирной кислоты', mol:'acylcoa', desc:'Ацил-КоА-синтетаза присоединяет КоА к жирной кислоте, образуя ацил-КоА. Расходуется АТФ (АМФ+PPi, что эквивалентно 2 АТФ). Это происходит в цитоплазме.', energy:[{label:'-2 АТФ',cls:'atp-used'}], quiz:{q:'Где происходит активация жирной кислоты в ацил-КоА?', opts:['В митохондриях','В ядре','В цитоплазме','В рибосомах'], ans:2} }, - { title:'ФАД-зависимое окисление', mol:'enoylcoa', desc:'Ацил-КоА-дегидрогеназа окисляет ацил-КоА, вводя двойную связь между α и β углеродами транс-Δ²-еноил-КоА. ФАД восстанавливается до ФАДН₂.', energy:[{label:'+ФАДН₂',cls:'fadh2'}], quiz:{q:'Какой кофактор восстанавливается в первой реакции β-окисления?', opts:['НАД⁺','ФАД','ГТФ','КоА'], ans:1} }, - { title:'Гидратация двойной связи', mol:'hydroxy', desc:'Еноил-КоА-гидратаза присоединяет воду по двойной связи L-β-гидроксиацил-КоА. Реакция стереоспецифична.', energy:[], quiz:{q:'Что присоединяется в реакции гидратации еноил-КоА?', opts:['CO₂','O₂','H₂O','НАД⁺'], ans:2} }, - { title:'НАД⁺-зависимое окисление', mol:'ketoacoa', desc:'L-3-гидроксиацил-КоА-дегидрогеназа окисляет гидроксильную группу кетогруппу, восстанавливая НАД⁺ НАДН.', energy:[{label:'+НАДН',cls:'nadh'}], quiz:{q:'Какая группа окисляется в этой реакции?', opts:['Карбоксильная','Аминогруппа','Гидроксильная','Метильная'], ans:2} }, - { title:'Тиолитическое расщепление', mol:'acetcoa2', desc:'Тиолаза расщепляет β-кетоацил-КоА присоединением КоА ацетил-КоА (2C) + укороченный ацил-КоА. Цикл повторяется.', energy:[{label:'+Ацетил-КоА',cls:'atp-prod'}], quiz:{q:'Сколько ацетил-КоА образуется из пальмитиновой кислоты (C16)?', opts:['4','6','7','8'], ans:3} }, - ] - }, - - synthesis: { - name: 'Синтез белка', - color: '#a78bfa', - colorRgb: '167,139,250', - desc: 'Трансляция — считывание мРНК рибосомой и полимеризация аминокислот в полипептидную цепь.', - stats: [ - { label: '~2 ГТФ / аминокислота', cls: 'atp' }, - { label: 'мРНК белок', cls: 'nadh' }, - ], - legend: [ - { color: '#a78bfa', type: 'circle', label: 'Участник трансляции' }, - { color: '#a78bfa', type: 'line', label: 'Этап синтеза' }, - ], - nodes: [ - { id:'mrna', label:'мРНК', formula:'5′-AUG…-3′', x:400, y:60, role:'substrate', desc:'Матричная РНК — несёт генетическую информацию от ДНК к рибосоме в виде кодонов (триплетов нуклеотидов).', props:['Матрица'] }, - { id:'ribosome',label:'Рибосома', formula:'60S+40S', x:400, y:160, role:'key', desc:'Эукариотическая рибосома (80S). Состоит из малой (40S) и большой (60S) субъединиц. Имеет 3 сайта: A (аминоацильный), P (пептидильный), E (выход).', props:['A-P-E сайты'] }, - { id:'trna', label:'аминоацил-тРНК', formula:'aa-tRNA', x:230, y:260, role:'inter', desc:'тРНК с присоединённой аминокислотой. Распознаёт кодон мРНК через антикодон. Доставляется в A-сайт в комплексе с EF-Tu·ГТФ.', props:['-2 ГТФ'] }, - { id:'peptide', label:'Растущая цепь', formula:'...aa-aa-aa', x:560, y:260, role:'inter', desc:'Нарастающая полипептидная цепь в P-сайте. Пептидилтрансфераза (23S rRNA) катализирует образование пептидной связи.', props:['P-сайт'] }, - { id:'peptbond',label:'Пептидная связь',formula:'—CO—NH—', x:400, y:360, role:'inter', desc:'Образование пептидной связи катализируется рибозимом (23S rRNA) — пептидилтрансферазой. Выделяется тРНК из P-сайта.', props:[] }, - { id:'translo', label:'Транслокация', formula:'EF-G·ГТФ', x:400, y:460, role:'inter', desc:'Фактор EF-G (с ГТФ) сдвигает рибосому на 1 кодон (3 нт) в направлении 5′3′. Освобождается Е-сайт. Расходуется ГТФ.', props:['-1 ГТФ'] }, - { id:'protein', label:'Белок', formula:'[полипептид]', x:400, y:560, role:'product', desc:'Готовый полипептид. Освобождается при встрече со стоп-кодоном (UAA, UAG, UGA) при участии факторов высвобождения RF1/RF2.', props:['Готовый продукт'] }, - ], - edges: [ - { from:'mrna', to:'ribosome', enzyme:'Инициация (eIF)', curveX:0 }, - { from:'ribosome',to:'trna', enzyme:'Декодирование', curveX:0 }, - { from:'trna', to:'peptbond', enzyme:'Пептидилтрансфераза', curveX:0 }, - { from:'peptide', to:'peptbond', enzyme:'', curveX:0 }, - { from:'peptbond',to:'translo', enzyme:'EF-G·ГТФ', curveX:0 }, - { from:'translo', to:'protein', enzyme:'Терминация (RF)', curveX:0 }, - { from:'translo', to:'ribosome', enzyme:'Следующий кодон', curveX:-70 }, - ], - steps: [ - { title:'Инициация', mol:'ribosome', desc:'Малая субъединица рибосомы распознаёт 5′-кэп мРНК при помощи факторов инициации (eIF4E/4G). Инициаторная Met-тРНК занимает P-сайт. Присоединяется большая субъединица.', energy:[{label:'-3 ГТФ',cls:'atp-used'}], quiz:{q:'Какой сайт занимает инициаторная Met-тРНК?', opts:['A-сайт','P-сайт','E-сайт','Все три'], ans:1} }, - { title:'Элонгация — доставка аа-тРНК', mol:'trna', desc:'EF-Tu·ГТФ доставляет аминоацил-тРНК в A-сайт. При правильном спаривании кодон–антикодон ГТФ гидролизуется, EF-Tu·ГДФ уходит.', energy:[{label:'-1 ГТФ',cls:'atp-used'}], quiz:{q:'Какой фактор доставляет аа-тРНК в А-сайт?', opts:['EF-G','EF-Tu','eIF2','RF1'], ans:1} }, - { title:'Пептидная связь', mol:'peptbond', desc:'Пептидилтрансфераза переносит пептидильную группу с P-сайта на аминогруппу в A-сайте, образуя пептидную связь. Энергия — из гидролиза аминоацильной связи тРНК.', energy:[], quiz:{q:'Что катализирует образование пептидной связи?', opts:['Белковый фермент','23S rRNA (рибозим)','ДНК-полимераза','АТФ-синтаза'], ans:1} }, - { title:'Транслокация', mol:'translo', desc:'EF-G·ГТФ сдвигает рибосому на 3 нуклеотида по мРНК. Цепь с тРНК перемещается из A P, пустая тРНК из P E и уходит. Расходуется ГТФ.', energy:[{label:'-1 ГТФ',cls:'atp-used'}], quiz:{q:'На сколько нуклеотидов сдвигается рибосома при транслокации?', opts:['1','2','3','4'], ans:2} }, - { title:'Терминация и высвобождение', mol:'protein', desc:'Стоп-кодон (UAA/UAG/UGA) распознаётся факторами высвобождения RF1/RF2. Пептидилтрансфераза гидролизует связь пептид-тРНК белок освобождается. Рибосома диссоциирует.', energy:[], quiz:{q:'Сколько стоп-кодонов существует?', opts:['1','2','3','4'], ans:2} }, - ] - } -}; +let PATHWAYS = {}; // данные путей грузятся из БД через API в init() (loadPathways) // ═══════════════════════════════════════════════════════ // STATE @@ -1060,6 +823,17 @@ function clickNode(id) { // ═══════════════════════════════════════════════════════ // LEARN MODE // ═══════════════════════════════════════════════════════ +// ── Загрузка данных путей из БД (API) ── +async function loadPathways() { + try { + const data = await LS.biochemGetPathways(); + if (data && Object.keys(data).length) PATHWAYS = data; + } catch (e) { + LS.toast?.('Не удалось загрузить пути', 'error'); + } + if (!PATHWAYS[currentPath]) currentPath = Object.keys(PATHWAYS)[0] || currentPath; +} + // ── Прогресс прохождения путей (персистентность Learn-режима) ── let _pathProgress = {}; async function loadPathProgress() { @@ -1253,6 +1027,7 @@ async function init() { // wait for layout await new Promise(r => setTimeout(r, 60)); + await loadPathways(); // данные путей из БД renderPath(); renderPathInfo(); loadPathProgress(); // отметить пройденные пути галочкой diff --git a/js/api.js b/js/api.js index 003d95f..b39d6e9 100644 --- a/js/api.js +++ b/js/api.js @@ -943,6 +943,7 @@ async function biochemSolveChallenge(id,payload) { return req('POST',`/bioche async function biochemGetSaved() { return req('GET', '/biochem/saved'); } async function biochemSave(atoms,bonds,name){ return req('POST','/biochem/saved',{atoms,bonds,name}); } async function biochemDeleteSaved(id) { return req('DELETE',`/biochem/saved/${id}`); } +async function biochemGetPathways() { return req('GET', '/biochem/pathways'); } async function biochemGetPathwayProgress() { return req('GET', '/biochem/pathways/progress'); } async function biochemSavePathwayProgress(pathway,step,completed){ return req('POST','/biochem/pathways/progress',{pathway,step,completed}); } @@ -1067,7 +1068,7 @@ window.LS = { biochemGetElements, biochemGetMolecules, biochemGetMolecule, biochemValidate, biochemGetReactions, biochemGetChallenges, biochemSolveChallenge, biochemGetSaved, biochemSave, biochemDeleteSaved, - biochemGetPathwayProgress, biochemSavePathwayProgress, + biochemGetPathways, biochemGetPathwayProgress, biochemSavePathwayProgress, prefs: lsPrefs, };