Как выявляют риски в госконтроле и зачем для этого машинное обучение

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

Оценка рисков

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

Возьмём для примера таможенное оформление: при ввозе любого товара в страну кроме множества различных сведений (стоимость, вес, упаковка, отправитель, получатель и т. д.) в декларации нужно заявить код по специальному классификатору — товарной номенклатуре внешнеэкономической деятельности (ТН ВЭД). По этому коду для товара затем определяется пошлина согласно таможенному тарифу (ТН ВЭД + ставки).

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

Так мы идентифицировали риск — заявление недостоверного кода товара в декларации с целью занижения таможенных платежей. Причина — наличие в классификаторе “пограничных” позиций с разными ставками пошлины.

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

Самый простой способ получить такие правила — довериться экспертным суждениям своих сотрудников.

Экспертные правила

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

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

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

Например, экспертное правило для таможенного контроля говорит нам, что все партии яблок со стоимостью ниже определённого порога, относятся к рисковым поставкам:

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

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

Поэтому применение экспертных правил обычно приводит к избыточному охвату объектов контроля и небольшой результативности (помните, наши квадратики из первой статьи?):

Не стоит винить экспертов: человеческое сознание ограничено в объектах, которыми оно может оперировать (когда-то на Хабре была опубликована любопытная статья, автор которой предположил, что их число ограничено семью). Отсюда и крупные мазки вместо точных деталей: скажем, риск пожара определяют только по году постройки здания, району нахождения и категории жильцов. Все эти характеристики однажды “сыграли”: в старом доме вспыхнул пожар, в неблагополучном районе загорелось помещёние. Поэтому эксперты ожидают в будущем угрозы именно от объектов подобного типа.

Но не все из таких “опасных” зданий в действительности собираются сгореть, даже если попадают под экспертное правило: многие старые и деревянные дома стоят, как ни в чём не бывало. Некоторые неблагополучные дома годами стоят без единого пожара. Просто эксперт не смог учесть какие-то тонкие индивидуальные особенности опасных объектов.

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

Статистические профили рисков

В этом случае мы решаем задачу бинарной классификации: специализированный аналитический алгоритм сам определяет, какие характеристики объектов позволяют отнести их “плохим” или “хорошим”. Если всё сделать правильно, на выходе мы получим довольно точные оценки рисков: детальные условия и автоматически рассчитанные вероятность плюс потенциальный ущерб (которые при экспертном подходе определяются тоже как-то “экспертно”). Эти характеристики определяют “профиль риска” — что, где, когда и насколько страшно.

Статистические профили рисков создаются по-разному. В основе может лежать дерево решений или случайный лес. Можно применить хитрую нейросеть с большим числом скрытых слоёв.

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

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

Любая проверка должна быть обоснована и это обоснование следует выразить словами. Иначе потом придётся краснеть перед прокурором и объяснять, как вышло, что госорган “зажимает” отечественный бизнес на основе таинственных указаний deus ex machina.

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


* значения параметров профиля изменены и не соответствуют реальным

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

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

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

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

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

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


* набор параметров профиля риска изменен и не соответствует реальному

Вот так строится статистический профиль риска с помощью алгоритмов класса “дерево решений” — каждый его уровень все лучше разделяет совокупность проверяемых субъектов на “хороших” и “плохих” и показывает, какая характеристика для разделения оказалась наиболее значимой (на скриншоте SAS Visual Statistics):

Статистические профили лучше, чем экспертные — точнее, избирательнее, беспристрастнее. Они помогают повысить результативность проверок, снизив число холостых “сработок”:

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

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

Поиск неизвестного

Пощупать неизвестность можно несколькими способами.

Первый — случайная выборка. Берём произвольный объект (в пределах своих полномочий) — товар, предприятие, здание или гражданина — и внимательно его рассматриваем. Подход достаточно беспристрастный, но не слишком эффективный — под “разбор полетов” может с равным успехом попасть и добропорядочный субъект. Силы госоргана и бюджетные деньги будут потрачены зря.

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

Например, при проведении экологического надзора выясняется, что завод потребляет неожиданно много электроэнергии:

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

Или товар на таможне имеет необычное соотношение веса товара и упаковки:

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

Впрочем, это самые простые примеры, которые в состоянии увидеть и человек. В реальности поиск аномалий происходит в многомерном пространстве атрибутов — их могут быть сотни. Алгоритм делает то, что не под силу человеку — находит объекты, которые значительно отличаются от остальных таких же одновременно по большому числу признаков, и определяет так называемые многомерные выбросы (на скриншоте SAS Visual Statistics):

Также за пределами человеческого восприятия находится многообразие правоотношений между различными компаниями, которые визуализируются с помощью графа (на скриншоте SAS Social Network Analysis):


* названия организаций выдуманы, совпадения с реальными компаниями случайны

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

Аномалия — это не риск, это просто “что-то необычное”. Профили аномалий нужны, чтобы давать новое “сырьё” для построения экспертных или статистических профилей, так как результат проверки аномалии включается в историю наблюдений за объектами контроля.

Гибридный подход

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

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

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

И уже интегральная оценка (например, на основе экспертной матрицы решений) определяет выбор контрольного органа — кого проверять, а кому доверять.

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


ссылка на оригинал статьи https://habr.com/post/421677/

Создание демо для старого телефона — AONDEMO

Хотел сделать демку с тех самых пор, как познакомился с этим явлением компьютерной субкультуры на классическом примере польской Lyra II. Также регулярно хотел выставить что-нибудь на крупнейшем российском демопати, Chaos Constructions, но каждый раз не доходили руки. Наконец-то удалось удовлетворить обе потребности сразу, в стиле Ван Дамма (двойной удар, с вертушки) — сделать и выставить AONDEMO. В конкурсе ZX Spectrum 640K Demo.

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

История

Телефоны с Автоматическим Определителем Номера (АОН), также известные как «определитель» или «электронный секретарь», появились в СССР примерно в 1989 году, и в последующие 15 лет бурно развивались, пройдя путь от средства заработка студентов, безработных инженеров (наряду со сборкой Спектрумов) и целых кооперативов, до основного предмета деятельности довольно крупных компаний. В середине 1990-х годов подобный телефон встречался чуть ли не в каждой квартире, и любой пользователь телефонной сети на раз мог по характеру гудков в трубке понять, определяется ли сейчас его номер (поддельные гудки и характерный звук запроса). К 2004 году популярность подобных аппаратов сошла на нет, сам сервис определения номера на АТС сначала стал платным, а потом и вовсе был упразднён, сменившись на более современный европейский стандарт. Повсеместное распространение мобильной связи быстро загнало проводные телефоны в глубокий андерграунд, где всё ещё выходят непонятно кем востребованные «элитные» потомки АОН 90-х (Палиха).

Сцена разработчиков и сборщиков ранних АОН — это как бы параллельная отечественному Спектруму реальность. Радиолюбительские корни и романтика. Стихийная разработка, развитие и кустарное производство. Схожее железо, схожие интересы, схожий период и объём популярности. Многие люди поначалу одновременно занимались тем и другим. Юные авторы всесоюзно известного ПО (Павлу Суходольскому, автору Руси, было тогда около 15 лет), невозбранное заимствование кода друг у друга, копирайты и послания в коде, фидошные адреса, статьи в прессе, книжки, мифология, и многое другое. Весьма масштабная, но уже основательно занесённая песками времени история начала цифрового века, ещё ждущая своих исследователей.

АОН и я

Моё знакомство с АОН состоялось в первой половине 90-х, уже после первых увиденных игр на Спектруме и Денди, но незадолго до начала созидательно-программировательной деятельности. Мне нравилось ковыряться с этими телефонами, экспериментировать с последовательностями клавиш в свежих или незнакомых прошивках, слушать популярные мелодии в «компьютерном» исполнении и удивляться «компьютерным» голосам, а также вычитывать в инструкциях упоминания неведомых артефактов «запись на магнитофон», «шлейф охраны», «голосовая плата», «бипер». Друг детства помогал своему отцу собирать подобные аппараты, а я увлекался электроникой и только-только увлёкся компьютерами, и таким образом урывками приобщался к тайному знанию про Z80, ВВ55 и другие магические обозначения. Одновременно «определители» стали появляться у всех друзей. Они часто ломались и попадали в мои руки с просьбой попробовать починить, чем я и занимался, иногда успешно, чаще нет. В 2000-х эта деятельность сошла на нет.

В 2013 году при раскопках самых дальних углов квартиры я наткнулся на пару сохранившихся телефонов и вспомнил былые времена. Немного позже тогдашние изыскания в области 1-битной музыки, DIY-синтезаторов и особо старых компьютеров типа KIM-1, навели меня на мысль, что АОН — это же готовый, вполне полноценный одноплатный компьютер, который может быть задействован в нестандартных музыкальных целях (как драм-машина или секвенсор). Исполнившись энтузиазма, я начал писать эмулятор и разбирать старые прошивки, но вскоре обнаружилось, что найденные ранее телефоны были вполне успешно выброшены в процессе уборки. Тема была отложена в долгий ящик.

Постепенно различные интересы, затеи и предметы — разработка PCSPE для PC Speaker, воспоминания и интерес к старым телефонам с АОН и их истории, чтение сайта 155la3 про редкие советские радиодетали (изумительные сегментные индикаторы!), старые идеи про музыкальное применение этого железа, приобретение множества АОНов на Avito, а также электронных запчастей и инструментов для разных проектов, продолжение работы над эмулятором, и так далее — сложились в нужную схему. Незадолго до Мультиматографа 2018 наконец-то оформилась логическая связь между сущностями «демо» и «телефон» (насколько я могу вспомнить, это было вызвано увиденным словосочетанием «демка для калькулятора» ), и началась целенаправленная работа. Конечно, ничего существенного за неделю с небольшим сделать не удалось, дело замедлилось, но возобновилось с приближением CC2018. В лучших традициях, ударным трудом и неимоверными усилиями за два дня и ночь перед пати удалось допридумать, донаписать и отладить большую часть задуманного, снять и смонтировать видео, и рано поутру отправить работу на конкурс.

Уже после релиза я узнал, что семисегментные дисплеи не редкий гость в работах для Wild Сompo. Но я таковых не видел и про них ранее не слышал.

Железо

По сути АОН представляет собой простейший одноплатный компьютер с семисегментным дисплеем, телефонной клавиатурой и интерфейсом сопряжения с телефонной линией. На протяжении полутора десятка лет железо менялось, начиная от конструкции на КР580ВМ80 (i8080) 1989 года и заканчивая заказным чипом R100-XP компании Русь-Телеком 2003 года (8051, периферия и аналог AY-3-8910 на одном кристалле), со множеством промежуточных остановок и ответвлений.

Я выбрал самую классическую и популярную версию разработки 1990 года, исторически и технически наиболее близкую духу Спектрума: Z80 на частоте 4 МГц ровно, 2 килобайта статического ОЗУ, 8-64 килобайт ПЗУ, порт 8255 и таймер 8253 со входной частотой 1 МГц. Один из каналов таймера генерирует прерывания, другой звук, третий не задействован. Эта схема была представлена в виде «большой» и «маленькой» плат, первая предназначалась специально для установки в корпус латвийского кнопочного телефона VEF-TA-12, вторая ставилась в самые разнообразные импортные телефоны, в основном клоны офисных Panasonic. Для этих плат существовали разнообразные прошивки, в частности, Арктур-36, Селена, Лира, Алло. И, конечно, самая знаменитая — Русь, до 23 версии включительно.

Перепрограммировать телефон очень просто — достаточно любого 5-вольтового ПЗУ нужного объёма и программатора. Я использовал различные EEPROM со старых материнских плат и свежие Winbond W27C512, закупленные в Китае, а также самый простой и доступный программатор WizardProg-87.

Наибольшей сложностью при работе с железом оказалось состояние панелек под ПЗУ на платах древностью в четверть века и более. Они изначально не отличались высоким качеством, а в наше время контакт в них постоянно теряется, что затрудняет определение — ошибка ли это в написанном коде или просто неконтакт в панельке. Я пытался решить этот вопрос установкой ZIF-сокета, но высота других компонентов на плате не позволила его впаять, а этажерка из разъёмов для наращивания высоты, вставляемая в оригинальную панельку, также страдала от постоянной потери контакта.

Эффекты

Перед началом разработки демо я написал, а точнее дописал начатый ещё в 2014 году, эмулятор АОН. Пришлось доразобраться с некоторыми неочевидными моментами, а также применить чужой код эмуляции таймера 8253, чтобы получить более-менее нормальный звук и частоту прерываний. Наличие эмулятора и хотя бы рудиментарных отладочных возможностей в нём многократно ускоряет разработку. Далее код в основном тестировался в эмуляторе, и лишь иногда на железе, чтобы убедиться, что всё работает правильно и нормально смотрится на светодиодном дисплее с динамической индикацией, адекватную имитацию которой я сделать пока не смог.

Код писался в обычном SjAsmPlus. У АОН довольно причудливая карта памяти, вероятно следствие минимизации переделок железа при расширении объёмов ПЗУ под новые, более крутые прошивки. В результате, хотя и можно установить до 64 килобайт ПЗУ, в памяти доступно только 32 килобайта, чередующиеся банками по 8 килобайт с ОЗУ. 32-килобайтные половинки полного объёма ПЗУ можно переключать выводом в порт, но для демо это не понадобилось, всё поместилось в 32К. В образе ПЗУ 8-килобайтные банки должны идти подряд, без зазоров, поэтому посредством директив ассемблера и BAT-файла пришлось организовать размещение банков по нужным адресам с дополнением нулями, раздельное сохранение и объединение в финальный образ.

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

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

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

Хотя это и было не совсем в тему, упустить возможность показать знаменитую семисегментную надпись ЕГГОГ было бы непростительно. Наиболее логичное место для неё нашлось в самом конце — демо начиналось имитацией сбоя, и завершилось сообщением об ошибке.

Разбор программной реализации эффектов не имеет особого смысла, всё достаточно прозрачно. Главной особенностью платформы, о которой стоит упомянуть, является необходимость программной динамической индикации, то есть надо постоянно перебирать разряды дисплея и включать нужные сегменты. Это сделано посредством прерываний. Частота прерываний выбрана довольно высокой, 960 герц (~4166 тактов на прерывание), а индикация сделана посредством списка произвольной длины, описывающего порядок включения разрядов. Помимо стабильной индикации с приличной яркостью это позволило легко сделать два эффекта — «зависание» с характерной яркой восьмёркой (перестаёт работать перебор разрядов) и эффект изменения яркости (в одном цикле некоторые разряды включаются несколько раз). В нормальном режиме индикации частота обновления дисплея составляет около 106 герц, что устранило заметное глазу мерцание и упростило последующую съёмку на видео.

Музыка

Единственный звуковой канал АОН построен на одном из каналов таймера 8253 и по сути копирует устройство PC Speaker, только с другой входной частотой — то есть он может гудеть звуком заданной высоты, пока процессор занимается своими делами. Возможности изменять форму и громкость сигнала при этом нет. Так как я уже некоторое время плотно занимался темой музыки на классическом PC Speaker’е — написал VST-инструмент PCSPE для удобного создания таковой музыки в современных DAW и накопил опыт аранжировки строго монофонических мелодий (в один момент времени всегда звучит только одна нота) — решение было очевидно: не писать очередной 1-битный движок, а просто сделать музыку в PCSPE и адаптировать под АОН. Это и менее трудозатратно, и аутентично по звучанию, и идеологически верно — выжать необычное из привычного.

Музыка писалась в Reaper. Так как художественной задумкой для начала демо была имитация стандартного запуска прошивки Русь, я точно повторил эту мелодию, имитировал некоторые типичные звуки (нажатие кнопок, стандартный звонок), и построил из них ритмическую композицию. Далее трек постепенно развивался, исходя из начальной идеи, по пути постепенного усложнения — всё больше и больше партий, создающих иллюзию одновременного звучания нескольких каналов. Так как идеей самого сложного в демо эффекта был бегающий влево-вправо символ с разными уровнями яркости, напоминающий светотехнику машины Kitt, я также сделал вставку с мелодией из Knight Rider и нашёл ей подходящее место.

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

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

Помимо звуков, прошивки для АОНов были примечательны голосовыми сэмплами. В процессе работы я разобрал в общих чертах их формат хранения и прослушал сэмплы, в которых нашлось немало любопытного (3-4 разных голоса, ненавязчивое заимствование их из прошивки в прошивку, фразы отсылания абонента в различные места). Была идея сделать в демо речевую вставку, составленную из этих сэмплов, говорящую что-то неожиданное узнаваемым голосом. Но на придумывание хорошей идеи и её реализацию не хватило времени. Как интересный факт, голос в старых прошивках хранится в виде 4-битных сэмплов с частотой дискретизации 4500-5000 Гц, и играется через ШИМ на таймере.

Видео

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

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

Интересной особенностью этого дисплея, калькуляторного АЛС318, оказалось то, что у всех экземпляров АОНов с ним, которые есть у меня в наличии, часть разрядов заметно утратила яркость. Скорее всего дело в том, что АОНы любили зависать, а при зависании динамическая индикация перестаёт работать и надолго зажигается полной яркостью один из разрядов. Хотя можно было бы выбрать и поставить наиболее живой дисплей, я не стал ничего предпринимать по этому поводу, решив, что это добавит аутентичности в видео.

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

Релиз и результаты

Раздел для тех, кто интересуется жизнью демосцены и организационными тонкостями.

Как получилось, что демо оказалось в категории ZX Spectrum. Буквально за две недели до события была введена поправка в правила, говорящая, что к участию в этой категории допускаются работы «для ZX Spectrum совместимых компьютеров и других компьютеров выпущенных не позднее 1991 года». Фактически категория превратилась в Combined Oldschool Demo, то есть демо для любых старых компьютерных платформ, причём по соображениям сценово-политического характера название осталось прежним. Конечно же это вызвало некоторое количества непонимания и критики, и уже начало становиться локальным сценовым мемом.

Дополнительно, на самом пати по причине недостаточного количества работ в разных конкурсах большую часть демо для редких платформ и Wild объединили в Combined Demo, а в ZX Demo помимо моей работы попала только одна не-ZX работа. В сложившейся ситуации я считаю, что уместнее было бы выделить эти две работы в Combined, оставив на этот раз конкурс с ZX Spectrum в названии только для ZX Spectrum. Если бы я знал о таком положении вещей на момент отправки работы, то выбрал бы категорию Combined Demo.

По каким соображениям я решил не выставляться в категории Wild (в ней традиционно выставляются работы в формате видео и анимации, хотя теоретически она также предназначена и для работ на нестандартных платформах). Не спорю, что по сути работа очень близка к этому направлению. Но всё же это реальное демо, с реальным TRD бинарником и исходниками, для реальной и весьма популярной в прошлом платформы, родственной нашим домашним компьютерам. Его можно легко запустить и посмотреть на реальном железе — нужен только программатор, как и в случае с приставками. Само железо тоже вполне доступно, определённо доступнее, чем, например, ZX-81. Также есть какой-никакой эмулятор. Иными словами, это не разовая уникальная сложно повторяемая акция в виде видеоролика (типа демки для банкомата или редкой модели фотоаппарата), посмотреть мою работу и сделать нечто подобное теперь достаточно легко сможет любой желающий.

Скачать

AONDEMO с исходниками
AONZ80Emu для Windows
LED9ED для Windows
PCSPE для DAW с поддержкой VSTi


ссылка на оригинал статьи https://habr.com/post/421961/

Сенат не хочет, чтобы роботы отвлекались на пиво. А про что еще писать в пятницу?

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

В 2015 исследователи из Массачусетского Технологического Института (MIT) представили проект по «кооперации нескольких роботов в неопределенных условиях». Они разработали систему, по которой роботы, не имея постоянной связи друг с другом, могут вместе решать задачи, условия которых довольно изменчивы. Например, складские работы, доставка медикаментов и тд.

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

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

Они записали видео, как работы занимаются доставкой пива и назвали их «Пивботы» (Beerbots).

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

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

Господин Президент, вы слышали шутку, как три робота зашли в бар? Не слышали. А это не шутка — это проект частично оплаченный Министерством Обороны. Эти так называемые «Пивботы» запрограммированы приносить холодное пиво студентам. Исследователи говорят, что использованные методы программирования могут быть применены в ресторанах и барах. Но частный сектор уже давно, взял роботов-барменов —или робарменов — на вооружение. Они сто лет как смешивают коктейли в барах и даже на круизных лайнерах.

С нашим национальным долгом, превышающим $21 триллион, налогоплательщики не должны платить за Пивботов и поддерживать прочие ненужные траты.

Как пишет издание Spectrum.ieee, которое первым из многих обрушилось с критикой на сенатора (Vice, например, предположили, а не является ли он сам «прочей ненужной тратой» для налогоплательщиков), выступление вряд ли остановит финансирование робототехники.

Один из авторов проекта так прокомментировал заявление Флейка:

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

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

Думаю, дроны разносчики кофе от IBM будут облетать сенатора стороной.


ссылка на оригинал статьи https://habr.com/post/421955/

Что делать, когда “this” теряет ссылку на контекст

Привет, Хабр! Представляю вашему вниманию перевод статьи «What to do when “this” loses context» автора Cristi Salcescu.

Лучший способ избежать потери контекста this – не использовать this. Однако, это не всегда возможно. Например, мы работаем с чужим кодом или библиотекой, которые используют this.

Литерал объекта, функция-конструктор, конструктор объектов класса в системе прототипов. Псевдопараметр this используется в системе прототипирования для того, чтобы дать доступ к свойствам объекта.

Давайте рассмотрим несколько случаев.

Вложенные функции (Nested Functions)

this теряет ссылку на контекст внутри вложенных функций.

class Service {   constructor(){     this.numbers = [1,2,3];     this.token = "token";   }      doSomething(){     setTimeout(function doAnotherThing(){       this.numbers.forEach(function log(number){       //Cannot read property 'forEach' of undefined           console.log(number);           console.log(this.token);       });     }, 100);   } } let service = new Service(); service.doSomething();

У метода doSomething() две вложенные функции: doAnotherthing() и log(). При вызове service.doSomething(), this теряет ссылку на контекст во вложенной функции.

bind()

Один из способов решения проблемы – метод bind(). Взгляните на следующий код:

doSomething(){    setTimeout(function doAnotherThing(){       this.numbers.forEach(function log(number){          console.log(number);          console.log(this.token);       }.bind(this));     }.bind(this), 100);   }

bind() создает новую версию функции, которая при вызове уже имеет определенное значение this.

function doAnotherThing(){ /*…*/}.bind(this) создает версию функции doAnotherThing(), которая берет значение this из doSomething().

that/self

Другой вариант – объявить и использовать новую переменную that/self, которая будет хранить значение this из метода doSomething().

doSomething(){    let that = this;    setTimeout(function doAnotherThing(){       that.numbers.forEach(function log(number){          console.log(number);          console.log(that.token);       });     }, 100);   }

Мы должны объявлять let that = this во всех методах, использующих this во вложенных функциях.

Стрелочные функции (Arrow function)

Стрелочная функция даёт нам еще один способ решения этой проблемы.

doSomething(){    setTimeout(() => {      this.numbers.forEach(number => {          console.log(number);          console.log(this.token);       });     }, 100);   }

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

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

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

doSomething(){        let log = number => {      console.log(number);      console.log(this.token);    }         let doAnotherThing = () => {      this.numbers.forEach(log);    }         setTimeout(doAnotherThing, 100); }

Функции обратного вызова (Method as callback)

this теряет ссылку на контекст при использовании метода в качестве функции обратного вызова. Посмотрим на следующий класс:

class Service {   constructor(){     this.token = "token";    }      doSomething(){     console.log(this.token);//undefined   }  } let service = new Service();

Давайте разберем ситуации, в которых метод service.doSomething() используется как коллбэк-функция.

//callback on DOM event $("#btn").click(service.doSomething); //callback for timer setTimeout(service.doSomething, 0); //callback for custom function run(service.doSomething); function run(fn){   fn(); }

Во всех случаях выше this теряет ссылку на контекст.

bind()

Мы можем использовать bind() для решения этой проблемы. Ниже приведен код этого варианта:

//callback on DOM event $("#btn").click(service.doSomething.bind(service)); //callback for timer setTimeout(service.doSomething.bind(service), 0); //callback for custom function run(service.doSomething.bind(service));

Стрелочная функция

Еще один способ – создание стрелочной функции, которая вызывает service.doSomething().

//callback on DOM event $("#btn").click(() => service.doSomething()); //callback for timer setTimeout(() => service.doSomething(), 0); //callback for custom function run(() => service.doSomething());

React-компоненты (React Components)

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

class TodoAddForm extends React.Component {   constructor(){       super();       this.todos = [];   }      componentWillMount() {     this.setState({desc: ""});   }      add(){     let todo = {desc: this.state.desc};      //Cannot read property 'state' of undefined     this.todos.push(todo);   }      handleChange(event) {      //Cannot read property 'setState' of undefined      this.setState({desc: event.target.value});   }      render() {     return <form>       <input onChange={this.handleChange} value={this.state.desc} type="text"/>       <button onClick={this.add} type="button">Save</button>     </form>;   } } ReactDOM.render(   <TodoAddForm />,   document.getElementById('root'));

В качестве решения мы можем создать новые функции в конструкторе, которые будут использовать bind(this).

constructor(){    super();    this.todos = [];    this.handleChange = this.handleChange.bind(this);    this.add = this.add.bind(this); }

Не использовать “this"

Нет this — нет проблем с потерей контекста. Объекты могут создаваться с помощью фабричных функций (factory functions). Посмотрите на этот пример:

function Service() {     let numbers = [1,2,3];   let token = "token";      function doSomething(){    setTimeout(function doAnotherThing(){      numbers.forEach(function log(number){         console.log(number);         console.log(token);       });     }, 100);   }      return Object.freeze({     doSomething   }); }

Контекст остается если использовать метод в качестве коллбэка.

let service = Service(); service.doSomething(); //callback on DOM event $("#btn").click(service.doSomething); //callback for timer setTimeout(service.doSomething, 0); //callback for custom function run(service.doSomething);

Заключение

this теряет ссылку на контекст в различных ситуациях.
bind(), использование переменной that/self и стрелочные функции — это способы решения проблем с контекстом.

Фабричные функции дают возможность создавать объекты без использования this.


ссылка на оригинал статьи https://habr.com/post/421959/

Отряд самоубийц. Как мы набираем самых лютых junior-разработчиков

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

Рекрутинговая модель

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

Была выведена следующая классификация:

0 уровень – fullzero-разработчик, человек прошел пару курсов, усвоил основные конструкции и семантику какого-то языка, почитал несколько статей на хабре по хайповым темам, в итоге от программиста там максимум наклейка на ноутбуке.
1 уровень – junior-разработчик, человек, который отлично пишет код, хорошо разбирается в стеках, находится в курсе текущих трендов, умеет самостоятельно декомпозировать задачу и решать ее.
2 уровень – middle-разработчик, человек обладает всеми вышеперечисленными качествами junior, а также способен выразить свое компетентное мнение по решаемой задаче на основе анализа ресурсов, и может влиять на ход ее выполнения в рамках, выбранного им тулчейна.
3 уровень – senior-разработчик, он же руководитель, он же отец-батюшка, человек, который трансформирует и проектирует задачи из бизнес-плоскости в плоскость разработки, распределяет эти таски по мидлам и джунам, контролирует и помогает с их выполнением.

К этой классификации добавлялись еще такие критерии как: знание нашего тулчейна, адекватность, опыт работы порядка 1-2 лет, и хотя бы один успешно реализованный проект, умение четко выражать мысли, наличие навыков коммуникации, способность признавать свои ошибки и недостатки (здоровая самокритика — это мощный инструмент). Приоритет по набору, как уже было сказано выше, ставился на junior-разработчиков, так как наш опыт общения с мидлами, показал, что, как правило, эти люди уже испорчены каким-то стеком технологий и “уникальными” подходами других компаний. Кроме этого практика показала, наличие большого количества людей на рынке, привыкших к существованию в жесткой вертикальной структуре, где к ним на стол попадает альденте материал из разжеванных задач, который остается лишь набить в виде кода, а задача сеньоров — бить палкой по голове за косяки. Только вот дело в том, что когда действие происходит в молодом стартапе, а в команде всего около тридцати человек, каждый из которых загружен под полный бак, то времени на персональную декомпозицию для каждого сотрудника нет, так как это будет равносильно выполнению этой задачи. В таких условиях, когда написание кода занимает примерно десять процентов от общего времени выполнения таска, необходимо включать не только пальцы, но и голову. Именно это и написано в “библии” всех программистов – Стивен Макконел “Идеальный код” он же Redbook (не путать с американским женским журналом).

И тут нас накрыло волной…

Кого только к нам не заносило, начиная от персонажей, которые считают, что они middle потому, что написали целое приложение на Android, у которого аж целых 37 скачиваний на Google Play, заканчивая людьми, которые считают себя супер синьорами, потому что работали ведущими разработчиками в какой-то студии, хотя их работа, по большому счету, сводилась к приемо-передаче задач от отдела проектирования в отдел разработки, то есть у них не было опыта ни в проектировании, ни в управлении разработкой, а было лишь много амбиций и куча гонора. Были и такие, кто с семимесячным опытом программирования считал себя синьорами, и требовали зарплату 240к, при этом не решая даже элементарных задач для джуниоров. С нашей точки зрения эти люди не были даже джунами. Подход простой, если человек программирует прям от души, он просто программист, если же человек плохо программирует или вообще не тянет, он не джуниор, он просто не программист. Здесь нам помог замечательный лайвхак по отсеву таких кандидатов, называется он “Закон Сантехника”, который гласит: “Каждый новый сантехник приходя на новое место работы поливает грязью другого сантехника, говоря, что у того руки-вантузы, и что теперь придется все делать с нуля”. На практике это работает примерно так: приходит соискатель на должность джуниора, ему дают какой-нибудь готовый кусок кода, например, фрагмент ядра Linux, и спрашивают, что он думает по данному решению? Если он начинает плеваться и говорить что-то вроде: “Что за рукожоп это писал? Здесь надо все переделывать! Дайте мне время, и я напишу все заново”, значит перед вами сантехник, и его первоочередная задача – это ругать предыдущего сантехника.
Микеланджело по этому поводу говорил так: “Я беру камень, отсекаю все лишнее.” Великий мастер не писал скрипты, зато хорошо понимал, что грамотный человек подходит к объекту работы с желанием его понять и при необходимости преобразить, но никак не разрушить и превратить в пыль. То есть если человек на такие вопросы отвечает: “Если код работает в продакшене и выполняет свои функции — это уже хорошо, в отдельных местах я считаю можно улучшить этот код, при необходимости могу показать.”, то с таким человеком можно и нужно продолжать диалог.
Еще одним приемом по определению low-skill джунов это фокус на хайп и хайповые стеки. Если человек приходит на интервью и начинает сыпать трендовые подходы, а на законный вопрос: “С чего ты сделал такой вывод, и проводил ли ты анализ этих инструментов?” — скорчив гримасу, достигшего просветления сеньора, отвечает: “На Этом можно написать все что угодно, за Этим будущее!”, то перед вами в лучшем случае слабенький джуниор, у которого нет никакого анализа ресурсов, стеков и прочего тулчейна, лишь поверхностная информация по хайповым инструментам и подходам.

Еще немного про интервью

Помимо вышеперечисленного при найме программиста очень важно получить от него открытую позицию по его знаниям в том или ином стеке. Вы определяетесь со стеком, и он выбирает язык, в котором он “вай вай вай как силен”, допустим он горец JavaScript. Есть готовый набор задачек, например, такая:

setTimeout(()=>{console.log('Hello World!')}, 1000); while (true) { let a = false; };

Если на вопрос по этой задаче: “Когда будет выведен «Hello World!» ?”, он начинает запинаясь отвечать в стиле: “ Ну…эээ…воот…после выполнения цикла while true или через одну секунду” — это значит, что он абсолютно не знает стек, врет о своих скилах, которые, скорее всего, близки к нулю. Дело в том, что конструкция while загрузит препроцессор, а так как JS однопоточный, то основной цикл никогда не заэмитит событие от таймера. Т.е. правильный ответ — никогда.
Если человек не готов адекватно и честно оценивать свои знания, не способен читать чужой код, то о какой работе в команде может идти речь. Если же человек не проявил себя в качестве “сантехника” и справился с задачками, подтвердив свои знания стека, либо конструктивно отнесся к задаче, своим ошибкам и частичной некомпетентности, то есть шанс, что он станет вашим новым сотрудником, и в перспективе сможет расти в сторону более высоких уровней классификации.

Бывают случаи, когда человек не согласен с внутренней классификацией фирмы, и негативно реагирует, на заявление, что он не тянет на мидла или даже на джуна, и что его решение не будет работать. В таком случае, если он продолжает настаивать, можно пойти на принцип, и запустить его решение в среде, естественно эта конструкция оказывается нерабочей, то есть человек зафакапился. Тогда он может начать давить авторитетом своей предыдущей работы. Например, были случаи, когда человек после такого провала заявлял, что он был очень ценным сотрудником какого-нибудь крупного банка и его там очень ценили. А на деле оказывается, что в этом банке работало еще двенадцать тысяч таких как он, и HR отдел просто проглядел его некомпетентность, и проторчав там около годика, теперь он заявляет о своем статусе специалиста. А здесь, где работает команда порядка двадцати программистов, каждый из которых отлично владеет своим делом, он просто потеряется не в силах работать по прежней клерковой схеме.
Наш CEO Илья Быконя по этому поводу говорит так:

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

Подытожим

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


ссылка на оригинал статьи https://habr.com/post/421949/