Сделал сыну тренажёр слепой печати, потому что существующие показались ему скучными

в 15:44, , рубрики: pet-project, React, TypeScript, UX, анализ ошибок, анимация, клавиатурный тренажер, слепая печать

Я фронтенд‑разработчик. Этой осенью сын пошёл в пятый класс, и с началом информатики я заметил, насколько медленно он печатает. Со смартфоном он на «ты», а за обычной клавиатурой теряется.

За компьютер мы его специально не усаживали: в начальной школе он пользовался им в основном для учебных тестов. Стало понятно, что пора подтягивать компьютерную грамотность. Решили начать с базового навыка — печати.

Мы попробовали несколько известных тренажёров: какие‑то я помнил сам, какие‑то нашли в поиске. Одни сыну не понравились визуально, в других мне не хватало понятной схемы пальцев и анализа слабых мест. Особенно хотелось, чтобы пользователь видел не только нужную клавишу, но и конкретный палец.

Так появилась идея сделать свой тренажёр. Заодно хотелось прощупать у сына интерес к IT, сделать современный интерактивный дизайн и добавить больше визуала прогресса и игровых элементов.

Понятно, что клавиатурных тренажёров уже много. Но мне было интересно не просто реализовать ещё один, а попробовать решить несколько задач: сделать понятную ребёнку схему пальцев с ярким интерактивом, научиться определять слабые места по реальным нажатиям и на их основе автоматически собирать персональные упражнения.

Первый экран тренировки: подсвечиваются нужная клавиша и палец.

Первый экран тренировки: подсвечиваются нужная клавиша и палец.

Чего мне не хватало в существующих тренажёрах

Делать обычный тренажёр, который просто выдаёт случайный текст или набор символов, не хотелось. Хотелось чем‑то выделиться. Подробного ресерча я не проводил, но в том, что мы пробовали, подобного не увидели.

Первая идея — анализ ошибок. Ты печатаешь, тебе показывают скорость и процент ошибок, и всё. А ведь по ошибкам понятно, что именно у человека не получается.

Вторая вытекает из первой: тренировка слабых мест. Если ты постоянно промахиваешься по «Ж» или путаешь сочетания правой руки, логично давать больше упражнений именно на них, а не гонять весь алфавит по кругу. Мне встречались «тренировки слабых мест», но это был просто линейный список упражнений без какого‑либо анализа.

Как это все реализовано

Стек обычный для меня: React + TypeScript и React Query на фронте, Node.js, PostgreSQL и Prisma на бэкенде.

Тренажёр запоминает каждое нажатие, не только ошибки: какую букву надо было нажать, какую нажали на самом деле и сколько на это ушло времени. Вся эта история сохраняется вместе с результатом урока, а считается всё уже в браузере.

Первая версия была совсем простой: процент ошибок по каждой букве за всё время. Но быстро вылезли две проблемы. Если ты когда‑то путался в букве, а потом научился, она всё равно числится «слабой». А если по букве было всего пять нажатий и две опечатки, она вдруг становится «самой худшей».

Поэтому сейчас логика такая:

  • по каждой букве смотрим только последние 60 нажатий;

  • старые ошибки со временем «остывают»: каждые две недели вес ошибки уменьшается вдвое;

  • если по букве пока мало данных, тренажёр ей меньше доверяет и не спешит записывать в проблемные;

  • если последние 20 нажатий прошли без ошибок, буква сразу считается выученной, и ждать, пока забудутся старые ошибки, не нужно.

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

Кроме отдельных букв тренажёр смотрит и на сочетания. Например, если после «О» ты часто промахиваешься по «В», проблемной считается пара «ОВ». Сочетания берутся только из обычного текста, а не из тренировочных наборов букв, иначе статистика была бы искусственной.

Слабые места считаются по свежим попыткам: отдельно по буквам и частым заменам.

Слабые места считаются по свежим попыткам: отдельно по буквам и частым заменам.

Из трёх самых слабых букв и двух самых слабых сочетаний собирается персональная тренировка: сначала слоги, потом слова, потом предложения. Самая проблемная буква попадается чаще всех, остальные реже, и это не случайность, а чёткое чередование по кругу. После тренировки видно, как изменился процент ошибок по каждой букве: было и стало.

Ещё одна мелочь для честной статистики: если переключиться в другую вкладку или окно, упражнение встаёт на паузу и секундомер останавливается. Тренажёр предлагает продолжить, и отсчёт идёт дальше только после возвращения.

При уходе на другую вкладку тренировка и таймер автоматически ставятся на паузу.

При уходе на другую вкладку тренировка и таймер автоматически ставятся на паузу.

Самое сложное для меня — руки

Больше всего времени ушло не на бэкенд и не на алгоритм, а на анимацию рук. Хотелось, чтобы было видно не просто подсвеченную клавишу, а какой палец нажимает и как рука к ней тянется.

Нарисовать красивые руки вектором сложно, а обычную картинку нельзя подсветить по отдельным пальцам. Поэтому я сделал гибрид: снизу лежит обычная растровая картинка рук, а поверх неё невидимые векторные контуры каждого из десяти пальцев. Когда нужно подсветить палец, его контур закрашивается цветом. Подсветка плавно растворяется к ладони, поэтому выглядит так, будто светится сам палец на картинке.

Положение руки рассчитывается относительно нужной клавиши — координаты для каждой клавиши не захардкожены.

Положение руки рассчитывается относительно нужной клавиши — координаты для каждой клавиши не захардкожены.

Картинка на экране одна и та же, но показана дважды: одна копия обрезана до левой руки, другая до правой. Так каждая рука двигается сама по себе.

Чтобы рука дотягивалась до нужной клавиши, я не храню никаких таблиц координат. Тренажёр просто смотрит, где на экране находится клавиша и где кончик нужного пальца, и сдвигает руку на разницу. Если поменять вёрстку клавиатуры, руки всё равно попадают куда надо.

По дороге было несколько граблей:

  • если мерить положение пальца, пока рука ещё едет от прошлой клавиши, замер получается неправильным, и рука промахивается. Пришлось перед замером мгновенно возвращать её в исходную точку;

  • на ноутбуках с небольшим экраном весь тренажёр немного уменьшен, и координаты приходилось пересчитывать с учётом масштаба;

  • руки иногда наезжали друг на друга, пришлось их раздвигать;

  • большой палец лежит на пробеле боком, и для него расчёт пришлось делать отдельно.

Ещё одна мелочь, которой я доволен. Когда нажимаешь одну и ту же букву несколько раз подряд, анимация нажатия пальца сначала срабатывала только один раз. Решилось неожиданно просто: я сделал две одинаковые анимации с разными названиями и переключаю их на каждое нажатие. Браузер думает, что анимация новая, и проигрывает её заново.

Звук нажатия, кстати, не записан в файл, а генерируется прямо в браузере: это короткий щелчок из шума.

Тестирование на главном пользователе

Главным тестировщиком, конечно, был сын. И он быстро показал вещи, которые взрослому в голову не придут.

Например, ему было непонятно, что Shift надо зажимать, а не нажимать. Он нажимал Shift, отпускал, потом нажимал букву и не понимал, почему не выходит заглавная. Для нас это очевидно, а для ребёнка, который раньше клавиатурой почти не пользовался, нет.

В итоге для Shift появилась подсказка в три шага: «Зажми Shift → Нажми букву → Отпусти Shift». На самой клавише Shift пульсирует надпись «Зажми», потом «Держи». А если отпустить Shift раньше времени, тренажёр так и говорит: «Не отпускай Shift».

Сделал сыну тренажёр слепой печати, потому что существующие показались ему скучными - 5

Для Shift появилась отдельная пошаговая подсказка: зажать → нажать букву → отпустить.

После таких случаев я стал внимательнее смотреть на всё, что мы, опытные пользователи, считаем само собой разумеющимся. 

Сын сейчас проходит 1–2 урока в день и старается следить прежде всего за точностью, а не за скоростью. Сейчас он печатает примерно 40 знаков в минуту.

Где помог ИИ, а где оказалось быстрее самому

Проект я делаю один, в свободное время, и честно использую ИИ‑агентов там, где моих знаний не хватает. В основном это бэкенд: как фронтендеру мне было бы сильно дольше разбираться самому. ИИ помогает и с дизайном: ему можно задать направление, и он предлагает довольно креативные решения. А если подключить плагин в Figma, можно заранее прорабатывать дизайн и потом переносить его в разработку.

Во фронтенде опыт вышел противоположный. Когда не было времени править самому и я отдавал баг агенту, иногда приходилось просить исправить его несколько раз подряд. В итоге я всё равно открывал код и правил руками, только уже потеряв время. 

Что пришлось сделать с публичными страницами

Сам тренажёр работает как клиентское React‑приложение, но для публичных страниц мне хотелось отдавать поисковикам готовый HTML. Поэтому главная и несколько информационных страниц пререндерятся на этапе сборки, а затем React гидратирует их через hydrateRoot. Страницы самого тренажёра оставил полностью клиентскими: поисковой индексации там всё равно делать нечего.

Где проект сейчас

Скажу честно: пользователей пока почти нет. Тренажёром пользуются в основном друзья и знакомые, поэтому все наблюдения выше — это пока ранний этап, а не выводы по большой выборке.

Сейчас в SkillTap есть уроки от отдельных букв до предложений с подсказками по пальцам, тест скорости печати, поиск слабых клавиш, персональные тренировки и статистика прогресса. Если кому‑то интересно посмотреть реализацию целиком, проект работает на https://skill‑tap.ru

Дальше хочу попробовать игровые режимы. Сын уже подкидывает идеи: например, скины для рук, которые можно открывать за заработанные в упражнениях монеты. Посмотрим, какие из этих механик действительно помогают не бросать занятия после нескольких уроков.

Вопрос к вам

Сколько вы печатаете и как вообще учились работать с клавиатурой? Особенно интересно мнение тех, у кого есть дети: учили их печатать специально или навык появился сам?

И отдельно интересно мнение разработчиков: как бы вы определяли «слабую» клавишу — только по ошибкам или учитывали бы ещё и время до нажатия? Я это время уже сохраняю, но пока не использую в расчётах.

Автор: Dadfront

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js