Идея для Clojure Cup этого года родилась примерно вот здесь:
(город Вырица, Ленобласть)
Ожидая обратную электричку мы убивали время, как могли, и грустили, что под рукой нет чего-то вроде Alias'а или Шляпы — всё же салонные игры это интеллигентнее, чем косплей гопоты в заброшке. TL;DR:
Играть: http://playthehat.com (ещё с багами и не работает не на хроме, мы не можем править до окончания голосования судей)
Голосовать: https://clojurecup.com/#/apps/thehat
Более длинная версия поста — ниже.
Подготовка
В прошлом году мы выиграли Clojure Cup в немалой части из-за того, что начали готовиться примерно за месяц. Что понимать под «готовиться»? Собрать команду; придумать идею; собрать предполагаемые библиотеки и попробовать слепить из них что-то полезное (в прошлом году это был clony); порисовать дизайн и экраны на бумаге; желательно, приготовить блог и всякое такое. В этом году я слишком расслабленно подошёл к подготовке и в итоге многие вещи пришлось делать по ходу — например, выбрали идею приложения из десятка вариантов мы примерно за сутки до начала соревнований. Также команда в этом году выглядела немного по-другому (я, Саша Пантюхов, Саша Сорокоумов, Саша Шер; Саша Дину не смог играть с нами в этот раз), поэтому победоносное название DEFDERP мы сменили на WocPocPoc. Так как команда снова была распределённой (Петербург, Москва и Мюнхен), основными методами коммуникации и синхронизации усилий стали Trello, Flowdock (он крайне удобен, особенно при интеграции с GitHub'ом, Trello и деплойментом) и Google Hangouts.
Наконец, после горячей дискуссии в Hangouts к началу соревнований у нас были рисунки интерфейса на бумаге и отдалённое представление о том, что и как мы будем писать.
Первый день
Мы специально взяли достаточно простую идею, планируя вместо реализации сложных алгоритмов добиться идеальной работоспособности и отполированного интерфейса. План частично оправдал себя — степень работоспособности The Hat в этом году многократно выше, чем CodeNotes в прошлом.
В первый день я занимался в основном разным инфраструктурным, пока Саша Пантюхов рисовал экраны (кстати, классный вид что CodeNotes, что The Hat — его рук дело, зависть-зависть), а два других Саши занимались реализацией логики игры. В ходе написания выяснилось, что figwheel абсолютно, сказочно божественен и очень облегчает вёрстку, особенно под несколько девайсов сразу: http://instagram.com/p/tce_F3FVe6/
Ближе к вечеру я обратил внимание, что большая часть команд уже сделала хоть какой-то landing, а мы нет, и решил быстро сделать стильную страницу и нам. Я давно хотел написать Poisson disc sampling, но (как это часто бывает) отладка затянулась и я потратил на это примерно в четыре раза больше времени, чем планировал. Тем не менее, после примерно 8 часов страдания получилось вот что (к чистому семплингу здесь добавлена маска из невидимого canvas'а): http://voting.playthehat.com/landing/ Конечно, это overkill, но команда отлично справлялась и без меня :)
К вечеру первого дня у нас было уже рабочий, но немного глючный webapp и мы занялись деталями, составлением словарей (важная часть хорошего геймплея для игр такого рода) и тестированием.
Деталями, например, такого рода:
В какой-то момент мы поняли, что на игровом экране не очень понятно, кто сейчас ходит, а полоски с нулевым счётом смотрятся очень плохо; обе проблемы частично решились добавлением неактивной области слева, стрелка в которой обозначает текущую команду. Fun fact: мы не смогли придумать, как сделать понятный и красивый экран выбора количества команд и оставили только две.
Словарями же занялся Саша Сорокоумов. После небольшой дискуссии мы решили, что составлять их целиком руками бессмысленно, поэтому, например, для Computer Science мы взяли тексты SICP и AIMA и прошлись по ним POS-tagger'ом из Stanford CoreNLP, оставляя только существительные, посчитали TF-IDF, взяли не самые редкие слова и проконтролировали результат на адекватность и сложность вручную.
Второй день
Во второй день Саши продолжили полировать приложение, а я занялся звуком. По правилам, которые мы адаптировали для этой игры, после окончания времени хода последнее слово могут угадывать обе команды; но тогда нужно сделать слежение за оставшимся временем более простым для второй команды. Использовать готовые WAV-файлы недостаточно стильно, поэтому нотификация синтезируется через Web Audio API (плюс Vibration API, если он поддерживается устройством).
В процессе тестирования выяснился забавный момент: на iPhone'ах Web Audio при заходе на страницу отключен и получает возможность воспроизводить что-либо только в том случае, если это происходит в ответ на действие пользователя (например, в onClick). К счастью, после воспроизведения чего-либо в handler'е Web Audio по-прежнему остаётся активен, поэтому проблема решилась одноразовым воспроизведением очень короткого и тихого звука на touchStart.
Наверное, самым грустным моментом из всего Clojure Cup этого года для меня стало то, что в итоге в продакшн мы залили вариант с неработающим звуком. В какой-то момент мы сломали его, не заметили этого вовремя и я не успел поправить это за час до конца соревнований.
Отдельной и важной для нас целью было сделать так, чтобы приложение работало максимально хорошо даже при сомнительном качестве мобильного коннекта. Отсюда вытекает решение заинлайнить в итоговый .js словари, тщательная минимизация количества загружаемых файлов (один .js, один .css и шрифт), выставленный в максимум expires в nginx'е (мы добавляем часть хеша статики в url'ы в процессе деплоймента для cache busting) и компрессия. Удивительно, но в Интернете очень мало (по сравнению со сжатием «на лету») упоминается модуль gzip_static, отдающий .gz-версии статических файлов, если они есть; вся наша статика сжата с gzip -9 при деплойменте.
За несколько часов до конца я открыл для себя HTML5 AppCache и ВНЕЗАПНО прикрутил его, попутно подперев наш деплоймент дополнительным костылём вида
echo "# `date`" >> cache.manifest
чтобы заставить клиентские браузеры всё-таки вытягивать обновлённую версию приложения. Благодаря этому The Hat отлично работает даже в Airplane Mode: http://instagram.com/p/tgl4tCFVdZ/
Наконец, незадолго до конца мы сделали то, что хотели сделать ещё в прошлом году — записали демо-видео:
Возможно, чуть позже мы выложим нарезку из неудавшихся дублей, которых было около десяти :)
Планы на будущее (когда голосование судей закончится):
- починить звук;
- починить игру в браузерах, которые не Chrome;
- ускорить анимацию смены карты (уже было несколько жалоб на это);
- сделать русскую версию.
В целом я очень доволен Clojure Cup этого года, несмотря на то, что и в пользовательском голосовании, и в голосовании жюри The Hat прямо сейчас не очень популярен (здесь должна быть картинка с грустной пандой). Я узнал много нового, написал много хорошего кода в замечательной компании (спасибо, Саши, вы очень крутые!) и принял участие в написании приложения, которое сам же и буду использовать. Кроме того, сам Clojure Cup отлично организован что в этом году, что в прошлом — очень рекомендую принять участие в следующем году!
И да, последнее, но тоже важное: проголосуйте за нас на https://clojurecup.com/#/apps/thehat, залогинившись через твиттер :)
Автор: si14