вторник, 6 марта 2012 г.

Про выборы

Я некоторое время сомневался не пойти ли мне наблюдателем на выборы, но в итоге решил, что ввиду свойств характера и патологической нелюбви к большим скоплениям людей, вряд ли смогу сколько-нибудь качественно исполнять эту роль. Но, зато когда мне предложили поработать в штабе наблюдателей, согласился без особых раздумий. "Яблоко" не могло посылать своих наблюдателей (но имеет некоторое количество людей в УИКах), зато могло посылать представителей прессы, благо местный филиал "Яблока" имеют свою газету и с оформлением наблюдателей как представителей прессы нет никаких проблем. Методика наблюдений была предоставлена "Голосом", которому и скидывались в итоге результаты.

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

Суть моей работы заключалась в том, что я должен был проводить анкетирование наблюдателей и вносить их в некую систему (которая оскорбляет меня как разработчика, но не суть). Первое анкетирование должно было проводиться с 10 до 11 часов, второе с 19 до 20, а третье после получения итогового протокола. Наблюдателей мне досталось немного, всего 11. Двое из них так и не вышли на связь (один телефон был выключен, другой не отвечал). Ещё двое людей перестали отвечать после первого анкетирования и больше на связь не выходили. Дополнительная сложность заключалась в том, что наши наблюдатели должны были иметь на руках специальный блокнот с анкетами, которые они должны были заполнить самостоятельно, а мне просто продиктовать ответы, но у большинства моих наблюдателей такого блокнота не оказалось. В итоге, мне приходилось зачитывать им вопросы (а ответы на некоторые из них требовали подготовки), а главной моей фразой стало "ДА или НЕТ?".

В течении всего дня по моим участкам всё было в полном порядке, нарушений особых замечено не было. На некоторых других участках было хуже. В частности, было обнаружено два вброса. Одну женщину, члена "Единой России" поймали в буквальном смысле за руку в момент вброса. Было ещё несколько историй с карусельщиками. При этом каждый раз в момент вброса кто-то отключал веб-камеру, следящую за урной. По вборосам были написаны заявления в прокуратуру, которая должна была прибыть на участки и не допустить дальнейшее использование скомпрометированных урн, но до конца дня они так туда и не приехали (хотя всё время утверждали, что уже едут). Ну этого из того что я слышал, ибо сбор анкет потребовала неожиданно много времени и внимания. Но всяком случае, когда в середине дня Рудомаха сел писать гневный пресс-релиз мне показалось, что оснований для подобных выводов и формулировок пока нет (ну может у него была дополнительная информация, но с моей колокольни пока ничего особо страшного не происходило).

Да, небольшой комментарий по выездные голосования. В целом оно проходило нормально, если на него выезжали наши наблюдатели, но тогда они не могли контролировать ситуацию на участке. Я знаю один случай, когда на выездное голосование уехала урна без наблюдателя и в итоге мы получили там 300 бюллетеней за 2 часа, что просто физически совершенно не реально. От другого наблюдателя я узнал, что в списках выездного голосования оказывались давно умершие люди, они физически не могли написать заявления! Так же, во время анкетирования получал информацию, что заявления на выездные голосования подавали не люди, а организации (чего делать нельзя).

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

Вот тут картина выборов начинает резко меняться. В офисе начинается телефонный ад, ибо постоянно идут попытки удаления наблюдателей. Большинство наших людей шли как представители прессы и не могли сами как-либо вмешиваться в происходящее. Видя нарушение закона они пытались как-то реагировать и это могло использоваться для их удаления, как мешающих процессу подсчёта голосов. На моих участках сначала вроде всё было спокойно, но потом началось. Один из наблюдателей приехал на участок на своей машине и в процессе подсчёта голосов у него сработала сигнализация, он вышел и не смог вернуть назад. Это полностью в рамках закона, но... Я опросил его по третьей анкете и оказалось, что процесс подсчёта голосов на этом участке был нарушен чуть более, чем полностью, но получить итоговый протокол стало невозможно. Следующая ситуация - звонит сотрудничающий с нами наблюдатель от Прохорова, говорит подсчёт окончен(за Путина у них было около 45%), но вот данные не входят с систему ГАС-выборы, что-то не так и тут вот совещаются что делать, но ей завтра рано на работу и стоит ли ей ждать завершения ситуации? Вообще, это грубое нарушение закона, ибо сначала составляется протокол, подписывается и заверяется и только после этого данные сообщаются в ТИК. Но на всех участках данные сначала отправлялись в ТИК и только после этого составлялся протокол. Как легко догадаться, это требуется для согласования результатов. Если ТИК даёт добро, то глава УИК даёт команду составлять протокол и т.п. По трём участкам я быстро получил протоколы, на которых за Путина было за 60%. По остальным случилось светопреставление. Та девушка от Прохорова больше не выходила на связь, я ей советовал держаться до тех пор, пока она не получит протокол на руки, он полагаю что ей действительно надо было утром на работу и она просто ушла. По двум участкам мне звонят в 3.00 ночи и сообщают, что главе УИК из ТИК дана команда не составлять протокол вообще! Кафка нервно курит в сторонке. Ещё бы, там ведь за Путина только 40%. Глава местного "Голоса" тока покачал головой "Ой-ой-ой, кого-то уволят" (не за нарушение, а за 40%). Как это не составлять протокол? Мы точно знаем, что Чуров дал команду посчитать всё до 9.00, об этом и говорим наблюдателям, терпите, ждите, ситуация кто кого пересидит. Я не дождался завершения, ибо ушёл домой около 5.00.

Но главное украшение ночи, это, конечно, история Артема Агеева. Он был членом УИК с правом решающего голоса. Началось с его звонка, что он снял на видео три пачки вброшенных бюллетеней, у него много интересного видео и его пытаются удалить. Вокруг это удаления развивается вся дальнейшая история. Мы напрягаем все силы, звоним во все возможные инстанции (ТИК, крайизбирком), шлём факсы с заявлениями, ситуация развивается часа полтора или может два (мне сейчас трудно оценить время), но в конце концов его всё таки удаляют с участка. Но дело в том, что члена УИК вообще нельзя удалять с участка! Глава УИК может принять решение об отстранении его, но его нельзя физически удалять из помещения, где происходит подсчёт голосов. Даже если он в порыве гнева убьёт там кого-нибудь, полиция должна обеспечить, что бы он не мешал работе, но ни в коем случае не удалять. Полицейский, который его удалял, отказался даже представится. И не мудрено. За несколько дней до выборов Нургалиев собирал специальную пресс-конференцию, где презентовал инструкцию для полицейских, якобы впервые полицейские больше не будут подчиняться главе УИК, а будут следить соблюдением законности. Мне рассказали, что этот вопрос специально обсуждался на совещании у Ткачёва и полицейские чины были в полном замешательстве, как это они могут обеспечить соблюдение законности? как это не подчиняться главе УИК? В итоге, ничего и не поменялось, как оказалось полицейские по прежнему подчиняются главе УИК и непосредственно участвуют в нарушении закона. Но лучше об этой истории узнать непосредственно от Артёма, https://twitter.com/#aaageev - здесь его твиттер, где выложены ссылки на снятое им видео (включая видео его удаления), http://www.itsec.pro/ - его блог, там уже есть рассказ про его приключения от первого лица.

Итого. Мы знаем, что были вбросы. Мы знаем, что были карусели (наши люди пытались поучаствовать в одной из них, но лавочку вовремя прикрыли). Мы знаем, что во время выездного голосования, если оно проводилось без участия наблюдателя, в выездных урнах могло появиться до нескольких сотен бюллетеней за сами понимаете кого. Мы знаем, что если всё это не помогало или не могло быть осуществлено и на участке получалась плохая ситуация за Пу, то УИК всячески затягивал оформление протокола, надеясь, что наблюдатель не выдержит и пойдёт спать, а если это не помогало, то привлекали полицию. Мы не может оценить объём фальсификаций, но может заявлять, что голосование сопровождалось вопиющими нарушениями избирательного законодательства. Лично моя оценка на основе тех данных, что я видел, это 40-45% за Путина в Краснодаре. При этом явка в Краснодаре около 50% (Ткачев в твиттер отчитался о явке в 70% по краю).

Пара наблюдателей, сообщая мне протоколы, были явно разочарованы. Я знаю несколько таких случаев, вроде и нарушений человек серьёзных не заметил, а на участке 65% за Путина, это может серьёзно подорвать моральных дух. Но мне сейчас совершенно ясно, что один человек в большинстве случаев не может что-либо предотвратить или заметить, если "плохие люди" действуют осторожно (тем более, на их стороне опыт). Как оказалось, при всей плохой организации "Яблока", именно яблочные наблюдатели пытались что-то сделать и фиксировали нарушения. Наблюдатели от Прохорова/Зюганова/Миронова вроде бы как и есть, но в основном занимают совершенно пассивную позицию. Я не знаю, откуда они берутся, возможно они просто получают деньги за участия в этих мероприятиях, а другой мотивации не имеют. Часть наших наблюдателей, кстати, вызвала у меня большие подозрения, ещё когда я их видел на обучении. Один наблюдатель, во время первого анкетирования мне стал заявлять, что вот он видит, что действительно много людей голосуют за Путина и наверное мы проиграем. Не знаю зачем он мне это рассказывал, цель наблюдателей - честные выборы, а не свалить Путина. В общем, у меня возникло подозрение, что некоторые наблюдатели совершенно не стремятся к честным выборам, а преследуют какие-то другие цели.

Из всего вышесказанного естественным образом рождается ответ на традиционный русский вопрос "Что делать?" - готовится к следующим выборам. Насколько я сейчас вижу, такая простая мысль приходит в голову не только мне. Сегодня на "Дожде" показывали одного человека (поздно включил, не понял кто он), который рассказывал о том, как его группе удалось обеспечить действительно чистые выборы на 5-ти участках, но для этого им потребовалось 40 человек и 7 дней подготовки. Ещё раз, яблочные наблюдатели, которые считаются самыми эффективными (видимо за счёт того, что не получают денег, а действуют исключительно из идейных соображений) - организованны очень плохо и имеют очень ограниченные возможности юридической помощи (людей знающих закон очень мало и они были порваны на множество маленьких частей). Кстати, "Голос" тоже организован плохо и мне не очень понравились люди, которые там работают. Т.е. сейчас в обществе нет структуры, способной качественно проконтролировать ход голосования. Как бы не развивалась ситуация в стране, но впереди у нас ещё много разных выборов и сейчас в России просто физически невозможно провести по-настоящему честные выборы. Необходимо создавать организацию, способную обеспечить качественный контроль за ходом голосования. Эта организация должна не только контролировать ход голосования, но и оказывать давлению на выборную систему, добиваясь реакции на обнаруженные замечания и шаг за шагом приучать людей из ТИКов и УИКов соблюдать закон. Даже если через месяц Навальный захватит Манежку, а Удальцов Кремль - потребность в честных выборах своей актуальности не потеряет. Вопрос лишь в том, найдутся ли люди, готовые заниматься такими проблемами.

В своё время меня сильно удивило то, что основную часть работы перед выборами и во время выборов в США делают волонтёры. Может ли хорошая работа быть сделана бесплатно? Главным итогом этих выборов для меня стало появление понимания, что только хорошо организованные и подготовленные волонтёры-активисты способные обеспечить честность выборов. Для Краснодара таких надо несколько тысяч. Ну да только мы всё любим понимать не любим что-либо делать :(

вторник, 26 апреля 2011 г.

Блог переехал

Блог переехал, теперь я буду жить тут: http://archimag.lisper.ru/

пятница, 25 марта 2011 г.

cl-sanitize

Написал cl-sanitize - библиотеку для очистки HTML от нежелательного содержания. Точнее, не написал, а портирова Sanitize (Ruby). Хотя "портировал" тоже не совсем верное слово, ибо реализация алгоритма очистки тривиальна и его я написал сам (это просто быстрее, чем разбирать код на Ruby), но вот самое важное - конфигурационные данные и набор тестов взял из Sanitize.

cl-sanitize основана на cl-libxml2. Я сомневался некоторое время, что взять за основу cxml или cl-libxml2 (сомнения тем более оправданны, что cxml и cl-libxml2 плохо совместимы между собой из-за конфликта имён), но всё таки решил использовать cl-libxml2. Во-первых, оригинальная версия основанна на libxml2, так что это позволило легко получить идентичные результаты на тестах. Во-вторых, я не имею такого доверия к "Closure HTML", как к libxml2. А это очень важный момент, ибо после просмотра тестов мне стало немного страшно ходить в интерент.

В процессе пришлось немного допилить cl-libxml2 - как то мне сейчас несколько страшновато заглядывать внутрь, всё таки это был фактически мой первый серьёзный опыт использования CL, отрефракторить бы её основательно, да боюсь, что до этого руки у меня не скоро дойдут.

вторник, 15 марта 2011 г.

Новый парсер для cl-closure-template

Полностью переписал парсер для cl-closure-template на базе esrap. Я вообще давно хотел переписать его на какой-нибудь более серьёзной базе, но те решения для парсинга на CL, которые мне попадались, меня совершенно не устраивали - запутанно и слишком громоздко. esrap понравилась мне сразу, во-первых это PEG, во-вторых описание грамматики можно разбивать на множество отдельных кусков, а не загонять их в один большой макрос, в-третьих - описание грамматики объединяется с кодом по обработке, так что никаких раздельных стадий лексического и синтаксического анализа - всё объединено.

Вообще, esrap принципиально очень сильно похожа на моё старое решение (которое я подсмотрел в коде dokuwiki, а туда оно попало из какого-то решения на Perl), но гораздо совершенней и основано на более выразительных инструментах. Благодаря принципиальной схожести переписывание оказалось довольно простым и заняло 2 дня. При этом, не сказать, что размер код сильно уменьшился, но вот соответствие оригинальной спецификации стало значительно более точным. Например, появилась возможность использовать экспоненциальную форму записи для чисел с плавающей точкой, целые в шестнадцатеричной форме, или напрямую писать коды Unicode в строковых литералах.

Самое главное изменение - теперь неверно записанный шаблон не будет компилироваться и будет вываливаться сообщение об ошибке, по которому можно примерно установить место ошибки. Точной информации там нет, но локализовать конкретный template можно.

Мне пришлось исправить несколько своих шаблонов по одной причине - старая версия дозволяла использовать символы { и } достаточно свободным образом (что противоречит спецификации) и пришлось завернуть соответствующие куски в literal секции. Плюс, было несколько мелких опечаток, которые проглатывались старой версией. Ещё в старой версии можно было записывать имена переменных как $foo-bar-x, что противоречит спецификации и я это запретил, но возможность записывать имена шаблонов в "лисп-стиле" пока всё таки оставил (может тоже запретить?).

Полный код парсера здесь.

P.S. Если придётся что-нибудь ещё парсить, то однозначно буду использовать esrap.

четверг, 3 марта 2011 г.

Ещё пара полезных декораторов

В веб-приложениях для отдачи статических файлов принято использовать возможности веб-серверов (Apache, Nginx), поскольку традиционные языки веб-разработки (Python, Ruby, PHP, Perl) справляются с этой задачей очень плохо. Однако, это связано с рядом ограничений. Во-первых, нельзя автоматически генерировать ссылки на основе информации о маршрутах. Но если это ещё можно пережить (хотя, честное слово, очень неудобно), то есть куда более серьёзная проблема - часто нужен "управляемый" доступ к статическим файлам. Например, скрипт должен проверить права доступа. Для решения этой дилеммы была придумана техника, когда скрипт выполняет свою логику, а реальную передачу файла делегирует веб-серверу путем настройки специальных заголовков ответа. Для nginx это X-Accel-Redirect, а для Apache - X-Sendfile.

При разработке на Common Lisp проблема отдачи статических файлов стоит значительнее менее остро, ибо язык сам по себе намного быстрее и Hunchentoot справляется с этой работой достаточно быстро. Я для публикации статических файлов пользуюсь restas-directory-publisher - модулем для RESTAS. Однако, следует признать, что возможны ситуации, когда отдавать статику средствами CL окажется не очень разумно.

Тут вот и возникла идея обеспечить возможность использования механизма XSendfile прозрачным для основной логики образом. В итоге, я добавил в RESTAS соответствующие декораторы для Apache и Nginx.

Ниже я приведу возможные примеры использования этих декораторов в пакете restas-doc, обеспечивающего работу http://restas.lisper.ru/.

для публикации файлов я использую такой код:
(restas:mount-submodule -publisher- (#:restas.directory-publisher))
При этом, сами файлы с документацией лежат в каталоге /usr/share/doc/restas/.

@apache-xsendfile
При работе с Apache всё просто:
(restas:mount-submodule -publisher- (#:restas.directory-publisher restas:@apache-xsendfile))
а в конфиге Apache необходимо установить значение параметра XSendFilePath таким образом, что бы публикуемые файлы оказались внутри указанного каталога. Самый простой путь
XSendFilePath /
Но это может оказаться не очень разумным с точки зрения администрирования, так что в данном случае можно и так
XSendFilePath /usr/share/doc/restas/
Более подробная информация о настройке сервера есть в официальной документации.

@nginx-accel-redirect
Настройка nginx является более сложной. Необходимо создать internal-секцию и дальше есть два варианта: либо установить root, либо задать alias. В зависимости от выбранного варианта необходимо различным образом формировать заголовок X-Accel-Redirect. Для поддержки этих вариантов в RESTAS добавлено три переменных:
(defvar *nginx-internal-location* nil)
(defvar *nginx-internal-alias* nil)
(defvar *nginx-internal-root* nil)
и их надо настроить точно в соответствии с настройками nginx. При этом, переменные *nginx-internal-alias* и *nginx-internal-root* являются взаимоисключающими и одна из них должна быть установлена в NIL. В принципе, их можно выставить глобально, но RESTAS позволяет сделать лучше. Например, для такого конфига nginx:

location /restas {
internal;
root /usr/share/doc;
}
Код на CL может быть таким:
(restas:mount-submodule -publisher- (#:restas.directory-publisher restas:@nginx-accel-redirect)
(restas:*nginx-internal-location* #P"/restas/")
(restas:*nginx-internal-root* #P"/usr/share/doc/"))
Настройка с root представляется мне довольно неудобной и если nginx поднят только для CL, то гораздо проще делать так
location /protected/ {
internal;
alias /usr/share/doc/restas/;
}
и
(restas:mount-submodule -publisher- (#:restas.directory-publisher restas:@nginx-accel-redirect)
(restas:*nginx-internal-location* "/protected/")
(restas:*nginx-internal-alias* "/usr/share/doc/restas/"))
Вообще, описанный функционал обеспечивает очень важную возможность работать со статическими файлами средствами CL, например, создавать повторно используемые компоненты, а в случае возникновения необходимости легко подключить механизм XSendFile с помощью подключения нужного декоратора.

Я пока разбирался с этими вопрос успел посмотреть советы по использованию XSendFile с RoR и Django - там это носит вид хаков, жёстко прибивающих код к конкретной конфигурации веб-сервера. Этот факт подкрепил моё мнение, что модель декораторов RESTAS вкупе с возможностями CL (такими, как CLOS) обеспечивает более гибкие и мощные возможности, чем более традиционная схема с middleware-компонентами.

Прозрачное использование Parenscript

Я использую Parenscript в реализации cl-closure-template. Но обычный код предпочитаю писать на JavaScript. На то есть несколько причин и одна из самых существенных - возникающие инфраструктурные трудности. На самом деле я бы хотел просто размещать файлы с кодом на Parenscript среди других статических файлов и больше ни о чём не думать, а оно пусть там как-нибудь само обрабатывается. После добавления в RESTAS декораторов реализовать такое поведение оказалось очень просто:
(defclass ps-compile-route (routes:proxy-route) ())

(defmethod restas:process-route ((route ps-compile-route) bindings)
(let ((result (call-next-method)))
(cond
((and (pathnamep result)
(string= (pathname-type result) "parenscript"))
(setf (hunchentoot:content-type*)
"text/javascript")
(let ((*package* (find-package '#:ps)))
(ps:ps-compile-file result)))
(t result))))

(defun @ps-compile (origin)
(make-instance 'ps-compile-route :target origin))
В случае если основной обработчик маршрута возвращает pathname с расширением ".parenscript", то данный декоратор компилирует его содержимое в код на JavaScript и отправляет клиенту, иначе возвращает результат без какой-либо обработки. Теперь я просто публикую статические файлы
(restas:mount-submodule -static- (#:restas.directory-publisher @ps-compile)
(restas.directory-publisher:*directory* #P"/path/to/static/")
И если мой Parenscript-код находится в файле "/path/to/static/js/core.parenscript", то в HTML он подключается как
<script src="/js/test.parenscript"></script>

среда, 2 марта 2011 г.

Интернет-магазина на Common Lisp

Если вы мечтали купить что-нибудь в интернет-магазине, написанном на Common Lisp, то с недавних пор имеете такую счастливую возможность (особенно, если живёте в Питере) - www.320-8080.ru, разрабатывается rigidus-ом на основе RESTAS и cl-closure-template!