# Часы сердца: фибрилляция желудочков

Дата: 14.10.2026
Статус: принята автономно (режим «Все автономно»). Работа потока приложения. Отложена из спеки двунаправленной ЖТ.
Свидетельства: `/mnt/project-files/evidence/ventricular-fibrillation.md`, строки 1–3, 13, 17, 19 и раздел ECG preset.

## Зачем

Статья о фибрилляции желудочков (ФЖ) вышла в 0.7.0 без часов сердца. Свидетельства говорят, что ни один пресет ей не подходит: мономорфная ЖТ вводила бы в заблуждение. У ФЖ нет зубцов P, комплексов QRS и зубцов T, а часы строят ЭКГ из ударов P–QRS–T. Нужен отдельный режим.

## Что говорят источники

- Минздрав 2025, 569_2, 1.1: «Фибрилляция желудочков – хаотическая электрическая активность в виде полиморфных осцилляций, постоянно изменяющихся по своей конфигурации, амплитуде, продолжительности и частоте, диапазон которой составляет от 300 и выше в 1 мин.»
- MSD Professional, Ventricular Fibrillation, 2024: "ultrarapid baseline undulations that are irregular in timing and morphology"; "uncoordinated quivering of the ventricle with no useful contractions".
- MSD Consumer, Ventricular Fibrillation, 2024: "the ventricles merely quiver and do not contract in a coordinated way. No blood is pumped from the heart".
- MSD Professional, Cardiac Arrest (строка 13): нет пульса.

Правила модели:

| Правило | Основание |
| --- | --- |
| ЭКГ: нерегулярные колебания от 300 в минуту, форма и размах меняются; нет P, QRS и T | Минздрав, MSD |
| Нет выброса крови | MSD Consumer |
| Нет пульса; ползунок частоты не применяется | MSD Cardiac Arrest |
| Тонов сердца нет | Вывод: нет закрытия клапанов после выброса. Допущение |
| Клапаны не открываются | Вывод из «нет выброса» для аортального и лёгочного; для митрального и трёхстворчатого — допущение |
| Предсердия: зубцов P и сокращения предсердий нет | Допущение: источники не описывают предсердия при ФЖ |
| Желудочки не сокращаются согласованно; модель не бьётся | MSD; вид дрожания источники не дают, поэтому оно не рисуется |

## Модель (PR 2)

- **Параметр.** `ventricularFibrillation`: 0 или 1, по умолчанию 0. Перекрёстная проверка в стиле `bidirectional` требует нулей у `pAmplitude`, `atrialContribution`, `fWaveAmplitude`, `flutterConduction`, `rrIrregularity`, `pauseEvery`, `blockedP`, `prStep`, `atrialRate`, `atrialPacing`, `ventricularPacing`, `prematureEvery`, `deltaWave`, `bidirectional` и `s2Split`.
- **Интервалы вместо ударов.** Часы по-прежнему делят время на интервалы, чтобы не менять устройство часов и истории. Каждый интервал в ФЖ помечается `Beat.fibrillation = true`. Для таких интервалов:
  - не рисуется `beatWaves`;
  - `soundEvents` возвращает пустой список;
  - `phaseAt` даёт фазу `fibrillation`.
- **Фаза.** Новое значение типа `Phase` — `fibrillation`. В массив `phases` оно не входит, потому что `phaseStarts` его индексирует. Строка `heartClock.phase.fibrillation` добавляется в `heartClockMessageKeys`, en.json, ru.json и тестовую локаль уже в PR 2, иначе HeartClockDemo не пройдёт проверку типов.
- **Волна ФЖ (`vfWaves`)** — функция абсолютного времени часов, как `fWaves`. Она добавляется в `ecgFrom` один раз, а не для каждого из трёх соседних интервалов.
  - Строится как вектор во фронтальной плоскости из двух независимых составляющих X и Y. Каждая составляющая — сумма нескольких синусоид с частотами 5,0–6,5 Гц (300–390 в минуту). Размах и частота каждой медленно плавают по псевдослучайному закону от `seed`.
  - Отведение I, II или III — проекция вектора по углу отведения, поэтому I + III = II в каждый момент.
  - Размах ограничивает длину вектора: не больше 0,8 мВ. Поэтому каждое отведение остаётся в полосе −1…1,5 мВ.
  - Допущения: частоты 5,0–6,5 Гц, размах до 0,8 мВ, отсутствие одной оси. Источник даёт только «от 300 в минуту».
  - Без отведения (II или V1 для часов с V1) берётся проекция на ось II.
- **Переход из ФЖ и в ФЖ** при `setParams` сглаживается за 50 мс (`fWaveBlendMs`), чтобы линия не прыгала.
- **Гемодинамика.** В интервале ФЖ `hemodynamicsAt` отдаёт постоянное состояние с флагом `noFlow`: объём ЛЖ 100 %, давления ЛЖ и ЛП равны конечно-диастолическому давлению ЛЖ, давление в аорте — диастолическое. Это допущение: как быстро падает давление, источники не говорят. Никто эти числа не рисует (см. PR 3), а 3D-модель берёт состояние из `cycleState`. Нормальный удар перед интервалом ФЖ строит свой спад к началу следующего интервала по своему времени, поэтому при `setParams` на границе интервала давления и объём делают шаг; сайт при смене пресета создаёт новые часы и этот шаг не показывает.
- **3D (`cycleState`).** Для интервала ФЖ: `excited` пустой, сокращение всех камер 0, все клапаны закрыты (0). Иначе модель подсвечивала бы проводящую систему, открывала лёгочный клапан по времени скрытого удара и держала желудочки сжатыми.
- **Пресета в PR 2 нет.** Без интерфейса из PR 3 часы показали бы его с ползунком частоты.

## Пресет и интерфейс (PR 3)

- **Пресет** `ventricular-fibrillation`: `ventricularFibrillation: 1`, `pAmplitude: 0`, `atrialContribution: 0`. Записи:
  - `presetGroup`: «Нарушения ритма»;
  - `presetShape`: null;
  - `presetSources`: Минздрав 569_2 (уже есть), MSD Ventricular Fibrillation, MSD Cardiac Arrest;
  - снимки кривых: добавляются только записи нового пресета.
- **Ползунок частоты.** Его заменяет текст «Пульса нет», а у поля вывода есть доступное имя. Пресет без частоты отмечается в модели, и интерфейс читает эту отметку, а не id.
- **Метка фазы:** «Фибрилляция желудочков: нет согласованных сокращений, нет выброса». Она соответствует MSD "no useful contractions".
- **Звук.** Кнопка остаётся, рядом текст «Тонов сердца нет», чтобы тишина не казалась поломкой.
- **Диаграмма Виггерса.** Вместо кривых, легенды и описания — текст «Сердце не перекачивает кровь: циклов нет».
- **3D-модель на странице часов** не бьётся. Подпись под ней: желудочки дрожат, но кровь не перекачивают; дрожание модель не рисует. Так неподвижная модель не читается как асистолия.
- **Встраивание.** Конструктор встраиваний скрывает поле частоты для пресета без частоты, а `EcgEmbed` игнорирует `?rate=` для него. Это проверяет e2e.
- **Описание для диктора (`.ecg`)**: хаотические колебания от 300 в минуту, без P, QRS и T. Без `{rate}`.
- **Описание пресета (`summary`)** не зависит от статьи, потому что его показывают и на странице часов, и во встраиваниях. В нём:
  - ФЖ — остановка кровообращения: сердце не перекачивает кровь;
  - нужны немедленный вызов скорой, сердечно-лёгочная реанимация и как можно более ранняя дефибрилляция (Минздрав 3.1.2, ESC);
  - частота и размах колебаний подобраны для модели.
  - Без номеров телефонов, без чисел о компрессиях и без лекарств.
- **Переход из ФЖ в норму:** при смене пресета часы начинают с нового удара, как сейчас. Это не изображение дефибрилляции. Пресета «после лечения» у ФЖ нет: он изображал бы реанимацию.
- **Сводка мономорфной ЖТ** говорит, что модель не показывает переход в ФЖ. Это остаётся верным, но после PR 3 её надо перечитать.

## Статьи (PR 4, через поток интерактива)

- `ventricular-fibrillation`: пресет `ventricular-fibrillation` рядом с нормой. Диаграмма Виггерса остаётся: в норме она показывает цикл для сравнения, а в ФЖ — текст. Поле `afterTreatment` не указывается: значение `false` схема статей отклоняет, если у пресетов статьи нет состояния после лечения.
- Тексты статей не меняются.

## Тесты

- `vfWaves`:
  - нет повторяющегося периода: автокорреляция на сдвигах 1–3 с ниже порога;
  - частота по пересечениям нуля в окнах от 2 с — от 300 в минуту;
  - длина вектора не больше 0,8 мВ.
- I + III = II в каждый момент; переход в ФЖ без скачка.
- В интервалах ФЖ: нет `soundEvents`, `noFlow`, фаза `fibrillation`, `cycleState` без возбуждения, сокращения и открытых клапанов.
- Перекрёстная проверка отклоняет ФЖ вместе с каждым параметром из списка.
- PR 3: пресет проходит проверку; снимки кривых получают только новые записи; e2e — пресет в группе «Нарушения ритма», текст «Пульса нет» вместо ползунка, текст Виггерса, встраивание без поля частоты, axe без нарушений.

## Перед PR 3

Запас бюджета JS на самой тяжёлой странице статьи — 33 байта (#408). Строки нового пресета его превысят, поэтому сначала нужно освободить место.

## Порядок

1. PR 1 — эта спека.
2. PR 2 — модель: параметр, волна ФЖ, гемодинамика, звуки, фаза, `cycleState`, строка фазы. Без пресета.
3. PR 3 — пресет, строки и интерфейс, после #408.
4. PR 4 — статья, через поток интерактива.
