Skip to content

About

Браузерний тренажер сенсорного набору (uk/en): три етапи навчання, аналітика ритму й помилок, гонки в реальному часі

Resources

Security policy

Stars

2 stars

Watchers

0 watching

Forks

Latest commit

 

History

230 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Typing-Race

Браузерний тренажер сліпого десятипальцевого набору для української (ЙЦУКЕН) та англійської (QWERTY). Задуманий як система навчання, а не як гра на швидкість: програма має три етапи, кожна клавіша закріплена за одним пальцем, а після кожної спроби учень бачить рівно одну наступну дію. Поверх навчання є ігровий шар: рівень, серія днів, перегони в реальному часі, групи й рейтинги.

Для кого: для тих, хто вчиться друкувати не дивлячись на клавіатуру, за комп’ютером із фізичною клавіатурою (від 1024 px завширшки; на вужчому екрані навчання каже, що потрібна клавіатура, а профіль, рейтинги й перегони можна переглянути).

Програма навчання коротко

  1. Етап 1, гами. Механічні вправи для пальців на вже відкритих клавішах: пробіги домашнім рядом, дзеркальні пари, чергування рук, ізоляція одного пальця, вертикальні переходи, Shift і цифри, метроном. Текст гам породжується з карти пальців, а не пишеться вручну.
  2. Етап 2, слова з відкритих клавіш. Слова зі словників, складені лише з клавіш, які учень уже засвоїв.
  3. Етап 3, Академія. Модулі з частотних біграм, морфем і темпу, кожен із видимим прогресом і критерієм завершення.

Клавіша відкривається, коли на вправі, де вона є фокусом, три залікові спроби поспіль мають точність не нижчу за планку. Швидкість нічого не відкриває й нічого не блокує. Залікова спроба йде без підказок, тренувальна з підказками й не рахується. Помилка, виправлена Backspace, лишається в статистиці. Після спроби екран результату показує метрики, помилки за символами, ритм, порівняння з попереднім результатом і одну наступну дію. Є керований сеанс на 15–25 хвилин із чотирьох блоків (розминка, головна навичка, закріплення, справжній текст), повторення слабких клавіш і переходів та вільне повторення будь-якої відкритої вправи. Докладно й з обґрунтуваннями: docs/pedagogy.md.

Що ще вміє застосунок

  • Мапа навчання: три етапи як один маршрут, вузол на кожен блок вправ.
  • Ігровий шар: рівень і XP за залікові спроби, серія днів із заморозкою, сезон. XP дають лише успішні залікові спроби, тож шар не винагороджує швидкість без точності.
  • Перегони в реальному часі: швидкий пошук суперника й приватні кімнати за кодом. Рейтинг перегонів (Elo) рахує сервер за результатами справжніх перегонів. Якщо розкладка ОС не збігається з розкладкою тексту, заїзд не приймає літер; застосунок помічає це з надрукованих літер і пояснює причину, а не мовчки стоїть.
  • Групи й таблиці лідерів, лише з нікнеймом: ім’я, пошта й аватар Google ніколи не показуються.
  • Необов’язковий акаунт Google. Навчання повністю локальне й ніколи не потребує входу. Увійшовши, учень переносить спроби, налаштування й нік на інший пристрій. У налаштуваннях є «видалити мої дані». Рішення: ADR-0006.
  • Доступність і налаштування: три теми (світла, темна, для слабкого зору), рух і звук вимикаються, розмір тексту вправи від 24 до 40 px, керування з клавіатури, дві мови інтерфейсу.
  • Без мережі: service worker дає працювати після першого завантаження.
  • Сторінки «Формули» (як рахуються SPM, точність, ритм), «Ліцензії» (джерела даних і шрифтів), «Приватність» і «Про проєкт».

Як це влаштовано

Навчання, метрики й прогрес працюють у браузері без сервера. Сервер потрібен лише для перегонів, груп, рейтингів і входу; коли його немає, ці розділи про це кажуть, а навчання нічого не помічає.

apps/web            односторінковий застосунок (Vite + React 19), екрани лежать у src/features
packages/engine     автомат вправи: життєвий цикл спроби, шлях натискання
packages/metrics    SPM, точність, ритм, затримки: чисті функції без API браузера й Node
packages/curriculum карти пальців, гами, порядок відкриття, правила майстерності, ігрові правила
packages/domain     спільні типи
packages/ui         компоненти дизайн-системи
data/               похідні дані словників (слова, n-грами) і навчальні матеріали
supabase/           міграції (PostgreSQL з RLS), конфігурація Auth, Edge Functions
tools/data          відтворюваний конвеєр обробки словників
e2e/                сценарії Playwright

Рішення, що визначають архітектуру, зведено в docs/adr/: шлях натискання лежить поза React (0002), спроби незмінні й мають UUID клієнта (0004), metrics і curriculum не знають про браузер, щоб той самий код рахував і на сервері (0005).

Чесна серверна частина:

  • Метрики спроби перераховує сервер з журналу натискань (Edge Function submit-attempt), а результат перегонів finish-race не бере з клієнта: він програє журнал проти тексту кімнати тим самим кодом packages/metrics, що й браузер. Рейтинг рахує сервер.
  • RLS увімкнено на кожній таблиці, функції мають ліміти запитів, supabase db advisors на живому проєкті не показує помилок. Видалення акаунта: delete-account.
  • Заголовки на Vercel: CSP, що діє (не лише звітує), HSTS на два роки, X-Frame-Options: DENY, суворий Referrer-Policy.
Вибір Чому
Vite + React 19, SPA, TanStack Router клієнтський рендер; шлях натискання лежить поза React
Прихований textarea + beforeinput/compositionend єдиний шлях, що читає кирилицю в усіх браузерах і який можна автоматизувати; keydown лише для часу
Zustand і власні типізовані редьюсери життєвому циклу вправи вистачає написаного вручну редьюсера; XState не використано
Tailwind + CSS-змінні дизайн-система Ametrin (варіант b-red); три теми це набори змінних
Paraglide українська та англійська, типізовані повідомлення
Supabase (PostgreSQL, Auth, Realtime, Edge Functions) перегони, групи, рейтинги, вхід через Google; розгортання фронтенду на Vercel
Biome один інструмент на лінт і форматування
Vitest, fast-check, Playwright властивісні тести для формул; справжні події клавіатури в браузері
Самостійно розміщені шрифти без звернень до сторонніх серверів, працює без мережі (data-sources)

Як запустити

Потрібні Node 24.19.0 і pnpm (версія закріплена в packageManager; corepack enable підтягне її). Для навчання не потрібні ні змінні середовища, ні Docker, ні акаунти.

pnpm install
pnpm dev            # сервер розробки
pnpm build          # production-збірка; на ній ганяються e2e
pnpm preview        # показати production-збірку локально

Щоб працювали перегони, групи й вхід, потрібен проєкт Supabase: скопіюйте .env.example у .env.local і задайте VITE_SUPABASE_URL та VITE_SUPABASE_ANON_KEY до pnpm build (обидва значення публічні за задумом: ключ захищає RLS, а не таємниця). Налаштування бекенду крок за кроком описано в .env.example.

Перевірки

pnpm check          # typecheck + lint + модульні тести
pnpm typecheck      # tsc --noEmit по всьому робочому простору
pnpm lint           # Biome
pnpm test           # Vitest: модульні й властивісні тести
pnpm data:check     # перезібрати словники в пам’яті й порівняти з закоміченими
pnpm test:e2e       # Playwright, Chromium, разом з аудитом доступності axe
pnpm test:e2e:input # шлях вводу в Chromium, Firefox і WebKit
pnpm test:e2e:cdp   # сценарій зі змодельованою фізичною розкладкою ЙЦУКЕН (лише Chromium)
pnpm test:latency   # затримка від натискання до малювання

Перший запуск e2e потребує pnpm exec playwright install --with-deps.

pnpm data і pnpm data:check читають сирий знімок словників організаторів у tasks/Typing-Race-2026-Hackathon/dictionaries/ (його не комітимо). У чистому клоні без знімка data:check завершується з кодом 2 й нічого не перевіряє; закомічені дані при цьому все одно перевіряє pnpm test: тести банків слів читають лише data/derived/ (немає нецензурних слів, чужих літер, перелічених русизмів; частота й контрольні суми збігаються зі звітом). Три перевірки §8.6–8.8 (кодування, контрольні суми сировини, відтворюваність) доводяться й без знімка: тест tools/data/pipeline.synthetic.test.ts сам пише крихітний знімок із справжнім CHECKSUMS.sha256 і проганяє через нього весь конвеєр.

GitHub Actions на кожному pull request і пуші в main ганяє чотири job:

  • checks: typecheck, lint, модульні тести, збірка з бюджетом початкового JS;
  • e2e: усі сценарії в Chromium, сценарії з реальними подіями клавіатури через CDP, шлях вводу додатково у Firefox і WebKit;
  • e2e against a local Supabase: supabase start піднімає з міграцій і функцій цього репозиторію Postgres, Auth, REST, Realtime і Edge-середовище; застосунок збирається проти нього, і біжать сценарії @backend (групи, синхронізація, перегони на двох браузерах, у тому числі на реальних клавішах) та набір атак на сервер. До живого проєкту CI не звертається ніколи;
  • secret scan: gitleaks.

Станом на 2026-10-03: 758 модульних і властивісних тестів, 270 сценаріїв e2e в Chromium (42 з них, позначені @backend, біжать у job із локальним Supabase) і 6 у проєкті CDP. Початковий JS у production-збірці: 147,0 КБ gzip при бюджеті 150 КБ, який ламає збірку в разі перевищення; запас малий, тож нове в початковий бандл вносимо лише ліниво. Lighthouse (десктоп) на розгорнутому сайті за аудитом 2026-10-02: 100/100/100/100 на Головній, Мапі, екрані вправи й Профілі, на «Про гру» 98/100/100/100. Сценарій демонстрації для журі (§9 специфікації) пройдено одним тестом e2e/jury.spec.ts; кожен основний екран перевіряється на 1024×768 без бокового скролу й порушень доступності. Що саме захищено й чим перевірено: docs/security.md.

Сценарії @backend локально з .env.local (живий URL) створили б тестові акаунти в живому проєкті; для перевірки без бекенду використовуйте pnpm exec playwright test --grep-invert @backend.

Обмеження

  • Лише дві розкладки: ЙЦУКЕН і QWERTY. Мобільного навчання немає: потрібна фізична клавіатура.
  • Браузер не каже, яка розкладка ОС активна. Ні getLayoutMap(), ні події зміни розкладки цього не дають, тож застосунок виводить її з літер, які учень надрукував. Перед стартом він просить натиснути літеру, а в перегонах на хибній розкладці пояснює, чому курсор не рухається. Автоматичні тести не можуть перемкнути розкладку ОС; ґ й апостроф на macOS не перевірено на справжньому Mac (docs/pedagogy.md).
  • Клавіші, яких немає у вправах. Схема пальців QWERTY малює лише клавіші, що виробляють підтримувані символи. [, ], / і клавіша зворотного апострофа за таблицею вимог належать правому мізинцю, але в схемі їх немає, бо жодна вправа їх не вживає.
  • Другий пристрій гостя. Якщо увійти в акаунт Google, який уже має дані, спроби цього пристрою додаються до нього, а перегони анонімного гостя лишаються під його гостьовим ніком і не зливаються (ADR-0006).
  • Немає експорту й імпорту прогресу файлом (прогрес переноситься входом через Google), редактора власного курсу, додаткових розкладок.
  • Затримку «натискання → кадр» вимірює pnpm test:latency, але в headless-середовищі нижня межа виміру близько 15–17 мс, тож вимогу «менше 16 мс» там не довести; JS займає близько 1 мс на натискання.

Дані й ліцензії

Слова Етапу 2 і 3 беруться з наданих організаторами знімків відкритих словників після очищення скриптом pnpm data; похідні дані лежать у data/derived/ і поширюються за CC BY-SA 4.0, сирі знімки не комітяться. Джерела, їхні ліцензії та спосіб використання: docs/data-sources.md, у застосунку сторінка «Ліцензії». Шрифти розміщено самостійно, їхні ліцензії теж у docs/data-sources.md.

Використання ШІ

Проєкт створено однією людиною разом з агентом Claude Code. Агент планував, писав код, тести й документи, людина ухвалювала рішення. У самому застосунку ШІ не використовується: базові уроки, вправи й рекомендації обчислюються правилами без жодної моделі. Повна декларація з перевіркою: docs/ai-use.md.

Документи

Документ Про що
docs/jury-guide.md карта для рецензента: умови §11, перевірки §8, сценарій §9, критерії §10 з посиланнями на файли й тести
docs/pedagogy.md чому програма вчить саме так: палець на клавішу, етапи, лічба помилок, режим без підглядання
docs/data-sources.md джерела вмісту, їхні ліцензії, заміри, шрифти
docs/security.md модель загрози, шари захисту, два набори атак, знахідки й виправлення, чого немає
docs/ai-use.md декларація про використання ШІ
docs/adr/ чинні рішення: скоуп, шлях вводу, метрики, архітектура, акаунт
docs/research/ звіти досліджень із посиланнями на першоджерела
CONTEXT.md словник предметної області
CLAUDE.md інструкція для агентів: як організована робота

Документи для агентів (CLAUDE.md, docs/adr/, CONTEXT.md) англійською; документи для журі українською.

Планувальні артефакти першої половини роботи — карта рішень із 24 тікетами, конституція, п’ять пакетів Spec Kit — заархівовано 2026-09-30 у git-тег archive/process-harness-2026-09-30. Вони описували процес, а не продукт; чинні рішення з них зведено в docs/adr/.

Ліцензія

Код розповсюджується за ліцензією MIT: LICENSE. Похідні дані в data/derived/ мають власну ліцензію, CC BY-SA 4.0; ліцензії шрифтів і джерел даних: docs/data-sources.md.

About

Браузерний тренажер сенсорного набору (uk/en): три етапи навчання, аналітика ритму й помилок, гонки в реальному часі

Resources

Security policy

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages