Category: it

Записи ЗАГСа и машинное обучение #ulsk

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

Давайте посмотрим. Пять миллионов записей. Шесть тысяч рублей в месяц зарплата легковооружённого дроида, 6 часов работы в день. Каждая загсовская запись — это, скажем, 30 секунд работы по вбиванию. Может даже минута.

5000000 / (4 * 5 * 6 * 60) / 2 = 347 месяцев работы одного человека, или около двух миллионов рублей денег только на зарплату. Если мы хотим оцифровать пять лямов за год, а не за 30 лет, нам понадобятся 30 человек.

Никакой погоды эти тридцать data-entry человек в масштабах Ульяновского «айти» не сделают.

Зато если потратить эти два лимона на двух аспирантов в годовом проекте оптического распознавания этой всей хрени, это получится три тысячи долларов в месяц на каждого аспиранта. И это в результате будет хайтек-проект, который затем можно будет тиражировать по стране, а то и дальше. Это высокотехнологический, среднерисковый проект, который может масштабироваться далеко за пределы ульяновской области.

Почему машинное распознавание рукописного текста в данном случае не является бредом?

  • Это считывание из фиксированной формы, это упрощает.
  • Имена, отчества, названия населённых пунктов повторяются, и OCR может быть натренирована на них целиком.
  • Данные не являются секретными, поэтому то, что не распозналось, можно засылать в РеКапчу. Ну или сделать какой-нибудь порносайт, и в качестве пароля туда просить распознать задетектированное слово или предложение.

Если области хочется вложиться в IT (на самом деле, CS, Computer Science), то на порядок лучше вложить его в политех, где есть необходимая компетенция по нейронным сетям и машинному обучению, чем тренировать 30 бабушек.

Лютый апгрейд подхода к обучению программированию

Вы наверняка уже знаете, что известнейшая Khan Academy, являющаяся пионером по онлайн-образованию школьников, совсем недавно выпустила интерактивные курсы по программированию. В качестве платформы используется JavaScript и библиотека Processing. Вполне логичный и достойный выбор, всячески поддерживаем и одобряем. JavaScript очень даже неплох в качестве первого языка программирования, да и потом в жизни почти каждого инженера он тем или иным образом пригодится. В нашей компании JavaScript вообще является основой бизнеса, ибо «Продукт есть интерфейс».



Брет Виктор — исследователь и визионарий новых интерфейсов человеко-машинного взаимодействия. Я уже писал о нём в моей заметке «Интерфейсы и инструменты»:
Программистам и дизайнерам интерфейсов посвящается. Настолько мощная презентация от изобретателя новых концепций пользовательского интерфейса в Apple, что одним ретвитом @stevebest не обойдёшься.

Так вот, этот самый Брет Виктор сказал, что этот Хан-Академийский интерфейс для обучения программированию — фуфло и туфта.



А так как Брет человек дела, а не только слова, то он написал не просто аргументированную критику связки JS+Processing, использующуюся в курсах Khan Academy, но и потрудился тщательнейшим образом реконструировать возможный интерфейс правильной системы для обучения. Эта работа Брета показалась мне настолько увлекательной, что в голове постоянно крутятся слова seminal paper в применении к данной работе. Это действительно работа мастера. Всем программистам и дизайнерам интерфейсов читать полностью, без вариантов и отмазок.

Читаем: Learnable Programming


В своей работе Брет постепенно, подход за подходом, прилагает очередную мощную идею из своего списка идей и ценностей проектирования интерфейса, и доходит до захватывающих результатов. При этом, его примеры — это не просто картинки, а живые видео-иллюстрации. Это нужно видеть!



Ближе к концу Брет отвлекается от проектирования надстройки над JavaScript, и делится видением по поводу метафор, стоящих за языками программирования.
Каждый язык программирования наполнен метафорами, но некоторые ложатся на мозг лучше, чем другие. Стандартный императивный подход использует метафору «присвоение переменным» — перемещение битов между маленькими коробочками. В отличие от черепашки Logo, эта метафора не была спроектирована для того, чтобы соответствовать тому, как люди учатся и понимают; она просто эволюционировала как тонкий слой над метафорами, использующимися в архитектуре низлежащей машины, такими как «сохранение в памяти».*

* Алан Кей в «The Early History of Smalltalk»: «Операторы присваивания — даже абстрактные — выражают очень низкоуровневые цели... Люди-программисты не являются машинами Тьюринга, и чем меньше их программные системы требуют техники от Тьюринг-машин, тем лучше.»

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

Из дальнейшего рассмотрения метафор, на которых построены некоторые другие языки программирования, мы видим, что Smalltalk (или тот же Erlang, если читать между строк) предоставляют очень вкусную метафору посылки сообщений между объектами. «Эта очень мощная метафора, потому что ролевые игры и разговоры являются мощными встроенными человеческими свойствами.»

Далее Брет Виктор цитирует одного из авторов языка Haskell:
Когда программист пишет модульную программу для решения задачи, он сначала разбивает задачу на подзадачи, затем решает подзадачи, и в конце концов объединяет решения. Способы, которыми программист может разбить оригинальную проблему, напрямую зависят от способов, которыми он сможет затем склеить решения вместе. Следовательно, для увеличения чьей-то способности модуляризировать задачи в принципе, нужно обеспечить новые типы клея в языках программирования.

Функциональные языки обеспечивают два новых, очень важных типа клея... Это ключевая вещь, обеспечивающая мощность функционального программирования — оно позволяет улучшенную модуляризацию.

Что касается среды Processing (изначально это библиотека для облегчения программирования графики для Java, но теперь доступна и на JavaScript, именно её использует Khan Academy):
Недостатки модульности среды Processing являются серьёзными барьерами для рекомпозиции. Программист не может просто взять у друга модель прыгающего мячика и положить рядом его собственного прыгающего мячика. Переменные должны быть переименованы или инкапсулированы вручную, соответствующие функции "draw" и работа с мышью должны быть переплетены друг с другом, и так далее. Можно легко начать работать с существующей программой Processing и изменять её, но язык не поощряет комбинирование двух программ.

Что ещё хуже, зависимость Processing'а от глобального состояния (там хранится графический контекст, например, матрицы трансформаций — lionet) убивает даже простейшие формы рекомпозиции.

Кстати, приводится непрямой аргумент в защиту Objective-C, который я люблю защищать именно из за этого свойства readability для новичков. В цитате ниже мысленно подставьте Objective-C вместо Smalltalk, синтаксис похожий там.
Smalltalk:canvas drawEllipseCenteredAtX:50 y:50 width:100 height:100.
Processing:ellipse(50,50,100,100);
x86 assembly:push 100; push 100; push 50; push 50; call _ellipse

В Smalltalk аргументы дают контекст. В Processing функция "ellipse" точно такая же таинственная, как и в языке ассемблера. Читатель должен подсмотреть или запомнить каждый аргумент — существенный барьер для чтения.

Для того, чтобы освободить меня от необходимости переводить и цитировать — идите и читайте сами :)

http://worrydream.com/LearnableProgramming/

Если из моих слов выше ещё не вполне понятно, то поясню: я считаю, что Брет Виктор написал очень крутую вещь. Последняя цитата:
Частый вопрос по поводу техник, которые описаны здесь: «Как это масштабируется до реального программирования?» Это очень хороший вопрос, но это примерно как спрашивать, как двигатель внутреннего сгорания сможет помочь лошадям. Вопрос подразумевает трансформацию не того рода.

P.S. Мы в Echo (aboutecho.com, echorussia.ru) очень сильно хайрим JavaScript-программистов в Ульяновск и Новосибирск. jobs@aboutecho.com

JSON parsers update

Апдейт к моему посту про JSON парсеры. Я тут связался с автором jsmn, и он починил работу с выходным массивом. Теперь по производительности парсинга jsmn минимум в пару раз обгоняет все остальные протестированные проекты: 482 мегабайта в секунду вместо 249 у наибыстрейшего конкурента. Инициализация парсинга тоже происходит быстрее. Из-за неё парсинг множества мелких JSON-объектов происходит тоже раза в два быстрее: 2.3 секунды на мой тест вместо 5.1.

Comparison and microbenchmark of #JSON parsers

Автор C++ о диспетчеризации по типам и о #Haskell

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3449.pdf

Open and Efficient Type Switch for C++

Yuriy Solodkyy, Gabriel Dos Reis, Bjarne Stroustrup


Автор C++, Страуструп сотоварищи, пишет в соавторстве статью о новой библиотеке для диспетчеризации по типам с помощью внешней интроспекции. Написано на шаблонах C++11 и оформлено в виде библиотеки. Называется Mach7. Выглядит в итоге как-то так:



Ну ничё так.

Теперь о том, что заинтересовало меня. В статье есть периодические отсылки к функциональному программированию.

Нет, не так. Давайте с начала.
В объектно-ориентированном языке без прямой поддержки алгебраических типов данных, тип, представляющий дерево выражения какого-то языка, обычно будет написан как абстрактный класс, с производными классами, реализующими более конкретные варианты.

struct Expr { virtual int eval () = 0; };
struct Value : Expr { ⋯ int eval (); int value ; };
struct Plus : Expr { ⋯ Expr& e1; Expr& e2; };


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

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

Насколько быстро теперь работает? Говорят, примерно как OCaml или Haskell:
Библиотека реализована как стандартный C++11 код с шаблонным мета-программированием и несколькими макросами. Оно работает примерно также быстро, как эквиваленты на OCaml или Haskell, и даже иногда приближается по быстродействию или даже становится быстрее написанного руками C++ кода, который использует Visitor дизайн-паттерн.

Ну это хорошо, что так быстро, как OCaml или Haskell. Вопрос, зачем при таком раскладе использовать C++, замнём для ясности.

Но дальше вообще прелесть идёт: критика паттерна Visitor!
Библиотека Mach7 и идеи в ней были мотивирована нашим неудовлетворительным опытом работы с различными C++-ными фронт-эндами и фреймворками для анализа программ. Проблема была не с самими фреймворками, но с фактом, что мы должны были использовать шаблон проектирования Visitor для того, чтобы смотреть, обходить и обогощать абстрактные синтаксические деревья целевых языков. Мы нашли Visitor-шаблоны неподходящими для прямого выражения логики приложения, удивительно сложными для обучения студентов, и часто более медленными, чем решения для обхода, написанные вручную. Вместо них, пользователи опирались на динамические приведения типов во многих местах, часто многоуровневые, таким образом предпочитая более короткий, более ясный, и более прямой код, нежели чем Visitor'ы. Соответствующий проигрыш в производительности был обычно незамечаем до более поздних стадий кодирования, когда уже было поздно что-то менять.

Ну можно поздравить C++, теперь можно на нём отдельные вещи писать почти так же коротко, ясно и почти так же быстро, как на OCaml.



Кроме функциональщины, в посте есть отсылка к лиспу, к Duff's device, и вообще, хорошая статья, надо студентам давать. C++ — это очень большой, огромный джип, и эта статья — неплохая иллюстрация.

Comparison and microbenchmark of #JSON parsers

Допустим, в вашем проекте понадобилось найти и использовать быструю библиотеку для парсинга JSON. Смотрим на json.org, там есть целый список на выбор.


Что выбрать? Давайте попробуем отсеять совсем уж шлак, совершив поверхностное сравнение качества исходного кода парсеров.
Collapse )

Сводная табличка


ProjectLicenseAPIUTF-8Neg. testsFollowersBenchmarkFinalist?Note
yajlISCSAXYY815/120249 MB/s, 5.1 sYLarge code base.
jsonslMITSAXNY10/2246 MB/s, 5.6 sYTiny source code base.
JanssonMITDOMYY234/5925 MB/s, 52 sY
csonBSD'DOMYYn/a30 MB/s, 44 sY
json-cBSDDOMYN103/4538 MB/s, 29.7 sY
json-parserBSDDOMNY276/2449 MB/s, 12.4 sYTiny! A single source file.
jsmnMITcustomNY65/416 MB/s, 3.3 s
482 MB/s, 2.3 s
YTiny!
js0npub.customNN67/10n/aN
LibUBSDN18/3n/aN
WJElementLGPLN7/2n/aN
M's JSON parserLGPLNn/an/aN
cJSONBSDNn/an/aN


Collapse )

Cache Performance of Lazy Functional Programs on Current Hardware

Arbob Ahmad and Henry DeYoung


http://www.google.com/search?q=Cache%20Performance%20of%20Lazy%20Functional%20Programs%20on%20Current%20Hardware

Cache Performance of Lazy Functional Programs on Current Hardware


Известно, что рантаймы функциональных языков зачастуют имеют отличные от императивных паттерны доступа к данным в памяти. А современные процессоры оптимизируются под паттерны поведения обычных программ, написанных на более распространённых языках.

Существует несколько исследований, показывающих, где и как функциональные языки неоптимально используют ресурсы процессора. Например, в исследовании 2002 года Nethercote и Mycroft исследовали поведение кэша при выполнении нескольких хаскель-программ, и нашли, что ожидания процессора при отсутствии данных в L2 кэше (cache miss stalls) составляли до 60% задержек при работе программ.

Товарищи из Carnegie Mellon решили ещё раз воспроизвести результаты теста 2002 года. Хардвер за десять лет поменялся довольно сильно, и хотелось определить, так ли пессимистично хаскель работает с кэшем второго уровня.

Использовали валграйндовый Cachegrind и Perf, в частности.

Короче, опредилили, что на тех же данных процессор теперь практически не ждёт на миссах в L2. В 2002 году кэша было 256k, а в 2009 году кэша было уже 4 мега.

К сожалению, они ещё внезапно нашли, что дефольтный размер для нового поколения (nursery) в GC хаскеля составляел 256 kb. То есть, старые тесты 2002 года наверняка упирались именно в то, что дефолтные значения были слишком большими для имеющегося размера кэша. В 2009 году этот же размер оказался более приемлемым.

На мой взгляд, эта находка практически полностью переводит обе статьи, и старую и новую, из подобия науки в разряд тыкания палочкой. Авторы старого исследования не заметили, что упираются в nursery, а авторы нового даже не отметили роль влияния GC-опций GHC на скорость программ. Кроме того, за семь лет изменился и характер нагрузки, а считалось всё на тех же тестах с почти теми же параметрами. Ещё одним соображением являются не абсолютные цифры неоптимальностей в хаскель-программах, а сравнения с эффективностью обычных императивных программ, написанных, скажем, на C или C++. Как поменялась относительная эффективность за эти годы? Нет ответа.
As a result, we conclude that the change in L2 cache size is responsible for most of the performance improvement.
Перевожу: «увеличили кэш, стало быстрее работать». Вау.

И всё же, даже до такого уровня исследования абсолютному большинству российских студентов пилить и пилить.

Что неделя грядущая нам готовит #ulsk

Про Ульяновские эвенты.

Originally posted by jay_is_here at Что неделя грядущая нам готовит

Давно что-то я ничего не писал сюда. Все больше по мелочи, да в facebook. Вот, решил немного поделиться планами на грядущую неделю, а она обещает быть насыщенной!

1. В среду, 12 сентября, будет день программиста. Планируется нечто конференцеподобное в «Тарелке» УлГТУ, где, среди прочих докладов, будут кратенькие 5-минутные блиц-презентации более-менее регулярных около-айтишных мероприятий. Среди прочих, будет и презентация «ИТ-посиделок», которые я периодически устраиваю. Собственно, я и буду презентовать. Из «тарелки» народ двинется в клуб «Техас», куда я тоже заскочу на час-полтора, чтобы успеть оттуда свалить до того, как все напьются.

2. В субботу, 15 сентября, пройдет «День свободы ПО». Хотя изначально я довольно скептически относился к этому мероприятию, но Михаил Дронов сделал невозможное и умудрился раскрутить его до вполне себе приличного уровня. У нас уже около десятка потенциальных докладчиков и несколько мастер-классов. Проходить вся эта движуха будет в областной научной библиотеке имени В.И.Ленина. Вроде бы как планируется видео-трансляция, запись докладов и «телемост» с другими группами, отмечающими SFD в России.

Я планирую рассказать о том, почему участие в конференциях и открытых проектах - это полезно и интересно, о грантах в открытых проектах и о том, почему сейчас уже практически нельзя себе позволить не уметь работать с Linux. Рекомендую попасть на этот доклад студентам профильных специальностей, потому что там будет много полезных вещей, которые в ВУЗах вам вряд ли расскажут.

Еще один очень важный доклад для будущих и настоящих программистов сделает Михаил. Он расскажет о свободных лицензиях, об их особенностях и о совместимости лицензий. Это нужно знать, чтобы не попадать в неприятные ситуации, когда заимствованный код или библиотека вдруг оказываются несовместимыми по лицензиям со схемой распространения программного продукта, принуждая либо открыть код всей вашей разработки, либо удалить «несовместимый» код. К сожалению, этого вы в университетах тоже пока не услышите, хотя наметки есть.

Есть еще пара готовящихся сюрпризов, связанных с SFD, но они пока под вопросом, поэтому про них я напишу потом, по мере готовности :)

Если кто-то хочет что-то услышать или увидеть, а еще лучше - что-то рассказать или показать - обращайтесь любым способом ко мне или организаторам SFD. Ну или хотя бы прямо тут, в комментариях :)

Дикие ударения в английских словах

Пока не забыл. Привёз из России несколько совсем уж диких произношений английских слов и смещённых ударений в них.

Слово — Произносят — Но лучше бы
Developer — Девелопер — Девелопер
Follower — Фалловер — Фолловер.
Header — Хидер — Хэдэр (голова (head) же хэд, а не хид).
Images — Имэджес — Имэджес
Livejournal — Ливджорнал — Лайвджорнал (т.к., «живой», а не «живи» («лив»))
MySQL — Мускль — Майэскьюэл (авт.), либо МайСиквел (трад.)
Nginx — Нджинкс — Энджин-экс
Profit — Профит — Профит
Pussy — Пасси (sic) — Пусси
Ruby — Раби — Руби
Support — Суппорт, либо Саппорт — Саппорт, либо вообще поддержка (e.g. «Я сижу на “суппорте”»)
Value — Валуе — Вэлъю

Для грубой проверки распространённых слов в терминале Mac OS X достаточно сказать "say word". Призываю делать это с незнакомыми словами, либо сразу в гугле искать.

Кого ещё что бесит?

Улучшизмы

Чем мне нравится программирование на C, так это тем, что какой файл бы ты ни открыл, всегда есть что улучшить. То там в сигнатуре int на void поменять, то здесь const добавить, то тут __attribute__((unused)) вкрячить. Вхождение в поток облегчается тем, что можно просто сесть, открыть любой файл и моментом втянуться в работу. Потому что независимо от того, что там у тебя написано, копать это говнище можно с любой стороны.

Ульяновский Хакатон № 1

Легко ли программисту найти 24 свободных часа на то, чтобы сделать что-нибудь необычное или давно желаемое?

16-17 июня, за две недели до ULCAMP'2012, мы провели в Ульяновске первый опытно-эксплуатационный хакатон специально для того, чтобы дать возможность людям оторваться по-полной и попробовать сделать что-то, до чего давно не доходили руки, или что-то полностью новое.

Без какого-то мощного пинка^Wмотиватора я обычно таким непрерывным куском времени не располагаю, поэтому мне вдвойне был интересен этот эксперимент, так как хотелось что-нибудь написать под iOS.

Собирались в субботу в полдень в офисе Echo. Стремящиеся попасть на хакатон программисты так лезли в окна, что даже уронили цветок с подоконника (см. рис.).



Первые пару часов мы знакомились. Обсуждали, кто что умеет, и предлагали варианты того, что можно сделать за 24 часа. Много предложений касалось приложений машинного обучения и распознавания изображений. На какие-то предложения сразу находились стартапы или проекты, их реализующие. В таких случаях мы внимательно изучали их опыт.




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



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

tonsky делал онлайновый блокнот на ClojureScript. Отчёт: http://tonsky.livejournal.com/263832.html, и конкретнее про кложу, с лекциями, которые Никита делал внутри Echo: http://tonsky.livejournal.com/tag/clojure

Фотка блокнота в действии:


gen_aav делал AI-движок для игр на Objective-C. Отчёт: http://gen-aav.livejournal.com/731.html

Презентация движка:


jay_is_here делал kexecboot. Отчёт: http://jay-is-here.livejournal.com/7358.html

Остальные участники разобрались по проектам и приступили к работе, заняв разные комнаты офиса Echo.



АвтоГеи. Навеянный успехом борьбы ульяновской общественности с нарушителями правил парковки проект создания мобильного приложения, которое бы позволило фотографировать нарушителя и отправлять его на email-адрес гаи (есть такой!). В итоге в проекте было сделано мобильное приложение и сайт, на котором была доступна вся эта информация. На закуску была даже сделана интеграция с твиттером: автогеи выкладывались вместе с фото и координатами. Twitter: @auto_gay.

Демонстрация сайта:


Geostreams. Проект по обнаружению всех твитов, сделанных в некоем радиусе от наблюдателя. Задача стояла так: «покажи все твиты, сделанные в радиусе 5 километров от меня». В итоге собирались не только твиты, но и фотки с инстаграмма (фликра?), а также было довольно скоро обнаружено, что и — барабанная дробь! — информация, порождаемая проектом АвтоГеи. Впрочем, всё логично :)
В рамках проекта был сделан сайт http://Geostreams.appspot.com и мобильный клиент.

Отчёт Дмитрия Клименко: http://geostreams.appspot.com/story.html

Демонстрация сайта:


Скриншот мобильного приложения:


AudioSMS. Мы с sidentdv решили сделать проект AudioSMS. Идея в том, чтобы снизить барьер для обмена сообщениями. Сообщения легче диктовать, чем печатать. Но сообщения легче читать, чем слушать. Поэтому понятно, что нужно делать распознавание голоса. Но распознаванием мало кто пользуется, потому что оно делает ошибки. А что, если пересылать голос вместе с текстом? Таким образом, если что непонятно, можно просто проиграть фрагмент.
sidentdv писать серверную часть на Erlang, в задачи которой входила работа с Google Voice Recognition API. Я же занялся клиентом. Под iOS я писал впервые, поэтому сначала нужно было вникнуть в экосистему: зарегистрироваться как разработчик, выкачать новый XCode и разобраться, как в нём набрасывать приложение. В числе прочего, понадобилось вкомпилировать в него из доступных исходников Speex audio codec, сделанный специально для задач VoIP и voice recognition, и нативно поддерживающийся гугловским API.

Скриншот мобильного приложения:


Вопрос с питанием в течение хакатона решился просто: первый, кто спросил про еду, был назначен ответственным за процесс. Таким образом Леонид Мосенков обеспечил нам здоровую и вкусную пиццу :)

Где-то в 4 ночи некоторых бойцов начало временно вырубать. Предусмотрев такой ход событий, для себя я взял спальник, но воспользоваться им не пришлось. А вот Юре Лукьянову и Юре Бушмелеву спальник бы не повредил — оба были найдены принимающими короткий сон прямо на столе:



Что удалось выяснить этим мероприятием. Формат хакатона предусматривает совместное интенсивное несколькочасовое (или -дневное?) выполнение работоспособного проекта. Некоторые непришедшие были озабочены тем, что 24 часа — это всё-таки слишком много, надо иногда и спать. Но все те, кто пришёл, неплохо справились с этим, даже если некоторым для продирания сквозь критическую фазу в районе 4—5 утра понадобился коньяк с шоколадом или крепко заваренный пуэр (спасибо, jay_is_here!). Все в результате представили работающий и неплохо выглядящий проект, который можно при желании продуктизировать уже относительно небольшим усилием.
Все мы поимели тонну радости при брейнсторминге в первой половине субботы. Этот энтузиазм порядком поутих к моменту демо-часа в воскресенье (10—11 утра), но после суток работы это вполне объяснимо.
Судя же по отчётам, эвент более чем удался!

В начале августа будем делать ещё один.