Files
obsidian-vault/personal/plans/ohotnichy-bilety-interaktiv.md
T

81 lines
6.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Интерактивные билеты охотника (a1-tir.ru/bilety)
Проект: скачать страницу билетов для экзамена на гражданское оружие и превратить в интерактивный тренажёр.
**Возможности:** номер правильного ответа скрыт · ответы кликабельны · выбранный неправильный → красный, правильный → зелёный.
**Файлы (исходники в `~/Downloads/`):**
- `bilety.html` — скачанная + расширенная страница (инъекция CSS/JS + метаданные)
- `bilety.js` — enhancer: парсер вопросов + click-логика
- `bilety.css` — стили подсветки (зелёный/красный)
- `a1-tir_bilety_raw.html` — оригинальная скачанная копия (667 КБ)
---
## Статус
- ✅ Страница скачана и переработана в интерактив.
- ⏸️ **Доставка в Eagle Dashboard Pages не завершена** — упирается в права: `/Library/WebServer/Documents/` root-owned, `sudo cp` требует пароль из неинтерактивного шелла. Нужно либо получить sudo-пароль от Alex, либо он запустит вручную:
```bash
sudo cp ~/Downloads/bilety.html ~/Downloads/bilety.js ~/Downloads/bilety.css /Library/WebServer/Documents/
```
После копирования страница появится в `http://localhost:8880/?tab=pages` под именем `bilety` (title/purpose/contains уже заполнены). Рестарт дашборда не нужен.
---
## Источник и структура (Tilda)
Страница — Tilda-лендинг, весь исходный HTML на одной строке (`a1-tir_bilety_raw.html`, строка 228 содержит контент).
Экзамен разложен по **4 блокам** `data-record-type="106"` (Tilda text-блок `div.field-text.t-text`):
- `rec465410787` — «Правовая подготовка», вопросы 1.1–1.49
- `rec1120437831` — без заголовка (продолжение правовой), 1.50–1.93
- `rec1120438216` — «Огневая подготовка», 2.1–2.41
- `rec465410788` — без заголовка (правила охоты), 58–103 · **вопросы из нескольких `<strong>`**
- Итого ~180 вопросов.
### Структура одного вопроса в DOM (проверено по сырым данным)
Каждый блок — один большой div; внутри `childNodes`:
- `<br/>` — разделители (шум)
- `<strong>Вопрос</strong>` — текст вопроса; может занимать **несколько подряд** `<strong>` (напр. вопрос 58); внутри возможен вложенный `<a>` (consultantplus)
- шапка раздела — `<p><strong>Заголовок</strong></p>` (strong вложен в p → не ловится как вопрос)
- текстовые узлы ответов: `"1. Текст"`, `"2. ..."`, `"3. ..."` (бывают ведущие пробелы)
- `<em>N</em>` — **номер правильного ответа** (чистое число)
- примечание — `<em><u>Примечание</u>: …</em>` (НЕ номер, сохранить)
- шум: `<strong>&nbsp;</strong>`, `<em>&nbsp;</em>`, пустой `<em>` с `<strong data-redactor-tag>`
Контентных `<img>`/`<svg>` в блоках вопросов нет — только текст.
---
## Решение — чисто клиентский JS (без библиотек/backend)
`bilety.js` на `DOMContentLoaded` обрабатывает каждый `[data-record-type="106"] .t-text`:
**Парсер `parseQuiz` (конечный автомат по childNodes):**
- `<strong>` с непустым текстом, не `&nbsp;`: если у текущего вопроса ещё нет ответов и фаза `question` → **мержим** текст (многострочный вопрос); иначе → **новый вопрос**.
- текстовый узел, матчащий `^\d+[\.\s:]` и при отсутствии заданного `correct` → ответ `{n, text}` (фаза → `answers`); иначе — продолжение последнего ответа.
- `<em>` с чистым числом → `question.correct = N` (только в фазе `answers`, чтобы не спутать с «Примечание»); с текстом → `question.note = innerHTML` (сохранить); пустой/`&nbsp;` → шум.
- `<p>` при `cur === null` и нет вопросов → `headerHTML` (заголовок раздела сохраняем).
- фильтр: оставляем только вопросы с `correct !== null`.
**Рендер `renderQuestion`:** карточка `.whale-q` → `.whale-q-text` (вопрос, `textContent`, жирный) + `.whale-answers` с кнопками `.whale-a` (`data-n` = номер ответа) + опционально `.whale-note`.
**Click-логика:** первый клик блокируется (`data-locked`). Если `n === correct` → класс `correct` (зелёный); иначе класс `wrong` (красный) **и** правильный ответ получает `correct` (чтобы показать верный). Управляется `data-correct` на карточке.
**Инъекция в страницу:**
- `<link rel="stylesheet" href="bilety.css">` перед `</head>`
- `<script src="bilety.js" charset="utf-8"></script>` перед `</body>`
- мета для дашборда в `<head>`: `eagle-test-purpose`, `eagle-test-contains`.
**Дизайн .whale-a:** карточки-кнопки (flex column), `#f5f5f5`, hover `#ececec`; `.correct`=`#d4edda`/`#28a745`, `.wrong`=`#f8d7da`/`#dc3545` (с `!important`).
---
## Pitfall: локальное открытие `file://`
Страница Tilda использует `sessionStorage` для анимации появления `.t-records` — при открытии локально это работает. Просто открыть `bilety.html` двойным кликом достаточно для проверки функционала.
---
## Связанное
- Доставка в дашборд — механика Pages: `personal/projects/personal-os/eagle-dashboard.md`.