- PVSM.RU - https://www.pvsm.ru -

Как мы писали Clojure Cup в этом году: The Hat

Идея для Clojure Cup [1] этого года родилась примерно вот здесь:

Как мы писали Clojure Cup в этом году: The Hat
(город Вырица, Ленобласть)

Ожидая обратную электричку мы убивали время, как могли, и грустили, что под рукой нет чего-то вроде Alias'а или Шляпы — всё же салонные игры это интеллигентнее, чем косплей гопоты в заброшке. TL;DR:

Как мы писали Clojure Cup в этом году: The Hat

Играть: http://playthehat.com [2] (ещё с багами и не работает не на хроме, мы не можем править до окончания голосования судей)
Голосовать: https://clojurecup.com/#/apps/thehat [3]

Более длинная версия поста — ниже.

Подготовка

В прошлом году мы выиграли Clojure Cup в немалой части из-за того, что начали готовиться примерно за месяц. Что понимать под «готовиться»? Собрать команду; придумать идею; собрать предполагаемые библиотеки и попробовать слепить из них что-то полезное (в прошлом году это был clony [4]); порисовать дизайн и экраны на бумаге; желательно, приготовить блог и всякое такое. В этом году я слишком расслабленно подошёл к подготовке и в итоге многие вещи пришлось делать по ходу — например, выбрали идею приложения из десятка вариантов мы примерно за сутки до начала соревнований. Также команда в этом году выглядела немного по-другому (я, Саша Пантюхов [5], Саша Сорокоумов [6], Саша Шер [7]; Саша Дину [8] не смог играть с нами в этот раз), поэтому победоносное название DEFDERP [9] мы сменили на WocPocPoc [3]. Так как команда снова была распределённой (Петербург, Москва и Мюнхен), основными методами коммуникации и синхронизации усилий стали Trello, Flowdock (он крайне удобен, особенно при интеграции с GitHub'ом, Trello и деплойментом) и Google Hangouts.

Наконец, после горячей дискуссии в Hangouts к началу соревнований у нас были рисунки интерфейса на бумаге и отдалённое представление о том, что и как мы будем писать.

Первый день

Мы специально взяли достаточно простую идею, планируя вместо реализации сложных алгоритмов добиться идеальной работоспособности и отполированного интерфейса. План частично оправдал себя — степень работоспособности The Hat в этом году многократно выше, чем CodeNotes в прошлом.

В первый день я занимался в основном разным инфраструктурным, пока Саша Пантюхов рисовал экраны (кстати, классный вид что CodeNotes [10], что The Hat [2] — его рук дело, зависть-зависть), а два других Саши занимались реализацией логики игры. В ходе написания выяснилось, что figwheel [11] абсолютно, сказочно божественен и очень облегчает вёрстку, особенно под несколько девайсов сразу: http://instagram.com/p/tce_F3FVe6/ [12]

Ближе к вечеру я обратил внимание, что большая часть команд уже сделала хоть какой-то landing, а мы нет, и решил быстро сделать стильную страницу и нам. Я давно хотел написать Poisson disc sampling [13], но (как это часто бывает) отладка затянулась и я потратил на это примерно в четыре раза больше времени, чем планировал. Тем не менее, после примерно 8 часов страдания получилось вот что (к чистому семплингу здесь добавлена маска из невидимого canvas'а): http://voting.playthehat.com/landing/ [14] Конечно, это overkill, но команда отлично справлялась и без меня :)

К вечеру первого дня у нас было уже рабочий, но немного глючный webapp и мы занялись деталями, составлением словарей (важная часть хорошего геймплея для игр такого рода) и тестированием.

Деталями, например, такого рода:

Как мы писали Clojure Cup в этом году: The Hat

В какой-то момент мы поняли, что на игровом экране не очень понятно, кто сейчас ходит, а полоски с нулевым счётом смотрятся очень плохо; обе проблемы частично решились добавлением неактивной области слева, стрелка в которой обозначает текущую команду. Fun fact: мы не смогли придумать, как сделать понятный и красивый экран выбора количества команд и оставили только две.

Словарями же занялся Саша Сорокоумов. После небольшой дискуссии мы решили, что составлять их целиком руками бессмысленно, поэтому, например, для Computer Science мы взяли тексты SICP и AIMA и прошлись по ним POS-tagger'ом из Stanford CoreNLP [15], оставляя только существительные, посчитали TF-IDF, взяли не самые редкие слова и проконтролировали результат на адекватность и сложность вручную.

Второй день

Во второй день Саши продолжили полировать приложение, а я занялся звуком. По правилам, которые мы адаптировали для этой игры, после окончания времени хода последнее слово могут угадывать обе команды; но тогда нужно сделать слежение за оставшимся временем более простым для второй команды. Использовать готовые WAV-файлы недостаточно стильно, поэтому нотификация синтезируется через Web Audio API [16] (плюс Vibration API [17], если он поддерживается устройством).

В процессе тестирования выяснился забавный момент: на 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 [18] и ВНЕЗАПНО прикрутил его, попутно подперев наш деплоймент дополнительным костылём вида

echo "# `date`" >> cache.manifest

чтобы заставить клиентские браузеры всё-таки вытягивать обновлённую версию приложения. Благодаря этому The Hat отлично работает даже в Airplane Mode: http://instagram.com/p/tgl4tCFVdZ/ [19]

Наконец, незадолго до конца мы сделали то, что хотели сделать ещё в прошлом году — записали демо-видео:

Возможно, чуть позже мы выложим нарезку из неудавшихся дублей, которых было около десяти :)

Планы на будущее (когда голосование судей закончится):

  • починить звук;
  • починить игру в браузерах, которые не Chrome;
  • ускорить анимацию смены карты (уже было несколько жалоб на это);
  • сделать русскую версию.

В целом я очень доволен Clojure Cup этого года, несмотря на то, что и в пользовательском голосовании [20], и в голосовании жюри The Hat прямо сейчас не очень популярен (здесь должна быть картинка с грустной пандой). Я узнал много нового, написал много хорошего кода в замечательной компании (спасибо, Саши, вы очень крутые!) и принял участие в написании приложения, которое сам же и буду использовать. Кроме того, сам Clojure Cup отлично организован что в этом году, что в прошлом  — очень рекомендую принять участие в следующем году!

И да, последнее, но тоже важное: проголосуйте за нас на https://clojurecup.com/#/apps/thehat [3], залогинившись через твиттер :)

Автор: si14

Источник [21]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/programmirovanie/70866

Ссылки в тексте:

[1] Clojure Cup: http://clojurecup.com

[2] http://playthehat.com: http://playthehat.com

[3] https://clojurecup.com/#/apps/thehat: https://clojurecup.com/#/apps/thehat

[4] clony: https://github.com/si14/clony/

[5] Саша Пантюхов: https://twitter.com/alwxtwi

[6] Саша Сорокоумов: https://twitter.com/ASorokoumov

[7] Саша Шер: https://github.com/sherpc

[8] Саша Дину: https://twitter.com/aluuu

[9] DEFDERP: http://2013.clojurecup.com/

[10] CodeNotes: https://codenotes.me

[11] figwheel: https://github.com/bhauman/lein-figwheel

[12] http://instagram.com/p/tce_F3FVe6/: http://instagram.com/p/tce_F3FVe6/

[13] Poisson disc sampling: http://www.jasondavies.com/poisson-disc/

[14] http://voting.playthehat.com/landing/: http://voting.playthehat.com/landing/

[15] Stanford CoreNLP: http://nlp.stanford.edu/software/corenlp.shtml

[16] Web Audio API: https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API

[17] Vibration API: https://developer.mozilla.org/en-US/docs/Web/Guide/API/Vibration

[18] HTML5 AppCache: https://developer.mozilla.org/en-US/docs/Web/HTML/Using_the_application_cache

[19] http://instagram.com/p/tgl4tCFVdZ/: http://instagram.com/p/tgl4tCFVdZ/

[20] пользовательском голосовании: http://voting.playthehat.com/

[21] Источник: http://habrahabr.ru/post/239191/