7.2 KiB
Интерактивные билеты охотника (a1-tir.ru/bilety)
Проект: скачать страницу билетов для экзамена на гражданское оружие и превратить в интерактивный тренажёр.
Возможности: номер правильного ответа скрыт · ответы кликабельны · выбранный неправильный → красный, правильный → зелёный.
Файлы (исходники в ~/Downloads/):
bilety.html— финальная статичная страница (кнопки вшиты в HTML, 181 карточка / 543 кнопки, ≈902 КБ); деплой в/Library/WebServer/Documents/bilety.htmlorigen_raw.html— оригинальная скачанная копия (чистый источник для генерации)gen2.py— Python-генератор оригинала →bilety.html(статические кнопки, без JS-скрипта)gen_fix.py,fix216.py— точечные скрипты восстановления потерянных вопросовbilety.js,bilety.css— ранняя (отклонённая) версия enhancer'а на клиентском JS; в финале НЕ используютсяa1-tir_bilety_raw.html— оригинальная скачанная копия (альтернативное имя)
Статус
- ✅ Страница скачана и переработана в интерактив.
- ✅ Задеплоено в Eagle Dashboard Pages —
/Library/WebServer/Documents/bilety.html(902285 байт), URL/local-pages/bilety.html. Рестарт дашборда не нужен (сканируется живьём). - ✅ Все 181 вопрос покрыты (1.1→1.93, 2.1→2.42, 58→103), каждая карточка ровно 3 кнопки, номер правильного скрыт, клик красит красный/зелёный.
- Изначально терялось 5 вопросов (1.93, 81, 83, 94, 2.16) из-за нестандартной обёртки
<em>и вопроса без<strong>. Восстановлены скриптами~/Downloads/gen_fix.pyи~/Downloads/fix216.py. Подробности — вpersonal/tech/bilety-oxota-interaktiv.md.
- Изначально терялось 5 вопросов (1.93, 81, 83, 94, 2.16) из-за нестандартной обёртки
Источник и структура (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.49rec1120437831— без заголовка (продолжение правовой), 1.50–1.93rec1120438216— «Огневая подготовка», 2.1–2.41rec465410788— без заголовка (правила охоты), 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> </strong>,<em> </em>, пустой<em>с<strong data-redactor-tag>
Контентных <img>/<svg> в блоках вопросов нет — только текст.
Решение — чисто клиентский JS (без библиотек/backend)
bilety.js на DOMContentLoaded обрабатывает каждый [data-record-type="106"] .t-text:
Парсер parseQuiz (конечный автомат по childNodes):
<strong>с непустым текстом, не : если у текущего вопроса ещё нет ответов и фазаquestion→ мержим текст (многострочный вопрос); иначе → новый вопрос.- текстовый узел, матчащий
^\d+[\.\s:]и при отсутствии заданногоcorrect→ ответ{n, text}(фаза →answers); иначе — продолжение последнего ответа. <em>с чистым числом →question.correct = N(только в фазеanswers, чтобы не спутать с «Примечание»); с текстом →question.note = innerHTML(сохранить); пустой/ → шум.<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.