From b6f07912436d9c386bbf410873b9e0cc501a4c52 Mon Sep 17 00:00:00 2001 From: Olga Bregar Dunaeva Date: Fri, 30 Oct 2026 17:20:47 +0100 Subject: [PATCH] initial commit --- bingo/.dockerignore | 12 + bingo/.env.example | 20 + bingo/.gitignore | 3 + bingo/CLAUDE.md | 206 ++++ bingo/Dockerfile | 24 + bingo/README.md | 343 ++++++ bingo/compose.yaml | 37 + bingo/deploy/nginx/bingo-subpath.conf | 52 + bingo/deploy/nginx/bingo.conf | 78 ++ bingo/dist/demo.html | 1074 ++++++++++++++++ bingo/docs/original-brief.md | 66 + bingo/package.json | 16 + bingo/public/admin.html | 285 +++++ .../fonts/manrope-cyrillic-wght-normal.woff2 | Bin 0 -> 14500 bytes .../fonts/manrope-latin-wght-normal.woff2 | Bin 0 -> 24836 bytes .../unbounded-cyrillic-wght-normal.woff2 | Bin 0 -> 31424 bytes .../fonts/unbounded-latin-wght-normal.woff2 | Bin 0 -> 50904 bytes bingo/public/index.html | 1096 +++++++++++++++++ bingo/schema.sql | 29 + bingo/server/cli.mjs | 30 + bingo/server/db.mjs | 30 + bingo/server/server.mjs | 418 +++++++ bingo/tests/api.test.mjs | 132 ++ bingo/tools/build-demo.mjs | 15 + 24 files changed, 3966 insertions(+) create mode 100644 bingo/.dockerignore create mode 100644 bingo/.env.example create mode 100644 bingo/.gitignore create mode 100644 bingo/CLAUDE.md create mode 100644 bingo/Dockerfile create mode 100644 bingo/README.md create mode 100644 bingo/compose.yaml create mode 100644 bingo/deploy/nginx/bingo-subpath.conf create mode 100644 bingo/deploy/nginx/bingo.conf create mode 100644 bingo/dist/demo.html create mode 100644 bingo/docs/original-brief.md create mode 100644 bingo/package.json create mode 100644 bingo/public/admin.html create mode 100644 bingo/public/fonts/manrope-cyrillic-wght-normal.woff2 create mode 100644 bingo/public/fonts/manrope-latin-wght-normal.woff2 create mode 100644 bingo/public/fonts/unbounded-cyrillic-wght-normal.woff2 create mode 100644 bingo/public/fonts/unbounded-latin-wght-normal.woff2 create mode 100644 bingo/public/index.html create mode 100644 bingo/schema.sql create mode 100644 bingo/server/cli.mjs create mode 100644 bingo/server/db.mjs create mode 100644 bingo/server/server.mjs create mode 100644 bingo/tests/api.test.mjs create mode 100644 bingo/tools/build-demo.mjs diff --git a/bingo/.dockerignore b/bingo/.dockerignore new file mode 100644 index 0000000..6c31a7e --- /dev/null +++ b/bingo/.dockerignore @@ -0,0 +1,12 @@ +.git +node_modules +data +dist +tools +tests +deploy +docs +*.md +.env +.env.* +compose*.yaml diff --git a/bingo/.env.example b/bingo/.env.example new file mode 100644 index 0000000..c1d3f1c --- /dev/null +++ b/bingo/.env.example @@ -0,0 +1,20 @@ +# Скопируйте в .env и заполните. cp .env.example .env + +# Ключ для страницы /admin (от 16 символов). Сгенерировать: openssl rand -base64 24 +# Пустой ключ = админка выключена. +ADMIN_KEY= + +# Сезон +TIMEZONE=Europe/Moscow # в каком поясе карточка обнуляется в понедельник 00:00 +SEASON_START=2026-11-02 # первый день, когда отметки идут в батарейку +SEASON_END=2026-12-21 # последний такой день (включительно) +GOAL=500 # цель сезона в шагах + +# Резервные копии базы в томе (раз в сутки), сколько последних хранить. 0 = выключить. +BACKUP_KEEP=14 + +# Куда пробросить порт на хосте. 127.0.0.1 — доступ только для nginx на этом же хосте. +# Если nginx на другой машине или в другом контейнере — см. README, раздел «nginx». +HOST_BIND=127.0.0.1 +HOST_PORT=8080 + diff --git a/bingo/.gitignore b/bingo/.gitignore new file mode 100644 index 0000000..9f77d70 --- /dev/null +++ b/bingo/.gitignore @@ -0,0 +1,3 @@ +node_modules/ +data/ +.env diff --git a/bingo/CLAUDE.md b/bingo/CLAUDE.md new file mode 100644 index 0000000..e43cb0f --- /dev/null +++ b/bingo/CLAUDE.md @@ -0,0 +1,206 @@ +# CLAUDE.md — Balance 2.0 Bingo + +Context for anyone (human or Claude Code) picking up this project. Read this first. + +## What this is + +A single web page for a team wellbeing initiative, **"Project: Balance — Season 2" ("Баланс 2.0")**, +run by Olga (project manager) for a remote team of ~20–25 people at Adacta Fintech, some of them +contractors from other companies. The season runs **2 Nov – 21 Dec 2026**, 8 weeks. The link gets +pinned in a Microsoft Teams channel. + +- Each person sees a **personal 4×4 bingo card** of small wellbeing habits and taps the ones they did this week. +- Every tick feeds one shared **"team battery"** that fills up over the whole season. +- The card resets every Monday 00:00 (season timezone). The battery never resets. +- **No accounts and no personal data.** This is a hard requirement — see "Anonymity" below. + +The UI and all user-facing copy are **in Russian** and must stay Russian. Code comments and README +are also Russian (historical). The owner and her husband now work in English — conversation, commit +messages and new docs can be English. + +The original brief (Russian) is in `docs/original-brief.md`. Some of it has been overridden; see below. + +## Decisions that changed the brief + +| Brief said | Now | Why | +|---|---|---| +| Only full **rows** give +5 | **Rows, columns and both diagonals** each give +5 (10 lines total) | Owner asked: "a diagonal is bingo too", then "vertical too" | +| Goal 300 steps | **Goal 500** | Owner's call after lines were added | +| Hosting: Cloudflare / Netlify / Firebase | **Self-hosted Docker Compose + nginx**, no external services | Owner wants independence from third parties | +| Fonts from Google Fonts | Fonts **self-hosted** in `public/fonts/` | No third-party requests (privacy, offline) | + +The "+5 per row" wording also appears in the project's planning docs (outside this repo); the page's +rule text now reads "Собрал ряд, столбец или диагональ — +5 в батарейку". + +## Architecture + +``` +Browser ──https──▶ nginx :443 (host) ──http──▶ 127.0.0.1:8080 container "bingo" ──▶ volume bingo-data (/data/bingo.sqlite) +``` + +- **Server:** `server/server.mjs` — plain `node:http`, Node.js ≥ 22.13, **built-in `node:sqlite`**, + **zero npm dependencies** (keep it that way). Serves static files from `public/` (preloaded into + memory at startup) and a small JSON API. +- **DB:** one SQLite file, WAL mode. Schema in `schema.sql`, applied idempotently on every start. +- **Frontend:** `public/index.html` (page) and `public/admin.html` (stats) — each a single self-contained + file with inline CSS/JS, no build step, no framework. All asset/API paths are **relative** + (`api/...`, `fonts/...`) so the app works on its own subdomain *or* in a subfolder behind nginx. +- **Container:** `Dockerfile` (base `node:22.22-alpine`), `compose.yaml` (project name `balance-bingo`). + Runs as user `node`, read-only rootfs, `cap_drop: ALL`, `no-new-privileges`, healthcheck on `/healthz`. + Port bound to `127.0.0.1` only. +- **Reverse proxy:** nginx on the host terminates TLS. Configs in `deploy/nginx/`. + +### File map + +``` +public/index.html page: card, row highlight + confetti, battery, weekly pulse question, demo mode +public/admin.html organiser stats, CSV export; key passed in URL fragment (#k=...) +public/fonts/*.woff2 Unbounded + Manrope, Cyrillic + Latin subsets +server/server.mjs HTTP server, API, season/week logic, security headers, daily backups +server/db.mjs openDb(), LINES_SQL (row/col/diag detection), LINE_BONUS = 5 +server/cli.mjs `backup`, `reset --yes` +schema.sql tables marks, pulse, totals +tests/api.test.mjs end-to-end tests (spawns the real server on a temp DB) +deploy/nginx/bingo.conf nginx: own subdomain (recommended) +deploy/nginx/bingo-subpath.conf nginx: subfolder of an existing site +tools/build-demo.mjs builds dist/demo.html — serverless demo for previews +Dockerfile, compose.yaml, .env.example, .dockerignore +README.md deployment guide (Russian) incl. full nginx config +docs/original-brief.md original requirements (Russian) +``` + +## Commands + +```bash +npm start # run locally on :8080, DB in ./data (needs Node >= 22.13) +npm test # 7 end-to-end API tests, no deps +npm run build:demo # dist/demo.html (forced demo mode, Google Fonts link for preview only) + +cp .env.example .env # set ADMIN_KEY (>= 16 chars) +docker compose up -d --build +docker compose logs bingo +docker compose exec bingo node server/cli.mjs backup +docker compose exec bingo node server/cli.mjs reset --yes # wipe test data before the season +``` + +Local testing during the pre-season: set `SEASON_START` to a past Monday, otherwise the server +rejects marks (`season_closed`). `http://localhost:8080/#demo` forces demo mode (no server calls). + +## Configuration (`.env`, read by the server at start) + +| Var | Default | Notes | +|---|---|---| +| `ADMIN_KEY` / `ADMIN_KEY_FILE` | empty | empty = admin disabled; < 16 chars = refuses to start | +| `TIMEZONE` | `Europe/Moscow` | weekly reset is Monday 00:00 in this zone | +| `SEASON_START` | `2026-11-02` | before it: "practice mode", marks not accepted by server | +| `SEASON_END` | `2026-12-21` | inclusive; after it: season closed | +| `GOAL` | `500` | battery target; above it the UI shows "Овердрайв!" and keeps counting | +| `BACKUP_KEEP` | `14` | daily `VACUUM INTO` copies in `/data/backups`; 0 = off | +| `HOST_BIND` / `HOST_PORT` | `127.0.0.1` / `8080` | compose port mapping only | + +The page fetches goal/dates/timezone from `/api/total`, so no HTML edits are needed for config changes. +Invalid config makes the server exit at startup with a clear message. + +**Open question for the owner:** 21 Dec 2026 is a Monday, so "week 8" is one day long. +`SEASON_END=2026-12-27` would give 8 full weeks. Not decided yet. + +## Scoring rules (server is the source of truth) + +- 1 ticked cell = 1 step. Each completed line = +5. Lines: rows 1–4, columns 1–4, + diagonals 01-06-11-16 and 04-07-10-13. Bonuses stack (a full card = 16 + 10×5 = 66). +- Unticking in the same week removes the step and the bonus of every line it breaks. +- Only the **current week** can be changed (client sends `week`, server returns 409 if it's stale). +- Primary key `(device, week, cell)` prevents double-counting. +- After every mark the server **recomputes the total from scratch** inside one transaction + (`RECOUNT_SQL` = count(marks) + 5 × count(LINES_SQL)) and caches it in `totals`. + Polling `/api/total` reads that one row. +- The client mirrors the same rules (`LINES` in `index.html`) for instant feedback and celebrations, + then reconciles with the server response. **If you change scoring, change both** `server/db.mjs` + and the `LINES` array in `public/index.html`, and update the tests and README. + +## API + +| Method & path | Body / query | Response | +|---|---|---| +| `GET /api/total` | — | `{total, goal, tz, start, end, week, weekNo, weeks, phase}`; phase = `pre` / `active` / `post` | +| `GET /api/me?d=` | — | `{week, cells:[...], pulse}` — this device's current week | +| `POST /api/mark` | `{d, week, cell 1–16, on: bool}` | `{ok, week, total, cells}`; 409 `week_changed`, 403 `season_closed`, 400 validation | +| `POST /api/pulse` | `{d, week, answer: full/mid/low}` | `{ok, answer}`; one answer per device per week, can be changed | +| `GET /api/admin/stats` | `Authorization: Bearer ` | weeks (cells, rows, cols, diags, steps, devices, pulse), per-cell counts | +| `GET /healthz` | — | `{ok:true}`; blocked by nginx from outside | + +Device id `d` = random UUID generated in the browser and kept in localStorage (`balance2-bingo-v1`), +regex `^[A-Za-z0-9-]{16,64}$`. Request bodies are capped at 2 KB (413 above that). + +## Anonymity — non-negotiable + +- Store nothing beyond: random device id, week (Monday date), cell number, pulse answer, the total. + **No** names, emails, logins, IPs, timestamps, user agents, analytics or third-party requests. +- The server logs only startup and errors — never request lines or IPs. +- nginx: `access_log off`; `X-Forwarded-For` deliberately **not** forwarded; error log at `crit`. +- Only the team total is public. The admin page shows aggregates only. +- Accepted trade-off: no anti-cheat (someone can use 10 browsers). Don't add fingerprinting or IP limits that store data. + +## Teams embedding gotcha + +The page must be embeddable as a Teams "Website" tab. The server sends +`Content-Security-Policy: frame-ancestors 'self' https://teams.microsoft.com https://*.teams.microsoft.com https://*.office.com https://*.cloud.microsoft`. +**Never add `X-Frame-Options`** (app or nginx); it breaks the tab. The subpath nginx config uses +an `add_header` inside `location` specifically to stop inheriting a site-wide X-Frame-Options. +A test asserts the header is absent. + +## Frontend notes + +- Visual spec from the brief: background `#12233D`, cells `#1B3150` with border `#2A4468`, radius 20px, + text `#F2F5FA` / muted `#A9B8CC`. Row colours: Тело `#FF8A65`, Фокус `#7CC4FF`, Границы `#B9A6FF`, + Люди и радость `#C6F432`. Accent `#C6F432`. Fonts: Unbounded (display), Manrope (text). Tokens are in `:root`. +- Deliberately single dark theme (brand look), not light/dark. +- Cells are real ` + + + + + +
+ +
+
+
+

+ + Батарейка команды +

+

… из 500 шагов · заполняем вместе до 21 декабря

+
+
0%
+
+
+
+
+
+ +
+ +

Анонимно: без имён, почты и логинов. Твоя карточка хранится только в этом браузере, на сервер уходит лишь «клетка отмечена или снята» со случайным номером устройства. Батарейка обновляется сама каждые 20 секунд.

+ + +
+
+ + + + + diff --git a/bingo/docs/original-brief.md b/bingo/docs/original-brief.md new file mode 100644 index 0000000..9057ed1 --- /dev/null +++ b/bingo/docs/original-brief.md @@ -0,0 +1,66 @@ + + +# Задача: интерактивная страница «Бинго «Баланс 2.0»» для команды + +## Контекст +Командная wellbeing-инициатива на 8 недель (2 ноября — 21 декабря 2026), ~20–25 участников. +Люди работают в разных компаниях (часть — подрядчики), общий аккаунт или SSO у всех не гарантирован. +Ссылку закрепляем в канале Microsoft Teams. Нужна одна веб-страница без регистрации. + +## Что делает страница +1. Каждый видит свою карточку 4×4 и кликает по клеткам, которые сделал на этой неделе + (повторный клик снимает отметку). +2. Когда собран целый ряд (4 клетки одного ряда) — ряд подсвечивается + конфетти. +3. Внизу общая «батарейка команды» — растёт в реальном времени (достаточно опроса сервера раз в 15–30 сек). +4. Личная карточка обнуляется каждый понедельник в 00:00 (часовой пояс — настройка, по умолчанию Europe/Moscow). + Батарейка НЕ обнуляется — копится весь сезон. + +## Подсчёт батарейки +- 1 отмеченная клетка = 1 шаг. Собранный ряд = +5 бонусных шагов. +- Снятие отметки в ту же неделю вычитает шаг (и бонус, если ряд распался). +- Цель сезона: 300 шагов (настройка). Отображение: «N из 300 шагов», процент и 10 делений по 10%. +- Больше 300 — показывать «Овердрайв!» и продолжать считать. + +## Анонимность (важно) +- Никаких имён, email, логинов и аналитики/трекеров. +- Личная карточка хранится в браузере (localStorage) + анонимный случайный id устройства. +- На сервер уходят только события «клетка X отмечена / снята, неделя W, анонимный id» — + чтобы сервер не дал отметить одну клетку дважды за неделю с одного устройства. +- Публично видна только общая сумма. Сменил браузер — карточка начинается заново, это допустимо. + +## Опционально (если несложно) +- Раз в неделю мини-вопрос «Твоя батарейка сейчас?» ⚡ Полная / 🔋 Средне / 🪫 На нуле — + анонимные счётчики по неделям (нужно для сравнения «до/после» в финале). +- Админ-страница по секретной ссылке: шаги по неделям, популярность каждой клетки, + распределение ответов на мини-вопрос, экспорт CSV. + +## Клетки (ряд = тема) +Тело: 01 Обед без экрана · 02 Разминка между созвонами · 03 Гимнастика для глаз · 04 Сон до полуночи +Фокус: 05 Фокус-блок на одну задачу · 06 3 главных дела на день · 07 Встреча превратилась в сообщение · 08 Время залогировано в тот же день +Границы: 09 Сказать «нет» или «не сейчас» · 10 Вечер без рабочих сообщений · 11 Попросить о помощи · 12 Ноутбук закрыт вовремя +Люди и радость: 13 Офлайн с друзьями или семьёй · 14 Хобби, спорт или что-то руками · 15 «Спасибо» или помощь коллеге · 16 Мем в чат Мемопятницы + +## Тексты +- Надзаголовок: PROJECT: BALANCE · СЕЗОН 2 · 2 НОЯБРЯ — 21 ДЕКАБРЯ +- Заголовок: Бинго «Баланс 2.0» (цифры «2.0» — акцентным цветом) +- Три правила: 1 Делай маленькие шаги · 2 Отмечай клетки за неделю · 3 Собрал ряд — +5 в батарейку +- Подпись батарейки: «Батарейка команды» / «N из 300 шагов · заполняем вместе до 21 декабря» + +## Визуальный стиль +- Фон #12233D, клетки #1B3150 с рамкой #2A4468, скругление 20px. +- Текст #F2F5FA, второстепенный #A9B8CC. +- Цвета рядов (номер клетки, иконка и название ряда): Тело #FF8A65, Фокус #7CC4FF, Границы #B9A6FF, Люди и радость #C6F432. +- Акцент (батарейка, «2.0», кружки правил): #C6F432. +- Шрифты Google Fonts: Unbounded (заголовки), Manrope (текст). Нужна кириллица. +- Слева у каждого ряда — иконка (сердце, мишень, щит, чашка, линейные) и название ряда. +- Отмеченная клетка: заливка цветом ряда, тёмный текст, галочка в кружке справа вверху. +- Должно хорошо работать на телефоне (ряды могут стать 2×2), клетки — настоящие + + + + + + + + + + + + + + diff --git a/bingo/public/fonts/manrope-cyrillic-wght-normal.woff2 b/bingo/public/fonts/manrope-cyrillic-wght-normal.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..3a062296a1269ded5bf605334d18f3e43088c888 GIT binary patch literal 14500 zcmV;VI9tbePew8T0RR91063%o6951J0DPDL05~=P0RR9100000000000000000000 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 C%jrD; literal 0 HcmV?d00001 diff --git a/bingo/public/fonts/manrope-latin-wght-normal.woff2 b/bingo/public/fonts/manrope-latin-wght-normal.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..71eb731d558046199aa7f985adbf812890a093a1 GIT binary patch literal 24836 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 literal 0 HcmV?d00001 diff --git a/bingo/public/fonts/unbounded-cyrillic-wght-normal.woff2 b/bingo/public/fonts/unbounded-cyrillic-wght-normal.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..102b4544462df67852ac719f97301a83c9b9de5f GIT binary patch literal 31424 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 literal 0 HcmV?d00001 diff --git a/bingo/public/fonts/unbounded-latin-wght-normal.woff2 b/bingo/public/fonts/unbounded-latin-wght-normal.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..3260a1939eb5a3020b48235c1a52852080f929b6 GIT binary patch literal 50904 zcmY&;V{mBO(rs+pwr$(aj&0kvZQHhOCp*@TZ994U+;i_&_4?0TYgTowS>3ZokI}W< zmG=&M)yxP$^7{U-s`J2By!i ztRkoqfIv zv5Dj`U`8DB$s$)lb!>l-O~|<2`=&Ab`@*sLyeOgi$i0gKOpW`t zgx8ZBw*64>=+mY2haa`J$+2T-56TTAJA0+;pk7jYbZctS%lho4n(R|B>%tJ{mHn+k z$iS-ZJwH#^XfslA`cIrkeJpxTbo5WM-26($^7z_24X|~Zsqi3CSo$;M&zzsr*H5~Y zn(8!R1xdUB0Z0Q#Q|Pl3hb(mSe5G37aBlc!n)FZqT+Pdm9<$gJ2E!;s!~(V=5^;%$ zh)SVIVK5%6kieXXd;^Dwz#ak_#fk_9YFS{&X@%Q~hZ_#n2`0}E{-s~%T#m;(KN7K_ z`dL_{vI9|+#I_M?*}jTMOzE}8G|acz`|Lw@OK#Kb!*CCV*=G(kT@w)zA%{aE7ovk4 z(@Ay9z7Rr#+;5t8ebGP(1c%)4Cc$hDhXKyH4s8TUUh09)U2S_dRBAcv>lcKCEpW!q zp`Y*9pN=_?n?=ZI_F{T*hCvxqp!Dn4iEsdP)T?JRr8trnfW1&Z_K$CZ8s&z&*qW~I z6lt?Bs~4-6j9J`=*5-8ZaAc%J1fp1r6Q434`Y9&REJ;9m0#~#Mr$x?>u((|(Ko5jT zN|MWTW3BzS`}gl1_PK9*HZHH45%3Sgd~PT4VV9`0Yv*z)(uzv=+a$S*9e);PG!21P z(N-Bk4gy@?!@@67d8O<)1t9t)_ADGE&sVpm8+mht7{PE1NXTH2wAKUHkxMJL9WTt> zbibPRSSy=qW!y>zo|&`0NvMiCgI}O_+3GOud=P+?$D3fWm$+%4?i2zJ-EFy4cFwT zjr)q3)#mHKD*$ogG5yl%1_GFHf`~|;-LZW&u{N~@^E<`}#xw@yZq z@6vt*a#NNgRZAo{ejJoP`dzrLSrSNzzaKu>V7b9*@5OQu;8VXzMeKoFk0}njd3a?? zf9syqAx>gIVFUB0BmzNYbELTZKnPF^_(OHp3=r~C92xkJoTaxMcdwx8E}cPJ`*-3a z_|u57_u49uq_?vIhwWR>IJ)od8Q{FZPqQaUjzXUOPL6JFZXPD-{_tb(%YfiD3+>P3 zQ!cxKI<)nYPM9w}*7yp!QFSsl&nZYIJfY>E4$|f8srYr~2T%bx3WW1gvE600L|fJC zI;$^pl+0;W_)x*x*9BMzh@i4~6=+)vDWwG)`$15WK}I=)L?HUskej)jfmz4;OAEi4 zI*O>-G`q`}ii+p<-s>Wf5|D!s>(*gS1R0Fhuk21Rp|_4||e z`TN?#5)8nKGMrlf)UsSlmuQPhs%M_2Hc?TyuvTYmAqPpLzYzL8Yx4@&s62G;Rm4x{9X(Xq zZAZ=@5lLoQ0$gwb19yI%m)a*itVtq*8KD>Q3g+b9p;2dMkgXSG(glG@HZ2!`GxlEJ~7< z7NvH)#@u>UpPI~E{hGvQP$LzB5ds;-Fo=T@gwh`YOG{8GZJ=CECD*N9@A^#EKG|C? ztGRDHeT&1_3}(!SqgQtt2m=$?Usun4{BQgdgKk52rGv&5U=#~sDz!mXQmDeiQVDWB zq3*VzhAUOWS@HGx-e4YB-2k8w34zdn$K&)8A@1VVqj;AEx00T}#MIP$+P#l1e#X6gML^ZJgb)YN>xFZFmH(qfSDz1E$^ z9^|}lQ{a2JoKDUs+IrvjR)5LcDN$9Gm9?=HAIkjw zSi5nwy;gUHavUInLaCx43hTnc5C}6xsaP<8B2CjY%9Y2Qol;{9Yo$3=l>77Un4Gi7%un=$VXlpo0it$LsnCW6&(n>X1U1=hvR>q`CVWgMbUGrT1f|f4ls6C-b zOrFS8Ns>Itns3GT%P|G3La}KgRdeT@Y!R7EKBskUe=#kc(Mc%w7Mu(*A%39{TNq=6 zQ0OzrDoV=8`D#$XG5oS&2d0di>>N$pYC~S`MRG9!YWM(R1!c4I!cdV^8%_v8Wiy#%tHbQnr+`UL<@J+thIOq%Wz${j z(EJ9INU}o#ED2?%frp@q5%4jtyAILsi7H!unbIaj?TVVV0A7hxBTJVH{05LB^pY7Ra&F=NOV-wZpN{%m9a zl7%TvTWJ}Hd0D)W=ay_LR9@cJEtdi@;8LrsDEqd3T#}F!T8xmONti_CvJ^}SR!Fo1 zNd^XKLPQyYOceg-Yx|HQNUSpK&@>NHe~3b6)?zQ-c#_sP4O`Z6O*|7Y{l`(r5@pMyXWz5dV(ZaDg)?JrQkhakgUL#BXCr-Qs z04O@W!J{G12xR^3@lx0q>do#~q|#}$dJWfD0*o|2COOH{F)L%*A6w{%j5bJ2Qd}yJ zr)k2H%rQ?BlVnoDspuxE>^5m)CF|$s*N>vfG}}f!(+QIVG87DS#lJ_nU<@{5$1c!? zprYoFNG^Rp`2qWqz8o_6d;{e0r1AI$ZHn1Y%(@66%x`GVlV;4slJoE#uD zAPX4p(*v2G;^;0sR5q ztEV9gtIIQO(^GLrAmy5}6-Gl;umsUcW+V-!&J3oQMZZP~r809R(5rCAuOGo1{UHGe z05;+NY(kSOYoL^2rlMOGHt$6W65X>wvZdfbJQ{)c+vE`lWLMa)O_b$&2uHfP_xD`y zKhm{ry0v-v1K+*}xPEi(&zkLA*gD7g;GVnnFmq8d!RoHqS^|UI!fA+(gaAPSX+S`M zB#Kr*Nup6L2ahHFNwFD>bS#H}!v5navY$$=iKAGj5DK#Q$+6pylh^0d3!MqywD9fi zfexjz;L-oKfrP!lBAZ_MMmYJdLIJPm)h*cf$0k6*J_EbX1{96*@|;VhWsu9qQP+Er zKUF8g2_2gUh2NR?UNUTEUhE@tR$?O4McV)rjBf`)e~{Ps#yu!%>XvSY3p{Be-A}kv z|9ZVXhVP+*sRG*8#TKU{!5s2~4~qgC?4Vd^fQ!xDV-%pf4cnCo>afn=*Uy|YFJzN8 zMbPvHLaiSw)-n^g_(%B%+Z#S_=;M~F8^mo$qn%K0jJ4j&joy=MU>{J(Ghk(|NN9Ck zA*`QTu~Mc3${jHdGqk@0acivr<`BWMe83-;p)?&uao^P*ykFhe{TVA5l1_}E6Y8>} zfTa1j{v_c977a|0q$-1@B*gx??ukZxNiCGkT1uMS@;&gecng2p-N_U_rUII~~sD5#1W}d!X28gUIib zH}^kz>?dUp`#h|1Gw{dPZ*u)m$j#7G$8=5)oL03w$IWcCgmElH&|YO;i_I2~Ec)k+Ety!dn1C8W5VCyt zsy6|vvxgJOg^7|zN|}eO&z~ercXH2UoWn|FU1WQ=LD(FBrSQ#T#C~w#$JSWS&SuYw z^jG=VyP(_i65jGxC-ANS`aN{fnplu#T~3?hRI9`Tn5!;c7Hww;o3E1vTg);`mN#+1 zj-}>MXSL~arMh?%mRbW;YL{#3y6&$55ZVMx*Gr$E{ZvGn2K^YpIybHLX-m<-!O~Z; z6l8h!w~68R@0=;QWc(souk)8##A)-TVtJWzhdZcc=jD%7h>4 z>RM#yWugGo$8zvxk+%+u`9Wkf{t>&B4d;)XS&ek#Fzn0jr{tCpp24$<(x+lrjf(Ro z+u7~C&MOUhVpx1h3t`zfX4S_)6VWb4>C}}MJ-0^I zS2pyIAP*9aC53!5rAcIcQA^!%II<~l_Y-0$+21vHaETL9Lj9>trNIs|z1nx~A0 zJk2^8aN?;;@mUrI)2sd6xD01G9>y>EMmiH-30Y_v>z(nvNsLp20RHz{t z{+iUfq1m`^-ZIaWuz{J#*eTY|VeJW*8}>l));ID@>` z{S(6dI1ppt~1v?j$cMGgb7F?)AlQU_lpD z4V>A$8F0PQ*maH*$)PBE#%r0AfiY-DFx2XqSX^N+OPf;MuY0SgBPR_q?nu0?mQKQM zHmCjNov=>V6U#~};e3bdqd4k?2@9&Y=MSDs+`5AjWIb8{(qj7~#vG?n89CbP^>bE(PBqhfgc zlk{n4nKzAFoPCd!jJP8AMD9&dm{pv)y07QL|vrUgK|F0 z{i^6xJ8(Ez`*gRVPYmPKt$-*3Z+?|ud9={mX5#k-B)CbczWzo(-rgXN;{)OV^i*+< zLbgQfUxRZV1E~q%#l#K30A;=d;Aw}CiUPgb_}!?pLZE!cV=r6k_(@}iBAORh{G=(u zKgY{Cb=qY0F;*uup!56E_xP!piLWXo2a{l*dZ^;#Qo*sr$ogPNmjMzl!$~jOlpM6| zGDS?GncPXn*9Nk`!$hD__el?y2zozNfz=kPCa;H@Q`>K^fkW(^mq@xQR7R=x2Qp4X zjmo)p@*Gu*m*o#$>L96+5}xm`Y7#Nm^RHD8;Ms^>n=TeD6N*;x6sk8oO{Lw6vPj;x z!oL#5M3~ze=v*M~4XEG80nRpB`ND1Wrk{)n_TlC=YYkseW;7IFC%CTPZ1><6uv@F; z`OA&ryTIz>y-T=?H~H z{QSZ-x~?S_0bLKBE8>^6!j~4dB4PHO3++)4tTM@UzW=NFkna9I%JKMV4XtF(6-lz| zJ|X`0vLEYU2m22>&LP21WEBB1A@5b7_>6C7=4VINmCmIudKcCt0tEro_A@%3zTw=g zS%cB(4R_xxpAoJwSH$SMP&`~38;FN# z)va`ls77=5SM#OZ{_#`;R;a@%L~htC{j<(@Dc7t=2rR~QA%9ocO$vx$iau&ZqKOye zhZ8*f3c*~{cXexx56xNgNF+ia7)#1g#N?=&7F!>NI@LX=O>uc>nlkh8im4X0g6C-A z5}05`IJi_hEgHiOYjJ9g-LezBo})P1)Zx-GxK2bC^nz6G39qg=x9BI5Q!+>??N^ou z_OFE2P*O#|r@@fj(V5T7v-ZBZ_eT~!?8f0M*YLvXB8wBxdE#S82Bv7=hj|eyaZS4v z7S%B&=}gY47e}s-x1=3~9-o5XC9%jENX?+!!D+x%oi-IO53LU+pMLLC2n}NN6`iw_ zmxewU`Pvl}cUiO=#n#GHSAHH-wU5pP?Y21rAo5ncEydJq*2NtkUpf(A*BZtbG_B$qUWqhRGdNRo6=o zzgeAdz0DI;ib#ahwi|sz8VsX6Okn#d~3WfWs4?B7i3jRQY`VLb^T zA(qsFP}0~bjz!f9O}pb=Lnw(gw#=>z*_jxwyk?EJF1^zf$mzz(FyfXcgHI%OKV)5@ zT*uTBC&U^qjx|klJ>ldxxMdvQi0tS+n;EY{$7Z#S0Q=KY?cja;*7u@GE+J&B^L)w zklVzqvJ&SgV|tFU1GCf)pE^;x_6;(YQn3nz`Rz}a1W}GaFDt5n<+FyCXgg*Qx{?q{ z(RE`UFCO%iek_ZFsDGvC$CV_eUoO}imDf&r4IlO-8;gIlv~XXc5T|`a%9*~32X7c5 z)@#x}G7Dt0al2jVcAagE%j*vrx8;viilJZV7eNNfbr>#iNPBepj+}jonE%8_#U*0$ zdIfm}*^bUkavs&gOl9DjxPdHB+p!e~eg`i_6X?o}o=ZW}i+Yy}A{1|MG1U2EsXDp2 z8b^`Jn{$MGy+eFz_t7QkOpb5hIlzb}4WXIyOQuAy z7P!!z4H1JUsy{Pc)EXT1dvb~&LFuLCE5N<&7cqK!zm80XQ@tp%*9w#)Y{E;-r| zFK#;PsZ0TB`R5+dB*6OjF3d$lnWTI*@)G|tJHoPl_=9>-74k#NWqLeQglwYhsbfsr z>LNx=v~H(G!s}<|_B=rFu>PHEA0zefWY;Q+rAgD0lTgVq(AE#uxdAB=Mg0y5Y6Q3m z`IC@&a2`A4UbKd}pdk_4e|~7uC!7n)T{lMLy{&?Fj}o`@=Mw6B7ZUGxhd8zLxqO-( z+k+P7=5IP*;kAp+t@>pAZnWLSQg6dI3$%X3*KZ(Ex?)87vF~h+A<|LKIdj%_zHy=l zD8dA1%7a>QYAfADXg?vP>2eWsN!<`5Ey#^0Wk`BDWr(OO*zDF%R{Yc7H((bNoH$_Y zVbcv#oekc=Wj%^K9vytIw@*vzQ@~TDGw@r#iYn` zZ%6KuH_WlU9+Pg^6KMNiC5vXe!Op^r8wuBp&5K}{k!NmUYm)%Add{gQoY4%2suEug zG_}4{C!A%uIH(*_eG5wA$ORTTd7DB;m|@K>GH$Q|k&AennUag)>OI@Np?WiF2T)~T z182>ec}rE-N1{;1$ZCLaEXJLlCF1TeD03ov)-K2K8f|y9(SC}xA3^NJfaDKD^s8bE zi4|F{@K}^N8@|LRx)p;3rGM=F@W?ms@HVH0FHXcOC&eXkQtqrIuLU0NEuCpJ9MXh) zFeh(zSW;vAH`%3_bgpbE^%Wy??!>J>#a*{~b&fD~qf($HQCbj~$Ati~*oJ4Pt$&YCnblK{p9J$`Da{&jB7FYFfVOnh6!-Gh zEmI6%NnEo+Q|l4=-o9vK`^xKfjAx0q4dW`%QzT=bs-t5wIs~w}UuL>7bF;|$7LuA& zZ7@!q8$D^LS2T}8OMV-4XGGw0>yyefXStq#xDA|+BmF9bI7%tf9-oI!Z z?#%jCJ0F@a((lq{XHhtr93xM4%zC7elouSorIW~&>$;Tnl>jj=<}Ksi?rveHTG3yjB2(v9N@SHd2PX$nI-`f zenhl9lFY#uKoxib6DOmnvGshZm|*UCUFI0$@KnM;ORP#!ooPvA0m?`6&J z9-laN-fTCMLJBq8gv+J`**m(EROcD#INL9|9~BeNTTQ|C5$*mnbX;+^ulSkF(-Z370hTaQ`K1wUeuHHuofd61%}w1_^+bZQ*eb zg3S1?&MyF9=W^*UB!{LHqEj*}AHcrO3eT*&@rARIwyK`ShIp zSK>CL&Nf2b2%C|U zk_T0S+_=KnM~OiJ7_zv+8RO1m;6|b|@cbNRm(P@lhLZTP!w7`|ONjdYmH`Et>q~rx zw5m~2N~C}v;nOr#z6VJ_YP1y&TNTAA{b`YP3OURt68hj-_N)kQ$0}6YReh^oXaXYk z@EeqD!Sk1dfsyOev4+juVT+yCaT#s=a8(+**h5jAOBuBu(gOX@bK&F)R9-WSw-v5w z%0n3aBESJju07h~BJE+rQ6xFIXfP~2NuqrQ)y^;TTm!n?ei2U@=|wKtyf5k3PttQ$ znzveltK1L`K5cf&vp1D_XXI$&8tNRb!^u^~0fVNrdHknr;%zkdoEr~0Y&3PR!BnZq z$0n5Dsxdcm7QwMAWe0K{MJg0zVokTxZc4B#tnP7rq~N?P&X4&fla;g-p3?j?U@WI+ zH(WexO;WPIn0#v$_XDHcDGKz(E+#)3Y#jSw+ZR77iKA zgCsTn1%YlEJ4kigS_-D>607QbN7S+;e>qmk42oO4tEBtAH~xlJ>>%jfUhfWZ2I}Cl2iLh z3sW7`)Cvpk!jzHjp(ro2J72!W0n_G4EXeG6hmVfhh)*l@1v0>0A>+ZhAgZ=accpMp z$|(yJI|v2y8HaIInx*|>7M3eFv}dYq@v`+AqHv~Oc1kCvKO+SKPp{VPqIKB;7**%%5zj z^G&wNEEP~^whES?cVp2v_MCFG74<-Up(*ZV*6FF^;zrHuoN-gD%zSzCCDm^xo=^s0 zu{&e8>hLJh_9%4gm(@}?SRC&H589Buqr#9Y)cKTeeNSjRNJIBol5d{}laaIbg7v_w4r{>M~N7xJ^ zj94Dflu!veYMXrI8Aa9bpl%W+cq0Md&IOwiN81ZNk?2>|g!dZ}Na@Hm<}E2p-D_;5 z0$O?7N#|w@c~Rk^%A1DNqJ2|Av`E#%`QNq%xpN-M>o$)mj~%z3;}W+RBYnK}l9pb2 zW2-?yEms<;B3buIrU|;mMZCT1=9j;^&ZJLZ)i}ih#Lo%V2s1Kww`@IH7x`QLcu%P~ zjjX^m9?hZ3nzgx5{U<$;7=6%^z%P713p?G)HgF_`P&gi{T8nQOu zslhBg(qUvZT8Uv!hop#AOMi%^4Egek43{*sg=J|WEaF4b4n9WFPae8}!7lHkX-^#; z;U|Qv(%M6N@46k_sYi0}(eN8zV-29#RS_D0k}EvG45CkROqrkDWUT6DFoa%es8WNT zDC@G@+SKmWfwZV#w|K6AuyJo}lla^Q5)cygSrkqqN)!xA6bVi!2;^fZNYNI_kg8S? zDwZvu!O(6zN{|s_AZK+_GMFkHqo^0-z+scLF0CsX8qO6+fHI@+W>Gn#U{ca7)i(BMzA7T&$Am&j zP|co{Qc+OhB)>|8d*^adbXrI4>@-r_T$M7CD8~#6aIi*(kul6FG{ahi;cc=j<$O@@ z+N)GvGXj9j0$ye!vRAr|HZN2bHS~un0Jd;G--*NcR`lR{BvAG;mLX((lRdtqP#}&9 z6is6s5&K%g4PdF6M+i+u*fUSE3b&IElp?f2Hc^uKlQxPHgo%2XXkl26B8SNd#ByX$ zHD2LtD40b_{Z4agv}iVz3af>a%0Z*Sew?;ZZXnaj=^q_C(_OY}+#oluU z+v@%kN8v*8<21}dvQ&Xa|(=c`Sosl!A*;JR);kxjhN809hG1vfY z(U#Nnl$zznGWk?B=6#wz$Vm0wqx8K%HfEs5CDU@JiamtQgblD^v@-J3)n)61`@||m zt6fqjLTh-8+B90tBRy-#{9^5f#<_R}WTPN*RSWDpP6P_iYiPL6q%6;CWI7^^wg8pW zA~nADI!m-Pw7ZLlkdQiI^tFv%EOvtmzdU2Hdt{b8xQC@~lR)O~0Ykgn8^}kN$T=-@ z3XKMA9U6T+8sumu^Ts{{?lFc1eftU8+V2yH+s?iMn#=D3IZ$(FyzXG_LMmr8h{_oT z-%;OHbSTw6kR!g+v`jZf-CZQkXU+T?Odq2sdB1}PwQBPzX+7N^31?&(L3mhp%hBu2 z)<@itzJ`cVO2RuDmXR!+GDqI+T*8Vh{p$rCd&{4v`b+}vh}-*g_XukNFP{=-`!tcm zBm%akit`a?6oqU6>ooXzNYYkTc{Oc3W*@Ub;x#BV3&_!nWtpP2^sttCm@Lu6_K7n| zM@OQr>zU+h+og(OAP(j-5_`;d#et7x746{MXk6Wnv3&4v^km#H|KMv1) z2Q~@`VKfqnw!~g!?9Ii{W=C;5^5ie;g0JybD}@& z9^^j%aAsp0f!90sg*8O*1L-zbkbQszY+FGdwZ8ksF>0u)!m)yy6sN8+a%E_9M?{E} zK*Fg+Mbz@ZL;F4*@VGF|JP>taTw%@WsOBNh_chI@kKamlYu_d9-hzXY7)cd%Kl;=! zf!Wf-gjI#U>`GP0{dA>!>rI{l`>-0q?ta7UYlXLLQ^`xY)F>g zPHvSBr>jOr-b*wnGuxM5rtQfrFD!o$+h^=O*w)hdZY+!#25iUU=#&Zmxrs021yapG9=Q^Y(-H884i08I++V2#{4a2~i zuy^G})zR0~a}v_&I+K5GAI|Y5IAH$=d0b*wXv~~UvT}Onl?npGqe!zFw`U_bde4RZ zzg2oo4u9PdGs3K4%6&>r<~qay)2PShwMEOWUVVlTw#PsVk8@MpG`mQxBlq&Of5=TV zlrcvpHhNuCzn~&<_|15GN^{UfK9`P=RMio6agjde(aZ)-7{`WWzS*UV)iYpG0{d}} zjqqC|j0y%04-nBJL&kCyuX4z5wCotKEXeGF`J^&ur2SznGzm)DU?g*9ueIoLH*;G7 zKH{=M9-<%jgx>2`dk6V)YuxG@87-K851RiQ=r~|^qR%i~eK;bGKr!*qkB?YU?fy5u z%^LcW0AEXzZMFV-MHPam;%_b~MX`KsQ5CjKy~s}Gr2)diXjCX8+H#w2Y|Bgtva~X& z71Gin`A5_2b@G$W+D?ybv%Ps`!Z;(J0fmd4MiTQ=jEIgPwz;#>I+j5qHu7KMoow-Z zEsz!3G&-SF`u|A}@Yt8^a}J|`iYNQbNcR#g4e!x8S(o81CKK*GQ8N`pT^t39D8G8r z%Y3OKwA%=mR(s-Vh;0#xR&x(4J<&p=mksyb#%zAT0W(IB_=jU0BXM3WPG_)U3srVD zIgx}H0iSORHD#>E6Rz>rax23noqA`5R|mX0T2fdFUf>Y(c#G@>JlD7GBqjZk*}=f{M@fRXqz%K+$)w@Zus(7nK09?wzn+{tEM*sO*5{g)tFl? zO|Y5=v>DbCE@fU)`*Yi=ld_d&;T<9NqPD{(=U1i@Y@8eXN9EmF3-3(@0g5kYzhS26izz8#C@yJpc9s*(2}nu}aSuyg{q(QL7|Z1C1By z!IzGgcm_MVgZ-C5Vgo4*bTQT5#{_I#VVjzzEfTwtD^=y|oOZn*fm8NB=10RMzhI$y zu5&6;(AKf=(sN)kqt2+dyYNymf9$D1w!Gk>f`Y^aL^R2Qy0{atK5+I_`FBIn$Zg!NvO;dGRl=5N+>pJ0@F-7JSAC|A28i91o^oyW#oF1t+2E z?%~#WU(3$i4Wavff_9th2b6${MurX6Uv%47bCCvW;v)aW`2SX_#1*GJb$d=qL$QZx zE~s(DUu?IVgq{|=oXWZL3f%f03xf+s5>||40y?59Y+s~>uLad4sM$MRALYj3cG=KxtOWWvhDEs*zV?5f9XGxl~vWK{Rn-&Ms{K4R@h2P zaZ8ft=7Gvy&t98@G@&%*G2_vm&)8u9ozhvg z+a_J-)$6BZhq0x>00bw;m0 zG{w!DNeN?9PBN+tWI(IgZh2JmBJb>?{#lqba{=b}-W$^sFd3tA0AGuW)WxNKcd0K| z@!5`3M6MZaF!<-Wd1f`D-yJ!<=}Bl1{ch6`OvdLjPEy#*Ndn?WG1vd&@Uu zSC%dPr`NeQc1alCwx%DfEuQj&1SR+tRNEFFhoFUx*GI&``%{q1;jep|bX@_r{40S~vEy@bf&Q!=Ay6>zIRA8s z17!+(BdS4>azi=nHARY$4yyJBsB*?K_-jjeX4H3m#(vZBatwGrnT#y>pLbTdsCtxN z)$7&Pt7duwJ#L>6x;qXqbv91>(;?LC*F5jJu&ys2A#L8XW#15d-b3);K(_GH9OTH! z2NFV#^wPBIUQZW;9B;wmnKgaP9Egom*WndW|93}Qki3rcq@^`SlJGhc5))ip$(T8b zq>ZN%yp(kZEh>E?VmSI7-|4!7#8KqwrK-g%sE8G64V5+W!MNmgf`xSkVo;`HXZ5xy z!yE9`+TdA0zfyofx!0d^GREp$Qt(Q2VxzSCQDr(c&_t1>gjJ^y*&U{?zP7XVHwD_b z(bI22_;|dVHST_hVh@_x7OmkZp7DLsZL)JF(CdN zHq6&yWM^R^fOI#mB-3g;7});n(#UH&t3Z6`2O^miu`)eOOUj-`l)qXMy!T#WO~6ul8J;3=I0fi zJh0gs5KP4~2qq&pl_b)}qwyZry8VR;pBA@?`-HYQ9Y8OkkV1+Ej1r2!StFwQxD2t7 zwNday+)-2Or84XCn`n4Wy|aCczwStxUfl|YmwO$H{_If{Yygw>7v6%j=awf_xWm~PS z){FE#?4aRpGEEN~%}~tfv^yM57!{<{UQzdOQS(gy#ZhlQ2K|1tDq8*~=A)TToi$v> zw{X#HcSs~s$=tHx+Q4Gh*q-GdP0bqN*vG@RdZv3CGG+s04Js|U$(q^{om?GoP4|1J zU-1eIu4?8`q6_e7WnOhD_O24Z000vCXjMkfw!kJWh|oWOK7-odOKJ3fj@Qce4$^e0 zfzvYG1~v}v5j?EFW?iqET%PDxxraNEwimqfPiiL1ZAr?3Gibex*QLfJeDr^h8P*#p zGgGkF)socpW;_tBpByu%BxLU6QsVpqrn@digxS%=FvjUI4)`}do}7mco(Guk4Avo_ z`?+Nexb~ZKz8q#e?ZV7#xfk4UZpiz?{{rD7Z__6Fe`LgPHs=7m-s>H@y@Uc_KWeri zlz7*>;&3q$n!`S+MDkzN@bP(JQ4o~OL#1VTSybO4!*^6jy{n>HP{{u)$allxoSFsF zE+Q2hkzJ%SnYm_h;43F)Sk;AgI8Ym|%)GY!R1WvIbnBsxO<92f#AV+RnQh0_bt8u% zL_7FspGmW#MCFU}8JPRtvwlOZuZ{lACA*M~#bl!Rf4Ybgd9!V$%au!K;zRjjF5S`f zpO)(5uVpslY2506@h#jL)+1R?rx3H5$v1TsoH!DU4sk~%_1cPSG}OW3?WD~8&zZHT zv8&225ek!`zUU*D5I*9!K|L8e5^0*FE_Q`sX1hA7;abUY_ z0Wv6!@q{vjNYMhAlwPW}zHrTQD|3M)G#eN$=QGBJi1kKJbL(NlXuC7}%uv#5^(M|O z*R3u1ChR56m@kgLdN4N{`sur^E4ZRs>VVzD5Xn{Hldf|$XZe|yiz;g1&nFw_{d(7xm5{})7uGx&=fBaGa1BusX|WR6 zh{^XEJ1|*$$>UFzHruOhXT)sEqp6&**0v*&oR$}24=Vn4h4>bOQXzaAur(M=UJIT{ zR-DpuUUTNI*tYd^jiP#$zpVj=D(l%TZMG%8A2;vi3ns4jV15vfd{(>N@nE*-26J`$ z2=$NR4*Bxy>py~mGGB9=t;zH37a=231Cd-eNJJuuxMkQ;bfz>76SF)qA@sWAAztF@ zn@^(8_Sy**gv}`m*I#+T{~viVQp&X2&iGNOIEUh5zG_*0AZ&7QwS!G2Gh5dAMm7Kg zKkK4TZT`&z&Ar^GJuTj}Rziugt&o*b2u|ixZETO<{JkT8u}4Pq4X*oo5guo%vIbix9Ku~IeET>++25D}AMyqO*F5E7 zy%HKAA@y1ttKm1)hzlf-@;m`{k)!7Vo~@PxFQ^UXQymK3ruL^hXu|liLfA`pao|7^ zJ4T}kGc>sWoR+pqGKpn#eNG-tRGqicJVGe6R+al}WPR=|TYvpulebqgz#bLAt<~SFMvwE-cM)pPm>DR@XatIC$emL^0 zKXVlAlvhK!BS7E&G!edS?GG3f zzh^x}-Nj%3!xN4L*P|rD1+9k(|I4q=_-KhL(D1H!8o{_O)RG za}YP~dk;rrdj1#<`@_=l6q5I%x)=$R=_yd6@@PRxX~CWRHh-Bw^sqN*v(I{*-I=Tw zHy)kfsH$fEzX34&9VWpX6~Hm<>Q0F6sz1kw>O-$md|O|dg%c_n1j7_ulz@Jn_%?5A z1(i|}M}QwgGNXN@gWBiG`-cYSoO9hn=5q~FUCsq1bWzrNRno-Lt*0eji}J{OHT3Lh z=FJKF6jIHXKW;;c0dyLuj z1q{i!Gly;X2;DZQ*19JqoAHubI#Jv+ceT9VPZbr#)g(W&S7P7i7{(l4RSN$~bb3q1 z`dxi)lHLYvd$KuSkww=n#5&ZamvU3?x+a#J_uYO&Hbn}U#iCSIx!9p+DYv2RJ-+#zEmaXEM9?&p_aCNH zyv2o71DiHDBl||mS`kR`x9xXx?08CDic$Ux!M6BFvF6<;c0*0E@>(ZyXKZ)L>eN1G zTYSht#$8QK7oA5LKB(3CeWM%GtorXO0w**zF3PDK54Ih+MW}>(nIXZ>Ba6qb`!D>^ zTGLXYA%A~b0@7`@;5??)AJJh{D8;P?O5#Hc(ua45O3fkpnkYkP+W71ULBS?<=52!H z3=x|)+vmGntkUkLbFAR`sFQA=BzxR57_UbQ|L-l$q7m!oZWTUmfnS5gZ`#>B-eTkq z2_bLe_J1my0La>jN7w8@3EkS5hW;RqEM)4d;MDBMGs9Z{SUg?g<$DJrPUE>#pFK$J zZe@S*WzIA%9w#%LyEzv=CP*${;6?Rr%sMAa&0Gp& zCm7m375?vl&ysPYvJn?FWj*E^Bm7Ii%5lp8T{H23`QE+dm8WGU4;nPqg8-&rFLyX51! zH=7dWG3e<7X=GgXRq?Dms@#}|Z^rYMqHXI>6f+w9GLO7O>?pTcj1Z9?W)=DIfns9@ z1euysmq>p%k6p*L)R&pekhZr>LxoO?N+NZil_HDIJ+rNn4YfP-FkGr$pb#}*_f&N~k1 z(<$V-^k!klHwY-CXXoBSc3OG68?oM#HIey;r_r-RuZIQV;sMbdiu~7{Bln-thdp2j z^)29#fdOIyqNkGn$tOk1nKNQ`CQ}HXdJKJL<764?j2gr!%XTNbw__6x24`6x@%l#) zx$F-6qtP62dEM^2xBCP7UFrb+5D$cLJvAAW|8;%o?UN9-Dc;%8aWG@xMnI1vY2trs zM}66Dzw^_hyzRa>zoI}!&^A)bHq8CBs_Y^I_}9%jyGHh)ev#HxGU;E9jP$@~Uiflh z$er#{#C+XYr{To`h`DZ!_21!3EAAN->@@%=ZEjU<3CwXc>c1D$z!#7~ zZfQQPSz?sU#E&oe`_hA+i6RAxVVI!+mQ67LGVn|N z>!F*dWh14^jz5l#{=Ph2UY5=QJQA^7B7i&vp9KRy!R`vepUY7R z;-ZM30nQ-cqpQf)@V0%!H6ttX6sn#jdS)@bYlM*RE%&5wODR|t%_U42fKQP^R~Yb2 zX5xV2exa~FH^#E8X9Su*Yf6ci1@J`|%-X*oSX3tkP0-Og^p&8G2q?Q?;{2iZ8)?_Q%%BF%12O1p)QNKx3t5YZcU3X3s~A@5!V1Si&l+Qvo6>AiJK`)%nZ$g= z7BFNAM5#TX3K~+6xpd^m7$a&u4r#Tt*`sBUhfg!Kf2(A`cmGB8B4azEuN@!Ne}bB;yA zAjS`Pj#L&KHJ^pO22<}d(0>_0AE@9uVAodOExa<~38you!OV9?CNb-ez-_4cIVRv& zPl6}~t7N5s@i(YSpU$gJBS&xa>{wsF-`x*Jo<@|^F&Kyhiiq{v`U45xDy~p zRZr?|ctRAI0c^C)9JE?~Je5ZDx22`s-3_H2mMVwa(bBzo(8sp3Xx}`&OF28#6Uyz% znkoYYi>IJiWw{3YRyQ?Wx=s0*K~s4<0se_@TKIds`<%xnUb9}>hrWGC{B0Z4H?C>w zhzqpVfG>$gm0y9WE41E6>-JhqM`9_9=FfxaGZ>Q=cS1j>3G%cjfoXS=QXC)~{AeD3 zc?8n%$WZA8#wAHT>d>~8%?I59{)g5IaUzRJXctM>`)dw5kHvU{7Toa)&3Jy_YS3Dv zrV9=ZwZ+EHDP^x^M{TlUFRIwKxyfGI5mC1F4Fuw9gO#Qn#0@%Y3@29OMiO#zPhB~ssf7|y>EUW)%Y4zFCv);Fale6ZFbHglY zMxVA!cP7hy+C1^xFF6!=CC)2OPzY~P0G|dJ{uyI1_A22ZxVZ=r+;Ed?7)@6c3w+@C zp@MhiF9`8Mg+=%t99u&~h;1Tm7xnEPdd zcm{DC?k&xQhFCW`zj72;(*SU)R_wgNpYUt|=nLc2TjTMMPtd^q1K~ zCAajVW`KxVdWjjQ%P{j5b0aL$W}IBknsg7&(acHn=ULeNe8@KC2-Fo&lJ0znP7)!f zp=+i|HVf?%*Yur=6{|>A_-Jm#rx|_TGzw^*N(RLLM;3DADfCsr$epM?t^pb^VC?&D z&4N*alL|{=#hT5sEn4E(kv`&QxZv#_P!rviTzbQx@i7+AP0Owkyu{nGEdn`yc4Q)2 z?2%rnZaj-wT#9YD1%_T%bYt~=R!oi22-`SXbWH@4^EoQ5*1SCV20uX z?F5#(!qRl7CTgSjct9f^XC(&Z)t5|F?Dok9M5uKkbvn39hX3@R$y;Gdd#C!B-VBCxEe!Loeeu=k=y#-?2a zxo@0$NV5An#CkyWS9+=5u~Sfi`UNi`{K{(s)f-cTRQ0$68owbXJ&7|+@%Y~}LRp8= z7VV`==GpBAUS^5uvHLEw-gqQ5@F5|u1WtQo=$@>v-MDyBia?JJyi08pM(v@q8oW4F z^TDrFgZx)ROfLt0^ucA+C&7jJ!Flw8vuVS?C7h-glrBB)m10mN)B=JaCkQeYf+RjT zTsEBT`dMWg_<)@>+rc3dG-#}kT1UE9mpjP9%s@*`VI7_rXcgZI_Da}xm(Lp^ax-Y- z6eVNLaq;;X%Kt~znu?bHt+*}!oPWlz@Jsw6KgZ9AZS#|=d;CLwgdZ&bU=W0}?$wZ{ zV%pZ9V1s0Z3e%o0`xUGBR2b>zhiH3@YI4QSG$jX{SlymcLQI5)=5%QB;uhP9>_u& z8eQok+Od1x#izSbKX5Ei@u8OEUc2sK^X!y;2MZVSTmwI{_odY9i3 z%!zWzF%TjRtA(t+xhfKdvm&68jLSYNrCvab8;Q~`U)rCb7hOoBdM@TUkZ|8Dm zv`V2Bq0nq>OlSidHft3Y1GyDd0H6q^kVsNLsxOOptq6odn;^$+p{Nl|dV_~LZ8Krq zV~N@&x}wtYLy~(TLJvC7iWW5E5KoT=eP#$DKp}G0*ArOAQ z6Kt44L=ZTj34tqD=7;=*Ie`_{D$B~EFnxC~VJha+ke=ZRSZK$2I(79;PYFNjTpa8g zdB~s?zhP^ApKAm`c%Td?*b%3fN)r+={h;S2!JEsYjjR&bxc#0hhc3&66w@k<%uxm5 zZEh1pRzMa_}!-MjMW<7>{EbaOqV&;oj5bm#F_w;VYW#;oLr3takUXcdi=I zcwH%-G|;CmY33F)g$#&HJrLFB`Z)dLZ>USs!NoQy%RYr`Nbk7favE235~1a@`J#oe z%Vo-64XI1(+k*56ufNs3ry)1l0W802DV!-cc)*~nz{#a!s5^cK5rFFfo<#OhH^ zZCJugaI}UhQ|KVKLriKk`XP(~EsG)hKOSNDjD4Q*G9wM&-61$4ILv2DRTTlp)fzYL ziJHui?@&Xmm(3e}0NkRdT_be-sC-kq8@- zEM&O*_KTqS4G-fUdlb#ID>@_#fS(xC(15Un1GQypJED20DGY7vWQ^G4e+T5bq4@jA zN4%5aN$n7#z?G#v2k9Bh3@{!>vd*Wgq6&!>czHpaOuDz3USwxVp+IEn*-udaYK_096m{ybi52(Y3N!Lp`2)<(+ESu{MOSkyn9I8dRokhrJC z7=Yi+Waus3n&<(nLpG_qU3Lm+x7ZIFyh+m(@-G*c`bXgBKc^t{fI3zPxs5xVR*DWD z;1b=Mn?)NqIrF!kQh(i2#rd~cQ6WvoBSN!^>yjurvKK2&B50&mq&zpODY?a0FFK`+ zE-M^6wY06OKsMFw)v`s{uxM8U@)xMhkV##t^y)j5G1#B34Gl3;X+({mrj(-Efvlof z8_0BM2ZcFwwNz3)ApH})VTts0Gw;;jjD!QbA>N9e5yv1XK9m?}%`iwj!3fCQ-)Qx} zyHKU5wpcy3>S1gO0gp0@IF^{Kf0TtYgPbsIjs6G*1b3vYFIAghQR{=Y4eimT6?@3J zc^+$Ua7|nbh{538l9_;et_$@2A!IQh<5QUN>Xf7e2Dw`%NL^Y}f&zS!7dQ3Q*^d~Q z*+J{FVH(c8w#d+zcbFD%9*-IUT>8WScKcAD`Sh07`Srfu^KYZBgtS-#p?T^GW1I)V znOwlmwhSlobR->EhJFwBX#%Y(7n`Mml;bu_sT&tM3q#n7ohG zTRBh&ggGG12c(yf0@9CC1Co0*mIowlAbo!qf%gJ^AaxZ3;N%l^Ns9QyP>}i+1sn?? z{+N(Ac-sp+W`}rSoGzN+JaubiO|WA^Mk%G7LPGmy>zeohrRtE+T{Qh=UG-0UCi{$>{Ep;X zQSurRMe3E9Hlz0#~1Al;sCi?1!A)}BGLj?v0kAR5uv*b~Y z;ZOz{b7_!#8X6%Jg)HRAQwYU;C_{xh4VtuQW6+^XkBLppUesc2cUHEe>^9jAIl0Gv ztanD-vBv4}+=auaxe)#mQXQP&%!MmA?mXt3%bk*^^5TupH~io)pb6S8VM|>EBSfe$ z;kJsfO{DFj>=51TJeApHcf@pySj35!AW@R!NWq>+jbd+$c^XK(O}a!TvSiDVdzqKx zB>yW)vsQQ~D8O;+V*q%{PbzeF!Hw>qEkk#>p%=K#2I?m~WT6weZ}sBqhP4npGg3Xa zX|$B28M}Inao`R&p(f|kA%}rkd2lY`kT75U-bGXtt^8Ez<7~7aYP}PprdO`91&6jCR(CNnjA^#S(zj@ySmWw0As^^?t%oR1TU1*(TXkwB?Cp0SCmnNQbgmERa}W*&$YAdX4NMPc*@{zx8eV`&#OOKXWk$0r zD5mHN7NXUdS_Yct`sf$@AfF+`Q>cBCF#8zc!-s55QN-{b+k!_5wj(MRg~@L{(8u2m z;l$v8ad-EyhuY+L#jdJRvel#G*nN*CZ%(wFU{_zU;ms+2U(b9Y<$7}!#MP;iFO21c z^GU}di>3s=dUq4{@@7m*a8lbL?rRYIUA=31n3J}979jHzx`Q!#z4p@b*>!*~QBRKX1$a|wR-3I2 z2I?R*8V*_n_5(|31km<_88()lJ%uR*sXQoUI}&x|uwiLCi_n3l7kQ+ULUx_|A(HqM z5F@0NsJ;e!9v$Y*m|If@r2CVWKo@2?d`)3fAF#(jlMGr#J`e~^fXtIYdy(>Pu@lTA z%`}osBql$`7*CX`gd0nc8Sv3V1Fm@}=tDnGgrtzvJ)*RRdcCTs=#t1OjC~;AniQgP z9%DA)77%1E>r)R1umwKtFG8q4scnEtaHX#FtjaUSKNR>O+C7R9dCx6F>KL=wsu$R0 zU-jWo{j0=800a4>TGU`JLL&$s!xUO-?K=|k#|FjiZD7PR6x}p75-F$UF@PUn=38)c zPN*J^EJBcFic;*|((RS1;fZSX-cwlqFa<@KPk2W6C{KQRZvmqkpijM5v6oI5R7au= z6=&I?{arH-6KxqK(|)q_s=BBR)m@M(%-WEt?vmt|NNSEm=1Mqn#9QN36~xLr4N(#G zIh_#bVq2A%mErEJ6tJh~y_{L(ojA-YfD26{MnBIzNwvb%Qpu;3Gjj0Gr;lVB5(pQi#4H8(lwj{ zLHtwgw_F3@eTzQAJe~Y<{+Wb+%)pI~{p&NyeJkv{jh-s}WhhtL%gLK{MoHhg;>m48 zV7{vzK?A1{GP;?B`r4_0>`?_t>zYcVOlruyp%hhewLz6?dQESHux8XNwg8|JKgnxIW`I2vE&*d^!xU(9#N}2c+c_0@bom%EkOCDH zC_;{8-8YMf+00WObxEo9H56Z+SXHGc*{tV0C$YsUtf&UypNX^(GBKw^M!Eg1DWXK2 z$|YnVFvY^4P7#e@@mPghv~mkpa!a5xSOYJej0+&gGH?Q! zJ!Jx=ti?e;!3?N}q9M3I-Ce7dk=49!jk+IKq@WZk?_Z<-N12HJ>y;4@CL^NF5PeX# zAsCa`0X&*U^p~cz-f9EKgf3OYB2FaK_SyP2QUiTm_2;Wl7cA5>Jmj8W=wfTZXH>~U z-kCwRxuelxp;b}Ch@l`-2o;e=*ftfu*w9SAh%%dY&rh~AfZoj6 zJY|Y#-ygyu-*tr#M?^RhWmMMgQ_JX}EO-$DcrYRhbM1eI6bw+G0t3`q;DGv%xdzt- zfp6-2TVnp1k!RRAgbY5=zgK^<{v~*AKD~tD_NC7)JXJ?|`RFElCG^6KepoRGJ30^) zN=)(j^5ZW+qBJ3Ak8-|f@WT3H=!Ju!+jm$q;_YsWR{V0n1uy;LtkvqX2V64jiCQ;n z-_88XJL{w8y5mpnBqsa;d%Wo3FmUFKU9Ro$w^^gRiM;ms;(j#gCnxjc7J`D**!F`~ z9Pw%JUo(g8aZH8NF6{M`ODg@m!-?@OQr?I{$Zr&b>wY!oh)(wiiH&P;)m;Zm|DNBx z(lJ@Q+n}oPJ^I`5$tSn$*X;gWu4vQZM^oPW$1_)5^%3wZfS*?f_!Ld5RXgga0|P)N z2o7%OA4r4*&pqE=7_z9wWruxm*MQ$m`x}craN8T_lCVEbtYVLhH5Adw<@u zx4^ku;ll0Ea3@sX14FcV?Y(g9|HvqfT*?Ry3$bcT0fD>ww8JmfkLR7^ROvNQ!!41d# zf-dC7+&f11*f^v^J~aQZ5TqlJz#^Q`6iwuTAJI}NOE;-{bCE+4HME&!gKdslwH2*m zRjYZ#GoJIJH%~rtnaWyjtC~tyrsHjNs&j4EV^I@JqQb;!U+l;J)sa3}d+^2SGt+0M z&rNSXJhxcuEiE5dvDhEWudFpfw=*CF!0VxB&2d8W>ktQbhx?y*?mom8N$9#Jk}w;N z^uNVy0^n*r0r8+ph?WgFuiVfFcs02EE_8=j{s)fGkaHc02@$k^}*u2}l5GoFXQYTic*H2<$`b ziF0HfHd~+(-X(vt6^yazDpm!3V2|iZBf$vCFCX@P{v z$qsw{02<73oh1_8B)D#*0IU`y*s0JcH)=<C;-s&5(NNy4ngGZ{rCR$dd#`z zxxXx$cbAyRD_w?k8gSVazkBO9y%r!Sq)3yYNQp8PblMnn=wdQq%8WS+9JcJ(<8pA{ zpb_ug8G)nCJbB{_6l9BF+wBl-r(I&CNVQj*44LxmldnLrdmbD1PKTd8^};i&o_Mf( z9;!0sPd7c<4=ww{MeXChU-S)7n`+ZqUGS5u2v9gActm7W3S`NVr$wCxO*DGg^syK* z@R}hTmaJIg*(9ASC(hitaO1&Cz^?hzju0wLI3K$uh!rPEyf+f%%91Tdp*@NiOCI!S z9T>dOTJFGvNu$P$lhF1+7D_csBh{+#j0UxY9K8+o-2xV)Q;Uv^Vuq(-j(?DaS=-ag zh!4e90Nm!>s`$wT84qj#Wao4rt0%M~~ zv_NhY-++urQ87wjyiN$8u~j6ZsRCofdJM@-v>2+fzst3Gnjdbt+Bygg7u8`ohD%02K!_6ZP>W(y-E!JR zG#OM(Tyt?FwtkjbNZhTr45lgcRJ$fN?po&{-K)QXF-?e&SOY7xAQA%D5RleNE6Ipk zr{p?{GWvXq`HYm8k3g*vSOwDJi$|f6cpxH%3<-eCl1q07$wrj#ZuNwJvsc$Cx|)INT6 z4OL9if(`M^LRzK*8T;(*yE9K2UD>mc*PVropLpc&JdXx<#}Xc(I61N2OEagRt}WUy zVUeuLjY(P9B3?R?A3e)+6kw(fQ!CH7mI}e>^ab`glM1U13){$HBa>@O^Tsrh#RmVL5t^red_+EaPF@DfH@^VsVPL^C_6z2N(;T_uZ#sWx*>xp7h8*&yf)Sx252Sirq|jX`w8bd!@`wJQ_?{#*gy$WgOt))=TNJM$WIqZq_G=^^G)T&*86v zvxhbj&Pc$94QkDeXZn6VHGVz(uem`!Qv1VNqSW4R)oHEzJ(EktLi<#0B-0pj9_`UG z6fFr^l2%<+w#ny{^?M(FdU1npwp@GXX4iw-s+tgtTw;P2{u)*q)=OMfStQ9{I8lOWWWA zLTt)HW*k-&HeBh-cUWEpVaHW(RB_8GbTPXt*UO7GvU+5*kiMMX@%H*$NP3o6F5{0i z?NH@Xda62c<(1;n_ko%jJ-(x?jauxYrozrRw1B{r(Db}L*^HQ!_&*dpM|v&eCzXfi zw4UxmUwkK@Q=)}-De7}a{_fffV6pXgi(PrVOXx#PoYiFm^1B6RZ0_0vrWOllXY=Qg!5+oWAwxz?)Wq6y<% zefLMOj6+?ZtEp~`lu%FMfwQRZ;)`arun0=-IzjMC6rN23p_3% zYGxF2K5Y>zS4)#^Y2pfu?VVj_oLb$h9Q%07mao(8hZ7Wv*+a;>?TdBzd&jBz*Rf>< zi*NcZ`e^M~^0*B=a%DJYz-KSs9ajzY_^kGAA#AkhV^<@4?Q!45=J)1u4;I}|)^~nT z9jKOQuDEW+2Y)Oh6jInnD|*HXVyO}F(qq`Apfz3`ckTpVZ4W3S7<7sYVr1<#OT( zQf{SO)fI}4gS-JLi=~CNvzV3=jFvux0VFI=M1*Y~6~{6fWy3!!gL0d~*8S7>KMnKt zRx}Mhn=R08u^7NetIBTL^m5`k(F%Nd6`zqXkmlB1FQy^!c zQ{0TkeCv~5E_zq;&m^eHzGww03f0ohVK|ah{m-mCEAd$*)nn@FG`d;mOk~kco`^wX zXt^3B#GoOp?v7pES+a;K0rdMiP>#f=ORDsmC%n;%xt#E5uSxfPBsQX)#dA_q7O%AC zA!ND1z?{`qWwuLdJ_k-3`8%%o=~N0F>bzlk^tKdfH0K54oJuXul5KA6?^jTL=3?OD zg;OZy*&Ds{d(CvJnkN%ywy+19{Q3-(rp4-7`L{*hu6O=VZLYTSa*iO8UoE@`RFW7V zlocM=IMr&~OG^c~TkUq<)^uQk=FFa#M~CMb)=f%P=?;Z8FAy&`o24s@ki$C4R>WqC z7YhR`)4oOYZ-8N{@V>D7&zb5E*mHK;2ELQ6L&A|p@0apYn=j&et}qrdjZKJx!Fv$n zhA_AbyRs>LZ^#owUwT7X4qliQ!bFD}0d%1;bgY2{8#@%Ed%@$F>E!)0gbp(fGWA!{=<~V7iTu-DE>DZR^FVhtB-mnEACjy@VbWD1 zk<(B3r)Ivqb*uN*%im=vM{>93+%gXfBw4jek`oE|WXiaL4adY{FLI;@Y!j_AqqZ`dMUZeLsCeZQLrKeRbIwX;=i0dAg5 zzJ0m=pQ+PdE;^Cb{(fn0e0BNnzdt(wp6*e)&L3Z3U@bHpcAu3Z8zz6Ha(<>B2ANPH zbbD&I#aanoTf2weF#vEwutRLbuI#-O=#)xvgT27C^wnx$Ga>Yg{!;td?S4 zrZKFQONv&Tq!9fYGqZ;kGHb$8~*h3%g?P|a}KcX zEVP@I>Y~{qDHarV&xlpHcZO@O{dq+P)~M^^(v3KRfi0lfBSZynCFYd7TH9(bpICrW z{R0^Fnio}ts_T@3*&#DWwo;?a%Ok3j$J;E0e8Fbr1U%GIe9|h?oJ7QIwOZPlOi%U@ zgFtwY84)BpSjP+N|bo?Yvh=MwxK`P* zZyougx+b@_ud`uK?10cbq*3epcS2stT0Cp}GQ_c}zfVFel*Kh0j|orPbjo#mwAmo+ zX`{%=WQxqw4nrv^}iu#X~S#O zoph$Li=b!n8IA~13XQc>-QByo@cpHqca`sJegD%kF<0C+QY)h;Gh7=MTJUG+*83N} zUj=}8LjXz&9~?QHbnG}RizwH&J(_rVm<449`xcd|SHhA(ozA#8YL>4VwbI4)(q(O3 zPNS}$+Tf84=9CzD3Yj>}LgjhwKB2ac&l)f?M_O!pyS7_T#97$ylv-pf zvoH`b1@js?YXr>tw_%h2oZq|}9R_?6217#3H&~jQEDdOhQ_1dzaA&w-q3bCzH??-( z3`#@xl5@}A$0Kkp#YX80P^P z@^~CGoxE$wwG2OvwE9(zeXG<9MLjN&mqfMmct*V>kuXh5pp^pq0^c6Fal36SM32wE zU8X76?ZV-81qBWQ+05a9V?e-n5{^G)%|Z8Osk-PetBUItc1O`D-{UW}-^jM&v??5( zYQ~cFT!>{45ny<2JJmgV7ZFHkBUcR>eR4$eRNemSu9aDh^15)g3x0%tk@o(`UVX-J zl~l!zGXB35+=`40A9*xmqE&XA2t+sX1{)n=sZ3aA`7W^K8k27r#`%If$yz6_;1QUs z89H5Sdu?1Xrx#@_2@|p6c9ul7w%uf1Pt=*E1$s%TEy{S8ds&(T(4{1(wt zY{$>4e@Po!TxkJESzG?xtmdu1Gy}T(e>=4eB>|@U(Va-ci~!jAGy-=Ei6dw!E#Awv zw0-zk!oiit|9cY9|HsUO9XG?5rwN#`=zS}W|M|?b0xPM96#Gj8CGSaZigCj7*FfZg zyPBfUvFr9NIQqA`B3l|9i6D>py|M9kOzYRa%U@$N<|e1SgpQP6f7p3fB}ISkaNu4k zSMnxtPLoSOT8( zth}$sbFsglIR;j)yw~RtS0q-i-%%_|&+641!0|r{V9nHYVMM}b(xXdg;K6ry>D|i@ z!oi+xY;9c9O?3_RggC$NAkcds>)}0PAos{SAWYjqV>7JqVDWM#V9c2#GWQ-3B)wb6 zDm#zL(XS-9${e#s+r@g0P#50EN+pl-?CIHxVky!ukH_N(w?$yAmX7K%Q3PbiDI2xVcT4N}v z_+D1%5ja~YFuto3Hn#}7&DCEaz2Lr~Z9UE6JU8;Yg<-R&Vd@IAjlH%Xw!qdF9MsXa zO5Y4wb{dHA(ENyR6U$;Nu%vOhQkUH&2n}EISubTWmP==SV9S4;oYUI7KR!MJ&JIuY z$Gx@_o?SDS9xr{sAB*h=kJ&8m2Ly2=+bJ4K%asv9yI8siu`CJA2J%6m+((HZ%*4{yQ2@$fCOi zL7%pZAOq6Yi)a0y=t&-OnJx}3H(iiS(m&$DaxsxiWVeouSuWxIiwC}%%CGls>@8dP zb7yoZ1^nc@yR^>b6C!VLBVQU5vYEaWJwE20&3TyK69M`&N`gz=0k?B)axd4>MwLN; zHfN5+)_V^(*t3Bmb8x79{Rlo(o}Dq?#WpfThTuJnaO5E0o}MKyqL8#a?2SVFZWA+> z^W_A}`W7_7$oBL^C36M9J2hSCXKs669ge-=Id%sWPqoJXD&qs~)pPoqgrRkiFw?Oj zL*Hyy6eTK74G2t#qZKd2O5CcTDor$(D@+W{1)AZtf7`&;8{;r#rOCryo#JUYhGr~; zZC|BoWbvX{wa66uFYx9fLvLKml*AP(eReC~J#^M_h}x&WT(3rpjk93_s27Hiv^8wSzs#C46d`f9c7AXeLOAO7!u&3>PF`A8W9pQwLG5~c*e5!ejG+YXCt7#!5uu9DK-W6H^t>3;aE=LXcpt6jE~O5Upm zWXv4-uq_dZiCH8E(*YLofw7L*z)5NPm3>&QYH`dd#cnk1$s&mRkJ`GCWN zTM=+P_-tS=`uoLYtJT+p|22Y?5#BQu0{NLr#8_ErL@NCf(6(NGe{aWUMWsPhS%n}~ zmE>`{3+$L_`j4CcZSQirx#|0+KDa8_^X>3uu<{4}{e3OZH#I)r((*#{(#Ct}P9U9H zr-*WPeb@Y6Q`39R3%AnrJh-`U@z>QqVlzpgP_%#Iu4C9Ct;R21yQVZVncukSK!1eH zwrtjRzWiA&y05d0IZGt6`2%>O41MpR4oIV|>-&Nm4}KvX<=)GqrnSE{HUGNSYUum5 zx#_n)@b=%9*^~QNHTpw@=qN(&S?^u%{3AO^sMhaiftOQpOPM|HmF}y(>b_dJRjY#~ zqp0NFqb*5LvVe*Pxkg}Q+Vmjr`Kt%Q)z#sFYOfZ++VxHR8^GGWD6k03mfB0f^;0n@ z!FweUGbNOasl%#QQfbwzV8l>|u68=rjTZxLW_(tv&cfn_%CBSzmno z?*6OQ<=H|N;i{CMw2$v7Z(uvv4dpw6^~r!w+-B+)P`72(T92%wC-(iO3k*~KHy*=X ze#5`S0BWa}7?$|oxQu)34RFNJT)XEBxsj{+hjAq;DT|0Pr>LyHohgKkl zr6(6vR8oyq6^-N0Y2M%BLUT_KiPpPaOvjTpkIiAxX!ZoedRNxNWbUdAZk^tiv%N{R+I%wx%2DnfvC( zkzXE;miDzstgBeCm&0V*2l)2+vvo@>y6)z!O-LkP@!V9Jlgp(! z+|&b8)1hgwbC}r9Qo1pt{5LIV*rB5|qm4hk%aN5?37fIq29at0o4DVqTc3x^KH?)~ zj?O1ZWRY&1P-56{=F2PGw7f`A78Z@v`7{E$0Wr?MT{ou&^8y?vF0(7f2;gjiej6hZ z;chmWj7dheGW3QPI*^cvg#BGs6DcQ=fJdHoB=lA6rFO^~B_hf+hZmPhg^QyU#fW3C zJus?bam6~rEn5Sfqf>jepKhC5l^un+(CS89Qf^bRFmVRCoF%(%ooZ4-}eL@xT z9A8gX3a>@c8M#+}p*YA)*M3)3^<8b6HOLTiNF*_PXqjeU(h81I_Mm;^Kt`K6r7;bf zHVTi-MIozRipf=6JAq{5alxVD zDr2&bfo;2~pTP}45I6=*rUAksGrF}ZgvC~gv>LJ5ELNV%_PO#AJDO4%F>hPFzD$Mu z8du7-P2N_)dQbGAz@D3_7%34C8iGDQL|yisqFy-1k6O2&5O)aG{;l19{|>exK1)0t z3o3nXkAPZp1F3l^f(n+d=%!nFLQP~Rdv>#WM{oz={vokS%+h7gUqx3z*`-%f*OFB% z_d20uwQbT`BX5;%W^dKC)RoLqXzi2U$VEWf!EteReKm-L?vI7agA#oGQ-@B}N=UHM zH%_%R&oY4gU*$C;e8@62o{EwjTWqQk!(?? zS%vm@tj>%VX)M1qz;`$2ZYl{7N#K0oTx( z$e-})1v06CFOvz-F5}}0`RE|3bKvB@*{ytQ(F^+4eJl1hsZBrFV%gF%OGOzV?wrZ; ze41~$)`-5=;_J|j*JhAF^E8=Vf9bEMZeKWE%FVrElbU)5&G(uC>T1JC?sqkq`)|Xh zE$8}%M;Q5$6nN@8G84pLSdUC@D2d@^z-!%7SHGndbEv-V5U9@2mI_SVni*HqcURnE zIcACYR(=oOf&w&5Y}Aaq>gig%)2s%GdK71>Ys+f!h}-@u%b9 zz>JEjMRWcm{;OE5j-^6+7~i@M1lk(Q$`((e%Wq5ufRb!x%XPG&S4Cf+MFzmU?0;3b z^DM9IyYMh3;*P_62ZzIqw#ET4zK+=R{TYM5p_!u9^TK`OOg^YC$b=_K_u(kF`5`5wV&-$Iti5S3KViV3;&}zo$w< z>Rp{>R$Y? z^;0E|{?`9Bt_!T)|MB84#NJock*736QWW!{ z$7iY%;DdV+XYE!9Iq73Q{_kiOpo3AEYl|AxoJM-?0$bzD2=oF#|1hd8b~#@kYGMlT zo{3o|>M}9WzEE5k%1!1{@FkNO?UMrRHm0C0Zp8)3>RF%HqJ$SR&rg4B|CMNoh$c37 z66m6x|Hx0V)5kDyGJnnaK?GDLrjJ32dsy^NPw#I&1>>LC{T_IJLD{JZES(jrJG}%% z@Wz*Vk&<{Ux4c`^ojWJP|MwFH=x1e^usXnR&2s=VO*7t4*c8qWBwkx}Gtfj%d<5iO z&ip4V-^V)UbbiI_zeBV(FgO12Kh@n+UP$`~RONg@rA#JAWkx$znM41B-nV|&vxD4Tq}J0aSz^p%l%h)AHemFC%94CB!jnt)SpEw_!gc@luF0~cN2)gp6r{pNIkaxxA7GE*?Kk8^xS7a7 zo#)qVBo=XsZL~e!6TF!Az#L*UzGU8yF02cD_o6K&SJ%vhPrTA32W&n1oIJm{WyPoy<3_jlql3Z2w_CerLG_xZ{_8st2pt=db?jR#7aS zqE^$!0OMnIDml?@2X*)N8>Ph@HKsj&nrtMCVb6`V9ThZp-iP1+->SO+svP;+CQ+_) zy500oKFGym0qIp?-Affu;AW ztTqO@7I_GH^`bqCW>=629({K4+lxQG_|NOBs|HrZj;$H^pIH0rBJr1YK3NKWSbo&` ziu3p_Q!4p~_#YG*#=WZdQF>O{_j#{Y*`L z&4!v&wRN@Qwa?eyuEW>uue)4-cm10BdzQ^xHneR2vM(Cs4atTT4PyE|H6;B&AY5+s00g_p>kD5OXs%6 z-I;x#?c_e}jma==7&9h_*^W7nxsLe?^H=N9w(>S++h^^L_Rl*Ob|^X=9jT71o$Z}_ zJHN;3v74~>V9#S8!@h|t#ns@*I62OP+lV`ad$5bq#~I#J@@~6VimWg!>6k6J8+RO{^nYh<@S#aXoR8_&jL_i9?c; zR+FA1y+XQ8`hoNh8AV=7ZX|b+ndA`p1qzz7pE6CAP*2mav~{$1=!hU9cL*kcN(Mp( z#O8n&ilHcqk}N8+^A|68p7%Uo+eHVTs%Cp%zVYVCXH7mU_J`;{eh79j@BsrL-~j;b z>xv}Z*jjqF`h?AcUm%M&xwA*nHPJsN_my9W)ddSFE95iFD@vPrYn!-#VPr(H|aXhH)22= z__7}cyl9r{@@2ti{IGmp2-YVZuK@ zy8k6V;8=`!EXlp&mwn9{s}Do5!QM8xNF6=wsLR;33ASOIw=*WFO{NgnmB5n0sprKh z(Mfxm0~gE4eJ4q!!F^fKR&Wr7fnuT3z=T4FArN5tBOuT6malVrQVn_FP=boU+DJ8- z{?g%0vp77QW+6+5H#v6iAb6&gEn={sMg^d-(*#P3GSaT z0xI&zyWt&yCY8~G;?d5O+2#QiKlpsB90WI2Zmod>+v){B3}gTzJIZ!;!>i3oOI9(J zDft`B6tWqhlwO{zz6i+MHG^QF?WbmBjA(FU{rlX$E@+_PjaG)*z?V5%87CX7*w0v@ zJFWAfL-zLBC>Te&(kXh$-U!aowrSDGDlWBGUg11!5}q^sHqKk(S@wr~qvJqLF2vY@GJ-j=dk4}^sD(zIgYjD`UIaoknc zm`kAYxc!>HzAa(phBDlWX5h9;<#jV_8aCU60b_@*j&QWv-sJ2B$wEEYaQFlMq(6Bfbav+A+4(1UAKuso zj$giY<6YA)Pj&I5zXP+v?YaSgG)D}2;Fw=bO*^5l!LD6m5{f8_q5F3mbMDDdqF(5b z^L}WhP7${-u9~Mb%f_W3adfA_dCsA%NU~-azOVOA^j@g2@?M0zZ7f3zdlX5)O$WqM z+Q5Xy%i2s-$H{f+fajnlz(rhMD2bc_<9@!S)$c)~qI)$MaO?yJc7Xx2xt5%Z+2Iy5 zYm~^+)RvVR2YFfZzv`-@N~PJ=6j`0<<%F0t7d6zJXb}`bVR67xm8=@HO6DTDoHWs& z40>eLbyi&#oLBcxqKW=kI+>7jRBjn8HClUma$04gzg?-LFySm3j<$zMU-s!S+#xLi1!L1grVM6VBv-Em_IlAD225o7o&jj=5PsJARfS&`dSaTeH zIF>Lub4csS-v}t4f3Neq4@fV=nity+;8jB zrk)So|NaQfg2?MK3ILd2Ju(u>FKQ>EQIGb@ za_D1ozkcVPd4)%GKA#L{{SId~c-`&Ld%V~5|2u#0at#nJoiGA5m=iXaK`00yx(YF7 z=$6pSpGWkh%d5B}cHKOei@Nfo2dC5Kh7D3wO5;BU3g&vcBOrk34*;@&wR;elrH_{5 z#mM16_}8bIh+UaJlDP{j7I0SbQ>hSwz7X$8=+NNC?yv6SEfz?76Xd9&2ByD?G2mJk z%Gb2l>^yd1S6{a$$$?wt@j&cOwPBVatoE}WiZzlrub(^kdXall!fm7d%jum^iK>cuDHvma0ymymcQh0&VC>*j}4H|bEC%|-A~E(D@g zou)XIuXp;nJASUpMcWt`)rC=K zR(=t%qjp*om_A`0aOj}Zni$}v0^9Nz>q+F+C`3ppJ)+bTfC6NP2Lr`$RI z2b;jZ@%C&&BEW+;|LDBNURiP%@I$o+#^Bo#@S2D-JJ6=+Zv^+rk=%*>_Sd&vyz(mj zIXk#%ZHaT81=4gZ)0;EiOvAyNt}m5RL^)|RGrElY0)&F%cfdQm7b80E?3 zePg{k*`s{!y;sI5;uS7#z+UYOjTpFlb^e?7t6&4(y}CkLrjP^_QE^)r`h_f=9%_B( z7oLEX6TD1}zIV$uI7PIe!-;4oeo+-ez8+)*=1=^`+x=@CzW|bOaNu;$&DV13&?6xt$0#oaeMp@3o;X29JWW9j}M20Uc$j`3y zakTX#X!7)oH&n<2lG)xWe?BA3#-kY+GfOsF+f@)j3E4P!vN_Wn*WQm5hxPX9e3Dgq zCWXZ!%UXdObHV0RASMeLHA0e(E@@yTd|97g3eZoKE1NgRTR^nXlfdkIK76_T0dNfZ z5;Op>|D#}D=~{6zq&_-}z)i%(|`C*sXS(&A+UYqtS7*^7YUUp*hNyV@-eo+~FgyU^4=iQQ8h(AsE= z>_XFw$4DxFD`v`eEy4m6=nE}AZO#1Zz;%BK1!%4GN3mRf<%`)*I-das=&{zHWo=T3 zBY!Zu{`^5E+rejffBoE|^sn)nMysR`-Jb5ERpLtRChS)qS^4%_<%5?8%V1b~NF4tL zkVDJ-F8c8ypJQ22O{G(8=dJN{^W^2ga@ z$SNI_K7m$AFPb8|+DQLi?9Ruy^!0BVXTTw)qm=fe$J-X#ru{;L2H9u<4y8r`Nis|y z?J>4a{r#@C!5M3C9e+imVUfFj7m4gLliy{KRu((p2z~NK4$4+J_oA~quR4sKKS+Wa z;Sdffhm61p%&!ZnRiCYmwJV~DsXaM*Dn`jI+vP(J+@oT9fGeM6$&4`xq(-n-z$iH- z8j}H;Wk_pW%96e!zNXKV94|uHXFk@?|KIKsOhR;j1;iovtu<~umF6l3 zK+0!PWH_e)#;|QV)TCK4sg(&G10$$|N6CkmoYZa8puoi_2L~&a*TL1wIxiSi2nc7y z5`|mhbEY*uH=gYTUa)FLEK*P#zbRYgbK}`Jch-WljuXIlY8hY0n-%cC_+Ph}&AE&Z zgt}2+$LG;!rqdBW`fn}69JnC1c^ER4|Ml<9G83$5q3t|E3hhP#VU*IGke29Lwf1AJ zX*P8j#)gL_Xf($z)V&ba;p+MJ3r^)0S0FMgAKc`%aXhnG@?0ngS@ThIFFy$-oLVJ8 z(^MpOE(2w-7nDpJZ|4_MaJN+mp&(82tn9k;Pr?LB+IArsW>nYOJ4UnB`HTs$5mxVZ zHqSkA5C?^!_Ya$~*zhi#fXNbp<7D&CmjO{C;b*EeoDaxkC`qba6sq95%C%{1a#kW4 z!6PZRLvpnZFmlm19DY0ObPn%#ACd5y?O}c^x*tlTwdL6m)-9#&!+r~2^5qvoY}Q2A zgW|PiKS7VAH3yr2e0I=&~9v)n;__a##Wmu^6C^#m8%Z3l7e`;FqlJoO7GxqmU0L&c3O z&A;DPi{%3KMXi$vzdfDWoVK!>nd4bJ>&`vmrijXF)rgwaS~Ja@LdsPby@OFJ!Ei%( zKkZ*QEgVleBDiA)LRjZqklzuCF;d6uo&&8P8-NOL;Fg(qej<0AkjR5XxL{zV)0( z`Gt7ChQq)?_K63{nC?bn_m5NTQte;|b`0eU#BiBK;z5<;;_*$x5a4vrZG3Wn)>$y7W4P%rc6VU>er;`dHv{5U#{!eR1TsiF-m&`B5TfIR7s!vDP)sr zaMH+42xGLNnB()h8e(wyDQO17Z->A8pw8lueC&*uatFFZt}z*aWV2SzyiM}r?Dg6> zBu$DY?pFmnoc(K%qCCr9ga861a`NNR=EBlXV4SJ!kUV_uE8*|JKDahibMICup&5k$ z;rzNkTj&KeGLV!(hr7Etmw0|Xe2cY)t=3j0-yK@yEaVskXrblAlXVsvb;}4X6TD7& zA{TATNfjHF3U|9@XGv{Se>Idi@x&l3s_RmQN@b0rT6v45O{!FE^yKk@c*9w7e7*N- zXt7210tG5qTYoe*Ten$f0~%zureOUC^k0>%cTo!(6?S{;~S~j!V8s0|c2o zn3L+=XO>hRiHj(GgN@w(52Pkj%=jNfr|w-IU%Q~3nrt1~;OEFcjy_^dWc++Zd%FxI zI^SvE{^xDcufcQ3OPnZj8>t)rC|ZzBmZKv(RA4|kVQ%;T=|1dTi3a?St{du7iRXQW z((!mI_VEDVmoQ^>OL855rTUax1DPF{O#TqP(i2HOx>0%9eByb}T9eED@qkVju)&`D z#w+3NWTpBv8xAU{v^I=zZlvSUkkz67kWRwsNpPadQ|edOa9(V2d7IoWxH^@`VV1)N zRF#=Zae0$#5a84aF6=~f-$u&-Lm_zes;e(MYI4fU)JfTirO_4 zU~H$|2w-cae6{_$so-XkL2rOycSWN*5UW?wu$v*^P2RZimKOy8bi=;ZjUY0 zOP?$xlW=lz-@fBbwuiwn9rEY{If>bs{N z$N4rIaH{Vc8)AYud|)UCR;yS$x12eNd?WIy7}v7xIy~&rMFVOlM)m5^7UdUg@ZwEi zL5wi%3l9cYOFUsnjIA<@fe8Ek&W8|A{n>6dqWiCGYV}P|2at9lZXWcSxPm7=7XTSc z^4u22eIhdh%$d{LfPY|TI%e)HWo_XMazPS=u|=Vp&ifMvjeOR(MGnrLry@6#SA2MQ zt(7Hlf}{JdG%`H=Ny^FAu=#a}YSy&+lPN&7V6K&4(qGd-@lGh9&>Hv%@guCv&~W51 zM>H786rdsj&J><0%e1q*^M%C4s1SiU6&cQ&!SIKL_#CBx*U<%g4tK!kFj);Upea0Q z%gkz@-E*zu0wit6%+hkT0x#ob_2Q31M>m!&C%4DOQG}A`Wd?V|o-GtHs8YFDWEEZM z$Z&uK5HWDL6#~C99}xhFfq{;<3UeBRV#tdk;dHUL@dY7ewWC{0Xei)lhL)Pm#dk(E zM2&Oi`9}x*LJB?yqgzP^O6Nvte%Ry>eJ$D5`OQr4T083i8mvu@jo3P5TYwVF5L zU_+_OGqt8Fw3A(ts!zJP=~gDmFn-iU9D3kD~b)rCTx~9^^N)$@d!A1z$>F1W)9vpVljB^eRFmxUnx~)E_dB zf&5p&!LwV<^3}?^LNF?ih3;Bx%3wAzZynjC(3}Ka-?ez9%tNi$X}fU6%4j`EkmJRN z_4<#WnC{Q^l7$^^z#3>Q(iD&JW8WV5vi&*WMD`r*7BaaIG-!uv-m=zyeIUZ^)Ct$` zpRm1az$xS;v~b6j5wBvricRx2?BXYrvldGqe%F2%DSY=+06|`$mDX`M=_QO|QYzFy z>YdMB!`#1qgaKdPcmMA64*duYs+~DAFt$n#7+?)_t@?*7>nZJz3AzVQR)9ak4)`#= ze?$QCCHSp!jzi%#x7{8lE%cYLDY|Hu6+rU{iggyGV zbUro=eZSQA>I%XNTTu^U5h041VH%0)pFv* z_q1y-Db82lb6h*Iu#eQzo8SLbLe-XT;P^&|hT_`SR9QIB1*kjV^39FB@yh@IU#9s* zkXDg}0R>dmho;OMz@_&;{1|~NP-mTY0UjSGg?#Ol&Fifr&pbL@FfRF|d4w2G5n$%4 zpMDsENEzQ-KjXTqRM%^sa>_OC za~*@g;ox9tn{!TU?#m9@uSV5U+jXy6_lS#Q=VSkT_w0J3y+%s!eW<^K{7#2?^)Hl> z>3JJZezVf9bMl}6uGZo1uYH515R4ri?Qj3~Z;?v<|8H5IrD=+E-CjMQM*g*B*oY)W zBKOV>T!l+@zp6tF)<8^PXy}LElq+6tLrmqSpWpZ%jLUX=tE+3<7hGWR)8_4K zI_>mwTl?f4j@Y}+1NUea8;xBqYHNB`a>k*D%nG{!CfW(TVFm6Qgu14xx~lb;;ju?( zX66?iKhk4Wv?MElR8(%;^L}KQ)a2IkH{N>t3x4Uj@Z!Fju|tQ(BHg)r@BYJwCr_V# z@W$&rMqs~}>=%vi$+owbl9zX}#A6;S6$+~5bb3$(%YYkPZE!evb@ct<0yqsOKY1s> zF0gHCl~b1U00B7SCI7_cITE#x6m#IF528@7mlCA@=ajn~4&Q2@d*Kk(Y&zF>pZ_+EngiW*L?fVbl!R*~O{pbd5zLfo6Z7sW8F^MXISL zV{wQKKB|dv{BnzoAi0LLHk)R)S^%u8a%E4ns<2=&E)*~r7^qsRMY;aY;Z?G#k0qL` zCIMfTJd1th9h5aD8e%F98K4z%j@euWvJQ-82Nk@cPPb*pCI1Fd zS+l{YiR+)+ToJMZKZ&3Ik)|OlvrOWgGOq?D`CSe-BCJiFOQHs}tHYgfWy{YSJoRtE8?Be@2!(Aw+{9WZ|TT?{9~{Z8RPedW7Oj?Unj-M ztA}Cucp{L^W)XKh;xh+h05eJ&D(p+PK6UDoNW`n1EQ=jWpOmR6PqDsc7ALS7FK*Hx z7j$WFuU05#AbMyAK~;6P>rcj$K*<=j0m5G-Ng%2HC)w@8+6&l8yw|6W_VI{ADkQ zCY<4M<;IE9%W=T67W_I#%!?%xoN=XPPyXRq(5#X#-lx`u$bFQYrmOAj&F-9G7+A0` zLw@*#8~t|-N~OGb4*byC%r()4b!wfszN>w-|1Vzns@7_qiGBi}oqo#x8d=X~Z}G4G z!!TI^t&$c5F}xzN98+oqBh_=0%c0YyI+#_F1P63X#6oj$Mej2otfmIq&{B(kg_RZ} zBV<1zgPG%UH}7be-RkP%u@<{kPA{aBxpaXQWsUT)n0zS4A^VqtC4sDk_6Dc_4!F0x z&;0SB`wpnJSoF2rf)osqWyT9oGr~5rwa1dt&BH$FY_E)B7nt6-1|7+y%2K-)RbXp$ zGjsG1SF2Vif`lotQqN)v>47a%N+BiBXH;Qyp9n9-8N_gS$r2Op`yIjir2e#?1#Dp> zs*=vd8XJWlRQgMmgPvk^By#0^xO(0$Exi)esbNN`*&&7<$81^R5D$ua5bBL(8TZQ+ zTaJ_4$WViW@LYhg+(yIiGJ+zo7E-#~K!6aamxUNcw1fW^O{D(g4h3{yhD&P z>~6gP442@ebCJLO@3z)|BV~9SZ#%2^$aIIGBFR%q8`wlbHlbm798q{!e4^o6%k$~_ zkT?=@JUD0BIZW;ZDRKot8MwxVILqO1veqr6$Xt0lsVHs7mdi+F!kPAct5>uRqN!yv zse&>kM@sTgG^EaS=_u`8v87*=qP;_s0;&CqV4{JJW#{POm?;6dR0kL&h-0Z(j5&Jg zp^=L_W$o$W{u&0!_L4VpPO{pmHbUcM%}XD2Ah##4k!@N{iV52CL3U4(BY#v}#n%)1a3}R=Gm0S60iVnWQd8*<((GAa(sTj}8)87Ev{@;24EPxUDNC3o0)x$E+la}Mi z4~E)lNv(~~w5Tc!;){`x&nQ_6Bmm2#9;; zB=f6M3;oZ(m?H;*%_Fu^Bg`)zUO{ibo5x=DWkM{v;^%LBP5Xq64&DW1!f!>H#j;V9 zrh(Ox6JWBdWv7ERz;}pSvSyO9GSixafd|o$Pb*p6^zS>iyg}!VJp;Q|kmg9oKA!npKU{<-W8eg*EpfmqLTx1|6TYI=ok{sN4z&^SV67Z!G zhIKs=Qh-Vw3?xwjTx+kC7|1S=)0#KhgYH~X(e8QhF)F_*uPh2z`H89;J4O+|x^jE^ zC*k<3>b}x{@qbTV{O_>>yRqBtdZUQG56fBuC%+b}Foi51MdClp>N9q#lZlN!zMWa` zR+q6pEOdr#3^khV>QzHzePh&$>q zgrV@4@i#T&EAD~)?*C6T?Y#KZ=*~Tv;Z3~hluKC{Z6wQfPAPDl zR;Q>SNVAFjW)s^{T;_!s6rJ*A2N<=8rZEUjU@_7{V|EfB42)JNzo>mnA6RjP048Wd@ACShy+rg||M$`POT ztMW?AboHjf5lA`p7Dg)_vc%4Xi5+|0YFL>OGcfSr=ZvD}G`*f+9Wlnv>BPZXYEoa( z-YX>xb^>?96h;%qUcaSXB7Jn^+V+DmBFKtq%cM}ZNz?Y2o!GV8@f}s{#+KKEh-LL- zCtK3#6+t}>F)oFIwy@F`*%&#R_1 ziaSVxAF4z=bd@;O)nte8UU?pKCM;EfXc?GM_R%Lo0z*5a`a@`^>BOW|@`Ag>qsc(H zhhCI#5o!nvY3Cz7(vId4q#ikNn&M_d1B_>>g`eLCt4l;LXA_APb`hu+I9hy_ap?Ki zl?|xbN#O%mLDjk!oVMV&Nol}nwsx5F11$kZy8`Dem@E*0gU_tc5rLsQunW$xJMQNx z{szwq0=VG$2}Gsb1?Tz*rJc>ss%laKUJno|VMOiZ!=N_va5$XB zx#+y|qw~I_$Hg8}05~i2GO;{_>DT4#Hk(?;h=Gl);Dvov>J~6R%!2c^j8U}SiTUoSYw|OP7GT+k*oGA zIqL#+FDD&w(mtHPI|$)eB2>}y=H%`C{CkmM;m~fLVNx*ZHD$iMZ5QdZ6A7#;_bmlL zM6K^h$FsSe4Ef=*-`}B=nas|+Ja`z`J7*LcRz`Mmjf z4;O6NFygV+nwU11d`mEnTx-f4{^82daT)y`Qto-_83L!-bDh>#<)&WI(OJJzeEaA9 z7h>8^NcpNS=vjpA@ccRCroSPF|Fdw2sBS3h$RoNv0|RTKWJ~Sh{@7`D+E@ZDnJr`@ z%&c%fcihf_Zbt+K_^s)#%vTl5sZ6P;$w*ZPqc!>D4F?kKaC~hgJ+o1SHOlv^+S2sK z-qhcG${e;4)hkS1@!geje-w^~h&G-o|*IZ&->6S!1&*q+n#y5QOn=NnPxQ3rG@dRK}90Cl9N4#pL2{$qbJ zaLE$%8oHEzeI}r$lu*Co&-%W4@L~g1nu$l1{(P%nehVyFx}~O2mlgM83C8^*byCs@ z*bcBXC&I`pb9XQ^t$M~sx0l|!61cv7)BFqAk9dmi>eBn}p8PF9cgEew&cQi4C7vP* zE|*QxH32$Im>M6|eFm5;!Pl+sE&(tFB<+T2SL4)XlOw@{hMvEK3)-O2$-05!VZ%Zg z;2~TG%n}aBq5c4Ov2W82mxVD{m^|lv|5i(Q2{bpk19!_2 z@kRguqx*-`d(jS#+R9xZfWNC2Y^z9|^Di+pjrtp@tXe8w1}8lTUReADdOwA~x9<${8e^=Wwt`UT?!J*m=qw7=u99TR5D1sG{OzI(1H&Q~BY z$}4j46FB;K9Q0q0#Qj(9pNPWYu!9OCKtq{<28aO=i{Lr%gKCq=LUY2FI3K;xA)3rF z9CeN2$b*+wofH)P(%|)oJKO7zI}k_Q-8t%38Ik!mpGw_ZErXIb=>KJXh87q_f4rZ&h%3 z@+te)PJU&J^oM9=(JIC7HU_NaBHs+isb)O)qU_d-#ja9#G&z^De3jqrQ5U|5_Z}DD zy1EmmBE#SxBp5+38vOPoZ#j+({{j9|IsP=seFO+{?AZ49$w(sO?5;lb1~Ex^_0;pP z0aWq%Z~FPb^|6KIQUAhgE!i^fV*ma5Uj;Zy^#IOBv`Q^9M zXhp&1KiGDSO$Vp7avJyC3i)EEZW#CE%WT7~#`!*T{P<6|rl0!Hk~hN^aayle=%W7&Yr)1URjle#gR&pNG>`mW79IWn;!Yw+QjYF?U`^2;16 ze#c-i#)I)6!Z7+zHuF@Ac5OteQ0~WgqI~pkeV+(|F>;<;q=CUrKK@QL8kuf^S6(~S z+K^bX!@*Iq3I-&Bn_Qv^E^ZaB6{*9S}eTn-DwmVQifs~hLJ|NeW63^*0=VUvONVB+z0o-!7%2&f|}Zn$;kN zjoewNQ4Zd|IPuhw?54OxPqDRINq|zy&RlT-wnLpzB?9$B)S}kP4hite2eyLDI zN4)vy3xzv)AlGV=sx>+G>nS&sI*Oq_M`MU$XNJCQOR~9b(VRe$h@FkVd_@hti2bCD z1G8P+)UgGE-|D03*se5;g}&VyifddD@R}KuMqNBo&{{d-lH%k2K?N%~gXT_?o{YJs zO`pNM(80*bI%_B;iD-b28d8A}A(4MC#C!=|w-qLP=>RUjgfjCQWjM@&c} zl|kjjVVv0>RxIGO+#6PEi?6n|F-y^5% zku}rCnG%O`mmiO1xlRm(L(z^;>FP(*5pE1N4C@3QC|X5Pwo+ruCV7*9kv7&R87n5< z8Z9QSk2qR)%Y6)S#(Y*MoNT+8!(fWzC^G3ts@i(EYAQl2`f`OvJXwtvn6_D24!Sw4 z=g2Z8YJNn16c2%%bzzIGN@gRIkfNk2i^o!xZKpVjlQ=~8!3d`bB0JnMO$Ho7nuW0{ zawXe0LnR>$v};R9nep*?boko`TI-q2$;jd>unEp%S^c7GqW=&MUYNXl98d%A8B$ah zytH-LqVVw2j%8rObV!JSzeWF+fp;5katuDr=PXchz78;pKI3coJw)4rR7#&BwOt~d4-vFn&kZ>W z9E|!5Q94UQ(H<1W16Aurg9BGAr4-_SQkfIXOGeAUAbWI7hIOmBg(wBP*>!Hzoe#Il zQPL+86r$+K#b*6DJep4K>S1v;j$AnlfuhwZl`6SF*xjlZAswa^)Sz!9C==iY@`{_g zo5(g`JURNw0GOQ+B`fv0PU9>JZi%YZRKY5a zlwuC7wDuj}28Br+ss}9Y+G&G^2o@(ST&#N!&0dCZF1N25rxL6j?Iv3}5*GBeU zcHh2ZyJnd;9BpTW-3q|6qON50fY(POCEQ@imtK~`!Ssut2qwUD3}Mmv6;Pk>VqY|_ zboG#~JnU%6JTk_N=~#vw^xJk#PJ`iq!O-)9J-QHpO_oi%gu!-M8RE1Im&`#m=&OEi zQ>mp*K~|!n|KllWV(YOvYoWbhw!?EwMNk?N{$k}C+GWtw%av{YOEBX6ECYISGf>R- zPW2l&i0nwgdIgvfiAw7O#_!er7x<7lAtW$))?PMmM|2y`Wz+N@v$$oRU%ci0lv-w} zn`Sa?s3a_04y8}uR|X8-#tdKL2Iw-4ot}D9DMdWcw0bKW3}!2~e~_yUR($Ey{M@AH zGb!s(Z%(Hp-ee<}E5Htb5CQZT=b1&J8tDz?IuTLi$VmP`G_H{n33I1DBZN~WBfwhu z1bSE9B4FHqaBxKm~Z3+%(vi_;^THeo{YGU{_kHnV{* zbqf!nj~?&stAYt|oZOQ)Lub-yZ+0r97+zHETnMRTOr?p-<)w2D8MbK>Cn>@=!yc%t zJg0Vx^j{SYD6E_EZXwX>n)#AYigzliGQSQL}W@j|*k{c|IXym=UN6e2&4xa!w?~xWyUE2Y_sXSdtecE){ zAexr|OC+I5)yYsdkTtz}#QKk9KO_D7@jD-5@;AO^ngNGsH|lDQT;)@tNeQGmIbvB* zkuwh7e(vo^t_JrSKcJ%Wnkl>)S&2VBeK{LtFgIjdHpRq_w4hwN?f<9b0q z)*56wPHLAHF6UnmX;EL06;g$NoN?@=PZDwE3GEbg={a4=9(V7R@&&fpS1B2l0Eqh~ zZ6a8chs=SPkR(THTTFEZ@dt^Zz?Qg@yIeJ-L?ZE}_8A&Aup-|xI138XJ?#@46qjyaI zrgbCrJPs!Rp=+9of(_;SQxf)=rmd#dE*JeeY3&YgfVwfZ@p0u(#_(O7M&mZd;GohG zFzj7vdi8*j_Ox0oR_BDE0DpnMz%F?qCBIJyhT-4g-@!|k-iTCpz=lqYb7c?=IldJe zOC*HVOQ4wtwhu_te!}=nw+_x7t~_yjm4Ocx47t zE*{SvEvcwzi3|+P5evXNx0R)%hPt1K{JdMo&ffy>&3o_k?WazUN}Ip;{>!(gr_ap( z_QsWuUK}jx)9cqi1>em1=E`fYT^Yp>3`ANgDzc5I#dD~7wiOOYal0vi@k^@}f~*6y zpX@4CiUd%^K)QZ0YQOerKfOOrn-euI1cQZTU4G{{&8FDd<^{Ze|LrYq)zjw^+ryl`}8s@iT=Dl$0an5A`* zo;i1TzA!N@#m>Oc>~*K5-1_h)w_5|i1pYuHfS?C9!h%NGN$+I=RG=OPoZye(#!kO3 zOxNYzbDE4hAJ9Z^zd+8nN|Wg0l^Qob^vwvlq-L^42)`soA5Y zB2F4J6yo@A(U~@&f$LG)HDjTHUgMnkZs?-=ybsfK4Y?6Iajk;_>x%Zf-Cuh~i`*ZX zg5Fmo;L$mN+0%h0IfcwFxQG`Ka){w~M9Krtll&}Uy@kq|l(hmTx6lA{->b%Kz+pe* zi3Bcbl28?PRMKG>u?L3#jo8;_X5l1ZF`tUFS-vDG_1cfy`HG~QmQtBt$z2%%5D`hS zcVCSu2>?G(mQEaoQIw?VKNERg5Jf@YInH<2rh64(%cNEjgmxv;2vI$Fp!t^>A}hy6 z_6w`9JeDOlvkXmB6NcZNB1IFTJq&$S)EkL!MObPh=WpMZ^siA})tx}5!gQUif8mw& z=mTRmxS>L<;2GJ^9WO4U>XkF}rxq%8P5}VL$rHrh2LQn=m~{io>ZK6)bhOK=zbeMSJs^HAWf_utAd~i1qrtK1V8JJ!Z0I(r1Yla3&&T6_y zy5u<3SFUB50L+%F^-r~`<7KTbnzjxHuM)$mV@wLJ-Zri7E2-98MlS`;ZZgt07mv_x zQ{T^{ZyT=z=*bFb(FHeybvV;q2guB5lg7T5UR&+~}c*7$2mmP41x% z_h>reupJyhIa04vAk$NDHxrRT65z;L$4)tl?ezV#-=F@+PfVPep-~^)n$ZKdari^m zH##b!&7;e~gL?gNZg!NgIn-uCq|*8H?(w}bvvHMN03yU^M$10IXwhmXzrU6g8_q~g zlD}={8ymQ-d_fz$MZ`3CEcAv?fF&0nIn$(4&{En4b8fSOCiR8Hwaz*}e?>_x&PO7s zD2b|~dPE$sta>csG|zEd3u|$dXJXB;&c4Ez=NiH4hN3D+2JRuK6!P@ zw2jK!W80J}C^7vYw{Br_Fjt z7>BocH7XwiaGi0kvBgMDVIx#Yuf`zdKBti@?2%G9`@kJoF=)>4yaclmp()sqPbhUc zUK=)!CeP1zQhRnLSol(;>FDZZYE4(>2M7D?w2|RU@v;)N)igLgnX%gI$~QLNn)LVU z*{(H{uQ#3Y^uKhjlJOxvydclvdJ2o`jqL3#aLF>?^DR}Sfa3+?6h?O>OF~ur2nlC@ zfMUVr?m4_qVTHZSoZSSdEptEL6KoLf4X4mZXxKa*IZCDDnwB}6shnQ69pT>h{4VMo7p(R`SRuz1f=kZvz!d4XV zT`?^w#=8_hHW(05iTN;KDaG0{g_RXX%z^MXa(yDRB{}POGz-TVcEv!C2nLmgUSe}O zB~1eU`J*CNB?JPBe*FWDSDzr_an0e8CV!rS0D9+rNLT&ZAME_T!$0S@v9|#J^!gtK z0DtzDu6OXuliler`a?hf1%QD2#rPfwesJ*k=-0s)5PS%0XWJ}vu0;Hrx38eIK-_lF zCYKh}_x&98`i4vTRi5tMlO}tZsByO9q8Y>lFFZs*@v?gt)S3&SY1LkGf}`e3UwI#s z)~ny)iCbDqIkl3su|CjxSWT8}i^l(w=ORv+XiaTo?sqo%wju(%DKH52Ur*6wZJrkC z+f9+DxV~c62z`p`pd}eNjs|GW!a}owlBSnke`YXEBOqjS5V#1?JF!7L34#S%6hF zgKSE{rm~^mcgTL0ls37Zfz>VJ5_)}ZC}aRF7MKN}k7aQkn>f{|i>i2$t}WU~zUrw) zo^A5EO*2mOcD+B5{qkvq9Qgk)J3hn%V2{S@^>MPS4p+Zm98=2)x-qSk2wYJ!7#L-7 z>=bt9+4|B6GFW?Z&aSIb!U#v1m)mzmzj#>$c`Lyn`SveT)g)01a5k(ofA{DespBVDdEaXouB307aCT+=;S z!kx{kte!3ng9THz%q{XHN|1wT`QEc_XU>#8Qyg|oTaC_R%~)d7B8NTO>)PV%=(!3; zd5@j|uG(Fm(ekIMO4II~lc7M?$chXc=2ww}A#_3f)^Ifz336D`lu5)^SgvvhF470n zCj)!Zn(BgRaEAvl;cW!j8QZ;kt_mw;o|oJ0$L(5;81KUuM6!*&eA2;MGDOAyRapGdweSP|gTysf>TW-Un&_h;BXuo<5D(&=E zm79n$Q0>@Yq4~?-1~BN*cGzyMT#;fJqZr2|n_?QXn8zZVSjH;Wv59T$VjpgJafoA_ z;vAQ_#x3sg$mV#)E8g)5Kfdvczb5V)J@V9&WzVKaV1lwG!3jxd!V;dXiO9BThk<;V z;6QMuOuks=_4nt39yvbI=TE4WB2;v?iczna8I3KDa%y5vUDDqhC6X!KvqGNGU1oTq zab2QR&*9&lM5Z)1)k=O=)q-4TPG4^@YRnDxiPE1cAq=hLJ4{7jLQX5N@d`^P-vxHOvT(Tbp@)6870Aop#ad70d)yzMkb6W!puoExr&m7h!sDZ zLfrp-IZ)PzAcTyy%kX&Orn)|Gx@>(6l#L+NP&_}r4SkOAZ%VD zIXo#&#XVCuDxC2S1pR$UUnCKADym!@3@-^ECr^ffP`PL#fRHFHj55DVkAxZu{OWnd z+8&-djyiimq^~dj<1)Zgy0b;|1AVz~m!W7$hTJ{LFz08Ga?QKgSei>N?6F7Ej)NlB ziTrp3x(tbh#+4M1soo{pI(ZG`Zsy<_SUCBe!%HN1SPuymh!H>F%|MA9k+eiNAFKS9 zBV3XlMNkCIDGgVx3x1!@>hBh&^oqOJ1Ow6F58>}7i}K5b)!LU$pqof~jyzlV=#2l0 J-t5f)003mPOdJ3J literal 0 HcmV?d00001 diff --git a/bingo/public/index.html b/bingo/public/index.html new file mode 100644 index 0000000..be3dae1 --- /dev/null +++ b/bingo/public/index.html @@ -0,0 +1,1096 @@ + + + + + +Бинго «Баланс 2.0» + + + + + + + + + + + +
+
+

PROJECT: BALANCE · СЕЗОН 2 · 2 НОЯБРЯ — 21 ДЕКАБРЯ

+

Бинго «Баланс 2.0»

+
    +
  1. 1Делай маленькие шаги
  2. +
  3. 2Отмечай клетки за неделю
  4. +
  5. 3Собрал ряд, столбец или диагональ — +5 в батарейку
  6. +
+
+ +
+
+ Неделя — + Карточка обнулится в понедельник в 00:00 +
+ +
+ + + + + +
+ +
+
+
+

+ + Батарейка команды +

+

… из 500 шагов · заполняем вместе до 21 декабря

+
+
0%
+
+
+
+
+
+ +
+ +

Анонимно: без имён, почты и логинов. Твоя карточка хранится только в этом браузере, на сервер уходит лишь «клетка отмечена или снята» со случайным номером устройства. Батарейка обновляется сама каждые 20 секунд.

+
+ +
+
+ + + + + diff --git a/bingo/schema.sql b/bingo/schema.sql new file mode 100644 index 0000000..2845aaa --- /dev/null +++ b/bingo/schema.sql @@ -0,0 +1,29 @@ +-- Бинго «Баланс 2.0» — схема SQLite (применяется сервером при каждом старте, повторно безопасно). +-- Хранятся только анонимные данные: случайный id устройства, неделя, номер клетки, ответ опроса. +-- Никаких имён, email, IP и времени событий. + +-- Текущие отметки: одна строка = одна клетка, отмеченная устройством на неделе. +-- Первичный ключ не даёт отметить одну клетку дважды за неделю с одного устройства. +CREATE TABLE IF NOT EXISTS marks ( + device TEXT NOT NULL, + week TEXT NOT NULL, -- понедельник недели, 'YYYY-MM-DD' + cell INTEGER NOT NULL CHECK (cell BETWEEN 1 AND 16), + PRIMARY KEY (device, week, cell) +) WITHOUT ROWID; + +-- Мини-опрос «Твоя батарейка сейчас?»: один ответ на устройство в неделю (можно поменять). +CREATE TABLE IF NOT EXISTS pulse ( + device TEXT NOT NULL, + week TEXT NOT NULL, + answer TEXT NOT NULL CHECK (answer IN ('full', 'mid', 'low')), + PRIMARY KEY (device, week) +) WITHOUT ROWID; + +-- Кэш общей суммы шагов: пересчитывается при каждой отметке, +-- поэтому опрос батарейки читает одну строку. +CREATE TABLE IF NOT EXISTS totals ( + key TEXT PRIMARY KEY, + value INTEGER NOT NULL +); + +INSERT OR IGNORE INTO totals (key, value) VALUES ('steps', 0); diff --git a/bingo/server/cli.mjs b/bingo/server/cli.mjs new file mode 100644 index 0000000..ecd872d --- /dev/null +++ b/bingo/server/cli.mjs @@ -0,0 +1,30 @@ +// Служебные команды. В Docker: +// docker compose exec bingo node server/cli.mjs backup — копия базы прямо сейчас +// docker compose exec bingo node server/cli.mjs reset --yes — стереть все отметки и ответы (после тестов) +import { mkdirSync } from 'node:fs'; +import { join } from 'node:path'; +import { openDb } from './db.mjs'; + +const dataDir = process.env.DATA_DIR || new URL('../data', import.meta.url).pathname; +const [cmd, flag] = process.argv.slice(2); + +mkdirSync(dataDir, { recursive: true }); +const db = openDb(join(dataDir, 'bingo.sqlite')); + +if (cmd === 'backup') { + mkdirSync(join(dataDir, 'backups'), { recursive: true }); + const file = join(dataDir, 'backups', `bingo-manual-${new Date().toISOString().replace(/[:.]/g, '-')}.sqlite`); + db.prepare('VACUUM INTO ?').run(file); + console.log(`Копия сохранена: ${file}`); +} else if (cmd === 'reset') { + if (flag !== '--yes') { + console.log('Это сотрёт все отметки, ответы опроса и обнулит батарейку. Повторите с --yes, чтобы подтвердить.'); + process.exit(1); + } + db.exec("BEGIN; DELETE FROM marks; DELETE FROM pulse; UPDATE totals SET value = 0 WHERE key = 'steps'; COMMIT;"); + console.log('Данные очищены, батарейка обнулена.'); +} else { + console.log('Команды: backup | reset --yes'); + process.exit(1); +} +db.close(); diff --git a/bingo/server/db.mjs b/bingo/server/db.mjs new file mode 100644 index 0000000..cd5ba60 --- /dev/null +++ b/bingo/server/db.mjs @@ -0,0 +1,30 @@ +// Общая часть для сервера и утилит: открыть базу, создать таблицы, правила подсчёта линий. +import { DatabaseSync } from 'node:sqlite'; +import { readFileSync } from 'node:fs'; + +export const LINE_BONUS = 5; +// Диагонали карточки 4×4: 01-06-11-16 и 04-07-10-13. +const DIAGONALS = [[1, 6, 11, 16], [4, 7, 10, 13]]; + +// Собранные линии — по одной строке на каждую: ряды, столбцы и диагонали. +export const LINES_SQL = ` + SELECT device, week, 'row' AS kind FROM marks + GROUP BY device, week, (cell - 1) / 4 HAVING COUNT(*) = 4 + UNION ALL + SELECT device, week, 'col' AS kind FROM marks + GROUP BY device, week, (cell - 1) % 4 HAVING COUNT(*) = 4 + UNION ALL + SELECT device, week, 'diag' AS kind FROM marks WHERE cell IN (${DIAGONALS[0].join(', ')}) + GROUP BY device, week HAVING COUNT(*) = 4 + UNION ALL + SELECT device, week, 'diag' AS kind FROM marks WHERE cell IN (${DIAGONALS[1].join(', ')}) + GROUP BY device, week HAVING COUNT(*) = 4`; + +const SCHEMA = readFileSync(new URL('../schema.sql', import.meta.url), 'utf8'); + +export function openDb(file) { + const db = new DatabaseSync(file); + db.exec('PRAGMA journal_mode = WAL; PRAGMA synchronous = NORMAL; PRAGMA busy_timeout = 5000;'); + db.exec(SCHEMA); + return db; +} diff --git a/bingo/server/server.mjs b/bingo/server/server.mjs new file mode 100644 index 0000000..7599839 --- /dev/null +++ b/bingo/server/server.mjs @@ -0,0 +1,418 @@ +// Бинго «Баланс 2.0» — автономный сервер: Node.js ≥ 22.13 + встроенный SQLite, без npm-зависимостей. +// +// Отдаёт страницу из ./public и API: +// GET /api/total → общая батарейка + настройки сезона (страница опрашивает раз в 20 с) +// GET /api/me?d= → отметки и ответ опроса этого устройства за текущую неделю +// POST /api/mark {d, week, cell, on} → отметить / снять клетку +// POST /api/pulse {d, week, answer} → ответ на «Твоя батарейка сейчас?» +// GET /api/admin/stats → статистика (заголовок Authorization: Bearer ) +// GET /healthz → проверка живости для Docker +// +// Хранится только: случайный id устройства, неделя, номер клетки, ответ опроса. +// IP-адреса, заголовки и время запросов не пишутся ни в базу, ни в логи. + +import http from 'node:http'; +import { readFileSync, readdirSync, statSync, mkdirSync, unlinkSync } from 'node:fs'; +import { join, extname, relative, sep } from 'node:path'; +import { createHash, timingSafeEqual } from 'node:crypto'; +import { openDb, LINES_SQL, LINE_BONUS } from './db.mjs'; + +const ROOT = new URL('..', import.meta.url).pathname; + +// ---------- настройки ---------- + +function readAdminKey() { + if (process.env.ADMIN_KEY_FILE) { + try { return readFileSync(process.env.ADMIN_KEY_FILE, 'utf8').trim(); } catch { return ''; } + } + return (process.env.ADMIN_KEY || '').trim(); +} + +const DATE_RE = /^\d{4}-\d{2}-\d{2}$/; +const CFG = { + port: parseInt(process.env.PORT || '8080', 10), + dataDir: process.env.DATA_DIR || join(ROOT, 'data'), + publicDir: process.env.PUBLIC_DIR || join(ROOT, 'public'), + tz: process.env.TIMEZONE || 'Europe/Moscow', + start: process.env.SEASON_START || '2026-11-02', + end: process.env.SEASON_END || '2026-12-21', + goal: parseInt(process.env.GOAL || '500', 10), + adminKey: readAdminKey(), + backupKeep: parseInt(process.env.BACKUP_KEEP || '14', 10), +}; + +function fail(msg) { + console.error(`Ошибка настройки: ${msg}`); + process.exit(1); +} +if (!DATE_RE.test(CFG.start) || !DATE_RE.test(CFG.end)) fail('SEASON_START и SEASON_END должны быть в формате ГГГГ-ММ-ДД.'); +if (CFG.start > CFG.end) fail('SEASON_START позже SEASON_END.'); +if (!Number.isInteger(CFG.goal) || CFG.goal < 1) fail('GOAL должен быть положительным целым числом.'); +try { new Intl.DateTimeFormat('en-US', { timeZone: CFG.tz }); } catch { fail(`неизвестный часовой пояс TIMEZONE=${CFG.tz}.`); } +if (CFG.adminKey && CFG.adminKey.length < 16) fail('ADMIN_KEY короче 16 символов.'); + +// ---------- база ---------- + +mkdirSync(CFG.dataDir, { recursive: true }); +const db = openDb(join(CFG.dataDir, 'bingo.sqlite')); + +const q = { + total: db.prepare("SELECT value FROM totals WHERE key = 'steps'"), + myCells: db.prepare('SELECT cell FROM marks WHERE device = ? AND week = ? ORDER BY cell'), + myPulse: db.prepare('SELECT answer FROM pulse WHERE device = ? AND week = ?'), + mark: db.prepare('INSERT OR IGNORE INTO marks (device, week, cell) VALUES (?, ?, ?)'), + unmark: db.prepare('DELETE FROM marks WHERE device = ? AND week = ? AND cell = ?'), + recount: db.prepare(` + UPDATE totals SET value = + (SELECT COUNT(*) FROM marks) + ${LINE_BONUS} * (SELECT COUNT(*) FROM (${LINES_SQL})) + WHERE key = 'steps'`), + pulse: db.prepare(`INSERT INTO pulse (device, week, answer) VALUES (?, ?, ?) + ON CONFLICT (device, week) DO UPDATE SET answer = excluded.answer`), + stWeeks: db.prepare('SELECT week, COUNT(*) AS cells, COUNT(DISTINCT device) AS devices FROM marks GROUP BY week ORDER BY week'), + stLines: db.prepare(`SELECT week, SUM(kind = 'row') AS rows, SUM(kind = 'col') AS cols, SUM(kind = 'diag') AS diags + FROM (${LINES_SQL}) GROUP BY week`), + stCells: db.prepare('SELECT cell, COUNT(*) AS n FROM marks GROUP BY cell'), + stCellWeeks: db.prepare('SELECT week, cell, COUNT(*) AS n FROM marks GROUP BY week, cell'), + stPulse: db.prepare('SELECT week, answer, COUNT(*) AS n FROM pulse GROUP BY week, answer ORDER BY week'), +}; + +// Синхронный SQLite в одном процессе: транзакция не пересекается с другими запросами. +function tx(fn) { + db.exec('BEGIN IMMEDIATE'); + try { + const out = fn(); + db.exec('COMMIT'); + return out; + } catch (err) { + db.exec('ROLLBACK'); + throw err; + } +} + +// ---------- даты и сезон ---------- + +function todayIn(tz, now = new Date()) { + const parts = new Intl.DateTimeFormat('en-US', { timeZone: tz, year: 'numeric', month: '2-digit', day: '2-digit' }).formatToParts(now); + const get = (t) => parts.find((p) => p.type === t).value; + return `${get('year')}-${get('month')}-${get('day')}`; +} +const dayNum = (iso) => Date.UTC(+iso.slice(0, 4), +iso.slice(5, 7) - 1, +iso.slice(8, 10)) / 864e5; +const isoOf = (n) => new Date(n * 864e5).toISOString().slice(0, 10); +function mondayOf(iso) { + const n = dayNum(iso); + return isoOf(n - ((new Date(n * 864e5).getUTCDay() + 6) % 7)); +} +const weekNo = (week, start) => Math.floor((dayNum(week) - dayNum(mondayOf(start))) / 7) + 1; + +function season() { + const today = todayIn(CFG.tz); + const week = mondayOf(today); + const phase = today < CFG.start ? 'pre' : today > CFG.end ? 'post' : 'active'; + return { + goal: CFG.goal, tz: CFG.tz, start: CFG.start, end: CFG.end, + week, phase, + weekNo: phase === 'active' ? weekNo(week, CFG.start) : null, + weeks: weekNo(mondayOf(CFG.end), CFG.start), + }; +} + +// ---------- API ---------- + +const DEVICE_RE = /^[A-Za-z0-9-]{16,64}$/; +const ANSWERS = ['full', 'mid', 'low']; +const readTotal = () => q.total.get()?.value ?? 0; + +async function handleApi(req, res, url) { + const path = url.pathname; + const method = req.method; + + if (path === '/api/total' && (method === 'GET' || method === 'HEAD')) { + return json(res, 200, { total: readTotal(), ...season() }); + } + + if (path === '/api/me' && method === 'GET') { + const d = url.searchParams.get('d') || ''; + if (!DEVICE_RE.test(d)) return json(res, 400, { error: 'bad_device' }); + const s = season(); + return json(res, 200, { + week: s.week, + cells: q.myCells.all(d, s.week).map((r) => r.cell), + pulse: q.myPulse.get(d, s.week)?.answer || null, + }); + } + + if (path === '/api/mark' && method === 'POST') { + const body = await readJson(req); + if (body === TOO_LARGE) return tooLarge(res); + if (!body) return json(res, 400, { error: 'bad_json' }); + const { d, week, cell, on } = body; + if (!DEVICE_RE.test(String(d || ''))) return json(res, 400, { error: 'bad_device' }); + if (!Number.isInteger(cell) || cell < 1 || cell > 16) return json(res, 400, { error: 'bad_cell' }); + if (typeof on !== 'boolean') return json(res, 400, { error: 'bad_state' }); + const s = season(); + if (s.phase !== 'active') return json(res, 403, { error: 'season_closed', phase: s.phase }); + if (week !== s.week) return json(res, 409, { error: 'week_changed', week: s.week }); + + const out = tx(() => { + (on ? q.mark : q.unmark).run(d, s.week, cell); + q.recount.run(); + return { total: readTotal(), cells: q.myCells.all(d, s.week).map((r) => r.cell) }; + }); + return json(res, 200, { ok: true, week: s.week, ...out }); + } + + if (path === '/api/pulse' && method === 'POST') { + const body = await readJson(req); + if (body === TOO_LARGE) return tooLarge(res); + if (!body) return json(res, 400, { error: 'bad_json' }); + const { d, week, answer } = body; + if (!DEVICE_RE.test(String(d || ''))) return json(res, 400, { error: 'bad_device' }); + if (!ANSWERS.includes(answer)) return json(res, 400, { error: 'bad_answer' }); + const s = season(); + if (s.phase !== 'active') return json(res, 403, { error: 'season_closed', phase: s.phase }); + if (week !== s.week) return json(res, 409, { error: 'week_changed', week: s.week }); + q.pulse.run(d, s.week, answer); + return json(res, 200, { ok: true, answer }); + } + + if (path === '/api/admin/stats' && method === 'GET') { + if (!isAdmin(req)) return json(res, 403, { error: 'forbidden' }); + return json(res, 200, adminStats()); + } + + return json(res, 404, { error: 'not_found' }); +} + +function adminStats() { + const s = season(); + const weeks = q.stWeeks.all(); + const lines = Object.fromEntries(q.stLines.all().map((r) => [r.week, r])); + const cells = q.stCells.all(); + const cellWeeks = q.stCellWeeks.all(); + const pulseByWeek = {}; + for (const r of q.stPulse.all()) { + pulseByWeek[r.week] ??= { full: 0, mid: 0, low: 0 }; + pulseByWeek[r.week][r.answer] = r.n; + } + const weekKeys = [...new Set([...weeks.map((r) => r.week), ...Object.keys(pulseByWeek)])].sort(); + + return { + generatedAt: new Date().toISOString(), + season: s, + total: readTotal(), + weeks: weekKeys.map((w) => { + const m = weeks.find((r) => r.week === w) || { cells: 0, devices: 0 }; + const l = lines[w] || {}; + const rows = l.rows || 0, cols = l.cols || 0, diags = l.diags || 0; + return { + week: w, + weekNo: weekNo(w, CFG.start), + cells: m.cells, rows, cols, diags, + steps: m.cells + LINE_BONUS * (rows + cols + diags), + devices: m.devices, + pulse: pulseByWeek[w] || { full: 0, mid: 0, low: 0 }, + }; + }), + cells: Array.from({ length: 16 }, (_, i) => ({ + cell: i + 1, + total: cells.find((r) => r.cell === i + 1)?.n || 0, + byWeek: Object.fromEntries(cellWeeks.filter((r) => r.cell === i + 1).map((r) => [r.week, r.n])), + })), + }; +} + +const sha = (s) => createHash('sha256').update(s).digest(); +function isAdmin(req) { + if (!CFG.adminKey) return false; // ключ не задан — админка выключена + const auth = req.headers.authorization || ''; + const given = auth.startsWith('Bearer ') ? auth.slice(7) : ''; + return timingSafeEqual(sha(given), sha(CFG.adminKey)); +} + +// ---------- статика ---------- + +const MIME = { + '.html': 'text/html; charset=utf-8', + '.css': 'text/css; charset=utf-8', + '.js': 'text/javascript; charset=utf-8', + '.json': 'application/json; charset=utf-8', + '.svg': 'image/svg+xml', + '.png': 'image/png', + '.ico': 'image/x-icon', + '.woff2': 'font/woff2', + '.txt': 'text/plain; charset=utf-8', +}; + +// Все файлы страницы читаются в память при старте: их мало, и так нет обращений к диску по путям из запроса. +function loadStatic(dir) { + const files = new Map(); + const walk = (d) => { + for (const name of readdirSync(d)) { + const full = join(d, name); + if (statSync(full).isDirectory()) { walk(full); continue; } + const rel = '/' + relative(dir, full).split(sep).join('/'); + const ext = extname(name).toLowerCase(); + if (!MIME[ext]) continue; + const body = readFileSync(full); + files.set(rel, { body, type: MIME[ext], etag: `"${createHash('sha1').update(body).digest('base64url').slice(0, 16)}"` }); + } + }; + walk(dir); + // Чистые адреса: / → index.html, /admin → admin.html + for (const [path, file] of [...files]) { + if (path.endsWith('/index.html')) files.set(path.slice(0, -'index.html'.length), file); + if (path.endsWith('.html')) files.set(path.slice(0, -'.html'.length), file); + } + return files; +} +const STATIC = loadStatic(CFG.publicDir); + +const CSP = [ + "default-src 'self'", + "script-src 'self' 'unsafe-inline'", + "style-src 'self' 'unsafe-inline'", + "font-src 'self'", + "img-src 'self' data:", + "connect-src 'self'", + "base-uri 'none'", + "form-action 'none'", + // Teams может открывать вкладку «Веб-сайт» во фрейме — разрешаем встраивание только туда. + "frame-ancestors 'self' https://teams.microsoft.com https://*.teams.microsoft.com https://*.office.com https://*.cloud.microsoft", +].join('; '); + +function serveStatic(req, res, url) { + if (req.method !== 'GET' && req.method !== 'HEAD') { + res.writeHead(405, { Allow: 'GET, HEAD' }); + return res.end(); + } + const file = STATIC.get(url.pathname); + if (!file) { + res.writeHead(404, { 'Content-Type': 'text/plain; charset=utf-8' }); + return res.end('Не найдено'); + } + const headers = { + 'Content-Type': file.type, + 'Content-Length': file.body.length, + ETag: file.etag, + 'X-Content-Type-Options': 'nosniff', + 'Referrer-Policy': 'no-referrer', + 'Permissions-Policy': 'camera=(), microphone=(), geolocation=(), interest-cohort=()', + }; + if (file.type.startsWith('text/html')) { + headers['Content-Security-Policy'] = CSP; + headers['Cache-Control'] = 'no-cache'; + } else { + headers['Cache-Control'] = url.pathname.startsWith('/fonts/') ? 'public, max-age=31536000, immutable' : 'public, max-age=3600'; + } + if (url.pathname.startsWith('/admin')) headers['X-Robots-Tag'] = 'noindex, nofollow'; + if (req.headers['if-none-match'] === file.etag) { + delete headers['Content-Length']; + res.writeHead(304, headers); + return res.end(); + } + res.writeHead(200, headers); + res.end(req.method === 'HEAD' ? undefined : file.body); +} + +// ---------- ответы ---------- + +const MAX_BODY = 2000; +const TOO_LARGE = Symbol('too_large'); +function readJson(req) { + return new Promise((resolve) => { + if (Number(req.headers['content-length'] || 0) > MAX_BODY) return resolve(TOO_LARGE); + let size = 0; + const chunks = []; + req.on('data', (c) => { + size += c.length; + if (size > MAX_BODY) { req.removeAllListeners('data'); req.pause(); resolve(TOO_LARGE); return; } + chunks.push(c); + }); + req.on('end', () => { + try { + const data = JSON.parse(Buffer.concat(chunks).toString('utf8')); + resolve(data && typeof data === 'object' ? data : null); + } catch { resolve(null); } + }); + req.on('error', () => resolve(null)); + }); +} + +function tooLarge(res) { + res.setHeader('Connection', 'close'); + json(res, 413, { error: 'too_large' }); +} + +function json(res, status, data) { + const body = JSON.stringify(data); + res.writeHead(status, { + 'Content-Type': 'application/json; charset=utf-8', + 'Content-Length': Buffer.byteLength(body), + 'Cache-Control': 'no-store', + 'X-Content-Type-Options': 'nosniff', + 'Referrer-Policy': 'no-referrer', + }); + res.end(body); +} + +// ---------- резервные копии ---------- + +// Раз в сутки и при старте: копия базы в DATA_DIR/backups, хранится BACKUP_KEEP последних. +function backup() { + if (CFG.backupKeep <= 0) return; + try { + const dir = join(CFG.dataDir, 'backups'); + mkdirSync(dir, { recursive: true }); + const stamp = new Date().toISOString().slice(0, 10); + const file = join(dir, `bingo-${stamp}.sqlite`); + try { unlinkSync(file); } catch { /* копии за сегодня ещё нет */ } + db.prepare('VACUUM INTO ?').run(file); + const old = readdirSync(dir).filter((f) => /^bingo-\d{4}-\d{2}-\d{2}\.sqlite$/.test(f)).sort(); + for (const f of old.slice(0, Math.max(0, old.length - CFG.backupKeep))) unlinkSync(join(dir, f)); + } catch (err) { + console.error('Резервная копия не создана:', err.message); + } +} + +// ---------- запуск ---------- + +const server = http.createServer(async (req, res) => { + let url; + try { + url = new URL(req.url, 'http://localhost'); + } catch { + res.writeHead(400); + return res.end(); + } + try { + if (url.pathname === '/healthz') { + readTotal(); + return json(res, 200, { ok: true }); + } + if (url.pathname.startsWith('/api/')) return await handleApi(req, res, url); + return serveStatic(req, res, url); + } catch (err) { + console.error('Ошибка запроса', req.method, url.pathname, err); + if (!res.headersSent) json(res, 500, { error: 'server_error' }); + else res.end(); + } +}); +server.requestTimeout = 15000; +server.headersTimeout = 10000; + +backup(); +const backupTimer = setInterval(backup, 24 * 3600 * 1000); +backupTimer.unref(); + +server.listen(CFG.port, () => { + const s = season(); + console.log(`Бинго «Баланс 2.0» слушает порт ${CFG.port}. Сезон ${CFG.start} — ${CFG.end} (${CFG.tz}), цель ${CFG.goal}, сейчас: ${s.phase}.`); + if (!CFG.adminKey) console.log('ADMIN_KEY не задан — страница /admin выключена.'); +}); + +function shutdown() { + server.close(() => { db.close(); process.exit(0); }); + setTimeout(() => process.exit(0), 5000).unref(); +} +process.on('SIGTERM', shutdown); +process.on('SIGINT', shutdown); diff --git a/bingo/tests/api.test.mjs b/bingo/tests/api.test.mjs new file mode 100644 index 0000000..a504dc4 --- /dev/null +++ b/bingo/tests/api.test.mjs @@ -0,0 +1,132 @@ +// End-to-end API tests: starts the real server on a free port with a temp database. +// Run: npm test (Node.js >= 22.13, no dependencies) +import { test, before, after } from 'node:test'; +import assert from 'node:assert/strict'; +import { spawn } from 'node:child_process'; +import { mkdtempSync, rmSync } from 'node:fs'; +import { tmpdir } from 'node:os'; +import { join } from 'node:path'; +import { createServer } from 'node:net'; + +const ADMIN_KEY = 'test-admin-key-1234567890'; +let proc, base, dataDir, week; + +const freePort = () => new Promise((resolve) => { + const s = createServer().listen(0, () => { const { port } = s.address(); s.close(() => resolve(port)); }); +}); + +async function api(path, body, headers = {}) { + const res = await fetch(base + path, { + method: body ? 'POST' : 'GET', + headers: { 'Content-Type': 'application/json', ...headers }, + body: body ? JSON.stringify(body) : undefined, + }); + return { status: res.status, data: await res.json().catch(() => null), headers: res.headers }; +} +const dev = (n) => `test0000-0000-0000-0000-${String(n).padStart(12, '0')}`; +const mark = (d, cell, on = true, w = week) => api('/api/mark', { d, week: w, cell, on }); + +before(async () => { + dataDir = mkdtempSync(join(tmpdir(), 'bingo-test-')); + const port = await freePort(); + base = `http://127.0.0.1:${port}`; + proc = spawn(process.execPath, ['--disable-warning=ExperimentalWarning', 'server/server.mjs'], { + env: { ...process.env, PORT: String(port), DATA_DIR: dataDir, ADMIN_KEY, SEASON_START: '2020-01-06', SEASON_END: '2099-12-31', GOAL: '500', BACKUP_KEEP: '0' }, + stdio: ['ignore', 'pipe', 'inherit'], + }); + for (let i = 0; i < 50; i++) { + try { if ((await fetch(base + '/healthz')).ok) break; } catch { /* not up yet */ } + await new Promise((r) => setTimeout(r, 100)); + } + week = (await api('/api/total')).data.week; +}); + +after(() => { + proc?.kill(); + rmSync(dataDir, { recursive: true, force: true }); +}); + +test('total reports season settings', async () => { + const { status, data } = await api('/api/total'); + assert.equal(status, 200); + assert.equal(data.goal, 500); + assert.equal(data.phase, 'active'); + assert.match(data.week, /^\d{4}-\d{2}-\d{2}$/); + assert.equal(new Date(data.week + 'T00:00:00Z').getUTCDay(), 1, 'week key is a Monday'); +}); + +test('scoring: cells, row, column, diagonal, idempotency, unmark', async () => { + const d = dev(1); + const t0 = (await api('/api/total')).data.total; + const steps = async () => (await api('/api/total')).data.total - t0; + + for (const c of [1, 2, 3]) await mark(d, c); + assert.equal(await steps(), 3); + await mark(d, 4); // row 1 complete + assert.equal(await steps(), 4 + 5); + await mark(d, 4); // same cell again: no change + assert.equal(await steps(), 9); + + for (const c of [5, 9]) await mark(d, c); + await mark(d, 13); // column 01-13 complete + assert.equal(await steps(), 7 + 10); + + for (const c of [6, 11]) await mark(d, c); + await mark(d, 16); // diagonal 01-16 complete + assert.equal(await steps(), 10 + 15); + + await mark(d, 1, false); // breaks row, column and diagonal at once + assert.equal(await steps(), 9); + + const me = (await api(`/api/me?d=${d}`)).data; + assert.deepEqual(me.cells, [2, 3, 4, 5, 6, 9, 11, 13, 16]); +}); + +test('full card is worth 66 steps', async () => { + const d = dev(2); + const t0 = (await api('/api/total')).data.total; + let last; + for (let c = 1; c <= 16; c++) last = await mark(d, c); + assert.equal(last.data.total - t0, 16 + 10 * 5); +}); + +test('rejects wrong week, bad input and oversized bodies', async () => { + assert.equal((await mark(dev(3), 1, true, '2020-01-06')).status, 409); + assert.equal((await mark(dev(3), 17)).status, 400); + assert.equal((await mark('short', 1)).status, 400); + assert.equal((await api('/api/mark', { d: dev(3), week, cell: 1, on: 'yes' })).status, 400); + const big = await fetch(base + '/api/mark', { method: 'POST', body: 'x'.repeat(5000) }); + assert.equal(big.status, 413); +}); + +test('pulse answer is stored once per device and week', async () => { + const d = dev(4); + assert.equal((await api('/api/pulse', { d, week, answer: 'mid' })).status, 200); + assert.equal((await api('/api/pulse', { d, week, answer: 'low' })).status, 200); + assert.equal((await api(`/api/me?d=${d}`)).data.pulse, 'low'); + assert.equal((await api('/api/pulse', { d, week, answer: 'meh' })).status, 400); +}); + +test('admin stats need the key and add up', async () => { + assert.equal((await api('/api/admin/stats')).status, 403); + assert.equal((await api('/api/admin/stats', null, { Authorization: 'Bearer wrong' })).status, 403); + const { status, data } = await api('/api/admin/stats', null, { Authorization: `Bearer ${ADMIN_KEY}` }); + assert.equal(status, 200); + const w = data.weeks.find((x) => x.week === week); + assert.equal(w.steps, w.cells + 5 * (w.rows + w.cols + w.diags)); + assert.equal(data.total, data.weeks.reduce((n, x) => n + x.steps, 0)); + assert.equal(w.pulse.low, 1); + assert.equal(data.cells.length, 16); +}); + +test('static pages and security headers', async () => { + for (const p of ['/', '/admin', '/admin.html']) { + const res = await fetch(base + p); + assert.equal(res.status, 200, p); + assert.match(res.headers.get('content-security-policy'), /frame-ancestors 'self' https:\/\/teams\.microsoft\.com/); + assert.equal(res.headers.get('x-frame-options'), null, 'X-Frame-Options would break the Teams tab'); + } + assert.equal((await fetch(base + '/fonts/manrope-latin-wght-normal.woff2')).headers.get('content-type'), 'font/woff2'); + assert.equal((await fetch(base + '/../server/server.mjs')).status, 404); + assert.equal((await fetch(base + '/nope')).status, 404); +}); diff --git a/bingo/tools/build-demo.mjs b/bingo/tools/build-demo.mjs new file mode 100644 index 0000000..9d48e6a --- /dev/null +++ b/bingo/tools/build-demo.mjs @@ -0,0 +1,15 @@ +// Собирает демо-версию страницы (без сервера) для предпросмотра: dist/demo.html +import { readFileSync, writeFileSync, mkdirSync } from 'node:fs'; +let s = readFileSync(new URL('../public/index.html', import.meta.url), 'utf8'); +s = s.replace(/[\s\S]*?/, + '' + + ''); +s = s.replace('\n