# Беклог — інтерактивні уроки bibletime

Відкладені рішення. Оновлюється в міру закриття.

## 0. Партія уроків — структуру з'ясовано, лишилися продуктові питання

Обсяг: **180 буклетів** (5 рівнів × 3 серії × 12), 1 296 сторінок, 720 тижневих
історій — уся тритічна програма. Число «120» було помилкою в записі.

Англійські оригінали завантажено в `~/projects/BibleTime/lessons/en`, повну
інвентаризацію типів завдань зроблено машинно — див. **`INVENTORY.md`**.
Коротко: 5 048 інструкцій, 18 механік, 78 % робиться полем форми, 4 %
не класифіковано (довгий хвіст одноразових фраз, не пропущена механіка).

Три висновки, що міняють план:

* **малюнки — основна механіка молодших рівнів**, а не виняток: 305 завдань у
  130 буклетах; у рівні 0 це 35 % інструкцій. Тобто панель Редактора
  (пункт 5) стає передумовою, а не покращенням;
* **колір задає інструкція** («Colour Joseph's robe **red**»), а не граф
  сусідства — правило §3.2a треба змінити, стосується 240 завдань;
* **рівні 0 і 1 не мають маркера `Q:` взагалі** — завдання вплетені в текст
  історії; детектор доведеться вчити наказовому дієслову. Заразом: `Q` — це
  ім'я персонажа, а `Adult Guidance` — вказівки дорослому, не завдання.

Лишилося спитати замовника (перелік у кінці `INVENTORY.md`): з якої мови
перекладаємо (українська версія існує, але старим дизайном), порядок робіт,
доля 419 невиконуваних завдань, чи входять супутні матеріали, і що робимо з
персонажами B.E.S. & Friends.

Дотичне: те, що зараз робить агент (переклад, головоломки, поля, області на
малюнках), **заміщує** ручну роботу Редактора, а не додає її — Редактор і так
робив переклад, кросворди й філворди вручну.

**Статус:** технічна частина закрита; чекає продуктових рішень.

## 10. Перебрендування: bibletime → Біблійна Година

Завдання замовника від 6 серпня. Діє на **всі 180 буклетів**, тобто робиться
не руками, а окремим кроком конвеєра після Скіла 2.

| # | Що | Де | Скільки на буклет |
|---|---|---|---|
| 1 | `bibletime` → **Біблійна Година** | шапка кожної сторінки | 8 |
| 2 | `www.besweb.com` → **www.bibletime.org.ua** | підвал кожної сторінки | 8 |
| 3 | логотип `bes` + «bible educational services» → наш логотип | кожна сторінка | 8 |
| 4 | `© Bible Educational Services. Відвідай www.besweb.com або телефонуй +44 (0) 28 6632 2462.` → `© Біблійна Година. Відвідай www.bibletime.org.ua або телефонуй +380964189292.` | остання сторінка | 1 |
| 5 | прибрати `Registered Charity UK CIO 1186004` і дату рівня `01/2025` | остання сторінка | 2 |

Разом ≈ 27 замін на буклет, близько 4 900 на партію.

Логотип: `data/bibletime-logo-ua.png`, 412×431 px — кругла емблема
(хлопчик пише, по колу напис «Біблійна година»).

**Два питання — обидва розвʼязані замовником 6 серпня.**

**Логотип перефарбовуємо в колір рівня.** Оригінал білий на прозорому тлі
(усі 53 450 непрозорих пікселів чисто білі), тож на сторінках 2–8, де тло
біле, він був би невидимий. Рішення: на кольоровій плашці обкладинки — білий,
на решті сторінок — у колір рівня, той самий, яким набрана шапка першої
сторінки. Прозорість оригіналу і є маскою, а краї згладжені саме альфою, тож
перефарбування зводиться до «RGB = колір рівня, альфа як була» і згладжування
не псує. Зроблено: `ua_build/brand.py` → `data/logo/logo_L0…L4.png` і
`logo_white.png`.

Лишається один технічний хвіст: 412 px на 45 pt — це **66 dpi** у друці.
Для екрана достатньо, для типографії замало; варто попросити вектор (SVG/AI)
або растр щонайменше 1 200 px.

**Напис лишається великим — його дозволено розтягнути вшир.** Заміри Arial:

| | `bibletime` | `Біблійна Година` |
|---|---|---|
| обкладинка, 52 pt | 208 pt (x 28…236) | **393 pt** (+89 %) |
| сторінки 2–8, 36 pt | 144 pt (x 28…172) | **272 pt** (+89 %) |

Місце є:

* **обкладинка** — праворуч від напису вільно до `www.besweb.com` на x 388,
  тобто 360 pt. При кеглі **47–48 pt** напис займе 355–363 pt і стане на
  місце; це 92 % від оригінальних 52 pt, на око різниці не видно. Ще ~14 pt
  звільниться, коли широкий `bes` (44.5 pt) заміниться круглою емблемою
  (≈31 pt при тій самій висоті);
* **сторінки 2–8** — кегль можна лишити 36 pt: напис займе x 28…300, а
  номер серії `A1` (зараз x 204…247) переїде праворуч, приблизно на 310.
  До логотипа у правому куті лишається понад 150 pt запасу.

Дотичне: `bes` на обкладинці — це **вектор**, а не растр
(прямокутник 415.9, 40.9 – 460.4, 71.6, тобто 44.5 × 30.7 pt), тож замінюється
тим самим механізмом «закрити білим і покласти зверху», що й сітки
головоломок (§2.1). Наш логотип круглий (1:1.05), а `bes` — широкий (1.45:1),
тож пропорції теж доведеться погоджувати.

**Зроблено 6 серпня.** Крок конвеєра — `ua_build/rebrand.py`, виконується
після набору тексту й головоломок; вимикається прапорцем `--no-brand`.
Застосовано до всіх пʼяти буклетів A1: `besweb`, `Registered Charity`,
`Bible Educational` і дата рівня — нуль згадок, `bibletime.org.ua` і
«Біблійна Година» — по одній на сторінку.

Чотири пастки, кожна коштувала перезбірки:

* **нічого не рухати.** Перша версія зсувала роздільник і номер серії, щоб
  дати напису повний кегль, — і зʼїла підзаголовок, а «A1» поїхало за край.
  Правильно: напис вписується у вільне місце (на обкладинці майже повний
  кегль, на внутрішніх сторінках менший);
* **закриття напису не має чіпати підзаголовок**, що стоїть просто під ним:
  ріжемо по базовій лінії, а не по габариту гліфів;
* **смуга кольорової плашки теж потрапляє в правий верхній кут**, і разом із
  нею габарит логотипа роздувався вчетверо — емблема вилазила за плашку.
  Беремо лише дрібні фігури, що не заходять за край сторінки;
* **витяг тексту віддає пробіли як нерозривні** (`\xa0`), тож пошук за фразою
  «Registered Charity» мовчки не спрацьовував. Плюс `get_text` щоразу створює
  нові обʼєкти спанів, тому `id()` для порівняння не годиться — рядок
  копірайту через це перемальовувався двічі.

**Статус:** зроблено. Лишилося попросити вектор логотипа: 412 px на 45 pt —
це 66 dpi, для друкарні замало.

## 9. `/MK <</CA ( )>>` — додавати чи ні

Дешева страховка проти переглядача, який перегенерує вигляд кнопки. На
нормальному шляху (клік у Acrobat, Preview, мобільний) не змінює **нічого**:
власний потік вигляду використовується як є. Спрацьовує лише тоді, коли
переглядач вирішив намалювати вигляд сам — тоді замість 252 галочок буде
порожньо.

Перевірено шістьма варіантами (`verify/acrobat_ticks_v01.pdf`): пробіл — єдиний,
що прибирає галочку; порожній рядок `()` Acrobat трактує як «підпису немає,
малюй типовий».

Ціна: один ключ на віджет, кілька байтів. Ризик: якщо якийсь переглядач
покладається на `/MK/CA` для власної підсвітки — побачить пробіл замість
галочки, що для нас і потрібно.

**Статус:** рекомендую додати; чекає твого «так».

## 1. Завдання, які не виконуються в полях форми

Було 15 чекбоксів «виконано». П'ять розмальовок контурних слів закрито типом
`paint` (див. «Закрито»), лишилося **10**, з них значущих — «намалюй»,
«з'єднай лінією», «проведи лінію» і «розфарбуй **малюнок**». Провести лінію
між двома точками в полях AcroForm неможливо.

Сторінки в дайджесті через це: 12, 16, 18, 21 (по одному-двох завданнях).
Разом 21 бал.

Варіанти: лишити чекбокс; прибрати завдання з електронної версії; замінити на
інший тип завдання.

**Статус:** відкладено, рішення продуктове.

## 2. Стор. 10 Q1 — «зафарбуй клітинки з крапкою»

Ряд 1×14 клітинок, усі з надрукованими літерами. Геометрично це та сама
історія, що й філворд, але правило «рядів ≥ 3» його свідомо відсікає. Зараз
завдання має лише чекбокс «виконано» і тип «не визначено».

Механізм заливки вже є (`paint`), але тут заливати треба **клітинку**, а не
гліф: літери в ряду друковані звичайним текстом, а не контурним, тож
`get_texttrace()` їх не відбирає, і потрібне окреме правило «ряд клітинок з
літерами + інструкція „зафарбуй“».

**Оновлено 6 серпня:** це не разовий випадок. У буклетах A1 така механіка
трапляється **тричі з п'яти** — L1 стор. 2 («Colour the dotted squares to find
out»), L1 стор. 7 і L2 стор. 7 («Write the letters with dots in the spaces
below»). Тобто правило доведеться писати; як разове воно вже не рахується.

**Оновлено 6 серпня — механізм зроблено** в Level2_A1 (стор. 7). Спроба
зіставити наявні крапки з літерами провалилася: крапка надрукована **між**
двома літерами, і геометрія не каже, якій із них вона належить. Рішення — не
розпізнавати, а **перемальовувати**: клітинки, літери й крапки малюємо самі,
тоді двозначності немає. Код — у `tr_Level2_A1.py`, `_draw_puzzles`.

**Статус:** механізм є; на партію лишилося винести його в `puzzlekit.py`.

## 3. Клікабельні області на векторних малюнках — розвідка проведена

Стор. 13 (свиня по крапках) і стор. 16 (самарянин), разом 8 балів.
Прототип: `verify/art_regions.py`, карти областей `verify/art_regions_*.png`.

Що з'ясовано:

* **Векторний шлях закритий.** У зоні малюнка стор. 16 — 97 фігур типу `f`
  (заливка) і **жодної** з `closePath`: кожна видима лінія намальована як
  тонкий залитий багатокутник. Замкнених областей як окремих шляхів немає.
* **Растровий шлях працює лише на суцільній графіці.** Заливка від пікселів
  (BFS, 300 dpi) на стор. 16 дала 42 замкнені області, і вони осмислені:
  сорочка, спідниця, обличчя, волосся, рука, долоня, сандалі. На стор. 13
  (свиня по крапках) — **1 область тла і 7 крихт** у пучках трави: пунктирний
  контур протікає, зафарбовувати нічого.
* **Прямокутник віджета ловить клік по всій своїй площі.** У 22 найбільших
  областей стор. 16 своїх пікселів у власному прямокутнику в середньому 49 %,
  чужих — 27 %; у 10 із 53 пар перекриття менший прямокутник накрито понад
  90 %. Порядок «менші зверху» рятує частину, але клік біля межі регулярно
  потраплятиме не в ту область.
* Друкований текст поруч дає фантомні області (внутрішні просвіти літер
  о, д, у, ю).

**Рекомендація: не йдемо** — як конвеєрна можливість на 120 уроків. Половина
цільових балів (стор. 13) недосяжна в принципі, решта вимагає ручного добору
областей на кожному малюнку, а точність кліку лишається поганою.
Якщо замовник захоче саме ці 4 бали на стор. 16 — це разова ручна робота, і
до неї треба ще написати трасування растр → полігон.

### Людина в циклі — наскрізний прототип пройдено

Замовник вирішив завести редактора уроків із стилусом. Зроблено тонкий
наскрізний прототип на стор. 16 (11 областей):

* `editor/regions.html` — редактор обведення (Pointer Events, стилус/палець/
  миша, Douglas–Peucker, палітра, зум, експорт та імпорт JSON у **пунктах**);
* `editor/make_page.py` — PNG сторінки; сторінка й dpi передаються **іменем
  файлу**, бо `file://` не дає читати сусідній JSON;
* `verify/regions_trace.py` — заготовка контурів (растрова заливка + трасування
  межі), щоб людина не обводила з нуля;
* `ua_build/regions_apply.py` — **необов'язковий** шар: JSON → чекбокси з
  напівпрозорою (`ExtGState /ca 0.45`) заливкою контуру;
* `verify/regions_click.py` — вимірювання проблеми кліку.

**Головне число: 96.7 % кліків по областях влучають правильно** (сітка 0.5 pt,
23 153 точки в областях). Ключ до цього — сортувати шар за **прямокутником**,
а не за площею контуру: за контуром «обличчя Ісуса» опинялося під «волоссям»
і мало 0 % влучань, за прямокутником — 100 %.

Слабке місце інше: **16.8 % площі малюнка — «нічийне»** (біле тло всередині
прямокутників), і клік там усе одно щось фарбує. Плюс дрібні деталі (сандалі,
пальці) прямокутником не описуються.

### Ратифікована конфігурація

Перевірено замовником у Acrobat на телефоні — **працює, беремо на потік**:

* **адаптивне прямокутне розбиття 2 pt без перекриття** — великі прямокутники
  всередині, дрібні клітинки лише вздовж контуру. Проти рівномірної сітки:
  138 віджетів замість 1 615, +67 КБ замість +702, обхід форми 0.09 с замість
  8.9 с, підсвітка **побітово та сама** (0 різних пікселів зі 192 818);
* **непрозора фарба + растровий трафарет** — шов зникає (0 пікселів при
  400 dpi), а чорні штрихи лишаються видимими, бо в трафарет вони не входять;
* **повне покриття малюнка**: 35 областей замість 11 підняли покриття з 73 %
  до 97 % ціною 252 віджетів і +127 КБ. Прогалин як деталей не лишилось —
  тільки волосяні лінії вздовж контурів;
* дрібні деталі (ремінці сандалей, пальці, 5–20 pt²) — **пальцем на телефоні
  влучити можна**, перевірено;
* підсвітка полів на 252 прямокутниках виглядає прийнятно, перевірено.

**Кількість областей визначає Редактор.** Технічно достатньо підсвітити всі
знайдені елементи — рішення «злити обидві ноги в одну область чи лишити
окремо» продуктове, не технічне.

**Перевірено в Acrobat Pro DC на комп'ютері (5 серпня).** Справжній клік
фарбує **всю** деталь власним кольором, штрихи видно крізь фарбу, галочок
немає; збережений файл зберігає потік вигляду побайтово. Підсвітка полів
лягає рівно по фігурі й виглядає прийнятно. Історія про «252 галочки»
виявилася артефактом перевірки — деталі в `STATE.md` і в §3.6 файла агента.

**Статус:** конфігурацію затверджено й перевірено на комп'ютері та телефоні;
повноцінна панель — див. пункт 5.

## 8. Панель редагування — три відкриті дрібниці

Панель працює: `.venv/bin/python editor/serve.py` →
`http://127.0.0.1:8765/editor/regions.html`. Цикл «поправив → Зберегти →
Перезібрати PDF → відкрити» замкнено, ручних файлів немає. Лишилося три речі.

**8.1. `.bak` — один слот.** Друге збереження поспіль затирає першу копію.
Агент на цьому вже спіткнувся під час перевірки й відновлював файл
перегенерацією. Для роботи Редактора потрібні нумеровані копії або проста
історія версій — інакше два необережні збереження знищують роботу без сліду.

**8.2. Вихідний PDF для перезбірки зашитий.** `art_apply.py` завжди накладає
області на чистий `forms/Level2_UA_form_v06.pdf` (константа `SRC`). Не
нашаровувати — правильно, але обрати інший вихідний файл із панелі не можна.
На партії зі 120 уроків вихідний PDF буде свій у кожного, тож це доведеться
параметризувати — дотично до пункту 4 (винести конфіг).

**8.3. Ім'я «завдання» стає префіксом полів.** Файл
`regions_p16_q2_full.json` дає поля `p16_q2_full_art01`. Зараз нешкідливо, але
на 120 уроків імена полів мають бути передбачуваними — від них залежить
автоматичне зчитування відповідей (див. пункт 7). Треба або зафіксувати шаблон
`p<NN>_q<N>`, або домовитись, що робочі набори називаються без суфіксів.

**Статус:** відкладено; 8.1 варто зробити до того, як Редактор почне реальну
роботу, решта — перед партією.

## 7. Автоматична відправка відповідей на сервер

Запит: PDF сам надсилає кожну відповідь на сервер одразу після вводу.

Механізм у PDF існує — `submitForm()` можна викликати з події зміни поля, а не
з кнопки. Але для цієї аудиторії він не працює:

* **мобільні переглядачі JavaScript не виконують** — із телефона не піде нічого;
* **мережевий доступ із PDF привілейований**: Acrobat Reader із розширеною
  безпекою блокує тихі запити, вимагає довіреного сайту або `crossdomain.xml`;
* **вбудовані переглядачі браузерів** `submitForm` не підтримують узагалі;
* **немає черги на офлайн** — відповіді зникають мовчки;
* тихе надсилання даних дитини — окреме питання згоди батьків.

Реально працює лише ручна кнопка «Надіслати» в Acrobat на комп'ютері — те, від
чого замовник відмовився на користь «зберегти файл і передати».

**Що можна натомість:** автоматизувати не доставку, а **обробку**. Дитина
надсилає заповнений файл як завжди, сервер читає його програмно — усі поля
мають осмислені імена (`p04_q1_s1`, `p12_q3_c07`), тож зчитування відповідей і
підрахунок балів автоматизуються повністю.

**Статус:** відкладено. Разом із пунктами 6 і «автозбереження» це один і той
самий корінь: PDF не має ані фонової логіки, ані мережі, ані інтерфейсу поза
сторінкою. Якщо збір відповідей на сервер стане вимогою — це аргумент
переглянути рішення «тільки PDF», а не шукати обхід у форматі.

## 6. Кнопка «Зберегти» у лівому верхньому куті

Запит: кнопка, завжди в лівому верхньому куті, натискання зберігає PDF.

Попередній аналіз — **у повному вигляді неможливо**, з трьох причин:

* **Зберегти з кнопки.** Дію виконує лише JavaScript `this.saveAs()` або
  `app.execMenuItem("Save")`. Обидва потребують підвищених прав: у Acrobat
  Reader вони заблоковані, якщо документ не має спеціальних прав від Adobe.
  Кнопка, яка мовчки нічого не робить, гірша за її відсутність.
* **Мобільні переглядачі JavaScript не виконують узагалі** — а це затверджений
  сценарій використання.
* **«Завжди в куті» не буває.** У PDF немає плаваючого інтерфейсу: віджет
  прив'язаний до позиції на сторінці. Довелося б класти 24 копії, по одній на
  сторінку, і кожна прокручувалася б разом зі сторінкою.

Що реально можна:

* **статичний напис-нагадування** в куті кожної сторінки («Заповнив? Не забудь
  зберегти файл») — звичайний текст, працює скрізь, нуль ризику;
* лишити як є: Preview і більшість мобільних застосунків зберігають зміни при
  закритті самі, Acrobat питає.

Перед остаточним «ні» варто витратити 5 хвилин на ручну перевірку `saveAs()` у
свіжому Acrobat Reader — решта висновків від переглядача не залежить.

**Статус:** відкладено; практично зводиться до вибору «напис-нагадування чи
нічого». Пов'язане: автозбереження після кожної відповіді визнано неможливим із
тих самих причин.

## 5. Повний редактор усіх елементів

Веб-панель, у якій редактор уроків бачить і може змінити **кожне поле на кожній
сторінці**: тип, координати, ім'я, прив'язку до завдання, колір заливки.
Найбільший контроль над результатом.

Ціна — найбільше ручної роботи: на 120 уроків це перегляд усіх сторінок, а не
лише сумнівних. Проміжний варіант — редактор як **черга на перегляд**: показує
тільки те, де конвеєр не впевнений (дайджест — зараз 7 сторінок із 24), з
можливістю за потреби відкрити будь-яку іншу сторінку вручну.

Передумова: спершу тонкий прототип обведення областей стилусом (у роботі) —
він покаже, чи взагалі життєздатна ідея ручного редагування поверх PDF.

**Статус:** відкладено; вирішувати після прототипу.

## 4. Винести конфіг перед партією зі 120 файлів

`fields_detect.py`, `fields_build.py`, `extract.py`, `build.py` прив'язані до
констант і форматів Level 2: `CONTENT_RIGHT`, `SCORE_X`, фірмові кольори, шляхи
до шрифтів, розміри клітинок. Перед партією винести в один конфіг, щоб на урок
припадав лише файл перекладу.

Сюди ж: прив'язка сітки до завдання за вертикальною смугою зламається, якщо на
іншому уроці сітку надрукують вище за її інструкцію; і растрова сітка (картинка
замість тексту) не буде знайдена мовчки — потрібен сигнал у дайджест «в
інструкції є слово „філворд“, але сітки не знайдено».

**Статус:** відкладено, робити перед партією.

---

## Закрито

* Кирилиця в полях форми — перевірено вручну в Acrobat, Preview і на мобільному,
  вбудовування шрифту не потрібне.
* `NeedAppearances` — вимкнено; вигляд позначеної відповіді власний.
* Синхронізація поля «Ім'я» між сторінками — спільне ім'я поля, без JavaScript.
* Філворди — 212 клітинок-чекбоксів, 32 бали повернуто в електронну версію;
  перевірено на телефоні.
* Розмальовка контурних слів — тип `paint`: 103 літери на 5 завданнях
  (стор. 3, 6, 10, 17, 19), 14 балів повернуто. Клік заливає літеру всередині
  її ж обведення; колір один на завдання, задається при збірці.
* Рамка з ілюстрацією більше не стає полем: на стор. 17 поле `area` накривало
  малюнок Ісуса, що молиться.
