«Острова» Яндекса: техническая сторона и API

16 мая на конференции YaC/m Яндекс объявил о запуске новой поисковой платформы «Острова». Уже в первые две недели после анонса вебмастера создали около 1000 островов для своих сайтов. Но новая платформа вызывает и множество вопросов. Мы уже рассказывали на Хабре о том, как Острова выглядят и почему они визуально устроены именно так.

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

От сниппетов к островам

Яндекс последовательно развивал представление поисковых результатов. С одной стороны, мы работали с результатами «органической» выдачи, с другой — делали специализированные ответы, которые назвали колдунщиками.

Страница результатов поиска состоит из 10 ссылок с короткими аннотациями — «сниппетами». Если раньше они включали в себя простые текстовые комментарии, то со временем в них начали появляться элементы, которые помогали человеку оценивать релевантность сайта: адрес, телефон и время работы организации, ссылки на популярные подразделы сайта, страницы в соцсетях и т.д. Вот как выглядит современный сниппет:

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

В 2000 году, когда по ленте новостей и базе товаров из интернет-магазинов начал осуществляться параллельный поиск, на странице поисковых результатов появилась новая форма ответа — колдунщики. Сервисы Яндекса, т.к. только у них была такая техническая возможность, стали использовать её для того, чтобы представить свою функциональность в поиске.

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

Для более сложных задач появились вертикальные сервисы, которые дополняют «универсальный» поиск в конкретных областях. Например, Яндекс.Маркет позволяет выбрать товар и определить лучшую цену на него в интернет-магазинах, а Яндекс.Карты — найти нужный адрес и построить к нему маршрут.

Чтобы сервисы лучше понимали пользователя и быстрее решали его задачу, мы начали выносить их функциональность в поиск. Например, Яндекс.Расписания научились определять из поискового запроса точки маршрута и проставлять их в форму поиска авиабилетов.

В результате такой богатый интерактивный ответ сокращает количество действий, которые должен совершить человек, и, естественно, улучшает представление самого сервиса.

Представление органической выдачи не успевало за нашими экспериментами с колдунщиками — не было технической возможности обеспечить real-time обработку данных для всех сайтов. А хотелось, чтобы все сайты могли быть представлены похожим образом. Так мы пришли к идее интерактивных ответов для органической выдачи — островам.

Интерактивные ответы

В процессе интеграции сервисов Яндекса в поиск мы поняли, какие возможности необходимо предоставить вебмастерам для создания интерактивных ответов:

  • переносить ввод данных на страницу результатов поиска;
  • передавать информацию от сервиса в режиме реального времени;
  • переносить начало или всю транзакции на страницу результатов поиска.

Опираясь на эти возможности, острова можно поделить на 3 типа:

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

Информационный остров в результатах поиска Яндекса

Поисковые. Формы для уточнения запроса, кнопки и другие элементы, подготавливающие к поиску на сайте.

Поисковый остров в результатах поиска Яндекса

Транзакционные. Возможность совершить действие прямо в результатах поиска или подготовиться к нему перед переходом на сайт.

Транзакционный остров в поиске Яндекса

Принципы

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

Opt-in
Концепция островов основана на добровольном участии. Владельцы сайта самостоятельно настраивают отображение своего контента на странице результатов поиска и контролируют, что будет вынесено на нее в качестве интерактивного ответа.

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

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

Ранжирование
Важно подчеркнуть, что интерактивные ответы — это интерфейсное решение, которое в ближайшее время никак не повлияет на ранжирование.

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


Техническая реализация

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

Сейчас мы предполагаем язык описания форм и API для real-time взаимодействия.

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

API для передачи real-time информации — второй и более сложный компонент создания интерактивных ответов. Он может возвращать в реальном времени данные для конкретной страницы (например, погоду на сегодня или табло аэропорта). А также дополнять работу с формой, моментально показывая результат, который ожидает пользователя. Например, при изменении параметров отвечать количеством найденных объектов или частичным превью.

Полная спецификация
Документация для описания поисковой формы и тестирования в нашем редакторе

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

Также с запуском в России бета-версии нового интерфейса мы начнем экспериментировать с островами и показывать часть из них реальным пользователям.

Если у вас есть ещё вопросы или предложения о том, как будут работать Острова, — задавайте их в комментариях. Мы постараемся обязательно на все важные ответить или даже участь их при планировании дальнейшей разработки Островов.

ссылка на оригинал статьи http://habrahabr.ru/company/yandex/blog/181646/

Сказ о том, как мы карту с биллингом дружили

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



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

В принципе все просто, 4 слоя:

  • Устройства (коммутаторы, медиаконвертеры, сервера и т.д.);
  • Логические связи (откуда куда идет сигнал);
  • Муфты, сплайс-кассеты;
  • Кабель: оптика и медь (если используется в качестве магистралей).

2 таблицы в Postgre SQL, первая для хранения точек, вторая — для линий.

Муфта это, коммутатор, или важный клиент — определялось полем type. На тот момент типов было несколько, и о возможных проблемах в будущем никто не думал.

Прошло какое-то время, устройства были нанесены. Хронологию событий передать уже не смогу, так как к каждой задаче возвращались неоднократно, каждый раз подтягивая гайки. В любом случае, нанесенные устройства не давали особо никакой полезной информации. Устройства продолжали кочевать, номера портов меняться (имею ввиду монтажников, которым по боку, в 25-ый или 28-ой порт подключать коммутатор). По большому счету, на тот момент мы смогли увидеть некоторые проблемные места — использование utp в качестве магистралей и разросшиеся сегменты (было и такое, что с одного коммутатора было подключено до 40 других, и когда пропадало электричество в этом доме, без интернета оставались до 30 домов). Уже на этом этапе ставились задачи руководителям филиалов по устранению этих косяков.

Что же касается работы с картой, то мы могли только использовать Zabbix, который тупо пинговал устройства и подкрашивал красным цветом те, что не доступны.
Как я писал в прошлой статье, параллельно шла работа над созданием новой оболочки с наращиванием функционала для UTM. Разбивая адреса абонентов по запятой с пробелом мы получали список населенных пунктов, улиц и домов. Поработав с этим списком мы получили свою собственную базу адресов. А к стандартной таблице UTM — users добавили поле house_id, по которому мы могли получить правильный адрес абонента без сокращений и опечаток вплоть до дома. В новой оболочке адрес абонента стал набором селектов вместо одного текстового инпута. Да, кстати, КЛАДР не совпадает с тем, что пишется в паспортах у абонентов, поэтому мы не стали его использовать.

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

Совсем забыл сказать, в нашем случае доступ к Интернету обеспечивался посредством vpn-соединения, поэтому пробелы в используемом оборудовании имеют место быть, особенно в случае поглощения одним провайдером другого, когда часть штата купленного провайдера отправляется за борт.

Так вот, есть список домов без устройств и с абонентами. Каждый случай уникален, где-то медная перекидка на соседний дом, где неуправляемый коммутатор подключен и т.д и т.п. Все проблемные места выявлены и устранены. Вновь найденные медные перекидки — под замену на оптику. Далее я перейду к другой теме, а подводя итог вышесказанного, повторюсь — к этим задачам мы возвращались неоднократно и в итоге смогли достичь 100%-ного знания о состоянии сети.

Далее я думаю стоит поговорить о логической составляющей процесса. Вообще, о настройке коммутаторов наверное есть смысл набросать отдельный пост, но и в этой теме не показать некоторые аспекты нельзя — не раскрою тему иначе.

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

  1. Оборудование находится в сетях 192.168.x.0/24;
  2. Каждый коммутатор 192.168.x.1 задает столько сегментов, сколько гигабитных портов у него есть (не более 24). К примеру, D-Link DGS 3627G — 24 сегмента. x — скажем так, номер сети (растет с каждым L3);
  3. Каждый сегмент состоит не более чем из 10 устройств с не более чем 240 абонентскими портами;
  4. Каждый сегмент начинается с коммутатора, чей ip-адрес формируется по принципу: 192.168.x.y0, где y — номер порта L3, с которого сегмент подключен. Например, для коммутатора L3 с ip-адресом 192.168.37.1 куст на 19 порту начнется с коммутатора 192.168.37.190 (т.е. последнее число в адресе первого устройства всегда будет кратным 10);
  5. Остальные коммутаторы в сегменте (не более оставшихся 9 из 10 управляемых) получают адреса 192.168.x.y1-192.168.x.y9;
  6. Первый коммутатор в сегменте задает ip-адреса абонентов, подключенных в этом сегменте так: 10.x.y0.n, где n — порядковый номер абонента, растет вместе с количеством абонентов в сегменте. Мы добавили некоторое ограничение, n не может быть меньше 10 (единичка — шлюз, остальные на всякий случай держим в резерве), т.е. абонентам, подключенным от коммутаторов 192.168.37.190-192.168.37.199 — достанутся адреса 10.137.190.10-10.137.190.249;
  7. Вся сеть управления вынесена в отдельный vlan, на каждый абонентский сегмент также выделен vlan (к этой статье отношения не имеют, поэтому останавливаться на них не стану).

Таким образом, в каждом сегменте мы можем теоретически подключить до 240 абонентов, на практике таких количеств нет (максимальные числа колеблются в районе 50-60 абонентов).

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

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

А ведь помимо разделения по сегментам, мы должны задавать однообразную модель работы железа глобально, по всей сети. Отчетливо отложилось в памяти, как меня учили настраивать коммутаторы. Было несколько текстовых файлов с примерами конфигов для разных железок, причем на каждое конкретное устройство конфигов было несколько и в принципе идентичное железо (скажем DES 3028 и 3200-28) настраивалось по-разному. Здесь есть настройка времени, тут нет; здесь есть ACL, и здесь есть, но отличается.

В 2011 году по Тверской области прошли сильные грозы, часть портов коммутаторов по всей сети погорело, сеть процентов на 30-40 легла. Легла потому, что хоть мозги у коммутаторов не пострадали, петляющие порты сделали свое дело — 100% нагрузка на процессор и коммутатор уже не хочет с нами общаться. 2 недели бессонных ночей (без преувеличения) — монтажники не успевали возить коммутаторы в офис, поэтому приходилось ждать те моменты, когда коммутатор по месту установки все-таки оживал на какие-то мгновения, бегом в него и настройки storm control просто из буфера. Вот этот и другие примеры сделали свое дело — были сформированы и другие стандарты. Скриптами залили нужные конфиги по всей сети, проблемы исчезли. Да, в прошлом году на всех транзитных коммутаторах выставили ИБП, разницу до и после не описать. Zabbix стал названивать в разы реже. Помимо решения проблемы перебоев с электричеством решили и проблему с грозами — дешевле поменять Рапан, чем коммутатор.

С этим разобрались. Следующий логичный шаг — снимать mac-адреса на портах коммутаторов. Зная mac-адреса абонентов, смогли определить кто в какой порт включен. Снова всплыли косяки. Оказывается стоит управляемый 24-портовый коммутатор, 7 абонентов, 2-ое на 1-ом порту, 3-ое на 7-ом и несколько по портам разбросаны. Ага, опять пятипортовые хабы. Ну да, монтажники в щитке поставили, чтобы на этаж второму абоненту utp не тащить. Ликвидируем. Навели порядок. Абонентов перепривязали. Наблюдаем, точнее идем дальше. Бац! Возвращаемся назад. Оказывается, в одном из городов монтажники, которые на сделке, те, что только на подключениях, когда абонента нового включают, чтобы времени меньше тратить берут и выдергивают уже работающего абонента с порта (визуально же видно — работает) и в этот порт включают нового, а работавшего куда попало. Они за это не отвечают. У другого монтажника всплывает заявка — у абонента интернет пропал. Причина, думаю, понятна. Вставили таких люлей руководителю филиала и его остолопам, что часть этих сдельщиков ушла. Хороший урок остальным. Где-то сохранял скриншот (искать лень), за дней десть примерно — 7 абонентов в одном порту побывало (новый дом так включали). Забегая вперед, скажу — на тот момент мы уже оттестировали систему — при выборе адреса абонента предлагались только определенные коммутаторы. А выбирая коммутатор — на выбор предлагались порты с пометками (свободен/сгоревший/занят/хаб) — т.е. порт можно выбрать любой, но предупреждение будет. Как только порт выбран и если он не помечен в системе, как сгоревший — на коммутатор посылается команда включения порта. Здесь много аспектов, я не буду на них обращать ваше внимание. В-общем, в этом городе, с разрешения учредителей, мы эту систему и включили. Бегали монтажники в мыле — проверили всех абонентов, у которых пропал интернет. Да, это было скажем так, грубо, по отношению к абонентам, и я обычно ярый противник экспериментов над абонентами, которые со своей стороны обязательства по ежемесячной оплате выполняют, но все делалось для них. Так, в течении нескольких дней мы получили жесткую привязку абонентов по портам и заставили монтажников работать согласно регламента. Подводя итог темы привязки к портам, могу сказать — по всей сети привязки impb созданы, все неиспользуемые порты выключены. По каждому абоненту мы можем сказать миграцию по портам.

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

  • Таблицу устройств;
  • 3 таблицы с населенными пунктами (тут же области и районы), улицами и домами (или другими объектами);
  • Таблицу абонентов.

Из вышесказанных постулатов определяем, что ip-адрес железа определяет ip-адрес абонента. Отсюда следует, что в таблице абонентов мы храним устройство как ip-адрес. Но ip-адрес это всего лишь один из параметров устройства, хранимого в таблице devices. Основным идентификатором в ней всегда был gid. Но gid подразумевает изменение — устройство может быть снято, а вместо него установлено новое, с присвоением ему того же ip-адреса. Кстати, над этой задачей я работаю сейчас.

Мы помечаем порты как сгоревшие и они никогда не будут включены, точнее до тех пор, пока устройство не отдадут в ремонт и оно не вернется назад с пометкой “восстановлено”. Но отправляя устройство в ремонт, его могут удалить с карты (могли), и вся информация будет потеряна. Сегодня, сейчас, мы не знаем, какое поле и где важнее. К сожалению, не все устройства имеют серийный номер (по-моему, из ремонта даже устройства возвращались с стертым sn, имею ввиду не бумажку конечно), но mac у нужных нам устройств есть у всех. Поэтому триггерами PostgreSQL в лог пишу все события с указанием всех полей (и gid, и ip, и sn, и mac). Пометки о сгоревших портах хранятся в таблице с привязкой к mac-адресу.

Теперь о карте. Изначально нанести точку в кугисе мог любой желающий. Сегодня эта операция запрещена триггерами в БД. Вся работа с железом перенесена в веб-интерфейс. Есть понятие “склад” (их несколько, по количеству офисов-филиалов), добавление устройств позволено определенным лицам, с указанием mac-адреса, серийного номера и модели устройства. Любой чих, как я уже говорил, пишется в лог. Более того, Zabbix регулярно снимает все параметры с железа, поэтому несанкционированная замена коммутатора приводит к тому, что абоненты работать не смогут, а руководителю вставят пистон. В комментариях к прошлой статье, насколько помню, был комментарий, что невозможно такую систему построить. Возможно. Закрутили гайки, наказали виновных, и всё.

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

Дело в том, что изначально, все эти линии, полигоны и точки на карте не были связаны между собой никак. Была подложка OSM, были 4 слоя, о которых писал выше и на этом всё. Набросав пару триггеров на изменение геометрии точки (читай устройства) и настроив прилипание при рисовании, мы смогли приклеить линии связей к устройствам. Таким образом, при перемещении на карте устройства меняется и точка соприкосновения “линка” с устройством. Так называемые линки привязаны к оборудованию (ровно как и оптика к муфтам) по нескольким параметрам. Во-первых, геометрически — начальная или конечная точка линии должна совпадать с координатами точки-устройства. Во-вторых, есть поля dstart, dstartport, dend, dendport, которые определяют с какого устройства и порта в какое устройство и порт идет этот самый линк. С этой задачей пришлось повозиться — проверить все нарисованные линии, все устройства, проверить геометрии, введенные значения, после этого навесить триггеры и наслаждаться полученным результатом.

Картина перед изменением координат устройства:

и после:

Сейчас, анализируя mac-адреса на портах коммутатора и зная mac-адреса устройств и абонентов, мы можем видеть, какая информация в этих линках не является достоверной. Благодаря этой системе визуально можно видеть какие потоки трафика идут между коммутаторами, какие порты задействованы под магистрали, какие виланы проброшены и т.д. и т.п. Вся эта информация также используется при создании конфига устройства. Сейчас, для того, чтобы привязать к порту управляемого коммутатора второго абонента требуется указать на карте устройство, с которого будет производиться подключение и нанести линк с управляемого коммутатора в эту тупую железку. Что поделать, бывают и такие ситуации — 25-ый абонент, а портов 24, но мы должны знать об этом. В противном случае абонента будет невозможно привязать к порту, а следовательно и не будет создана impb запись и работать этот абонент не сможет.

Собственно, концом статьи это назвать никак нельзя, но что поделать — надо ехать за дочкой (сегодня в садике короткий день), а если сохраню в черновике на полуслове, то вернувшись назад в очередной раз удалю написанное.

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

  • Используемые типы объектов (муфты, коммутаторы и т.д.) были разделены дважды (базовые классы, и более подробные реализации каждого класса);
  • По устройствам на карте вычислили id домов из OSM, расширили собственную таблицу домов, добавив туда osm_id и osm_geometry (и таким образом знаем правки интересующих нас домов);
  • Нанесли часть не существующих в проекте OSM домов;
  • Добавили возможность участия одного коммутатора в нескольких сегментах (это когда 2 провайдера один коммутатор используют);
  • Перевели абонентов с vpn на ipoe (только с привязкой по mac-адресу).

и много-много всего другого.

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

ссылка на оригинал статьи http://habrahabr.ru/post/181652/

Создаем Shazam на Java

Пару недель назад, я наткнулся на эту статью How Shazam Works
Мне стало интересно, как же работают такие программы как Shazam… Что еще более важно, насколько тяжело написать что-либо похожее в Java?

О Shazam

Если кто-то не знает, Shazam это приложение с помощью которого вы можете анализировать/подбирать музыку. Установив ее на свой телефон, и поднеся микрофон к какому-либо источнику музыки на 20-30 секунд, приложение определит, что это за песня.

При первом использовании у меня возникло волшебное чувство. «Как оно это сделало!?» И даже сегодня, когда я уже пользовался им много раз, это чувство меня не покидает.
Разве не будет классно, если бы мы смогли написать что-то сами, что вызывало бы такие же чувства? Это и было моей целью в прошлый уикенд.

Слушайте внимательно..!

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

Теперь мы можем считывать данные с TargetDataLine как с обычных потоков InputStream:

Этот метод позволяет легко открывать микрофон и записывать все звуки! В данном случае я использую следующий AudioFormat:

И так, теперь у нас есть записанные данные в классе ByteArrayOutputStream, отлично! Первый этап пройден.

Данные с микрофона

Следующее испытание – анализ данных, на выходе, полученные данные были в виде байтового массива, это был длинный список чисел, наподобие этого:

Хммм… да. И это звук?

Чтобы узнать, могут ли данные быть визуализированы, я закинул их в Open Office и преобразовал в линейный график:

Да! Теперь это похоже на «звук». Выглядит так, как если бы вы, например, пользовались Windows Sound Recorder.

Данные такого типа известны как time domain (временная область). Но на данном этапе эти числа для нас бесполезны… если вы прочтете вышеупомянутую статью о том как работает Shazam, то вы узнаете, что они используют spectrum analysis (спектральный анализ) вместо непрерывных данных временной области.
Поэтому следующий важный вопрос – это: «Как нам преобразовать наши данные в формате спектрального анализа?»

Дискретное преобразование Фурье

Чтобы превратить наши данные во что-то пригодное, мы должны применить так называемое Discrete Fourier Transformation (Дискретное Преобразование Фурье). Что позволит нам преобразовать наши данные из временной области в частотные интервалы.
Но это только одна проблема, если вы преобразуете данные в частотные интервалы, то каждый бит информации касательно временных данных будет потерян. И так, вам будет известна магнитуда каждого колебания, но вы не будете иметь ни малейшего понятия, когда она должна произойти.
Чтобы решить эту проблему, воспользуемся протоколами sliding window. Берем часть данных (в моем случае 4096 байтов данных) и преобразуем только этот бит информации. Затем нам будет известна магнитуда всех колебаний возникающих в течении этих 4096 байтов.

Применение

Вместо того, чтобы думать о Преобразовании Фурье, я немного прогуглил и нашел код для так называемого БПФ (Быстрое Преобразование Фурье). Я называю этот код – код с пачками данных:

Теперь у нас есть два ряда с пачками всех данных – Complex[]. Эти ряды содержат данные обо всех частотах. Чтобы визуализировать эти данные я решил воспользоваться анализатором всего спектра (просто убедиться в том, что мои расчеты верны).
Чтобы показать вам данные, я скомпоновал из вместе:

Ввод, Aphex Twin

Это немного не по теме, но я бы хотел рассказать вам о электро-музыканте Aphex Twin (Ричард Дэвид Джеймс). Он писал сумасшедшую электронную музыку… но некоторые его песни обладают интересной характеристикой. К примеру, его величайший хит — Windowlicker, в нем заложено изображение – спектрограмма.
Если вы посмотрите на песню как на спектральное изображение, то увидите красивую спираль. Другая песня — Mathematical Equation, показывает лицо Twin’а! Узнать больше вы сможете здесь — Bastwood – Aphex Twin’s face.
Прогнав эту песню через мой спектральный анализатор я получил следующие результаты:

Конечно же не идеально, но это должно быть лицо Twin’а!

Определение ключевых музыкальных точек

Следующий шаг в алгоритме приложения Shazam – определить некоторые ключевые точки в песне, сохранить их в виде знаков и затем попытаться подобрать нужную песню из своей более чем 8 миллионной базы песен. Это происходит очень быстро, поиск знака происходит со скоростью — O(1). Теперь становится ясно, почему Shazam работает так великолепно!

Так как я хотел, чтобы у меня все заработало по истечению одного уикенда (к сожалению это максимальный промежуток времени моей концентрации на одном деле, затем мне нужно найти новый проект) я постарался упростить мой алгоритм насколько это возможно. И к моему удивлению это сработало.
Для каждой линии в спектральном анализе, в определенном диапазоне я выделил точки с наивысшей магнитудой. В моем случае: 40-80, 80-120, 120-180, 180-300.

Теперь, когда мы записываем песню, мы получаем список чисел, подобных этому:

Если я запишу песню и визуализирую ее, то она будет выглядеть примерно так:

(все красные точки – «ключевые точки»)

Индексация моей собственной музыки

Имея на руках рабочий алгоритм, я решил проиндексировать все мои 3000 песен. Вместо микрофона вы можете просто открыть mp3 файлы, конвертировать их в нужный формат, и считать их таким же способом, как и при использовании микрофона, используя AudioInputStream. Конвертирование стерео записей в моно режим оказалось сложнее чем я думал. Примеры можно найти в интернете (требует немного больше кодировки, чтобы выкладывать здесь) придется немного поменять примеры.

Процесс подбора

Наиболее важная часть приложения – процесс подбора. Из руководства к Shazam понятно, что они используют знаки чтобы найти совпадения и затем решить какая песня доходит лучше всего.
Вместо использования замысловатых временных группировок точек я решил строку наших данных (например, 33, 47, 94, 137) как один единственный знак: 1370944733
(в процессе тестирования, 3 или 4 точки – лучший вариант, сложнее с тонкой настройкой, каждый раз приходится реиндексировать мои mp3!)
Пример кодировки знаками, используя 4 точки на линию:

Теперь я создам два массива данных:

-Список песен, List (где List index это Song-ID, String это songname)
-Базу данных знаков: Map<Long, List>

Long в базе данных знаков представляет собой сам знак, и включает в себя сегмент DataPoints.

DataPoints выглядят следующим образом:

Теперь у нас есть все что нужно для начала поиска. Сначала я считал все песни и сгенерировал знаки для каждой точки данных. Это войдет в базу данных знаков.
Второй шаг – считывание данных песни, которую мы хотим определить. Эти знаки извлекаются и производится поиск совпадений с базой данных.

Это только одна проблема, для каждого знака существует несколько хитов, но как мы определим какая песня та самая..? По количеству совпадений? Нет, так не пойдет…
Наиболее важная штука – это время. Мы должны наложить время…! Но как нам это сделать, если мы не знаем в какой части песни находимся? С таким же успехом мы просто могли записать последние аккорды песни.

Изучая данные, я нашел нечто интересное, так как мы имеем следующие данные:
— Знаки записи
— Совпадающие знаки вероятных вариантов
— ID песни вероятных вариантов
— Временной поток в наших собственных записях
— Время знаков вероятных вариантов

Теперь мы можем сминусовать текущее время в нашей записи (например, строка 34) с временем знака (например, строка 1352). Эта разница сохраняется вместе с ID песни. Так как этот контраст, эта разница, указывает нам на то, где мы можем находиться в песне.

После того, как мы покончим со всеми знаками из нашей записи мы останемся с кучей ID песен и контрастов. Фишка в том, что если у вас много знаков с подобранными контрастами, то вы нашли свою песню.

Итоги

К примеру, слушая The Kooks – Match Box первые 20 секунд, мы получаем следующие данные в моем приложении:

Работает!!!

Прослушав 20 секунд оно может определить почти все песни, которые у меня есть. И даже эту live recording of the Editors можно определить после 40 секунд прослушивания!
И снова, это чувство волшебства!
В настоящий момент, код нельзя считать завершенным и он работает неидеально. Я слепил его за один уикенд, это больше похоже на доказательство теории/изучение алгоритма.

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

Дополнение

Юристы обладателей патентных прав на Shazam присылают мне мейлы с просьбой прекратить выпуск кода и удалении этой темы, прочитать об этом можно здесь.

От переводчика

Небольшой анонс: летом 2013 года Яндекс открывает Tolstoy Summer Camp— экспериментальную мастерскую для тех, кто хочет научиться создавать и запускать стартапы. В рамках двухмесячного курса Яндекс поможем участникам собрать достойную команду, правильно сформулировать концепцию, получить на нее фидбек от правильных экспертов и разработать прототип проекта. Разнообразные семинары и воркшопы позволят прокачать необходимые скилзы. Также мы будем регулярно публиковать интересные переводные статьи на около стартапную тематику. Если вам попадается что-то интересное, кидайте в личку! Кст, статья на хабре как Яндекс учился распознавать музыку.

Подать заявку (осталось 2 дня!!) и найти более подробную информацию можно здесь. А также в анонсе на хабре. Я буду рассказывать про Lean-методы, Customer Development и MVP. Приходите!

ссылка на оригинал статьи http://habrahabr.ru/post/181654/

Простой блог с комментариями на Django: разработка и развертывание для самых маленьких

Данная статья предназначена для новичков в web-программировании и освещает вопросы разработки блога на Django с использованием Twitter Bootstrap и его развертывания на бесплатном хостинге PythonAnywhere. Я старался написать как можно более проще и понятнее. Более опытным пользователям данное чтиво не расскажет ничего нового, да и некоторые приемы возможно покажутся неэффективными.


Предполагаю, что читатель уже ознакомлен с синтаксисом Python, имеет минимальное представление о Django (для начала неплохо пройти обучение на http://codeacademy.com по соответствующей теме и прочитать туториал по Django), а также владеет приемами работы в командной строке.
Итак, начинаем с организации рабочего окружения на локальном компьютере. В принципе, для наших запросов подойдет любая операционная система в которой вы чувствуете себя уверенно, здесь я описываю процесс для GNU/Linux, а для других систем шаги могут незначительно отличаться. В системе должна быть установлена virtualenv — утилита для создания изолированного рабочего окружения (чтобы библиотеки, которые мы используем не мешались другим программам и проектам).

Cоздаем и активируем окружение:

mkdir ~/projects cd ~/projects virtualenv env source env/bin/activate  

В ОС Windows последняя команда должна быть такой:

env/Scripts/activate  

Устанавливаем Django с помощью pip — менеджера пакетов Python.

pip install django 

Создаем новый проект. Назовем его как-нибудь оригинально — например mysite.

django-admin.py startproject mysite && cd mysite 

Скрипт отработает и создаст каталог mysite с еще одним каталогом mysite и несколькими *.py файлами внутри.

Используем скрипт manage.py для создания приложения django с именем blog.

python manage.py startapp blog 

Отредактируем настройки в файле mysite/settings.py (обратите внимание: я имею ввиду ~/projects/mysite/mysite/settings.py) добавив туда следующее:

# coding: utf-8 import os  BASE_DIR = os.path.dirname(os.path.dirname(__file__)) 

В первой строке укажем кодировку в которой работаем, во избежание путаницы и глюков предлагаю указывать ее во всех изменяемых файлах *.py, перекодируя их соответственно в UTF-8.
В BASE_DIR будет храниться полный путь к нашему проекту, что бы использовать относительные пути при дальнейшем конфигурировании

Настроим базу данных, в нашем проекте вполне можно использовать SQLite

DATABASES = { 'default':     {         'ENGINE': 'django.db.backends.sqlite3',         'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),     } } 

Настроим часовой пояс и язык:

TIME_ZONE = 'Europe/Moscow' LANGUAGE_CODE = 'ru-ru' 

Для того что бы Django узнало о созданном приложении, добавим ‘blog’ в кортеж INSTALLED_APPS, а также раскомментируем строку ‘django.contrib.admin’ для включения встроенной админки:

INSTALLED_APPS = (     'django.contrib.auth',     'django.contrib.contenttypes',     'django.contrib.sessions',     'django.contrib.sites',     'django.contrib.messages',     'django.contrib.staticfiles',     'django.contrib.admin',     'blog', ) 

Чтобы админка заработала, редактируем mysite/urls.py

from django.conf.urls import patterns, include, url  from django.contrib import admin admin.autodiscover()  #функция автоматического обнаружения файлов admin.py в наших приложениях  urlpatterns = patterns('',     url(r'^admin/', include(admin.site.urls)), #URL админки http://имя_сайта/admin/ ) 

Cоздаем модель в blog/models.py

from django.db import models  class Post(models.Model):     title = models.CharField(max_length=255) # заголовок поста     datetime = models.DateTimeField(u'Дата публикации') # дата публикации     content = models.TextField(max_length=10000) # текст поста      def __unicode__(self):         return self.title      def get_absolute_url(self):         return "/blog/%i/" % self.id 

На основании этой модели Django автоматически создаст таблицы в базе данных.

Регистрируем ее в админке blog\admin.py

from django.contrib import admin from blog.models import Post # наша модель из blog/models.py  admin.site.register(Post) 

Создадим таблицы командой:

python manage.py syncdb 

При первом вызове этой команды Django предложит создать суперпользователя, воспользуемся данным предложением.

Запускаем отладочный сервер который предоставляет Django:

python manage.py runserver 

Теперь вводим url в браузере

http://localhost:8000/admin/

Если все прошло хорошо, мы должны видеть это:

Заходим с ранее созданным логином\паролем в админку — теперь мы имеем возможность добавлять и удалять посты (кнопки справа от Posts)

Создадим несколько постов для отладки.

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

Редактируем blog/views.py

from blog.models import Post  from django.views.generic import ListView, DetailView  class PostsListView(ListView): # представление в виде списка     model = Post                   # модель для представления   class PostDetailView(DetailView): # детализированное представление модели     model = Post 

Добавим в urlpatterns mysite\urls.py строку

url(r'^blog/', include('blog.urls')), 

Для того что бы все URL-ы начинающиеся с /blog/ будут обрабатываться с помощью urls.py из модуля blog, и создаем сам файл urls.py в каталоге blog со следующим содержанием:

#coding: utf-8 from django.conf.urls import patterns, url  from blog.views import PostsListView, PostDetailView   urlpatterns = patterns('', url(r'^$', PostsListView.as_view(), name='list'), # то есть по URL http://имя_сайта/blog/                                                                                      # будет выводиться список постов url(r'^(?P<pk>\d+)/$', PostDetailView.as_view()), # а по URL http://имя_сайта/blog/число/                                                                                         # будет выводиться пост с определенным номером  ) 

Теперь нужно создать шаблоны страниц. По умолчанию для класса PostListView Django будет искать шаблон в blog/templates/blog/post_list.html (такой длинный и странный путь связан с логикой работы фреймворка, в силах разработчика поменять это поведение, но в данной статье я этого не касаюсь)

создадим этот файл:

{% block content %}     {% for post in object_list %}         <p>{{ post.datetime }}</p>         <h2><a href="{{ post.get_absolute_url }}">{{ post.title }}</a></h2>         <p>{{ post.content }}</p>     {% empty %}     <p>Нет постов</p>     {% endfor %}  {% endblock %} 

Что же, давайте попробуем как все работает, зайдя по URL на http://localhost:8000/blog/. Если ошибок нет, то мы увидим список постов, где заголовок каждого поста является ссылкой.
Пока эти ссылки ведут в никуда, надо это исправить. По умолчанию для класса PostDetailView шаблон находится в blog\templates\blog\post_detail.html.

Создаем его:

{% block content %}     <p>{{ post.datetime }}</p>     <h2>{{ post.title }}</h2>     <p>{{ post.content }}</p> {% endblock %} 

И снова проверяем: http://localhost:8000/blog/1/

Добавим возможность комментирования наших записей, в этих целях мы воспользуемcя услугами DISQUS, который установим с помощью pip

pip install django-disqus  

Этот модуль предоставляет функционал комментариев, с защитой от спама, аватарками и прочим, а также берет на себя заботу по их хранению:

Добавляем в post_detail.html перед {% endblock %}

<p>     {% load disqus_tags %}     {% disqus_dev %}     {% disqus_show_comments %} </p> 

В INSTALLED_APPS файла settings.py добавляем ‘disqus’

INSTALLED_APPS = (     'django.contrib.auth',     'django.contrib.contenttypes',     'django.contrib.sessions',     'django.contrib.sites',     'django.contrib.messages',     'django.contrib.staticfiles',     'django.contrib.admin',     'blog',     'disqus', ) 

А также добавляем в settings.py

DISQUS_API_KEY = '***' DISQUS_WEBSITE_SHORTNAME = '***' 

Два последних значения получаем, зарегистрировавшись на http://disqus.com.

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

Качаем архив http://twitter.github.io/bootstrap/assets/bootstrap.zip и разархивируем его в каталог static нашего проекта (я имею в виду ~/projects/mysite/static — создаем его)

Редактируем settings.py, что бы Django знало где искать статические страницы.

STATICFILES_DIRS = (     os.path.join(BASE_DIR, 'static'), ) 

Создаем файл blog/templates/blog/base.html следующего содержания

<!DOCTYPE html> <html lang="ru">     <head>         <meta charset="utf-8" />         <title>MyBlog</title>         <link href="{{STATIC_URL}}bootstrap/css/bootstrap.css" rel="stylesheet">         <style>             body {                 padding-top: 60px; /* 60px to make the container go all the way to the bottom of the topbar */             }         </style>         <link href="{{STATIC_URL}}bootstrap/css/bootstrap-responsive.css" rel="stylesheet">         <!--[if lt IE 9]>         <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>         <![endif]-->         <script src="{{STATIC_URL}}bootstrap/js/bootstrap.js" type="text/javascript"></script>         {% block extrahead %}         {% endblock %}         <script type="text/javascript">         $(function(){         {% block jquery %}         {% endblock %}         });         </script>     </head> <body>  <div class="navbar navbar-inverse navbar-fixed-top">     <div class="navbar-inner">         <div class="container">             <div class="brand">My Blog</div>             <ul class="nav">                 <li><a href="{% url 'list' %}" class="">Список постов</a></li>             </ul>         </div>     </div>  </div>  <div class="container">      {% block content %}Empty page{% endblock %} </div> <!-- container -->  </body> </html> 

Это основной шаблон для наших страниц, включаем его в post_list.html и post_detail.html дописав первой строкой в них

{% extends 'blog/base.html' %} 

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

Регистрируем бесплатный N00b аккаунт на PythonAnywhere. Мне понравился этот сервис легкостью в установке Django, все происходит практически так же как и на локальном компьютере.

Допустим мы создали пользователя на PythonAnywhere с именем djangotest, тогда наше приложение будет располагаться по адресу djangotest.pythonanywhere.com. Внимание: заменяйте далее по текстк ‘djangotest’ на свой логин в PythonAnywhere.

Меняем в settings.py

DEBUG = False 

и дописываем

ALLOWED_HOSTS = ['djangotest.pythonanywhere.com'] 

Закачиваем файлы на хостинг любым из доступных способов.

На мой взгляд, для неискушенного пользователя, проще всего заархивировать папку проекта, залить архив на сервер (в разделе Files->Upload a file) и разархивировать его на сервере командой в bash — шелле (Раздел Consoles -> bash):

например если мы залили файл mysite.tar.gz то выполняем в консоли PythonAnywhere

 tar -zxvf mysite.tar.gz  

Теперь настраиваем рабочее окружение на сервере, вводим в консоли PythonAnywhere:

virtualenv env  source env/bin/activate  pip remove django pip install django django-disqus 

Настраиваем статические страницы в разделе Web -> Static files:

В первой строке — место где лежит bootstrap, во второй статические файлы встроенной админки Django.

Настраиваем WSGI (Web -> It is configured via a WSGI file stored at: …):

activate_this = '/home/djangotest/env/bin/activate_this.py' execfile(activate_this, dict(__file__=activate_this))  import os import sys  path = '/home/djangotest/mysite' if path not in sys.path:     sys.path.append(path) os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings'  import django.core.handlers.wsgi application = django.core.handlers.wsgi.WSGIHandler() 

Нажимаем кнопку Web -> Reload djangotest.pythonanywhere.com

Заходим на djangotest.pythonanywere.com/blog/ — поздравляю, это было нелегко, но Вы справились. Теперь у Вас есть собственный уютненький блог, разработанный своими руками на самых современных веб-технологиях!

ссылка на оригинал статьи http://habrahabr.ru/post/181556/

Дайджест предстоящих IT-событий на июнь 2013 года

Представляет Вашему вниманию 5-й выпуск нашего (мы это портал Айти-событие.рф) «Дайджеста предстоящих IT-событий» на июнь 2013 года.

Для удобства навигации все события разделены на 6 категорий:

  • I. Девелоперские
  • II. Джуниорские
  • III. Стартаперские
  • IV. Маркетинговые
  • V. Разное


I. Девелоперские

Встреча DrupalCamp Kyiv 2013

/ Киев / 7.06.2013 / Стоимость 150 — 250 грн. image
DrupalCamp Kyiv это мероприятие, которое объединит в совместном кругу Drupal-разработчиков со всего мира. В этом году мероприятие соберет около 400 специалистов и энтузиастов для общения, обмена опытом и идеями. Проходит в формате двухдневного barcamp-а, каждый день которого состоит из четырех параллельных потоков докладов.

Встреча Web Standards Days

/ Санкт-Петербург / 8.06.2013 / Участие бесплатное image
Главной целью этой встречи является качественное образование и обмен опытом в области веб-разработки. Подобный формат не подразумевает продвижение каких-либо отдельных коммерческих интересов и технологий — нас объединяет идея построения единого открытого веба.

Конференция IV международная конференция веб-разработчиков WebCamp 2013

/ Одесса / 12 июня 2013 / Стоимость 400-600 грн. image
В первый день — доклады в 4-х основных потоках: веб-технологии и управление проектами, юзабилити и дизайн, интернет-маркетинг, стартапы, а также состоится Startup Crash Test и аллея стартапов. Второй день будет полностью посвящен проведению различных мастер-классов.

Конференция DevConf 2013

/ Москва / 14.06.2013 / Стоимость 4 000 — 8 500 руб. image
Участникам DevConf предоставляется уникальная возможность — получить доступ сразу ко всем лидирующим технологиям веб-разработки, послушав доклады от основателей этих технологий, приехавших в Москву со всего мира.

Конференция Я.Субботник в Санкт-Петербурге

/ Санкт-Петербург / 15.06.2013 / Участие бесплатное image
Докладчики из санкт-петербургского, московского и симферопольского офисов поделятся своими знаниями и опытом и обсудят актуальные вопросы в области веб-разработки. Организаторы будут рады видеть тех, кому интересно общение на профессиональные темы в уютной и почти домашней атмосфере.

Конференция JDay Lviv

/ Львов / 29 .06.2013 / Стоимость 240 $ image
На конференции выступят: Николай Красько (JetBrains), участник команды проекта Котлин; Mikalai Alimenkou (XP Injection, Zoral); Филипп Торчинский (JetBrains), технологический эксперт компании JetBrains; Russ Hertzberg (SoftServe Inc), вице президент Technology Solutions for SoftServe Inc и многие другие.


II. Джуниорские

Семинар Основы разработки на CMS Drupal

/ Екатеринбург / 2.06.2013 / Стоимость 9000 руб. image
Участие в семинаре позволит Вам: разрабатывать интернет-проекты с использованием CMS Drupal; оптимально подбирать концепцию проекта на CMS Drupal для дальнейшего его развития; получить квалификацию и претендовать на интересную работу с требованием наличия знаний по CMS Drupal.

Курс Третья Школа менеджеров Яндекса

/ Москва / 28.06.2013 / Участие бесплатное image
Школа приглашает целеустремленных старшекурсников и недавних выпускников, которые хотят профессионально управлять проектами в интернете, но пока не обладают достаточным опытом и знаниями. Для поступления необходимо до 9 июня включительно заполнить анкету с тестовыми заданиями.

Конференция Всероссийский учебный марафон «Программист»

/ Москва / 29.06.2013 / Участие бесплатное image
Всероссийский учебный марафон по программированию призван объединить тысячи активных пользователей интернета, интересующихся современными информационными технологиями, в рамках общего онлайн-мероприятия. Цель марафона – дать каждому желающему возможность освоить ключевые базовые навыки профессии программиста.


III. Стартаперские

Встреча AppClub { build, monetize } #6 Kyiv

/ Киев / 5.06.2013 / Стоимость 13.28 — 500.00 $ image
Темы встречи: прототипирование и дизайн мобильных приложений, разработка игр, мобильный маркетинг, презентации стартапов. К участию приглашаются стартапы.

Первый Хакатон в Саранске

/ Саранск / 08.06.2013 / Участие бесплатное image
На первый Хакатон в Мордовии приглашаются все любители и профессионалы разработки ПО. В программе, помимо кодинга, конкурсы, игры и прочая развлекуха – но не думайте, что вам придется много отдыхать!


IV. Маркетинговые

Конференция DEMO Europe (Россия)

/ Москва / 3.06.2013 / Стоимость 10 000 — 20 000 руб. image
DEMO — конференция, посвященная новым технологиям и инновациям. На конференции демонстрируются перспективные разработки и представляются прорывные идеи и проекты в области информационных технологий.

Конференция Digitale 3

/ Санкт-Петербург / 3.06.2013 / Стоимость 4 000 руб. image
Мероприятие, посвященное теме инноваций в маркетинге.Интерактивные лекции, идущие одним потоком, будут посвящены таким направлениям, как партизанский маркетинг, маркетинг без бюджета, шоппер-маркетинг и автоматизация маркетинга.

Форум MoCO и Mdday#MoCO 2013

/ Москва / 4.06.2013 / Стоимость 3 500 — 27 000 руб. image
В этом году на Mdday#Moco организаторы внедрят новый формат организации пространства. Конференция, которая будет состоять из выступлений мобильных вендоров и открытых дискуссий, будет совмещена с выставочным пространством Developer Alley, где студии будут показывать свои работы и вести переговоры с партнерами и заказчиками. Будет шумно. Будет невероятно полезно и эффективно.

Конференция DIGITAL БЕЗ СИЛИКОНА

/ Москва / 7.06.2013 / Стоимость 15 000 руб. image
«Digital без силикона» – уникальная конференция по цифровому маркетингу, где лучшие специалисты-представители брендов делятся своим опытом и практическими знаниями. Задача мероприятия — дать возможность маркетологам и представителям брендов поделиться опытом работы в сфере маркетинговых коммуникаций.

Конференция White Nights: Mobile Games Conference

/ Санкт-Петербург / 27.06.2013 / Стоимость от 200 $ image
Ожидается более 800 человек из ведущих компаний, включая Supercell, Rovio, Wooga, Chillingo, Kabam, PlayFirst, Facebook, Microsoft, Google. Несколько причин побывать на конференции: уникальный спикерский состав; лекции и круглые столы, посвященные практическим кейсам, пройдут в два потока во второй половине дня. Также состоятся мастер-классы; бизнес-контакты; нетворкинг и т.д.


V. Разное

Выставка FriendWork FEST

/ Санкт-Петербург / 1.062013 / Стоимость 0 — 5 000 руб. image
Мероприятие будет интересно всем, кто мечтает найти работу в новых и перспективных проектах в различных сферах – от IT до PR. Не упусти свой шанс изменить свою жизнь и найти по-настоящему крутую работу на FriendWork FEST!

Турнир IT Paintball Cup 2013

/ Харьков / 15.06.2013 / Стоимость 2 400 грн. image
Самое захватывающее событие года: битва сильнейших среди программистов! В этот день лицом к лицу встретятся все те, кто давно мечтал оторваться от спинок своих кресел, мониторов, нескончаемых тасков, kanban бордов и неизбежных дедлайнов. Приглашаютя новые и существующие команды программистов принять участие в соревнованиях и отстоять честь своей компании. Этот день для вас!

Фестиваль ЛАФ 2013

/ Калужская область, д. Петрово / 29.06.2013 / Стоимость 4 000 — 5 000 руб. image
ЛАФ — это ежегодный двухдневный фестиваль системных аналитиков, который проводится уже в четвёртый раз. Первый день — конференция. Этот день будет посвящён традиционным докладам и мастер-классам. Второй день — общение в свободном формате. Круглые столы на свежем воздухе, обсуждения, развлечения, культурный отдых.


Мы в социальных сетях:

Вконтакте / Twitter / Facebook / Linkedin / Хабрахабр


Наши Google Сalendar’и:

Все города / Москва / Санкт-Петербург / Киев / Минск / Новосибирск / Екатеринбург / Нижний Новгород

ссылка на оригинал статьи http://habrahabr.ru/company/it_dominanta/blog/181552/