-Поиск по дневнику

Поиск сообщений в rss_rss_hh_new

 -Подписка по e-mail

 

 -Статистика

Статистика LiveInternet.ru: показано количество хитов и посетителей
Создан: 17.03.2011
Записей:
Комментариев:
Написано: 51

Habrahabr/New








Добавить любой RSS - источник (включая журнал LiveJournal) в свою ленту друзей вы можете на странице синдикации.

Исходная информация - http://habrahabr.ru/rss/new/.
Данный дневник сформирован из открытого RSS-источника по адресу http://feeds.feedburner.com/xtmb/hh-new-full, и дополняется в соответствии с дополнением данного источника. Он может не соответствовать содержимому оригинальной страницы. Трансляция создана автоматически по запросу читателей этой RSS ленты.
По всем вопросам о работе данного сервиса обращаться со страницы контактной информации.

[Обновить трансляцию]

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

Четверг, 20 Июля 2017 г. 19:18 + в цитатник
На просторах сети можно найти огромное количество самой разной информации о дизайне мобильных приложений: об основных принципах, трендах, свежих идеях, примерах для подражания и т.д. Так вот эта публикация не об этом.
Я нередко слышу, что дизайн для мобильного приложения по сути не так уж и важен. Важна функциональность, качество кода и общая архитектура в проекте и другие технические нюансы, а дизайн не так уж важен в конце концов это просто внешний вид приложения и я с этим не согласен. На мой взгляд дизайн не менее важен.
В этой публикации я хочу поделиться с вами своим мнением на этот счет и тем как на мой взгляд должно быть построено взаимодействие между командами разработки и дизайна.

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


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

Функциональность


Итак, почему же мы используем программные продукты в целом и мобильные приложения в частности? Ответ прост — потому что нам нужны какие-либо функции того или иного приложения.
Какзалось бы ну как дизайн может определять функциональность? Да никак! Все функции приложения должны быть описаны в требованиях, ТЗ или спецификации.
Но давайте не будем спешить и посмотрим на это с другой стороны. Предположим в приложении есть некий прекрасный функционал (для примера пусть это будет отправка отзыва о полученной услуге в каком-то приложении-агрегаторе), но вы не можете найти тот раздел приложения где это можно сделать. Но ведь те возможности приложения, которые пользователь в приложении так и не нашел — это, по сути, возможности, которых нет в этом приложении для этого пользователя. А что если таких пользователей не один а 5 человек или 10%?
Рассмотрим еще один момент. Существует два приложения со схожим функционалом (пусть это будет какая-нибудь карта или навигатор) и в одном приложении кнопки масштабирования и возврата к местоположению пользователя расположены так, что вы без труда их используятолько большой палец руки, которой смартфон и держите, а у второго приложения эти кнопки расположены менее удобно. Какое приложение выберет пользователь? Вам ведь важно, чтобы люди пользовались именно вашим приложением?

Архитектура


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

И многое другое...


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

По этим причинам я считаю что дизайн — это половина приложения.

Как с этим быть?


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

Что должно быть первым шагом в создании дизайна?


Что должен сделать дизайнер когда он начинает работу над новым проектом?
На мой взгляд это не вайрфреймы. В первую очередь дизайнер должен быть пользователем той платформы/устройства под которую ему поручили нарисовать макет. К примеру если это приложение для iPhone, то желательно, чтобы дизайнер использовал это устройство в повседневной жизни.

Отлично, дизайнер пользователь этой платформы. Что дальше?


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

Теперь приступаем к созданию вайрфреймов


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

У нас есть одобренные вайрфреймы


Отлично, мы можем приступить к самому дизайну. Здесь дизайнер уже точно должен постоянно взаимодействовать и консультироваться с разработчиками. Взаимопомощь никогда не будет лишней в команде, верно? Разработчики по своему опыту могут предсказать потенциальные недочеты в дизайне или слишком нетривиальные места и сложности в разработке. Кроме того разработчики знают о каких-то интересных инструментах (конечно, имеются в виду инструменты для создания UI), которые помогают делать классные приложения и должны делиться этими знаниями с дизайнерами.
Разработчики и дизайнеры вместе должны думать о каждом разделе приложения. Допустим дизайнер подготовил наброски для какого-то списка. Как он будет выглядеть если для отображения нет данных? Или наборот слишком много данных? Как это будет выглядеть на экране больше/меньше?

Дизайн готов


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

Дизайн утвержден


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

Вместо заключения


Вот такие мысли о важности дизайна в мобильной разработке сформировались у меня по мере появления опыта в создании разнообразных приложений. Я ни в коем случае не стану утверждать что именно такой подход к дизайну и разработке может являться правильным. Тем не менее все выводы появились в результате того или иного опыта в разработке так что возможно мои умозаключения кому-то помогут избежать некоторых ошибок.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/333812/


Метки:  

Getsploit: поиск и загрузка эксплойтов по агрегированной базе данных

Четверг, 20 Июля 2017 г. 18:43 + в цитатник

Когда я думал над дальнейшим вектором развития Vulners, я обратил внимание на наших старших братьев — базу данных Exploit-DB. Одной из основных утилит в их арсенале является searchsploit. Это консольная утилита, которая позволяет искать эксплойты по пользовательским поисковым запросам и сразу же получать их исходные коды. Она является базовой частью Kali Linux и оперирует данными по эксплойтам из базы Exploit-DB. Что самое "вкусное", что утилита умеет работать с локальной базой и ты можешь всегда взять ее с собой. Так чем же мы хуже? Мы собрали в Vulners не только коллекцию эксплойтов из Exploit-DB, но и Packet Storm, 0day.today, Seebug, Zero Science Lab и многих других. Что же, давайте изобретем новый велосипед с преферансом и поэтессами.


Смотрим внимательнее на searchsploit


И видим внутри bash скрипт длиною 711 строчек. Он скачивает с публичного репозитария exploit-database копию данных и ищет уже по ней. Но где же Google-style синтаксис и прочие прелести современного поиска? Увы, в их подходе нашлись и плюсы и минусы. Плюсы оказались в том, что они способны находить эксплойты по критериям применимости. Минусы — довольно бедный функционал для неточного поиска. На этом идея интегрироваться с ним была отброшена и решение писать свой форк стала доминирующей.


Что должен делать getsploit?


Начнем с того, что определимся с функциональностью.


  • Поиск эксплойтов по всей коллекции Vulners с применением Full Text Search и Lucene
  • Сохранение исходных кодов эксплойтов на диск
  • Offline-поиск с локальной базой данных
  • Кроссплатформенность и минимум зависимостей
  • Быть Open source

Let there be code


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


isox$ git clone https://github.com/vulnersCom/getsploit
isox$ cd getsploit
isox$ ./getsploit.py -h
usage: Exploit search and download utility [-h] [-t] [-j] [-m] [-c COUNT] [-l]
                                           [-u]
                                           [query [query ...]]

positional arguments:
  query                 Exploit search query. See https://vulners.com/help for
                        the detailed manual.

optional arguments:
  -h, --help            show this help message and exit
  -t, --title           Search JUST the exploit title (Default is description
                        and source code).
  -j, --json            Show result in JSON format.
  -m, --mirror          Mirror (aka copies) search result exploit files to the
                        subdirectory with your search query name.
  -c COUNT, --count COUNT
                        Search limit. Default 10.
  -l, --local           Perform search in the local database instead of
                        searching online.
  -u, --update          Update getsploit.db database. Will be downloaded in
                        the script path.

Основная механика поиска строится на базе Vulners API. Таким образом вы всегда получите актуальные данные на момент "здесь и сейчас". Что же, поищем эксплойты под Wordpress?



Довольно неплохо, да? Попробуем теперь ограничить нас только коллекцией Packet Storm. Синтаксис выражений полностью совпадает с поисковой строкой сайта и его можно подглядеть на страничке help.



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



Но что же делать, если у нас нет онлайн подключения к интернету? Вспомнить об этом пока он еще доступен и сделать "--update"!


isox$ ./getsploit.py --update
Downloading getsploit database archive. Please wait, it may take time. Usually around 5-10 minutes.
219686398/219686398 [100.00%]
Unpacking database.
Database download complete. Now you may search exploits using --local key './getsploit.py -l wordpress 4.7'

При таком запросе getsploit скачает SQLite базу данных со всей коллекцией эксплойтов. Это порядка 594 мегабайт данных на момент написания статьи.


Обратите внимание, что если у вас Python скомпилирован без поддержки sqlite3 (что в принципе редкость), то локальная база, увы, работать не будет.


Здесь пришлось пожертвовать совместимостью ради скорости работы и возможности полнотекстового поиска с FTS4 модулем SQLite.


Но все не так плохо, основная масса сборок Python по умолчанию идет с модулем sqlite3. Попробуем найти эксплойты локально?



Отлично! Теперь можно взять с собой всю коллекцию эксплойтов с Vulners и использовать ее в оффлайне без регистрации и смс.


Ну и конечно же, исходные коды лежат на нашем GitHub.
Pull-request'ы крайне приветствуются.

Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/333808/


Метки:  

Superjob PHP-meetup. Прямая трансляция

Четверг, 20 Июля 2017 г. 18:37 + в цитатник
Сегодня в 18:30 по московскому времени в офисе Superjob состоится встреча PHP-разработчиков. Присоединяйтесь к прямой трансляции!






Спикеры и темы:

Алексей Коротин, старший разработчик Superjob, с докладом «Внедрение RESTful в mature проект»

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

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

Антон Довгаль, Senior C Developer Badoo, с докладом «Как мы разрабатываем модули в Badoo»

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

— Что такое модули PHP, как они работают
— Как начать писать свой модуль PHP
— Скелет модуля — Функции, классы, методы
— Разбор параметров функции
— Сборка модуля
— Подгрузка модуля
— Простой пример модуля из Badoo
— Сложный пример модуля из Badoo

Надежда Рябцова, Senior DevOps Engineer Skyeng, с докладом «Как медиа сервисы Skyeng переехали на Symfony 4»

Я расскажу, как мы приняли решение и внедрили в продакшн новый инструмент для сборки бекенда приложений – Symfony Flex – менее чем за один месяц. О преимуществах и недостатках подхода для сборки бандлов с помощью рецептов. Сейчас нам удалось укротить зоопарк подключаемых бандлов, и оформить схему переезда на Symfony 4 для последователей внутри компании и за ее пределами.

В своем проекте мы реализовали легковесное api для браузерных расширений и сопровождаем его стопроцентным покрытием автотестами. И я расскажу, как вписать Symfony Flex в процессы непрерывной интеграции, схожие с нашими. А также, как развивать и эксплуатировать проект на альфа версии фреймворка в продакшне.

Василий Грудистов, руководитель департамента производства QSOFT, с докладом «Как построить SOA в связке laravel и 1C-Битрикс. Опыт большого проекта»

В ходе доклада я расскажу, как мы достигли увеличения производительности международного портала с 1млн. пользователей в сутки, до 50 млн., при этом сильно расширив функционал.
— Как спроектировать сервисно-ориентированную архитектуру (SOA);
— Как создать отказоустойчивую/катастрофоустойчивую платформу;
— Как реализовать совмещение предыдущей разработки на 1С-Битрикс и не потерять взаимосвязь пользователей в SOA;
— Как организовать совместную работу 1С-Битрикс и сервисов на PHP Framework laravel в рамках одного портала, исключив необходимость внесения дублирующего кода;
— Как закэшировать ВСЁ, при этом не потерять динамические функции портала.

Александр Макаров, активный участник OpenSource проектов, один из разработчиков PHP-фреймворка Yii и его представитель в PHP-FIG, с докладом «Yii. Что дальше?»

— Что происходит с PHP: стоит ли с ним работать или пора переходить на другие языки?
— Ошибки 2.0. Что мы сделали не так и почему. Для понимания этого нужно знать историю Yii, так что немного нырнём и в неё.
— Планы на 2.1. Как мы будем исправлять ошибки и что будет нового в следующей версии.
— Планы на 3.0. Если он будет. О том, что мы никому не показываем, но потихоньку пилим.

Официальная группа Superjob IT-meetup в Facebook.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/333804/


Интеграция Oculus Rift в десктопное Direct3D приложение на примере Renga

Четверг, 20 Июля 2017 г. 18:17 + в цитатник
Всем привет! В этой статье хочу разобрать процесс подключения шлема виртуальной реальности к десктопному приложению под Windows. Речь пойдет об Oculus Rift.

Архитектурная визуализация — очень благодатная тема для различного рода экспериментов. Мы решили не отставать от тренда. В одной из следующих версий наших BIM-систем (напомню, что я работаю в компании Renga Software, совместном предприятии АСКОН и фирмы «1С»): Renga Architecture — для архитектурно-строительного проектирования и Renga Structure — для проектирования конструктивной части зданий и сооружений, появится возможность хождения по проектируемому зданию в шлеме виртуальной реальности. Это очень удобно для демонстрации проекта заказчику и оценки тех или иных проектных решений с точки зрения эргономики.

image


На сайте разработчика шлема доступно для скачивания SDK. На момент написания статьи последняя доступная версия 1.16. Существует еще OpenVR от Valve. Сам я эту штуку не пробовал, но есть подозрения, что она работает хуже, чем нативный для Oculus SDK.

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

#define OVR_D3D_VERSION 11 // in case direct3d 11
#include "OVR_CAPI_D3D.h" 

bool InitOculus()
{
  ovrSession session = 0;
  ovrGraphicsLuid luid = 0;

  // Initializes LibOVR, and the Rift
  ovrInitParams initParams = { ovrInit_RequestVersion, OVR_MINOR_VERSION, NULL, 0, 0 };
  
  if (!OVR_SUCCESS(ovr_Initialize(&initParams)))
    return false;

  if (!OVR_SUCCESS(ovr_Create(&session, &luid)))
    return false;

  // FloorLevel will give tracking poses where the floor height is 0
  if(!OVR_SUCCESS(ovr_SetTrackingOriginType(session, ovrTrackingOrigin_EyeLevel)))
    return false;
  
  return true;
}


Инициализация завершена. Теперь у нас есть session — это указатель на внутреннюю структуру ovrHmdStruct. Его мы будем использовать для всех запросов к oculus runtime. luid — это идентификатор графического адаптера, к которому подсоединился шлем. Он необходим для конфигураций с несколькими видеокартами или ноутбуков. Приложение должно использовать для отрисовки этот же адаптер.

Процесс создания кадра в обычном режиме и для шлема Oculus Rift отличается не очень сильно.
Для каждого глаза нам нужно создать текстуру вместе с SwapChain и RenderTarget.
Для создания текстур Oculus SDK предоставляет набор функций.

Пример обертки для создания и хранения SwapChain и RenderTarget для каждого глаза:


struct EyeTexture
{
    ovrSession               Session;
    ovrTextureSwapChain      TextureChain;
    std::vector TexRtv;

    EyeTexture() :
        Session(nullptr),
        TextureChain(nullptr)
    {
    }

    bool Create(ovrSession session, int sizeW, int sizeH)
    {
        Session = session;

        ovrTextureSwapChainDesc desc = {};
        desc.Type = ovrTexture_2D;
        desc.ArraySize = 1;
        desc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB;
        desc.Width = sizeW;
        desc.Height = sizeH;
        desc.MipLevels = 1;
        desc.SampleCount = 1;
        desc.MiscFlags = ovrTextureMisc_DX_Typeless;
        desc.BindFlags = ovrTextureBind_DX_RenderTarget;
        desc.StaticImage = ovrFalse;

        ovrResult result = ovr_CreateTextureSwapChainDX(Session, pDevice, &desc, &TextureChain);
        if (!OVR_SUCCESS(result))
            return false;

        int textureCount = 0;
        ovr_GetTextureSwapChainLength(Session, TextureChain, &textureCount);
        for (int i = 0; i < textureCount; ++i)
        {
            ID3D11Texture2D* tex = nullptr;
            ovr_GetTextureSwapChainBufferDX(Session, TextureChain, i, IID_PPV_ARGS(&tex));
            D3D11_RENDER_TARGET_VIEW_DESC rtvd = {};
            rtvd.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
            rtvd.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
            ID3D11RenderTargetView* rtv;
            DIRECTX.Device->CreateRenderTargetView(tex, &rtvd, &rtv);
            TexRtv.push_back(rtv);
            tex->Release();
        }

        return true;
    }

    ~EyeTexture()
    {
        for (int i = 0; i < (int)TexRtv.size(); ++i)
        {
            Release(TexRtv[i]);
        }
        if (TextureChain)
        {
            ovr_DestroyTextureSwapChain(Session, TextureChain);
        }
    }

    ID3D11RenderTargetView* GetRTV()
    {
        int index = 0;
        ovr_GetTextureSwapChainCurrentIndex(Session, TextureChain, &index);
        return TexRtv[index];
    }
    
    void Commit()
    {
        ovr_CommitTextureSwapChain(Session, TextureChain);
    }
};


С помощью этой обертки создаем для каждого глаза текстуру, куда мы будем отрисовывать 3D-сцену. Размер текстуры необходимо узнать у Oculus Runtime. Для этого нужно получить description устройства и с помощью функции ovr_GetFovTextureSize получить необходимый размер текстур для каждого глаза:

ovrHmdDesc hmdDesc = ovr_GetHmdDesc(session);
ovrSizei idealSize = ovr_GetFovTextureSize(session, (ovrEyeType)eye, hmdDesc.DefaultEyeFov[eye], 1.0f);

Еще удобно создать так называемую Mirror Texture. Эту текстуру можно показывать в окне приложения. В эту текстуру Oculus Runtime будет копировать объединенное для двух глаз изображение после постобработки.

image

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

Код создания mirror texture:

   // Create a mirror to see on the monitor.
    ovrMirrorTexture mirrorTexture = nullptr;
    mirrorDesc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB;
    mirrorDesc.Width = width; 
    mirrorDesc.Height =height;
    ovr_CreateMirrorTextureDX(session, pDXDevice, &mirrorDesc, &mirrorTexture);   

Важный момент при создании текстур. При создании SwapChain с помощью функции ovr_CreateTextureSwapChainDX мы передаем желаемый формат текстуры. Этот формат используется в дальнейшем для постобработки рантаймом Oculus.

Чтобы все правильно работало, приложение должно создавать swap chain в sRGB цветовом пространстве. Например, OVR_FORMAT_R8G8B8A8_UNORM_SRGB. Если вы в своем приложении не делаете гамма-коррекцию, то необходимо создавать swap chain в формате sRGB. Задать флаг ovrTextureMisc_DX_Typeless в ovrTextureSwapChainDesc. Создать Render Target в формате DXGI_FORMAT_R8G8B8A8_UNORM. Если этого не сделать, то изображение на экране будет слишком светлым.

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

ovrHmdDesc hmdDesc = ovr_GetHmdDesc(session);

ovrEyeRenderDesc eyeRenderDesc[2];
eyeRenderDesc[0] = ovr_GetRenderDesc(session, ovrEye_Left, hmdDesc.DefaultEyeFov[0]);
eyeRenderDesc[1] = ovr_GetRenderDesc(session, ovrEye_Right, hmdDesc.DefaultEyeFov[1]);

// Get both eye poses simultaneously, with IPD offset already included. 
ovrPosef         EyeRenderPose[2];
ovrVector3f      HmdToEyeOffset[2] = { eyeRenderDesc[0].HmdToEyeOffset,
                                                   eyeRenderDesc[1].HmdToEyeOffset };

double sensorSampleTime;    // sensorSampleTime is fed into the layer later
ovr_GetEyePoses(session, frameIndex, ovrTrue, HmdToEyeOffset, EyeRenderPose, &sensorSampleTime);

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

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

Делается это так:

OculusTexture  * pEyeTexture[2] = { nullptr, nullptr };

// ...
// Draw into eye textures
// ...

// Initialize our single full screen Fov layer.
ovrLayerEyeFov ld = {};
ld.Header.Type = ovrLayerType_EyeFov;
ld.Header.Flags = 0;

for (int eye = 0; eye < 2; ++eye)
{
    ld.ColorTexture[eye] = pEyeTexture[eye]->TextureChain;
    ld.Viewport[eye] = eyeRenderViewport[eye];
    ld.Fov[eye] = hmdDesc.DefaultEyeFov[eye];
    ld.RenderPose[eye] = EyeRenderPose[eye];
    ld.SensorSampleTime = sensorSampleTime;
}

ovrLayerHeader* layers = &ld.Header;
ovr_SubmitFrame(session, frameIndex, nullptr, &layers, 1);

После этого в шлеме появится готовое изображение. Для того чтобы показать в приложении то, что видит человек в шлеме, можно скопировать в back buffer окна приложения содержимое mirror texture, которую мы создали ранее:

ID3D11Texture2D* tex = nullptr;
ovr_GetMirrorTextureBufferDX(session, mirrorTexture, IID_PPV_ARGS(&tex));
pDXContext->CopyResource(backBufferTexture, tex);

На этом все. Много хороших примеров можно найти в Oculus SDK.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/332806/


[Из песочницы] Wi-Fi адаптер через OTG

Четверг, 20 Июля 2017 г. 18:14 + в цитатник


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

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

Итак, как подключить внешний Wi-Fi адаптер к устройству на Android или бег с препятствиями на дистанции «вставил — netcfg wlan0 up»:

Должно быть в наличии:

  1. Телефон на Android
  2. Поддержка OTG и сам OTG
  3. Terminal Emulator
  4. ROOT
  5. Исходники ядра

    FAQ — структура выглядит так:

    Скриншот


  6. Внешний Wi-Fi адаптер («свисток»)
  7. Его firmware
  8. Linux дистрибутив
  9. ADB (не обязательно, но так удобнее)

Мой случай:

  1. Samsung GT-P5100 Galaxy Tab 2 10.1, Андроид 4.2.2
  2. OTG «30-pin — USB»
  3. Terminal Emulator for Android
  4. ROOT
  5. Исходники стокового ядра 3.0.31-1919150 с сайта Самсунг
  6. Адаптер TP-LINK TL-WN722N на чипсете AR9271
  7. ath9k_htc/htc_9271.fw
  8. Дистрибутив Ubuntu 15.04 в VMware
  9. android-tools-adb

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

I. Старт


Первым делом необходимо добыть фирмварь вашего адаптера. Вставляю адаптер в компьютер и выполняю команду dmesg. Нахожу:

...
[  256.815266] usbcore: registered new interface driver ath9k_htc
...

Где слово правее слова driver — искомая информация. У меня это — ath9k_htc. Гуглю для него firmware. Качаю. Закидываю .fw-файл на телефон в /system/etc/firmware

Затем устанавливаю ADB:

apt-get install android-tools-adb

Третьим этапом качаю тулчейн (компилятор под ARM) отсюда. Там большой архив, мне нужна лишь папка android-platform_prebuilt-android-sdk-adt_r20-0-ga4062cc.zip\android-platform_prebuilt-a4062cc\linux-x86\toolchain\arm-eabi-4.4.3, которую я распаковываю в произвольное место.

II. Разгон


Для начала пишу терминале:

export ARCH=arm
export CROSS_COMPILE=~/тот самый произвольный путь/arm-eabi-4.4.3/bin/arm-eabi-

Затем перехожу в терминале в каталог с исходниками ядра, загруженными ранее, пишу

make help и получаю тучу информации, среди которой нужно найти нечто, заканчивающееся на _defconfig, у меня это:

...
android_espresso10_omap4430_r02_user_defconfig - Build for android_espresso10_omap4430_r02_user
...

Скопировал, затем:

make android_espresso10_omap4430_r02_user_defconfig

И в завершении запускаю графическую конфигурацию ядра:

make menuconfig

Появляется вот такое окно:

Скриншот


Продвигаюсь по маршрутам:

  1. Networking support -> Wireless
    Спускаюсь к Generic IEEE 802.11 Networking stack (mac80211) и нажимаю на пробел, наблюдая появление значка М перед этим пунктом

  2. Device Drivers -> Network device support -> Wireless LAN
    Ставлю М у своего чипсета, в моем случае — Atheros Wireless Cards
    Затем перехожу в сам этот раздел и внутри отмечаю все тем же пробелом и знаком M нужный мне пункт.

    Скриншот

  3. Exit -> Do you wish to save your new configuration? -> Yes

Далее захожу в папку с исходниками ядра и открываю файл Makefile. Нахожу строку CFLAGS_MODULE = и дописываю туда -fno-pic так, чтобы получилось:
CFLAGS_MODULE = -fno-pic
Сохраняю. Возвращаюсь в терминал, а если вы его закрыли, то в и каталог с исходниками тоже, и выполняю сначала make modules_prepare, а следом просто make. Результат потребует ожидания. Мой итоговый набор:

MODPOST 8 modules
  CC      drivers/net/wireless/ath/ath.mod.o
  LD [M]  drivers/net/wireless/ath/ath.ko
  CC      drivers/net/wireless/ath/ath9k/ath9k_common.mod.o
  LD [M]  drivers/net/wireless/ath/ath9k/ath9k_common.ko
  CC      drivers/net/wireless/ath/ath9k/ath9k_htc.mod.o
  LD [M]  drivers/net/wireless/ath/ath9k/ath9k_htc.ko
  CC      drivers/net/wireless/ath/ath9k/ath9k_hw.mod.o
  LD [M]  drivers/net/wireless/ath/ath9k/ath9k_hw.ko
  CC      drivers/net/wireless/bcmdhd/dhd.mod.o
  LD [M]  drivers/net/wireless/bcmdhd/dhd.ko
  CC      drivers/scsi/scsi_wait_scan.mod.o
  LD [M]  drivers/scsi/scsi_wait_scan.ko
  CC      net/mac80211/mac80211.mod.o
  LD [M]  net/mac80211/mac80211.ko
  CC      net/wireless/cfg80211.mod.o
  LD [M]  net/wireless/cfg80211.ko

Потребуются модули (.ko-файлы), включающие слово ath и mac80211.ko. Переношу их на телефон.

Можно использовать adb, работая через компьютер, а можно не использовать и работать через терминал телефона, печатая команды пальцами по экрану. Я выбрал adb.

Напомню, как он работает. Подключаю телефон через USB (отладка, естественно, включена) и выполняю:

adb start-server
adb shell
su


Я в телефоне и под рутом.

Смотрю, какие модули уже есть командой lsmod и выгружаю их все, если это возможно, командой rmmod имямодуля

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

cd /sdcard/ваш путь/

Можно убедиться в их наличии командой ls.

a@ubuntu:~/Kernel$ adb start-server
* daemon not running. starting it now on port 5037 *
* daemon started successfully *
a@ubuntu:~/Kernel$ adb shell
shell@android:/ $ su
root@android:/ # cd /sdcard/temp
root@android:/sdcard/temp # ls
ath.ko
ath9k_common.ko
ath9k_htc.ko
ath9k_hw.ko
mac80211.ko

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

ath.ko
ath9k_hw.ko
ath9k_common.ko
mac80211.ko
ath9k_htc.ko

III. Препятствия


В этом и вся соль, без которой статья была бы слишком простой.

1. Версии


Естественно, первая ошибка возникает на первом этапе.

insmod ath.ko

insmod: init_module 'ath.ko' failed (Exec format error)

Смотрю, что скажет об этом буфер сообщений ядра, выполнив команду dmesg:

... ath: version magic '3.0.31 SMP preempt mod_unload modversions ARMv7 p2v8' should be '3.0.31-1919150 SMP preempt mod_unload modversions ARMv7 p2v8'

Не совпадают версии. 3.0.31 не есть 3.0.31-1919150.

Решение:

Открываю тот самый Makefile в исходниках ядра и в самом верху файла нахожу:
VERSION = 3
PATCHLEVEL = 0
SUBLEVEL = 31
EXTRAVERSION =
NAME = Sneaky Weasel
Дописываю к EXTRAVERSION = недостающий кусок версии -1919150 так, чтобы получилось:
VERSION = 3
PATCHLEVEL = 0
SUBLEVEL = 31
EXTRAVERSION = -1919150
NAME = Sneaky Weasel
И сохраняю.
Заключительный этап пройдет в каталоге /include/config, где в файле kernel.release я поменяю 3.0.31 на 3.0.31-1919150
Снова make modules_prepare, make и далее по предыдущему пункту.

2. ewma


Загружая mac80211.ko снова имею ошибку, о которой dmesg скажет следующее:

<4>[ 3491.160949] C1 [         insmod] mac80211: Unknown symbol ewma_add (err 0)
<4>[ 3491.161865] C1 [         insmod] mac80211: Unknown symbol ewma_init (err 0)

Решение:

Чудом прочитав на одном из англоязычных форумов опасное, но единственное в интернете, «решение», я перехожу в /net/mac80211/ и в файлах rx.c и sta_info.c и просто удаляю [либо комментирую (//)] строки ewma_add(&sta->avg_signal, -status->signal); и ewma_init(&sta->avg_signal, 1024, 8); соответственно.

Скриншоты




Опять перекомпилирую модули и двигаюсь дальше.

3. Светодиод


При загрузке ath9k_htc.ko и mac80211.ko очередные ошибки, у mac80211.ko это:

dmesg
<4>[ 2435.271636] C1 [         insmod] mac80211: Unknown symbol led_trigger_unregister (err 0)
<4>[ 2435.271820] C1 [         insmod] mac80211: Unknown symbol led_brightness_set (err 0)
<4>[ 2435.271972] C1 [         insmod] mac80211: Unknown symbol led_blink_set (err 0)
<4>[ 2435.272033] C1 [         insmod] mac80211: Unknown symbol led_trigger_register (err 0)
<4>[ 2435.272155] C1 [         insmod] mac80211: Unknown symbol led_trigger_event (err 0)


А у ath9k_htc.ko это:

dmesg
<4>[ 2709.396392] C1 [         insmod] ath9k_htc: Unknown symbol ieee80211_start_tx_ba_cb_irqsafe (err 0)
<4>[ 2709.396972] C1 [         insmod] ath9k_htc: Unknown symbol ieee80211_free_hw (err 0)
<4>[ 2709.397155] C1 [         insmod] ath9k_htc: Unknown symbol ieee80211_alloc_hw (err 0)
<4>[ 2709.397216] C1 [         insmod] ath9k_htc: Unknown symbol ieee80211_start_tx_ba_session (err 0)
<4>[ 2709.397369] C1 [         insmod] ath9k_htc: Unknown symbol ieee80211_register_hw (err 0)
<4>[ 2709.397430] C1 [         insmod] ath9k_htc: Unknown symbol led_classdev_unregister (err 0)
<4>[ 2709.397491] C1 [         insmod] ath9k_htc: Unknown symbol __ieee80211_create_tpt_led_trigger (err 0)
<4>[ 2709.397766] C1 [         insmod] ath9k_htc: Unknown symbol ieee80211_get_buffered_bc (err 0)
<4>[ 2709.397827] C1 [         insmod] ath9k_htc: Unknown symbol ieee80211_find_sta (err 0)
<4>[ 2709.398284] C1 [         insmod] ath9k_htc: Unknown symbol ieee80211_stop_tx_ba_cb_irqsafe (err 0)
<4>[ 2709.398376] C1 [         insmod] ath9k_htc: Unknown symbol wiphy_to_ieee80211_hw (err 0)
<4>[ 2709.398498] C1 [         insmod] ath9k_htc: Unknown symbol ieee80211_queue_delayed_work (err 0)
<4>[ 2709.398712] C1 [         insmod] ath9k_htc: Unknown symbol ieee80211_rx (err 0)
<4>[ 2709.398895] C1 [         insmod] ath9k_htc: Unknown symbol ieee80211_wake_queues (err 0)
<4>[ 2709.399230] C1 [         insmod] ath9k_htc: Unknown symbol ieee80211_tx_status (err 0)
<4>[ 2709.399291] C1 [         insmod] ath9k_htc: Unknown symbol ieee80211_stop_queues (err 0)
<4>[ 2709.399505] C1 [         insmod] ath9k_htc: Unknown symbol ieee80211_iterate_active_interfaces_atomic (err 0)
<4>[ 2709.399597] C1 [         insmod] ath9k_htc: Unknown symbol ieee80211_unregister_hw (err 0)
<4>[ 2709.399749] C1 [         insmod] ath9k_htc: Unknown symbol ieee80211_beacon_get_tim (err 0)
<4>[ 2709.399871] C1 [         insmod] ath9k_htc: Unknown symbol led_classdev_register (err 0)
<4>[ 2709.399932] C1 [         insmod] ath9k_htc: Unknown symbol ieee80211_queue_work (err 0)


Если ieee80211_-ошибки от ath9k_htc.ko это потому что я пытаюсь его загрузить до mac80211.ko, то led_-ошибки от обоих модулей от того, что телефон не понимает, что делать со светодиодом на моем адаптере. Тут два варианта развития событий.

В первом просто убирается в графической конфигурации ядра значок [] напротив
Networking support -> Wireless -> Enable LED triggers и Device Drivers -> LED Support.

А во втором этот самый значок заморожен и снять его нельзя. Это значит, что при выборе моего адаптера, автоматически выбирается «поддержка» светодиода, убрать которую нельзя. Конечно же, это мой случай:

Скриншоты



Решение:

Кнопка помощи по Device Drivers -> LED Support выводит следующую информацию по разделу:

Скриншот


Меня интересует:
Defined at drivers/leds/Kconfig
А значит все настройки хранятся в данном файле. Долго я мучал Kconfig в /drivers/leds/ пока не додумался посмотреть такой же файл в своем /drivers/net/wireless/ath/ath9k, где нашел ответ на свой вопрос:

config ATH9K_HTC
tristate «Atheros HTC based wireless cards support»
depends on USB && MAC80211
select ATH9K_HW
select MAC80211_LEDS
select LEDS_CLASS
select NEW_LEDS
select ATH9K_COMMON
...
Сходу удаляю строки, включающие страшное слово LED, получаю

config ATH9K_HTC
tristate «Atheros HTC based wireless cards support»
depends on USB && MAC80211
select ATH9K_HW
select ATH9K_COMMON
...
и сохраняю. Теперь можно снимать галочки:

Скриншоты


Здесь и вовсе исчез пункт:


Опять и снова перекомпиляция, новые модули и т.п.

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

4. Версия firmware


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

[ 7582.477874] C0 [ khubd] ath9k_htc 1-1:1.0: ath9k_htc: Please upgrade to FW version 1.3
...
Скриншот


Решение:

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

IV. Финиш


Теперь никаких проблем быть не должно. Выключаю родной Wi-Fi, все модули загружены, фирмварь нужной версии. Вставляю адаптер и netcfg впервые приносит счастье. Устанавливаю для появившегося сетевого интерфейса режим монитора и поднимаю его. Успех!



Родной Wi-Fi выключен


Ну а как и зачем зачастую используется режим монитора, вы и так все знаете. Спасибо за внимание!

Aircrack через OTG



Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/333806/


Метки:  

Stantinko: масштабная adware-кампания, действующая с 2012 года

Четверг, 20 Июля 2017 г. 17:27 + в цитатник
Рекламное ПО – не самый простой для анализа тип вредоносных программ. Обнаружив комплексную угрозу Stantinko, мы не сразу поняли, что это: рекламное ПО, вредоносная или шпионская программа. Потребовалось время, чтобы выявить ее цели и схемы, поскольку угроза оставляет не так много следов на зараженной машине. Разбираться в экосистеме Stantinko – примерно как собирать пазл.

Stantinko специализируется на рекламном мошенничестве, но выделяется на общем фоне технической сложностью. Шифрование кода и оперативная адаптация для защиты от обнаружения антивирусами позволили операторам Stantinko оставаться вне зоны видимости как минимум на протяжении пяти лет. Кроме того, внимание привлекает масштаб Stantinko – это одна из наиболее распространенных в России киберугроз, в составе ботнета около 500 000 устройств.



Обзор


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




Видео 1. Пользователь загружает и запускает вредоносный файл

Операторы Stantinko управляют ботнетом и монетизируют его, в основном, путем установки вредоносных расширений браузера для несанкционированного внедрения рекламы и кликфрода. Проблема в том, что на этом они не останавливаются. Вредоносные службы позволяют исполнить на зараженной системе все, что угодно. Мы наблюдали отправку полнофункционального бэкдора, бота для массового поиска в Google, а также утилиты для брутфорс-атак на панели управления Joomla и WordPress (предназначена для взлома и возможной перепродажи).

На рисунке ниже представлена полная схема киберкампании Stantinko – от вектора заражения до постоянных сервисов и соответствующих плагинов.


Рисунок 1. Полная схема угрозы Stantinko

Ключевые параметры


Характерная особенность Stantinko – обход обнаружения антивирусом и противодействие реверс-инжинирингу, определяющему вредоносное поведение. Для проведения всестороннего анализа угрозы необходимо несколько компонентов – загрузчик и зашифрованный компонент. Вредоносный код скрыт в зашифрованном компоненте, который находится либо на диске, либо в реестре Windows. Код загружается и расшифровывается безвредным на первый взгляд исполняемым файлом. Ключ генерируется для каждого из заражений. Некоторые компоненты используют идентификатор бота, другие – серийный номер тома жесткого диска ПК жертвы. Детектирование по незашифрованным компонентам – крайне сложная задача, поскольку артефакты, хранящиеся на диске, не показывают вредоносного поведения до выполнения.

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

Основные функциональные возможности Stantinko – установка в зараженной системе вредоносных расширений браузера The Safe Surfing и Teddy Protection. На момент анализа оба расширения были доступны в Chrome Web Store. На первый взгляд, это легитимные браузерные расширения, блокирующие нежелательные URL-адреса. Но при установке в рамках схемы Stantinko расширения получают иную конфигурацию, содержащую правила кликфрода и несанкционированного показа рекламы. В видео 2 показан процесс установки расширения The Safe Surfing. Кликнув по ссылке, пользователь перенаправляется в поисковик Rambler.


Рисунок 2. Teddy Protection в Chrome Web Store


Рисунок 3. The Safe Surfing в Chrome Web Store




Видео 2. Переадресация трафика на сайт Rambler

Stantinko – модульный бэкдор. Его компоненты включают загрузчик, позволяющий выполнять любой исполняемый Windows-файл, передаваемый C&C-сервером напрямую в память. Эта функция реализована в виде гибкой системы плагинов, которая позволяет операторам выполнить в зараженной системе все, что угодно. В таблице ниже приведено описание известных нам плагинов Stantinko.



Монетизация


Разработчики Stantinko используют методы, которые чаще встречаются в APT-кампаниях. Тем не менее, их главная цель – деньги. Операторы предлагают свои услуги на самых доходных рынках компьютерных преступлений.

Во-первых, кликфрод сегодня является крупным источником доходов в экосистеме киберпреступников. Исследование, проведенное компанией White Ops и Национальной ассоциацией рекламодателей (США), оценило мировые издержки от кликфрода в 2017 году в 6,5 млрд долларов США.

Как уже описывалось выше, Stantinko устанавливает два расширения браузера – The Safe Surfing и Teddy Protection, которые показывают рекламу или осуществляют редирект. Это позволяет операторам Stantinko получать деньги за трафик, который они обеспечивают рекламодателям. На рисунке ниже показана схема переадресации.


Рисунок 4. Кликфрод, процесс переадресации

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

Во-вторых, операторы Stantinko пытаются получить доступ к панелям управления сайтов на Joomla и WordPress. Атака построена на брутфорсе с перебором логинов и паролей по списку. Цель – угадать пароль, испробовав десятки тысяч комбинаций. Взломанные аккаунты могут быть перепроданы и далее использоваться для переадресации посетителей сайтов на набор эксплойтов или для размещения вредоносного контента.

В-третьих, наше исследование раскрыло, как Stantinko работает в соцсетях. Мы уже описывали этот тип мошенничества в отчете по Linux/Moose. Схема действительно приносит прибыль – 1000 лайков на Facebook стоят около 15 долларов (даже если их генерируют фейковые аккаунты в составе ботнета).

Операторы Stantinko разработали плагин, взаимодействующий с Facebook. Помимо всего прочего, он может создавать аккаунты, ставить лайк на странице и добавлять друзей. Для обхода капчи в Facebook он использует специальный сервис (на рисунке 5). Масштаб сети Stantinko является преимуществом операторов, поскольку позволяет им распределять запросы между всеми ботами – это усложняет задачу Facebook по распознаванию мошенничества.


Рисунок 5. Сервис по обходу капчи, используемый Stantinko

Заключение


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

Кроме того, операторам Stantinko удалось выложить в Chrome Web Store два расширения для браузера, которые выполняли несанкционированное размещение рекламы. Одно из них впервые появилось в Chrome Web Store в ноябре 2015 года.

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

Основные выводы:

  • Около 500 000 компьютеров скомпрометировано Stantinko
  • Основные цели – Россия (46%) и Украина (33%)
  • Операторы Stantinko монетизируют ботнет, устанавливая расширения браузера для несанкционированного показа рекламы
  • Компоненты, остающиеся на диске, используют кастомный обфускатор кода, который усложняет процесс анализа угрозы
  • В большинстве компонентов Stantinko вредоносный код скрыт внутри легитимного бесплатного ПО с открытым исходным кодом, которое было модифицировано и перекомпилировано
  • Stantinko устанавливает несколько перманентных служб, которые могут восстанавливать друг друга, предотвращая удаление из системы
  • Наиболее распространенное использование Stantinko – рекламное мошенничество. Тем не менее, его возможности значительно шире. Мы наблюдали отправку полнофункционального бэкдора для удаленного администрирования, бота для массового поиска в Google и утилиты для брутфорс-атак на панели управления Joomla и WordPress

Индикаторы заражения доступны в нашем аккаунте на GitHub. По любым вопросам, связанным с Stantinko, включая передачу образцов, пишите на threatintel@eset.com.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/333798/


Метки:  

Компания HPE начала продажи новых серверов HPE ProLiant Gen10

Четверг, 20 Июля 2017 г. 17:22 + в цитатник
11 июля HPE начала принимать заказы на новые серверы ProLiant Gen10, и в этом материале мы хотим рассказать о ключевых технологиях и характеристиках моделей в этом юбилейном поколении.

Хотя выпуск нового поколения серверов и совпал с выпуском процессоров Intel Xeon Scalable Family, это была далеко не единственная причина для обновления. Предпосылками стали новые задачи заказчиков HPE. Среди них: появление новых классов нагрузок (в т.ч. требующих обработки больших объемов данных в памяти и высокой производительности дисковой подсистемы), улучшение управляемости аппаратной инфраструктуры (переход на управление через REST API, интеграция с различными средствами автоматизации ИТ, поддержка шаблонов и сценариев), новые модели потребления ИТ-ресурсов (например, финансовые услуги и оплата по мере использования), а также, не в последнюю очередь, новые угрозы в информационной безопасности, связанные с уязвимостью низкоуровневых компонентов серверов (BIOS и прошивок).

Что же нового появилось в серверах HPE ProLiant Gen10 в ответ на все эти задачи. Разберемся по порядку.

Процессоры


Во главе угла стоит повышение производительности сервера с помощью собственных технологий HPE под общим названием Intelligent System Tuning:
Workload Matching (настройка под задачу) – это набор преднастроек сервера под различные конкретные задачи, которые в каждом случае повышают отдачу за счет тонких изменений конфигурации памяти, процессоров, питания, дисковой подсистемы и т.д. (всего существует около 30 регулируемых настроек, поэтому настроить сервер под конкретную задачу самостоятельно может быть непросто)

Jitter Smoothing (сглаживание дрожания). С включением этой технологии, сервер начинает отслеживать «дрожание» частоты процессора в режиме TurboBoost, и сглаживать перепады частоты для устранения задержек обращения к разным уровням памяти, которые возникают при резком изменении частоты. В результате, в требовательных к частоте и задержкам задачах (например, ОС реального времени и некоторые Java-приложения) мы получаем прирост производительности даже сверх обычного прироста в турбо-режиме. Почитать подробно об этой технологии можно здесь: h20565.www2.hpe.com/hpsc/doc/public/display?docId=a00018313en_us
image
Core Boosting (ускорение ядер). Эта технология станет доступной в серверах Gen10 в ближайших релизах (осень 2017 – весна 2018), для некоторых процессоров Intel Xeon Scalable семейств 6000 и 8000. Она предназначена для повышения частоты активных ядер в процессорах Intel Xeon в режиме TurboBoost сверх «обычной» доступной частоты в этом режиме. В результате таких настроек можно оставаться на том же уровне производительности, например, в БД Oracle, работая при этом на меньшем числе ядер. А это прямая экономия денег на лицензиях.
image
Для включения Jitter Smoothing и Core Boosting на сервере должна быть активирована лицензия iLO Advanced или выше. Core Boosting, кроме того, будет работать не на всех процессорах и конфигурациях сервера. Кратко обо всех трех технологиях – здесь: www.hpe.com/h20195/v2/Getdocument.aspx?docname=a00018328enw

Память



Также были доработаны механизмы обеспечения отказоустойчивости памяти. В современных системах, где объем памяти исчисляется сотнями гигабайт, вероятность появления ошибок в каких-то чипах памяти очень высока. Поэтому применение инструментов для обеспечения надежности памяти (RAS) становится все более обоснованным. С поколением Gen10 HPE представила еще один такой инструмент – технологию SmartMemory Fast Fault Tolerance (FFT). С включением FFT упреждающие алгоритмы анализируют состояние чипов памяти, и в случае появления риска для данных в какой-то области памяти в чипе, назначают ей «запасные» области сравнимого объема на том же канале памяти. В результате запись и чтение данных в защищаемой области идет с контролем целостности, и пропускная способность и общий объем падают только для этой маленькой области.

В чем отличие это технологии, например, от механизма Lockstep с DDDC от Intel, который используется в процессорах Xeon E7 сейчас? В том, что с тонким контролем HPE Advanced Error Detection и Fast Fault Tolerance, мы снижаем производительность только при появлении вероятности потери данных и только для малой области памяти, в отличие от Lockstep, где производительность снижается на всех модулях памяти. В результате с FFT в целом по системе пропускная способность падает в среднем не более, чем на 1%. Эта технология также уникальна для HPE и не появится в серверах других производителей еще 2 года по лицензионному соглашению с Intel. В целом, применение современных технологий RAS в серверах HPE, по статистике HPE, снижает число «падений» системы в год (Annual Crash Rate) на 85%. Еще один ответ на вопрос почему память от HPE называется Smart Memory.

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





Другой набор инноваций по работе с памятью – это две технологии энергонезависимой оперативной памяти HPE NVDIMM и HPE Scalable Persistent Memory. Первая – это существующие уже более двух лет модули оперативной памяти, совмещенные с энергонезависимой флешкой (на том же модуле) с питанием от батарейки в сервере. Такие модули видны обычным ОС (Windows и Linux) как очень быстрое блочное устройство — см. эксперименты вот здесь: habrahabr.ru/company/hpe/blog/282395. А некоторым приложениям (например, Microsoft SQL Server 2016) такой модуль виден как особое устройство с побайтной адресацией (как в RAM), но с устойчивостью к отключению питания. При размещении на таких модулях, хвоста лога транзакций (Tail of transaction log) MS SQL Server'а, мы видим прирост производительности базы данных до 4 раз по сравнению с размещением хвоста лога на SSD. Новые модули HPE NVDIMM теперь имеют емкость 8 и 16 ГБ, в то время как для БД SQL размером в несколько сотен гигабайт в большинстве случаев достаточно 1 модуля NVDIMM для размещения хвоста лога транзакций.

HPE Scalable Persistent Memory – это комплексные устройства, построенные на базе серверов HPE ProLiant DL380 Gen10, обычных модулей памяти DDR4 и особого механизма защиты RAM от потери питания с помощью NVMe-накопителей и резервного блока питания с внутренним ИБП в самом сервере. С этим устройством вы можете разместить в памяти до 1 ТБ данных без риска потерять их при отключении электричества, и таким образом многократно ускорить работу многих приложений. Например, во внутренних тестах с MySQL операции Checkpoint (сохранения данных БД из памяти на энергонезависимый носитель) на HPE Scalable Persistent Memory выполнялись в 27 раз быстрее, чем на HDD и в 3 раза быстрее, чем на SSD. А Restore (обратная операция – возвращение данных в память после сбоя) происходила в 13 и 5 раз быстрее соответственно. И кроме того, с такой системой практически любую БД можно превратить в in-memory, многократно повышая ее производительность.
image
Использование NVMe-накопителей также получило очень глубокое развитие. Теперь в каждый сервер можно установить в разы больше NVMe-накопителей (до 20 штук в DL380 Gen10, например), и в одну и ту же дисковую корзину в сервере можно устанавливать и NVMe, и SAS/SATA диски (продолжают существовать и обычные корзины без поддержки NVMe, если она вам не нужна). Плюс, появилась поддержка нового формата накопителей – uFF (micro-Form Factor), которых помещается 2 на место одного SFF-накопителя (объемы 120 и 340 ГБ, SATA). uFF-SSD могут использоваться как загрузочные или кэширующей диски для целого ряда задач, и экономят место в сервере для более емких накопителей под продуктивные данные.

Обновилась и линейка контроллеров. Теперь они быстрее (до 1,6 млн IOPS с контроллера) и могут работать одновременно в HBA и RAID-режиме (какие-то диски на контроллере в одном режиме, какие-то в другом). Полная линейка контроллеров в Gen10 на данный момент выглядит так:
image

iLO 5



Одна и самых мощных новинок поколения Gen10 – усовершенствованная система удаленного управления HPE iLO 5. Кроме более быстрого чипа iLO, который ускоряет операции с удаленной консолью и виртуальными накопителями, появился целый ряд новых возможностей:
image

Технология HPE Silicon Root of Trust – это проверка прошивки iLO на наличие в ней вредоносного кода или повреждений с помощью сверки контрольной суммы с аппаратным чипом внутри системы iLO. Когда прошивка iLO проверена, это средство управления само проверяет прошивки всех остальных компонентов сервера, включая BIOS на предмет вторжения злоумышленников или другие нарушения целостности. В случае обнаружения проблемы, iLO может автоматически или по команде восстановить конкретную прошивку в последнее рабочее состояние из защищенного репозитория прошивок, вернуть сервер к заводским настройкам или не реагировать.

imageЗачем эта технология? Во-первых, прошивка компонента может повредиться в процессе обновления вручную или просто из-за сбоя в микросхеме. Во-вторых, аналитики угроз ИБ с каждым годом обнаруживают все больше уязвимостей в прошивках и другом низкоуровневом коде серверов. Последний громкий пример – найденная уязвимость в патчах для прошивок серверов SuperMicro, которые закупила себе компания Apple (ссылка: arstechnica.com/information-technology/2017/02/apple-axed-supermicro-servers-from-datacenters-because-of-bad-firmware-update). Этот уровень практически не контролируется привычными антивирусами, поэтому и угроза там скрывается значительная.

Уникальность подхода HPE здесь: а) полный контроль над производством прошивок компонентов; все компоненты под брендом HPE имеют специально разработанную, либо проверенную и поставляему только через канал HPE прошивку и, начиная с поколения Gen10, поставляются с цифровой подписью HPE. И б) только HPE разрабатывает и производит собственную систему управления iLO, от софта до микросхем, благодаря чему может встроить в нее средство проверки подписей прошивок.
Еще одно небольшое, но полезное улучшение безопасности – датчик открытия корпуса сервера, при срабатывании которого iLO может заблокировать работу сервера до выяснения причин инцидента.

Функциональное улучшение в iLO 5 – теперь средство настройки сервера, включая настройки RAID, под названием Intelligent Provisioning можно запускать прямо из консоли iLO, а не только при загрузке сервера по нажатию F10. Благодаря этому можно избежать лишних перезагрузок сервера.

Быстрее стала проходить и сама процедура загрузки при использовании UEFI-режима BIOS – в среднем загрузка в 3 раз быстрее. Изменился и стал более удобным интерфейс настройки BIOS RBSU, и запустить его тоже можно из Intelligent Provisioning (а его – из iLO).
Большой плюс для пользователей различных средств автоматизации, в том числе в многовендорных окружениях – iLO теперь поддерживает большинство инструкций Open IPMI. И к тому же HPE продолжает лидировать в наполнении стандарта управления «железом» через интерфейс REST API (читайте здесь: habrahabr.ru/company/hpe/blog/268885). Теперь REST API от HPE полностью соответствует стандарту DMTF Redfish, кроме части управления RAID-контроллерами (там пока собственные REST API). Для управления через REST API есть как собственное средство, так и масса вспомогательных средств (например, для Python и PowerShell).

Еще одно новшество – на этот раз в части диагностики неисправностей. Если раньше Active Health System Log (запись «бортового самописца» сервера) можно было только выгрузить через iLO и отправить в Центр поддержки HPE для анализа, то сейчас его можно выкачать на флешку через спецальный USB-порт на лицевой стороне сервера и проанализировать самостоятельно с помощью бесплатного сервиса Active Health System Viewer (http://www.hpe.com/servers/ahsv). Сервис показывает и предлагает решение для 25% возможных уязвимостей, а для остальных – просто значительно облегчает обращение в поддержку, сокращая время на анализ неисправности.
image

Новые модели HPE ProLiant Gen10



Вторая часть нашего обзора – о моделях, которые уже доступны к заказу сегодня. Вот так будет выглядеть весь основной портфель серверов HPE (здесь мы не говорим о линейках Apollo, Integrity и некоторых других):
image

Зеленым выделены те модели, которые можно заказать сейчас. Краткий обзор моделей в картинках:

ProLiant DL360 Gen10





ProLiant DL380 Gen10





ProLiant DL560 Gen10




ProLiant BL460c Gen10 – да, мы продолжаем выпуск блейдов в текущем шасси!




MicroServer Gen10



Кроме того, сейчас доступны к заказу новые серверы для платформы Synergy– SY480 Gen10 и SY660 Gen10, а сама платформа Synergy получила поддержку 25/50 GbE фабрики Mellanox, мощные графические опции и расширение вариантов конфигурации внутренних дисковых полок.

Плюс, существенно обновилась линейка продуктов для высокопроизводительных вычислений (НРС). Представлен новый флагман суперкомпьютерного мира – система HPE SGI 8600 с жидкостным (водяным) охлаждением. Отвечая стремительному прогрессу в мире НРС и потребностям заказчиков HPE, полностью переработана 6000-ная серия – представлена новая высокоинтегрированная система HPE Apollo 6000 Gen10 (узлы XL230k Gen10 и шасси k6000). Для решения широкого спектра задач в области искусственного интеллекта и некоторых других нагрузок, было представлено новое семейство узлов HPE Apollo 10-series, поддерживающих самые современные технологии ускорения вычислений Intel Xeon Phi 7000 и NVIDIA Tesla P100 на шине NVLink.

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

А пока, много отличных видео о Gen10 можно посмотреть здесь:

www.youtube.com/user/HewlettPackardVideos/videos
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/333800/


[Из песочницы] Система электронной очереди в банковском бизнесе

Четверг, 20 Июля 2017 г. 16:44 + в цитатник
Взгляд эксперта по IT-разработкам компании «Технологии Будущего» Москалевой Марины на функциональные возможности системы электронной очереди в банковском бизнесе.

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

Начало начал


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

  • терминал регистрации для выбора посетителем требуемой услуги и получения талона с номером;

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

  • табло на рабочем месте сотрудника, на котором обозначаются номер клиента, вызванного непосредственно к этому сотруднику банка;

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

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

12 функциональных возможностей системы, актуальных для банков


Специализация рабочих мест. Суть этой функции заключается в том, что клиент, выбравший необходимую услугу, будет направлен к определенному сотруднику банка, который специализируются именно на этом вопросе. Специализация рабочих мест предполагает возможность использовать принцип приоритетности в распределении клиентского потока. Если рассматривать на деле, то можно привести наипростейший пример. Представим, что основной услугой окна № 1 является оплата коммунальных платежей (высокий приоритет). Соответственно в первую очередь к окну обслуживания №1 будут вызываться клиенты, желающие заплатить за коммунальные услуги. При этом, в случае необходимости, для этого же окна обслуживания можно добавить услугу пополнения счета (присвоив ей низкий приоритет). Тогда при отсутствии клиентов на оплату коммунальных платежей, в окно № 1 будут вызваться клиенты с услугой второго приоритета. Аналогично можно добавлять другие услуги, задавая значение приоритета в числовом выражении.

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

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

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

Приоритет клиентов. Определенным категориям VIP-клиентов в системе может быть задан приоритет обслуживания (например, держателям карт Gold и Platinum). Таких посетителей система будет автоматически ставить в начало очереди на выбранную услугу. Идентификация может производиться путем считывания банковской карты, в этом случае терминал регистрации должен быть оснащен карт-ридером. Помимо этого, идентификация карты может быть осуществлена путем ввода ее номера с помощью виртуальной клавиатуры или с применением биометрических технологий.

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

СМС-оповещение. Если при выборе услуги на терминале прогнозируемое время ожидания обслуживания превысит заданную величину (например, 1 час), клиенту будет предложено ввести номер телефона для дополнительного СМС-информирования формата «Ваш номер … будет вызван через 15 мин. Пожалуйста, подойдите в отделение». Помимо этого, есть возможность считать QR-код с полученного талона и при помощи смартфона отслеживать свою очередь в режиме онлайн. Это позволит клиенту не сидеть долгое время в зоне ожидания.

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

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

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

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

Статистические отчеты в автоматическом режиме по заданному расписанию отправляются на электронную почту ответственного лица.

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

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

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

Из новенького


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

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

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

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

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

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

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

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

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

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

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

То есть как мы можем видеть, потенциал для разработок и внедрения новейших технологий масса. Все зависит от конкретных потребностей людей с которыми мы сотрудничаем. А уж использовать стандартный набор функций системы или же поломать голову и создать что-то новое, это уже вопрос стремления развить свой бизнес и желание сделать его максимально эффективным.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/333794/


Метки:  

VAX — инструмент для визуального программирования, или как написать SQL мышкой

Четверг, 20 Июля 2017 г. 16:39 + в цитатник


Я хочу рассказать про созданный мною web редактор для «визуального программирования» и его историю создания.

Случилось как-то мне столкнуться с одной очень надоедливой задачей на работе в компании PimPay, в которой я занимаю должность технического директора. Есть у нас отдел, занимающийся претензионной деятельностью с Почтой России. Ребята ищут потерянные/не оплаченные/не доставленные отправления. В сухом остатке для разработчиков эта задача сводилась к написанию очень большого количества разнообразных и огромных (>150 строк) SQL запросов на диалекте PostgreSQL, которые ОЧЕНЬ часто менялись и дополнялись в силу активного появления новых гипотез, а также поступления новых сведений о заказах.

Естественно, нам, как программистам, это дело очень быстро надоело, и сразу захотелось предложить отстать от нас какой-то визуальный инструмент конструирования фильтров, которые в итоге транслируются в SQL. Сначала захотели налепить просто много формочек с кучей «инпутов», но идея быстро провалилась, т.к. было понятно, что все фильтры надо уметь как-то «композиционировать» (compose): объединять в группы, пересекать с разными условиями И, ИЛИ, параметризовать и прочее. И даже простейший реально используемый фильтр начинал выглядеть ужасно. Плюс сбоку закрадывалась мысль, что в принципе данные фильтры являются частным вариантом просто общего сборщика SQL, и вообще, раз уж дошло дело до «визуального программирования», то можно постараться полностью абстрагироваться от предметной области.

И тут, как в фильме «Проблеск гениальности» («Flash of Genius»), у меня перед глазами всплыла картина визуального редактора схем (blueprints) из UE4 (Unreal Engine 4), с помощью которых персонажи запускали файрболы в своих врагов:
image

Прибежав в тот же вечер домой, я взял первую попавшуюся JavaScript библиотеку, умеющую рисовать красивые прямоугольники и сложные линии — ей оказалась Rapha"el от нашего соотечественника DmitryBaranovskiy. Нарисовав пару прямоугольников и подёргав их с помощью библиотечных drag-and-drop, я сразу написал автору библиотеки с вопросом поддерживает ли он её. И не дождавшись ответа (до сих пор), я в ту же ночь наплодил более 1000 строк кода на JavaScript, и моя мечта на глазах почти стала явью! Но предстояло ещё много работы.

В итоге, что же захотелось сделать:
  • Красивый и удобный редактор в вебе, который предоставляет средства для манипуляции и связывания «узлов» разных типов, которые описываются в доменной схеме, передающейся редактору при инициализации. Тем самым сделать редактор независимым от предметной области.
  • Возможность сериализации ацикличного графа пользователя в древовидную структуру, которую очень легко разбирать (parse) (например JSON) и интерпретировать на любом языке.
  • Предоставить удобный формат для описания типов и компонентов предметной области.
  • Придумать богатую систему типов и ограничений, которая поможет пользователю создавать графы, корректные с точки зрения предметной области.
  • Дать возможность пользователю создавать свои компоненты из комбинаций существующих.


В итоге вот что получилось: image

Видно, что чертёж (blueprint) состоит из узлов (nodes), которые являются конкретными экземплярами компонентов (component), описанных в схеме предметной области (schema). Узлы соединяют проводами (wires). Провод всегда идёт от выхода (output) одного узла к входу (input) другого (и наоборот). Из одного выхода может идти много проводов, но на вход можно привязать только один.

Все входы и выходы имеют тип, и соответственно накладывают ограничения на возможные связи. Например, возьмём следующую систему типов:
types:
    # Всегда есть тип Any, который супер-родитель всех типов
    Scalar:
    Numeric:
       extends: Scalar
    String:
       extends: Scalar
    List:
       typeParams: [A]

Таким образом можно выход типа Numeric связать с входом типа Scalar, но не наоборот. Для параметризованных типов вроде List подразумевается ковариативность, т.е. List[String] можно передать в List[Scalar], но не наоборот. Плюс всегда присутствует супер тип Any, наследником которого являются все остальные типы.

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

Также узлы бывают параметризованы по типам. Например, дан компонент:
IfThenElse:
  typeParams: [T]
  in:
    C: Boolean  
  out:
    onTrue: @T
    onFalse: @T

При создании узла на базе компонента IfThenElse редактор попросит нас указать тип T и подставит его во все места с T:
image

Типы входов и выходов также помогают пользователю при проектировании. Если вы потянете проводок из выхода с типом Numeric и отпустите мышку, то вылезет окно создания компонентов, отфильтрованных таким образом, что там останутся только те, вход которых совместим (conforms) с типом Numeric. И даже автоматически привяжется проводок.

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

Итак, господа, настало время творить! Возьмём самый нереальный случай, когда вам надо предоставить «не техническому» пользователю возможность визуально программировать процесс складывания чисел. Мы пониманием, что нам нужен всего лишь один тип Numeric и пару компонентов: возможность задать число (Literal) и возможность сложить два таких числа (Plus). Далее приведён пример схемы данной предметной области: (все примеры схем описаны в формате YAML для наглядности, в реальности же вам надо будет передавать нативные javascript объекты):
types:
    # Всегда есть тип Any, который супер-родитель всех типов
    Numeric:
        color: "#fff"
      
components:
  Literal: # Название компонента
    attrs: # Атрибуты
      V: Numeric 
    out: # Исходящие сокеты
      O: Numeric

  Plus:
    in: # Входящие сокеты
      A: Numeric
      B: Numeric
    out:
      O: Numeric

Пример собранного редактора с данной схемой и простым графом можно посмотреть тут.

Поиграйтесь! Нажмите X для создания нового элемента, удалите элемент двойным кликом. Соедините узлы проводками, выделите их все и скопируйте и вставьте через Ctrl+C и Ctrl+V. Потом выделите все Ctrl+A и удалите с помощью Delete. Ведь всегда можно сделать Undo, прибегнув к Ctrl+Z!

Теперь допустим, наш нехитрый пользователь собрал следующий граф:
image

Если мы попросим редактор сохранить наш граф в дерево, то получим:
[
  {
    "id": 8,
    "c": "Plus",
    "links": {
      "A": {
        "id": 2,
        "c": "Literal",
        "a": {
          "V": "2"
        },
        "links": {},
        "out": "O"
      },
      "B": {
        "id": 5,
        "c": "Literal",
        "a": {
          "V": "2"
        },
        "links": {},
        "out": "O"
      }
    }
  }
]
Как видим нам тут пришло дерево, которое очень легко рекурсивно обойти и получить какой-то результат. Допустим, языком нашего бэкэнда является тоже JavaScript (хотя может быть любой). Пишем тривиальный код:
function walk(node) {
    switch (node.c) {
        case 'Literal':
            return parseFloat(node.a.V);

        case 'Plus':
            return walk(node.links.A) + walk(node.links.B);

        default:
            throw new Error("Unsupported node component: " + node.component);
    }
}

walk(tree);
Если мы прогуляемся такой функцией по вышеуказанному дереву, то получим 2+2=4. Вуаля!

Очень приятным бонусом является возможность у пользователя определять свои «функции», объединяя существующие компоненты.

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

Теперь у нас появилась пользовательская функция x3:

Которой можно воспользоваться, как новым компонентом:

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

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

Возьмём к примеру замечательный язык SQL. Если присмотреться, то любой SQL запрос на самом деле очень легко раскладывается в дерево (этим и занимается первым делом БД, когда получает ваш запрос). Понаписав достаточное количество типов и компонентов можно получить нечто уже более устрашающее:
image

P.S. Если какой-то из примеров не открывается...
Возможно это связано с тем, что вы уже попытались сохранить пользовательскую функцию для одной из схем. А так как по умолчанию (но можно и нужно определять свои обработчики) все пользовательские функции хранятся в localStorage, то может возникнуть ситуация, когда редактор попытается загрузить компоненты или типы, не описанные в текущей схеме.
Для этого просто очистите текущий localStorage с помощью:
localStorage.clear()


К сожалению, демонстрацию превращения данного графа в реальный SQL провести не получится, т.к. она сильно завязана на наш проект. Но в реальности это собирается в следующий SQL:
SELECT 
     COUNT(o.id) AS cnt
   , (o.created_at)::DATE AS "Дата" 
FROM tbl_order AS o 
WHERE o.created_at BETWEEN '2017-1-1'::DATE AND CURRENT_DATE 
GROUP BY (o.created_at)::DATE 
HAVING ( COUNT(o.id) ) > ( 100 ) 
ORDER BY (o.created_at)::DATE ASC

Который сразу же исполняется и отдаёт готовый отчёт в формате Excel. Переведя данный SQL на человечий, получаем:
Показать количество загруженных заказов за каждую день в хронологическом порядке, начинания с 1 января 2017 года, выкидывания дни, где загрузили меньше чем 100 заказов. Вполне себе реальный отчёт для бизнеса!

Схему в формате JSON для данного примера можно посмотреть тут.

Я не буду в статье приводить полное описание системы типов и компонентов, за этим отправляю в соответствующий раздел документации. Но для подогрева интереса лишь немного «вброшу», что можно писать вот так (немного косячит подсветка вычурного синтаксиса YAML):
Plus:
        typeParams: [T]
        typeBounds: {T: {<: Expr}} # Параметризованный тип 'T' ограничен сверху типом 'Expr',
                                   # что означает, что нам надо сюда передать наследник типа 'Expr'
        in:
            A: @T
            B: @T
        out:
            O: @T

Это как если бы вы в Scala объявили функцию:
def Plus[T <: Expr](A: T, B: T): T = A + B


В итоге, подготовив достаточное количество компонентов, и придумав хорошую систему типов (и написав много немного backend кода для обхода деревьев) мы сбагрили дали возможность пользователю составлять свои ad-hoc отчёты на базе SQL. Немного расширив доменную область, мы сильно упростили исходную задачу с фильтрами для поиска проблемных заказов, описанную в начале статьи. А самое главное дали бизнесу возможность самостоятельно тестировать свои гипотезы без привлечения разработчиков. Теперь правда, приходится обучать и писать новые компоненты, но это куда более приятное занятие! Надеюсь, что на SQL и фильтрах дело не остановится, и мы воспользуемся этим инструментом в другим областях проекта.

Самое главное, что я с радостью передаю этот инструмент в общественное достояние на GitHub под лицензией MIT.

Кому интересно, есть идеи/задачи по дальнейшему развитию инструмента:
  • Более удобная навигация по компонентам в схеме + их документация для пользователя
  • Сокеты-атрибуты (как в UE4)
  • Возможность определять атрибуты в пользовательских функциях.
  • Режим read-only для отображения схем
  • Узлы кастомной формы (как в UE4), а не только прямоугольники
  • Ускорение и оптимизация для работы с большим количеством элементов
  • Интернационализация
  • Экспорт картинки в SVG/PNG
  • You name it!


Будет круто, если кому-то захочется воспользоваться этим инструментом на практике и поделиться своим опытом.

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

P.P.S. Я проводил презентацию инструмента в компании с помощью данного документа.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/333750/


Метки:  

Как перейти от КЛАДР к ФИАС и ничего себе не сломать

Четверг, 20 Июля 2017 г. 16:00 + в цитатник
ГНИВЦ ФНС сообщает, что с начала 2018 года КЛАДР перестанет существовать и скачать его будет нельзя.

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

Правильные адреса нужны компаниям, которые любят своих клиентов. Знакомые банки, страховые и интернет-магазины, которые сейчас используют справочник КЛАДР, спрашивают нас, что же делать дальше. Поэтому мы запарились и написали пошаговое руководство по переходу с одних букв на другие от КЛАДР к ФИАС.



Зачем нужны классификаторы адресов


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

Как вы думаете, какой государственный орган наиболее заинтересован в том, чтобы вы получали от него письма? Правильно! Налоговая. Поэтому ФНС России много лет разрабатывает и поддерживает ведомственные общероссийские классификаторы адресов. И так как более полных справочников нет, их стали использовать повсеместно.

Сначала был КЛАДР, и было в нем 6 уровней:

Регион -> Район -> Город -> Населенный пункт -> Улица -> Дом со строениями и корпусами

С 2012 года в эксплуатацию ввели новый классификатор — ФИАС. Про основные отличия мы писали три года назад в статье «ФИАС или КЛАДР: выбираем справочник адресов». В ФНС к разработке нового классификатора подошли основательнее и постарались учесть все грабли минусы КЛАДР. Из интересного добавили дату начала и окончания записи, ввели фиксированный ID для каждого дома (предполагается, что он не будет меняться).

До сих пор продолжают обновляться оба классификатора, но поддерживать совместимость становится сложнее. В прошлом году в ФИАС начали добавлять новые уровни. Например, планировочные структуры — это всякие дачные товарищества и микрорайоны, в классификаторе их уже больше 81 000. В конечном итоге в ФНС приняли логичное решение прекратить поддержку КЛАДР и удалить его в конце 2017 года.



Как адреса хранятся в ФИАС и КЛАДР


Мы видели много способов хранения адресов в структуре КЛАДР. В основном они сводятся к двум вариантам:

  1. Код КЛАДР до улицы + домовая часть вида «дом 1 строение 3 квартира 33», так как части домов в классификаторе хранятся как диапазоны
  2. Адрес в виде текста — одним полем или разбитый по структуре КЛАДР.

Так как в ФИАС нет части домов, мы рекомендуем хранить адрес как:

  1. Код ФИАС до улицы + дом + квартира для идентификации адреса (подробные рекомендации).
  2. Адрес одной строкой в формате ФИАС. При этом лучше сохранять исходный адрес. ФИАС — это все-таки справочник налоговой, и там есть не всё.

То есть задача миграции сводится к тому, чтобы перевести код или текстовый адрес в формате КЛАДР в код ФИАС.

Классификационные коды выглядят так:

  • КЛАДР: СС+РРР+ГГГ+ППП+УУУУ+ДДДД;
  • ФИАС: СС+РРР+ГГГ+ППП+СССС+УУУУ+ДДДД (или ЗЗЗЗ)+ОООО.

Смотрится страшно, рассмотрим пример: Ленинградская обл, Всеволожский р-н, деревня Кудрово, мкр Новый Оккервиль. Адрес реально существует, вот он на Яндекс.Картах. Классификационный код КЛАДР и ФИАС на первый взгляд для него выглядит одинаково: 470050000550023. Разложим его на составляющие.
Уровень Пример код ФИАС код КЛАДР
1 Регион Ленинградская область СС: 47 СС: 47
2 Автономный округ
3 Район Всеволожский р-н РРР: 005 РРР: 005
4 Город ГГГ: 000 ГГГ: 000
5 Внутригородская территория
6 Населенный пункт деревня Кудрово ППП: 055 ППП: 055
65 Планировочная структура мкр Новый Оккервиль СССС: 0023
7 Улица УУУУ УУУУ: 0023
75 Земельный участок ЗЗЗЗ
8 Здание, сооружение, объект незавершенного строительства ДДДД ДДДД
9 Помещение в пределах здания, сооружения ОООО
90 Дополнительная территория
91 Подчинённые дополнительных территорий
Раскладываем адрес по уровням ФИАС и КЛАДР

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

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

Чтобы избавиться от этого, в ФИАС добавили еще идентификационный код ФИАС. Это глобальный идентификатор для каждого объекта: города, улицы, района и т. д. Выглядит он как набор букв и цифр, который формируется по стандарту GUID (Globally Unique Identifier). Типичный GUID в ФИАС выглядит так: f77948dc-7bc8-42cb-979e-2c958d162d63.

Код КЛАДР -> идентификационный код ФИАС


Если адрес у вас хранится как код КЛАДР улицы + домовая часть («дом 1 строение 3 квартира 44»), то для него все относительно просто.


Таблица ADDROBJ хранит все адресные объекты с их идентификаторами

Для работы понадобится таблица ADDROBJ из выгрузки ФИАС в формате xml или dbf. В ней хранятся все объекты (города, улицы и т. д.) подряд с уникальными идентификаторами GUID.
Будем использовать следующие колонки:

  • код КЛАДР (PlainCode);
  • наименование и тип текстом (FormalName и ShortName);
  • актуальность объекта (CurrStatus);
  • почтовый индекс (PostalCode);
  • собственный и родительский идентификатор ФИАС (AoGuid и ParentGuid);
  • уровень (AoLevel).

Пример: Москва, ул Александра Солженицына. Код КЛАДР: 77000000000151900.

Шаг 1. Выделяем из кода КЛАДР код до улицы, то есть берем первые 15 цифр: 77000000000151900.

  • Если КЛАДР меньше 15 цифр, берем 11 и дополняем нулями — это код до населённого пункта: 770000000000000;
  • Меньше 11 цифр — берем 8: 77000000000000000;
  • Меньше 8 — берем 5: 77000000000000000;
  • Меньше 5 — берем 2 цифры кода региона: 77000000000000000.

Шаг 2. Ищем код КЛАДР в поле PlainCode. Если нашлась одна запись, то сохраняем значение поля AoGuid и пропускаем следующий пункт. Но по нашему коду 770000000001519 находится три записи, нужна дополнительная проверка.

Шаг 3. Находим актуальную запись. Значение поля CurrStatus = 0 означает, что запись актуальна. Выбираем ее и сохраняем значение поля AoGuid. Идентификационный код ФИАС найден!

  • Александра Солженицына, CurrStatus = 2;
  • Коммунистическая Б., CurrStatus = 1;
  • Александра Солженицына, CurrStatus = 0, AuGuid = f77948dc-7bc8-42cb-979e-2c958d162d63.

В качестве бонуса соберем текстовый адрес по найденному AoGuid:
  • берем PostalCode — это почтовый индекс: 109004
  • добавляем ShortName и FormalName: 109004, ул. Александра Солженицына
  • если объект является регионом (поле AoLevel = 1), то адрес готов. Но в нашем случаем AoLevel = 7 — это улица. Поэтому ищем родительский элемент по полю ParentGuid и повторяем предыдущий пункт;
  • для улицы Александра Солженицына родительская запись сразу имеет уровень региона — это Москва. Сохраняем ShortName и FormalName и собираем адрес: 109004, г. Москва, ул. Александра Солженицына

Но можно поступить еще проще и воспользоваться готовым сервисом. DaData.ru умеет подсказывать адреса в конкретных регионах, районах, городах и населенных пунктах. Понимает названия («Петергоф»), коды КЛАДР («7800000800000») и ФИАС («8f238984-812b-4bb1-850b-49749fb5c56d»).


Строчный адрес КЛАДР -> код ФИАС


Самый простой вариант — воспользоваться DaData.ru. Сервис сделает все за вас автоматически. Но можно и развлекаться самостоятельно.

Адреса одной строкой


Если адреса у вас хранятся одной строкой, вроде этой:
г Москва, улица Большая Коммунистическая, дом 3,то поздравляем, это самая интересная задача. Нужно писать свой адресный парсер, который будет разделять строку в формате КЛАДР на части, искать каждый ее компонент в ФИАС с учетом опечаток, сокращений, исторических названий и определять по ним ФИАС-код. Легче это сделать уже готовым адресным парсером. Как выбрать алгоритм для адресного фильтра, мы рассказывали раньше.

Адреса по КЛАДР


Если адреса у вас хранятся разложенными по КЛАДР, то задача немного проще.
Тип региона Название региона Тип улицы Название улицы Тип дома Номер дома
г Москва улица Коммунистическая Б. дом 3
Примерно так выгядит адрес, разложенный по КЛАДР

Код ФИАС можно собрать, используя всё ту же таблицу ADDROBJ. Но в этом случае двигаться по уровням нужно от большего к меньшему.

Шаг 1. Берем название региона и ищем его в поле FormalName таблицы ADDROBJ.

FormalName = Москва ->
AoGuid = 0c5b2444-70a0-4932-980c-b4dc0d3f02b5


Шаг 2. Идем дальше по уровням вниз и ищем по FormalName с фиксированным родителем — найденным AoGuid на предыдущем шаге. В нашем случае уровни «город» и «населенный пункт» пустые, а следующий непустой уровень — улица.

ParentGuid = 0c5b2444-70a0-4932-980c-b4dc0d3f02b5,
FormalName = Коммунистическая Б. -> AoGuid=f77948dc-7bc8-42cb-979e-2c958d162d63


Шаг 3. Если дошли до улицы, то можно найти и дом. Для этого в таблице HOUSE ищем номер дома с фиксированным AoGuid улицы. ФИАС не полон домами, поэтому не расстраивайтесь, если нужный номер не найдется.

AoGuid = f77948dc-7bc8-42cb-979e-2c958d162d63,
дом номер 3 ->
HouseGuid = bce8be1f-f2f7-4cce-836e-08daac0b931e


Подводные камни


Может ли что-то пойти не так? Конечно. Например, по названию может легко найтись несколько объектов. «Москва, Тверская» — это про площадь или про улицу? Тогда нужно сравнивать типы, но не все так просто.
LEVEL SCNAME SOCRNAME KOD_T_ST
7 тракт Тракт 727
7 туп Тупик 728
7 ул Улица 729
7 уч-к Участок 730
7 ф/х Фермерское хозяйство 789
7 ферма Ферма 769
7 х Хутор 758
7 ш Шоссе 731
Таблица SOCRBASE хранит полные и сокращенные типы объектов

Тип по КЛАДР может быть сокращенным и полным: «ул» — «Улица», «х» — «Хутор». В ФИАС в явном виде хранится только сокращенный тип (в поле ShortName). Полный тип в сокращенный можно превратить с помощью таблицы SOCRBASE, в ней для каждого уровня хранится соответствие сокращенный и полных типов.

§ § §

И напоследок хорошая новость для тех, кому лень запариваться всем перечисленным. В ближайшее время мы планируем выпустить ФИАС в формате КЛАДР для тех, кто не успеет перейти на формат ФИАС до конца года. Следите за новостями :-)

P.S. Благодарю за неоценимую помощь в создании этой статьи моих коллег по HFLabs Михаила Березина, Елену Расторгуеву и Антона Жиянова.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/333736/


[Из песочницы] Asterisk func_odbc или странный ael

Четверг, 20 Июля 2017 г. 15:46 + в цитатник
По итогу голосования в группе начинаю цикл статей «Asterisk realtime» и первая статья будет посвящена func_odbc или как упростить свою жизнь.

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

Func_odbc зачем он?


И так зачем же мне использовать Function_ODBC если я могу сделать такой же запрос в ael?

  • в extensions.ael это выглядит «опрятней» если ваш запрос повторяется несколько десятков раз в конфигурации
  • удобнее работать с нескольким базами

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

Func_odbc.conf


Будем рассматривать самый простой пример asterisk + mysql.
Итак у нас есть sipuser (много sipusers) и у них есть внешний номер cid, который по независимым от нас причинам постоянно меняется, и нам необходимо его каждый раз спрашивать.

Второй пример: нам нужна переадресация.
Пропускаем настройку odbc.ini и res_odbc.conf, так как вы это и так умееете.

Приступаем к пункту 1:

Прописываем в func_odbc.conf следующее

[cid]
dsn=asterisk
readsql=SELECT cid FROM sipusers WHERE username = ${ARG1} 

И разбираем по частям

dsn=asterisk — Параметр DSN отвечает за подключение Asterisk к базе данных, указанной в файле /etc/odbc.ini.

readsql=SELECT cid FROM sipusers WHERE username = ${ARG1} — нужный вам запрос sql, но с переменной.

Теперь смотрим, что же у нас получилось в ael:

_89. => {
                Set(cid=${ODBC_cid(${CALLERID(num)})});
                SET(CALLERID(num)=${cid});
                SET(CALLERID(name)=${cid});
                ......
}

Set(cid=${ODBC_cid(${CALLERID(num)})}); - собственно это SELECT cid FROM sipusers WHERE username = ${CALLERID(num)})} , думаю пояснения излишни.
SET(CALLERID(num)=${cid}) - устанавливаем CALLERID(num) 
SET(CALLERID(name)=${cid}) -  CALLERID(name)

Собственно далее ваша фантазия в запросах и переменных.

Приступаем к пункту 2:

Добавляем func_odbc.conf

[forward]
dsn=asterisk
readsql=SELECT numforward, `type` FROM call_forwarding  WHERE number = ${ARG1} 

Следует заметить, что в данном ответе мы получим массив.

Теперь смотрим, что же у нас получилось в ael:

macro redirect(number, from){
    Set(ARRAY(forward,type)=${ODBC_forward(${number})});
    }
    if (${EXISTS(${forward})}) {
        switch(${type}) {
            case all:
                ....
            case noanswer:
                ....
            case noanswer-worktime:
                ....
                break;
            default:
                break;
        }
        hangup;
    }
    return;
};
    

Здесь для пере адресации я решил, что удобнее использовать макросы

Set(ARRAY(forward,type)=${ODBC_forward(${number})}); — мы получаем от запроса два параметра, следовательно, нам нужно использовать массив.
if (${EXISTS(${forward})}) — если существует номер переадресации, то действуем дальше…

switch(${type}) — определяем тип переадресации и в зависимости от нужного типа, делаем условия пере адресации.

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

P.S.: Это конечно не realtime. Но суть в том, что часть параметров вы получаете в нужный момент при конкретном обращении, и вам для изменения cid нет необходимости лезть в конфиг менять его и делать reload.

P.P.S.: кроме readsql, существует writesql, который работает по тому же принципу.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/333790/


Метки:  

Сортировка пузырьком в коде Qualcomm

Четверг, 20 Июля 2017 г. 15:37 + в цитатник
Забавной находкой поделился сегодня пользователь fj333 с Reddit. Разбираясь в появившемся год назад проприетарном коде Qualcomm Technologies для Android, он обнаружил, что неизвестный программист решил в production-коде использовать сортировку пузырьком для того, чтобы найти… максимум в массиве.

Посмотреть исходный файл вы сможете по ссылке на Github или же под катом, а оценить его в работе может любой владелец устройства с Qualcomm Snapdragon 200 MSM8610 под управлением Android.

Как известно любому, кто знаком с алгоритмами сортировки, сортировка пузырьком — алгоритм учебный, и в промышленном коде не применяющийся в силу своей неэффективности; дело в том, что в наихудшем и среднем случаях он имеет сложность О(n2), к тому же его емкостная сложность в данном случае — O(n). Кого это не убедило — использовать сортировку пузырьком не рекомендует даже Барак Обама.

И это всё не учитывая того, что для поиска максимума хватило бы и простого перебора.

#ifndef ABS
#define ABS(x)            (((x) < 0) ? -(x) : (x))
#endif

/*==============================================================================
 * Function:           bubblesort
 *
 * Description: Subroutine for sorting 1-D array elements
 *
 * Parameters: double *x    --->   input one-dimensional array
 *             int n        --->   size of input array
 *             int *m       --->   indices of sorted elements
 *============================================================================*/
void bubblesort(double *x, int n, int *m)
{
  int i, j, t1;
  double t2;

  for(i = 0; i < n; i++)
    m[i] = i;

  for(i = 0; i < n; i++) {
    for(j = 0; j * bubblesort */

/*==============================================================================
 * Function:           absmax
 *
 * Description:
 *
 * Parameters: double *x    --->   input one-dimensional array
 *             int n        --->   size of input array
 *============================================================================*/
double absmax(double *x, int n)
{
  int j, *l;
  int index = 0;
  double *y;

  l = (int *)malloc(n * sizeof(int));
  if (NULL == l) {
    CDBG("%s: Error mem alloc for l.\n", __func__);
    return -1;
  }

  y = (double *)malloc(n * sizeof(double));
  if (NULL == y) {
    free(l);
    CDBG("%s: Error mem alloc for y.\n", __func__);
    return -1;
  }
  for(j = 0; j < n; j++)
    y[j] = ABS(x[j]);
  bubblesort(y, n, l);
  index = l[0];

  free(l);
  free(y);
  return ABS(x[index]);
}

Проводилось ли Code Review? Об этом история умалчивает…
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/333782/


Метки:  

A!Hack Summer — хакатон Альфа-Банка 5 и 6 августа 2017

Четверг, 20 Июля 2017 г. 15:01 + в цитатник
Привет, Хабр! 5 и 6 августа мы будем проводить внешний летний хакатон “A!Hack Summer”.



Если вам интересны такие вещи как Artificial Intelligence, Machine Learning, AR/VR, Data Science, вы умеете с ними работать и подумывали сделать что-то свое или знаете, как на базе этого сделать продукт для клиентов банка — заходите в Deworkacy (Москва, Берсеневская наб. 6 стр. 3) 5 и 6 августа.

А о том, для чего мы все это делаем, расскажет Владимир Урбанский, руководитель Альфа-Лаборатории.

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

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

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

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

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

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

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

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

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

Критерии успешности хакатона


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

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

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

Оценка идей


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

Хакатон, который будет проводиться 5 и 6 августа – внешний.
Цель хакатона — найти идеи и людей, способных их реализовать.

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

Но нам также интересны и люди, возможно, нас не зацепит сама идея, но мы захотим работать с этими людьми. Венчурные компании часто инвестируют в команды, а не в идеи. Поэтому мы тоже ищем людей.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/333784/


Как работать с UX-подрядчиками? Опыт мессенджера «Ответ»

Четверг, 20 Июля 2017 г. 14:03 + в цитатник
В марте мы закончили проектирование интерфейсов мессенджера «Ответ». Сели писать кейс, стали вспоминать и обнаружили, что это был практически эталонный пример того, как надо работать с внешним подрядчиком по UX-проектированию. То есть с нами. И очень честный такой пример, без розовых пони. Было бы преступлением скрывать от общественности те мысли, которые мы наконец-то оформили в слова. Так что кейс подождет, а пока поговорим про совместную работу.




Главный вопрос жизни


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

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

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

Наша роль в «Ответе»


Как бы ни хотелось подчеркнуть важность UX-специалиста, реальность такова, что разработка интерфейсов никогда не начинается с чистого листа.

До начала работы с нами у «Ответа» уже было много всего. А именно:
  • команда разработчиков;
  • видение продукта (текстовое описание);
  • знание рынка, сильных и слабых сторон конкурентов;
  • концептуальные идеи по отстройке от конкурентов;
  • целый ворох функционала, который хорошо было бы реализовать;
  • трезвая оценка своих технических возможностей и ограничений.

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

Все перечисленное укладывается в набор обязанностей UX-проектировщика. Стандартная постановка задачи с двумя вариантами развития событий: укомплектовать штат собственными проектировщиками или передать работу внешнему подрядчику. «Ответ» выбрал второй вариант.

Точка отсчета


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

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

Кто про что?


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

Такое «принятие» не избавляет UX-команду от обязательного этапа аналитики. Мы провели четыре интервью с потенциальными пользователями. Это много или мало?

  • Катастрофически мало, чтобы строить на этих вводных новый продукт.
  • Достаточно, чтобы проверить видение об реальность. Механизм простой: если в интервью не выявлено существенных противоречий с нашими идеями, то идеи ОК. Если один целевой интервьюер из четырех не понял, о чем вообще речь, — беда.

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

Давайте уже рисовать?


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

  • Исполнителю — принять волевое решение и остановиться. Слишком велик соблазн составить идеальное ТЗ и потом по любому поводу тыкать в бумажку: «мы же не договаривались». Не работает такой подход.
  • Заказчику — терпеливо ждать. Поверьте, вникнуть в новую тему, даже если это не высшая математика, за три дня не получится.
  • Всем вместе — доверять друг другу. Естественная «притирка» приходит уже на этапе работы-работы, а сейчас велик риск «характерами не сойтись».

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

Проектирование


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

  1. Единый список сценариев.
  2. Единый список функционала.
  3. Ручной контроль нашего менеджера.
  4. Контроль заказчиком.
  5. Общение проектировщиков между собой.

Дальше — долгие часы проектирования. И новые риски, что что-то пойдет не так. Успех проекта зависит и от заказчика, и от исполнителя. А факторы успеха такие.

Постоянное общение команд


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

Коллективный UX-разум


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

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

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

Докопаться до мышей


Этот фактор целиком и полностью в руках заказчика. Бывает, что он просто говорит «угу» на отдельные картинки. Но лучше (и в «Ответе» было именно так), когда заказчик просит рассказать про каждую кнопочку и ссылочку. Не в документации описать, а голосом поговорить.

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

Споры до хрипоты


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

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

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

И отстоять свои решения. И капитулировать перед здравыми решениями заказчика.

И что в итоге?


Прототипы приняты. Продукт создан. Идет закрытое тестирование.

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

Кстати, про UX-поддержку нам тоже есть что рассказать. Но уже в другой раз, на другом примере и на другой площадке — это наша последняя публикация в корпоративном блоге на Хабре. Спасибо всем читателям, ищите нас в соцсетях.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/333774/


Метки:  

[Из песочницы] Пусть интернет прогнётся под нас

Четверг, 20 Июля 2017 г. 13:51 + в цитатник


Если ты давно хотел сделать Интернет чуточку лучше (для себя), но всё было лень некогда, то сегодня твой счастливый день. За 21 шаг я покажу тебе как достичь этой заветной цели.

Бесплатный бонус! В добавок к интернету, делаем лучше и Google search. Может, Google оценит идею и предложит руку и сердце (если что, я согласная, даже учебу брошу ради него).


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

Плагин позволят легко внедрять собственный JavaScript/CSS на любые страницы просматриваемые в браузере. Т.е. этакий chrome extensions API версия lite.

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

TL;DR

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

Код плагина можно загрузить с GitHub.

И после этого:

  1. Открыть chrome://extensions в Хром браузере
  2. Поставить галочку напротив «Developer mode»
  3. Нажать на «Load unpacked extensions» и выбрать директорию в которую сохранили исходный код
  4. После этого для плагина «CustomActions» выбрать «options»
  5. На форме опций, нажать «Demo config» и «Save»



Вот и все, можно пользоваться, например открыть google.com или Хабр, поправить конфигурацию или поиграться со скриптами.

Дальше идет развернутая версия, с лирическими отступлениями.

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

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

Но еще печальнее было осознать, то что мои 9-ть с половиной сайтов не идеальны. Поэтому в рамках курсовой работы было решено сделать их (ну заодно и остальной интернет) лучше.

В большинстве случаев, для этого требовалось написать всего 3-4 строчки на JavaScript и/или 2-3 на CSS.

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

Определяем наши хотелки:

  1. При открытии сайта внедряется пользовательский Ж-скрипт ассоциированный с этим сайтом
  2. Пользовательский скрипт конфигурируется на странице предпочтений
  3. В тулбар браузера добавляем кнопочку для быстрого вызова конфигурации

Техзадание определено, начинаю кодить.

Шаг 1.

Читаю getstarted до просветления, или посинения, смотря с какой стороны посмотреть.

Шаг 2.

Определяю структуру проекта

options.html
options.js

popup.html
popup.js

background.js

manifest.json

icon.png
images
images\icon128.png
images\icon16.png
images\icon48.png

Шаг 3.

Создаю манифест.

{
  "name": "CustomActions",
  "description": "plugin for CustomActions",
  "version": "1.0",
  "background" : {
    "scripts": ["background.js"]
  },
  "icons":
   {
      "128": "images/icon128.png",
      "16": "images/icon16.png",
      "48": "images/icon48.png"
   },
  "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'",
  "permissions": [
    "webRequest", "tabs", "activeTab", "http://*/*", "https://*/*", "storage", "unlimitedStorage", "contextMenus", ""
  ],
  "browser_action": {
      "default_title": "Custom Actions Injection plugin",
      "default_icon": "icon.png",
      "default_popup": "popup.html"
  },
        "commands": {
          "cmd-exec-1": {
            "suggested_key": {
              "default": "Ctrl+Q"            
	     },
            "description": "Custom Action #1"
          },
          "cmd-exec-2": {
            "suggested_key": {
              "default": "Ctrl+B"
            },
            "description": "Custom Action #2"
          },
          "cmd-exec-3": {
            "suggested_key": {
              "default": "Ctrl+Y"
            },
            "description": "Custom Action #3"
          }
},
  "options_page": "options.html",
  "manifest_version": 2
}

Шаг 4.

Работаю над формой options.html.

Не зря посещала предыдущую сессию. Пригодились знания по knockout.js из курса «Дизайн Веб-страниц 2.0»

Добавляю файлы knockout-3.4.1.js и knockout.mapping-latest.js в структуру проекта.

Ничего не работает. Копаю. Не помогает. Рою. Нарыла что chrome extensions не любит knockout.
Заставляю полюбить, обновляю манифест.

"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'"

Шаг 5.

После боли и страданий в попытке реализовать пользовательский интерфейс приходит озарение.

Тянем всё из chrome://settings

Встали на плечи гиганта и дело пошло:



Шаг 6.

Надо сохранять данные. Читаю про chrome.storage
Дилемма выбора между chrome.storage.sync и chrome.storage.local

chrome.storage.sync привлекательней, но жёсткие лимиты.

Еще одно озарение – у меня же тестовый проект, так что local — это наше всё.
Правлю манифест чтобы не было проблем с лимитами.

И пользую chrome.storage.local.set для сохранения конфигурации.

            chrome.storage.local.set(items, function () {
                self.status('Items saved.');
                setTimeout(function () { self.status(''); }, 750);
            });

Шаг 7.

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

Ага, сладкая парочка chrome.runtime.sendMessage:
            chrome.storage.local.set(items, function () {
                self.status('Items saved.');
                setTimeout(function () { self.status(''); }, 750);

                chrome.runtime.sendMessage({ command: 'refreshConfig' });
            });

и chrome.runtime.onMessage:
            chrome.runtime.onMessage.addListener(
               function (request, sender, sendResponse) {
                   onCommand(request.command);
            });

Шаг 8.

Открываю popup.js. Закрываю. Снова открываю. И так 7 раз. Ничего не понятно.

Это я одна такая или где? Наступает долгожданное утро и тут споткнулась о samples — спасибо вам невидимые труженики гугла.

Разгребаю завалы драгоценных знаний. В конце концов нахожу нужный пример и использую волшебную комбинацию ACV ( Ctrl-A / Ctrl-C / Ctrl-V ). 13 часов спустя — дело сделано.

Шаг 9.

Пора приступать к главной части, перехват и внедрение.

Перехватчик — chrome.tabs.onUpdated:
chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
        var url = '';
        if (changeInfo && changeInfo.url)
            url = changeInfo.url.toLowerCase();
        else if (tab && tab.url)
            url = tab.url.toLowerCase();

	// . . .
});

и внедренец — chrome.tabs.executeScript:

if (item.sourceType == 'InjectCSS') 
	chrome.tabs.insertCSS(item.output == 'Owner tab' ? tabId : null, { code: item.data });
else
	chrome.tabs.executeScript(item.output == 'Owner tab' ? tabId : null, { code: item.source });

Все прошло легче чем могло, но всё же дольше чем хотелось.

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

Шаг 10.

Всё готово. Можно идти за честно заработанной пятеркой…

… не так быстро. Вместо пятерки принесла кучу замечаний и улучшений.

Шаг 11.

Начнем с самого легкого, в popup.js добавляю поддержку функции «добавить текущий сайт»

Нет так легко как кажется, надо передать данные из popup.js в options.js.

Потратила 3 часа пытаясь поймать messages, сохранить в extension storage и прочитать обратно, но в конце концов решила, что умный в гору не пойдет, он её обойдет.

Query string – наш ответ этой горе.

Шаг 12.

Следующая функция посложнее, добавить поддержку context menu.
Примеры снова спасают. Всё оказывается проще чем могло бы — chrome.contextMenus.create:
chrome.contextMenus.create({ id: item.id, 
				contexts: ["page", "frame", "selection"], 
				title: item.name, 
				onclick: function (info, tab) { 
							onCommand(info.menuItemId); 
					} 
});

Шаг 13.

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

Надо сделать поддержку вызова через горячие клавиши.

Всё делаю как в примерах, правлю манифест:
"commands": {
          "cmd-exec-1": {
            "suggested_key": {
              "default": "Ctrl+Q"            
	     },
            "description": "Custom Action #1"
          }
}

и использую chrome.commands.onCommand:
chrome.commands.onCommand.addListener(onCommand);

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


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

Шаг 14.

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

Технологии приходят на помощь. Гугл транслейт vs преподаватель английского – счёт 1: 0 в пользу гугла животворящего!

Шаг 15.

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

Возвращаюсь с новым словом рефакторинг (до этого знала только слово ФАКторинг. Особенно часто говорила его в начале проекта).

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

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

Шаг 16.

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

Шаг 17.

Добавляю пример для lorem ipsum. Кто это посоветовал? Учитель латыни?

Требование: при нажатии на комбинацию клавиш заполняем поля на форме предложениями языка lorem.

Сделала, вроде работает.

    var loremDemoData = {
        names: [
            { firstName: "Victoria", lastName: "Veit", email: "Victoria.Veit@noreply.ru" },
            { firstName: "Gisele", lastName: "Gillard", email: "Gisele.Gillard@noreply.ru" },
            { firstName: "Edmund", lastName: "Edelson", email: "Edmund.Edelson@noreply.ru" },
            { firstName: "Joey", lastName: "Janelle", email: "Joey.Janelle@noreply.ru" }
        ],
        lorem: [
            "Orem ipsum dolor sit amet, consectetur adipiscing elit. Etiam sit amet purus condimentum, porta nulla sed, consequat felis. Phasellus quis condimentum odio. Maecenas scelerisque vehicula leo, sit amet tristique tellus molestie sed. Aenean lacus lorem, feugiat semper imperdiet a, vehicula ac orci. Pellentesque ac nisi commodo, pellentesque lorem quis, fringilla tellus. Fusce bibendum erat sit amet libero maximus rutrum. Integer dictum nibh sodales efficitur congue. Mauris nulla libero, hendrerit eget dictum nec, aliquam eu mi. Donec ipsum nisi, bibendum et consequat eu, imperdiet eget nisl. Duis tincidunt nibh et nibh tempor, quis mattis mi vulputate.",
            "Suspendisse quis eleifend lectus. Sed nec vehicula elit. Praesent ac sollicitudin diam. Nam at venenatis lectus. Fusce condimentum tortor nec augue vestibulum tempus. Nullam faucibus vehicula lorem, et mollis justo dapibus a. Proin sagittis velit in lectus vehicula, id eleifend urna hendrerit. Integer rhoncus dui sed enim sollicitudin, a finibus magna fermentum.",
            "Fusce at urna vitae magna semper scelerisque id volutpat tellus. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Sed ut elit nisl. Duis sit amet ante accumsan nibh ultricies pharetra at vitae purus. Donec a felis eget ipsum euismod tempus. Donec elementum vel tortor vel efficitur. Nunc tristique, magna hendrerit sagittis placerat, odio sem commodo ligula, eu aliquam arcu elit sit amet diam. Etiam ultrices vehicula auctor."
        ],
        loremShort: [
            "Morbi nec sollicitudin augue.",
            "Suspendisse sagittis fringilla aliquam.",
            "Curabitur malesuada dolor.",
            "Praesent quis lacus neque. Duis vitae vehicula felis"
        ]
    };

        function getRandomInt(min, max) {
            return Math.floor(Math.random() * (max - min)) + min;
        }

        var name = data.names[getRandomInt(0, data.names.length)];
        var hadEmail = false;

        var t = document.querySelectorAll('input[type=text], textarea');
        for (var i = 0, l = t.length; i < l; i++) {
            var e = t[i];
            var ro = e.getAttribute('readonly');

            if (e.disabled || ro === '' || ro === 'true' || ro == '1')
                continue;

            var loremTxt = data.lorem[getRandomInt(0, data.lorem.length)];
            var loremShort = data.loremShort[getRandomInt(0, data.loremShort.length)];

            var na = ('' + e.name).toLowerCase();
            var ia = ('' + e.id).toLowerCase();

            if (na == 'firstname' || ia == 'firstname' || na == 'fname' || ia == 'fname')
                e.value = name.firstName;
            else if (na == 'lastname' || ia == 'lastname' || na == 'lname' || ia == 'lname')
                e.value = name.lastName;
            else if (!hadEmail && (na.indexOf('email') >= 0 || ia.indexOf('email') >= 0)) {
                e.value = name.email;
                hadEmail = true;
            } else {
                e.value = (e.tagName == 'TEXTAREA' ? loremTxt : loremShort);
            }
        }

Шаг 18.

Следующий пример для сайта habrahabr.ru

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

В процессе узнала о существовании Хабра и Гиктаймса. Знала бы о них раньше, все было бы по крайней мере в два раза быстрее. Провела три дня читая без остановки. Осилила статьи только за последний год, впереди еще много интересного!

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

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

Оказалось, что статью написать легче, чем код. Может чукча не читатель, а писатель?

{
    "showCompanies": [
        "yandex",
        "mosigra"
    ],
    "hideCompanies": [
        "hashflare"
    ],
    "hideHubs": [
        "lib"
    ]
}

        function hideParent(el) {
            if (el.classList && el.classList.contains('post_teaser'))
                el.style.display = 'none';
            else if (el.parentElement)
                hideParent(el.parentElement);
        }

        function sanitizeParent(el) {
            if (el.classList && el.classList.contains('post_teaser')) {
                el.querySelectorAll('img').forEach(function (img) { img.style.display = 'none'; });
                el.querySelectorAll('.post__body_crop').forEach(function (chld) {
                    chld.style.maxHeight = '4em';
                    chld.style.overflow = 'hidden';

                    el.addEventListener('mouseover', function () {
                        chld.style.maxHeight = "inherit"; chl
                        d.querySelectorAll('img').forEach(function (img) {
                            img.style.display = 'block';
                        });
                    }, false);

                    el.addEventListener('mouseout', function () {
                        chld.style.maxHeight = "4em";
                        chld.querySelectorAll('img').forEach(function (img) {
                            img.style.display = 'none';
                        });
                    }, false);

                });

                el.querySelectorAll('.post__title a').forEach(function (titl) { titl.style.color = '#707040'; });

            } else if (el.parentElement)
                sanitizeParent(el.parentElement);
        }

        document.querySelectorAll('a[href*="https://geektimes.ru/hub/"]').forEach(function (el) {
            var hub = el.getAttribute('href').replace(/^.*\.ru\/hub\//, '').replace(/\/.*$/, '');
            if (data && data.hideHubs && data.hideHubs.indexOf(hub) >= 0)
                hideParent(el);
        });

        document.querySelectorAll('a[href*="https://geektimes.ru/company/"], a[href*="https://habrahabr.ru/company/"]').forEach(function (el) {
            var company = el.getAttribute('href').replace(/^.*\.ru\/company\//, '').replace(/\/.*$/, '');
            if (data) {
                if (data.hideCompanies && data.hideCompanies.indexOf(company) >= 0) {
                    hideParent(el);
                    return;
                } else if (data.showCompanies && data.showCompanies.indexOf(company) >= 0)
                    return;
            }

            sanitizeParent(el);
        });

Шаг 19.

Бродя по просторам интернета, увидела интересную идею и решила реализовать её в качестве примера для google search.

Может завлаб оценит инициативу и перестанет придираться по пустякам.

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

После примера для Харба, это пара пустяков.

    var googleDemoData = [
        { "keywords": "python", "title": "python" },
        { "keywords": "javascript", "title": "javascript" },
        { "keywords": "php", "title": "php" },
        { "keywords": "mysql", "title": "mysql" },
        { "keywords": "site:stackoverflow.com", "title": "at stackoverflow.com" },
        { "keywords": "site:developer.mozilla.org", "title": "at developer.mozilla.org" },
        { "keywords": "site:developer.chrome.com", "title": "at developer.chrome.com" },
        { "keywords": "site:habrahabr.ru", "title": "at habrahabr.ru" }
    ];

        function ggSetTimeRange() {
            var elemId = this.getAttribute('data-range');
            var timeLimit = document.querySelector('#' + elemId + ' a');
            if (timeLimit)
                timeLimit.click();
        }

        function ggReplaceAndSearch() {
            var kw = this.getAttribute('data-search');

            if (document.location.href.indexOf('chrome-search://') == 0 || document.location.href.indexOf('https://www.google.com/_/chrome/newtab?') == 0) {
                document.location.href = "https://www.google.com/search?q=" + encodeURIComponent(kw);
                return;
            }

            var inputText = document.querySelector('input[name="q"]');
            if (inputText) {
                setTimeout(function () {

                    var keyword = '' + inputText.value;
                    if (kw.indexOf('site:') >= 0 && keyword.indexOf('site:') >= 0) {
                        keyword = keyword.replace(/ *site:[^ ]+/, '');
                    }
                    else if (keyword.indexOf(kw) >= 0)
                        return;

                    kw = ' ' + kw;

                    if (kw.indexOf('site:') >= 0) {
                        inputText.value = keyword + ' ' + kw;

                        setTimeout(function () {
                            var btn = document.querySelector('form[action="/search"]');
                            if (btn) {
                                btn.submit();
                            } else {
                                btn = document.querySelector('button[name="btnK"]');
                                if (btn) {
                                    btn.click();
                                }
                            }
                        }, 100);
                    }
                    else {
                        inputText.value = kw + ' ' + keyword;

                        var strLength = ('' + inputText.value).length;
                        inputText.setSelectionRange(strLength, strLength);
                    }
                }, 200);

                setTimeout(function () {
                    inputText.focus();
                }, 100);

            };
        };

        var ggHelper = document.getElementById('ggHelper');
        if (!ggHelper) {
            var helperHtml = '
' + '
'; var bodyTag = document.querySelector('body'); if (bodyTag) { var e = document.createElement('div'); e.innerHTML = helperHtml; bodyTag.appendChild(e.firstChild); document.querySelectorAll('#ggHelper .gg-keyword').forEach(function (el) { el.addEventListener('click', ggReplaceAndSearch); }); document.querySelectorAll('#ggHelper .gg-range').forEach(function (el) { el.addEventListener('click', ggSetTimeRange); }); } }

Шаг 20.

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

После переписки, нашла еще не менее 6-ти багов. Ревью – это сила! Надо запомнить и это слово.
Стало приятно смотреть на код, начала даже понимать что и зачем там написано.

Шаг 21.

Все готово.

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

Пожелайте удачи!

P.S.:. В конце хотелось бы выразить сердечную благодарность создателям и пользователям сайта stackoverflow.com

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

Даже сейчас, иногда всё еще хочется вырвать всю растительность на голове, а иногда и того похуже.

P.P.S.:. Критика приветствуется. Любая.

Update 1. Выставили оценки, мне 4++.

Один бал завлаб вычел с формулировкой: «слишком много плагиата с StackOverflow», но плюс добавил за статью на Хабре. На вопросы по поводу второго плюса, загадочно ухмыляется в усы.

Update 2. Две радостные новости.

Первая. Преподаватель по сетевым технологиям обещал поставить экзамен автоматом если добавлю функцию «поделиться с другом». Группа экспретов говорила незнакомые слова.

Сижу, курю node.js, походу придется начать не только курить, но и пить. Без бутылки не разобраться.

Голова в облаках. На Хероку оно мне надо? Может лучше сдать как обычно — шпаргалки и зубрило. А то здоровье дороже.

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

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

Озвучьте ваши самые смелые фантазии.

Третья. Если так пойдет, может и диплом на чём-нибудь прокатит?

Update 3. Ура! Первая зарплата в долларах. По программе work & travel изучаю английский на кухне местного макдональдса.

Первая выученная идиома: «маньяна на траваху». Чувствую, что к концу лета буду флюент.

Умножаю доллары на 60, количество нулей конкурирует с лучшими предложениями для программистов в нашем областном центре. А у нас в райцентре, надо вводить коэффициент N.

Нет N мало, надо брать M.

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

Много думаю.

Может моё призвание это кулинария? Выпишу бабушку, откроем чебуречную, будем диетическими пирожками торговать. А то на диете бесплатного макдональдса, я точно останусь очччень сферическим пользователем.

До скорой встречи!
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/333776/


Метки:  

Особенности национальной SMS-авторизации

Четверг, 20 Июля 2017 г. 13:17 + в цитатник
SMS-пароли уже давно вошли в нашу жизнь как сравнительно удобный (особенно, если сравнивать с отправкой документов «Почтой России») способ дистанционного подтверждения личности. Способ этот, безусловно, не идеальный, поскольку успешность процесса доставки SMS зависит от корректности взаимодействия нескольких действующих лиц. Как правило, это: отправитель — сотовый оператор получателя — получатель. Поэтому на страницах сети Интернет можно найти 1000 и 1 ответ на вопрос «Почему не приходят SMS». Но, готов поспорить, что с такой оригинальной причиной как та, о которой я собираюсь сейчас вам поведать, вы еще не сталкивались...image
Как-то так получилось, что мое желание поделиться полезной информацией вылилось в целое эссе, поэтому, если Вы не особо любите описания чужих душевных терзаний, то можете смело их пропустить, перейдя непосредственно к развязке.

Прелюдия


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

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

Здесь нужно сказать, что у ростовских нотариусов существует какой-то картельный сговор. Они все как один утверждали, что не могут заверить подлинность моей подписи под набранным мною текстом на листе А4 (хотя в их прайсах присутствовала такая услуга, стоимостью в 100 рублей), а просто таки обязаны оформить этот текст на гербовой бумаге за 1000+ рублей. И сколько ты им не тверди, что московские компании требуют лишь заверить подпись под установленной ими текстовой формулой, а документы на гербовой бумаге им, наоборот, более сложно обрабатывать в рамках их бизнес-процессов, результата это не принесет.

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

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

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

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

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

Кульминация


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

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

Следующим этапом стало обращение в службу поддержки сервиса. Меня уверили, что исправно отправляют все уведомления и даже прислали лог всех транзакций с момента крайнего полученного уведомления. Лог был заверен печатью сторонней организации (SMS-провайдера), у которой сервис приобретал услуги по рассылке уведомлений. Как можно видеть, у всех уведомлений, который я не получил, наблюдался статус «В пути»:

image

Тогда я принялся искать похожие ситуации в которых пользователи не получали SMS-уведомления лишь от какого-то конкретного сервиса (поскольку уведомления от Я.Денег и Сбер.Онлайн мне по-прежнему поступали). Что меня насторожило, во всех случаях, которые мне удалось обнаружить, фигурировал мой сотовый оператор (например: 1, 2). Я описал ситуацию знакомому в штате моего сотового оператора и получил от него следующий комментарий:
Я не уверен, что там применяется фильтрация. Возможно речь идёт о том, что это т.н. A2P-сообщения, по которым заключается межоператорское соглашение. Если такого прямого контракта между сервисом и оператором нет, или нет соглашения с SMS-агрегатором, или контракт прекратил действие, то оператор может не пропускать такие сообщения. Это как один из вариантов. Чтобы СМС как-то фильтровались — таких данных у меня нет. Но если есть подтверждение от оператора, что смс отправлено на другого оператора, то можно отследить шлейф. Должна быть транзакция отправки смс на СМС-Центр.

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

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

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

Развязка


image

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

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

В первую очередь на ум пришли положения ст. 426 ГК РФ, в частности:
Отказ лица, осуществляющего предпринимательскую или иную приносящую доход деятельность, от заключения публичного договора при наличии возможности предоставить потребителю соответствующие товары, услуги, выполнить для него соответствующие работы не допускается.
Но потом я вспомнил, что у меня имеется то самое соглашение, оформленное в 2015 году, в котором черным по белому прописано обязательство сервиса отправлять SMS-пароли на тот самый номер. Разумеется, в том же соглашении был прописан и ряд исключений, включая наличие форс-мажорных обстоятельств, но, на мой взгляд, самодурство подрядчика на форс-мажор как-то не тянуло.

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

Но, как вы понимаете, осадочек-то остался! Я потратил немало времени и нервных клеток (причем, не только своих, но и сотрудников моего сотового оператора), а мне даже не принесли извинения. Но это не самое страшное. Меня пугает то, что теперь я никогда не буду уверен в том, что своевременно получу доступ к своему аккаунту. Причем не только на этом сервисе, но и на каком-либо другом. Мой мир больше никогда не будет прежним.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/333558/


Метки:  

Выбранный UI-фреймворк – вред. Архитектурные требования – профит

Четверг, 20 Июля 2017 г. 11:49 + в цитатник


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

  • Войти в метро теперь – не просто кинуть пятачок, а приложить карту Тройка, записанную на телефон и учитывающую пересадку.
  • Позвонить по телефону и посмотреть телевизор – давно уже не провести два провода в квартиру и вносить фиксированную абонентскую плату, а triple play с кучей опций и возможностей.
  • Посмотреть дневник сына – на святое же покусились! – теперь можно с планшета, заодно ответив на комментарий классного руководителя о его неудовлетворительном поведении.

Ну и я уже молчу про всякие Tinkoff, Apple Pay, Google Now, умные дома и многое другое.

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

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

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

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

  • Декаплинг. Строгое разделение на back-end и front-end. REST-сервис под каждый отдельный UI.
  • Микросервисы. Каждая команда независимо разрабатывает свою часть, но все эти части должны сложиться в одно работающее приложение.

Эти особенности фактически развязали руки front-end разработчикам и позволили разным командам выбирать front-end технологии в зависимости от бизнес-задач, экспертизы команды, предпочтений и «религии».

Во многом поэтому мы сейчас наблюдаем активный рост и отсутствие явного и безоговорочного лидера в UI-фреймворках: AngularJS, ReactJS, EmberJS, ExtJS и др. При этом, вполне вероятно, надо быть готовым к тому, что завтра появится новая front-end технология, которая будет более эффективной и будет более активно поддерживаться/развиваться сообществом. Именно поэтому считаю неправильным сейчас делать долгосрочный выбор и останавливаться на одной front-end технологии. Более того, вести разработку надо так, чтобы front-end технология была относительно дешево заменяемой, всегда держать это в голове при разработке архитектуры конкретного приложения. Это задача номер один.

Кроме того, при дальнейшем увеличении команды мы будем иметь уже несколько front-end команд, которые разрабатывают одно UI-приложение. Каждая команда независимо разрабатывает свою часть, но все эти части должны сложиться в одно работающее приложение так, чтобы UI одной команды не конфликтовал с UI другой. Это задача номер два.

Для решения этих задач мы, front-end практика в компании Netcracker, разрабатываем архитектурные требования, которые обязательны для всех продуктов.

Немного теории модульного подхода


В основе архитектурных требований лежит подход, который подразумевает независимые JS-блоки и их встраивание друг в друга. У этого подхода есть несколько названий: Scalable JS Apps, Modular JavaScript, JS Portals. Такие фреймворки сравнительно молоды и, можно сказать, сделаны по принципам Николаса Закаса: если можете писать, просто пишите монолит, если нужна интеграция с различными блоками, то придется использовать модульный подход.

Терминология


  • Application (конечное приложение) – набор html/js/css, который отображается пользователю. Конечное приложение может в общем случае не использовать принципы Modular JavaScript и быть написано на любом языке, хоть на flash.
  • Application Controller – JS-объект, реализующий принципы Modular JavaScript, позволяющий модулям общаться и встраиваться рядом и друг с другом.
  • Module – JS-приложение на любом языке, подобном JS.
  • Sandbox – объект, через который Module может общаться с внешним миром.
  • Service – утилитарные объекты, имеющие логику, но не имеющие UI.
  • BroadcastService – сервис, позволяющий модулям общаться.
  • Plugin – встраиваемый в Application Controller модуль. Application Controller может использовать его, чтобы получить новый функционал.



Modular JavaScript. Принципы


Принципы основаны на том, что мы считаем каждый модуль ребенком. Поэтому к ним применимы следующие правила:

  1. Модуль может вызывать только свои методы или методы Sandbox.
  2. Нельзя смотреть на DOM вне своего Sandbox.
  3. Нельзя трогать ненативные глобальные переменные.
  4. Если модулю что-нибудь нужно, это нужно спросить у Sandbox.
  5. Не разбрасывать игрушки (модуль не должен создавать глобальные переменные).
  6. Не разговаривать с незнакомцами (модуль не должен напрямую вызывать другой модуль).

Оригинал можно прочитать здесь.

Эти принципы реализованы Николасом Закасом в ряде проектов, например здесь: http://t3js.org. Однако есть альтернативные реализации: http://openf2.org/ (хотя принципы там те же, о них рассказывается в видео).

Взяв за основу эти принципы, мы начали уточнять и развивать их в наших проектах.

Наша специфика и архитектура


Уточнения и дополнительные принципы, которые диктуются спецификой наших проектов:

  1. сервис не имеет UI;
  2. сервис обычно singleton;
  3. модули могут общаться через сервис общения (это может быть EventBus или publish/subscriber);
  4. есть только один сервис общения, общий для всех модулей;
  5. поскольку мы имеем дело с JS, нужен статический анализатор кода (например, ESLint), который запретит внесение изменений в код в случае нарушения принципов;
  6. реализация Modular JavaScript должна быть JS Agnostic, т. е. модуль может быть написан на любом языке, подобном JS;
  7. необходима поддержка модуля в модуле, так как часто хочется переиспользовать код (например, модуль table может быть отрисован внутри модуля dashboard, который, в свою очередь, рисуется на модуле tab navigation – наподобие панели c вкладками для переключения);
  8. из-за того, что модуль не может выйти за рамки своего элемента, необходим DialogManagerService, который управляет body для показа диалогового окна; модуль, который хочет показать диалоговое окно, использует модуль dialog и передает его в сервис;
  9. поскольку модулей в проекте может быть много, компилирование всех в один пакет или предварительное соединение ссылками может привести к проблемам с производительностью, поэтому модули должны уметь подгружаться асинхронно по требованию и, естественно, запускаться только после того, как подгружены все другие модули и сервисы, от которых они зависят; отсюда следует, что нам понадобится устранять конфликты между зависимыми модулями.

И вот какая получается архитектура



Блок T3-NC-powered представляет собой Application Controller. У Application Controller есть набор базовых плагинов (треугольники), которые дополняют его функциональность. Плагины не имеют доступ к Application Controller. Наиболее важным является плагин, позволяющий общаться с сервером для «ленивой» загрузки модулей.

Сервисы могут обмениваться данными с Application Controller. Наиболее важным является сервис для обмена сообщениями между модулями. Также сервисы могут использовать плагины. Сервисы не имеют UI, так как предоставляют JS-функции.

При старте модуля по его имени создается Sandbox, который ограничивает модуль. Основной API – дает возможность получить сервис и DOM element, в который модулю нужно встроиться. Если необходимо запустить два модуля с одинаковым именем, то Application Controller создаст два экземпляра модулей, внутренние id которых будут разными.

Заключение


Совместная разработка большой распределенной командой принесла декаплинг и микросервисы, что развязало руки front-end разработчикам и позволило разным командам выбирать различные front-end технологии. Это могло бы породить хаос и превратиться в бесконечный спор.

Но мы хитрые. :) Модульная разработка и архитектурные требования позволяют собирать в одно UI-приложение части, разрабатываемые различными front-end командами, и гарантируют относительно дешевую замену front-end фреймворка.

Если вы интересуетесь модульным подходом или уже вовсю используете его, пишите в комментариях – давайте делиться опытом. Мы в свою очередь готовы дать больше технических деталей, если у сообщества будет интерес.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/333734/


Метки:  

Быстрое восстановление данных. Схема бабочки для регенерирующих кодов

Четверг, 20 Июля 2017 г. 11:40 + в цитатник

Автоматическое создание миграций Liquibase для PostgreSQL

Четверг, 20 Июля 2017 г. 11:22 + в цитатник
Работа с Liquibase всегда приносит уверенность в том, что объекты БД находятся в том состоянии, в котором ты этого хочешь. Именно эта уверенность и делает системы миграций баз данных столь популярными.

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

Логотип Liquibase и pgCodeKeeper


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

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

Сегодня мы исправим это недоразумение и научимся создавать файлы миграций для liquibase, во-первых на SQL, во-вторых с секцией отката, в-третьих эти файлы будут формироваться автоматически. Не верите? Сейчас я всё подробно расскажу.

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

Все команды ниже будут отображены с учетом работы в Linux shell. Для генерации секции файлов миграции нам потребуется pgCodeKeeper, а для формирования секции rollback наличие в системе утилиты sed.

Давайте условимся, что у нас есть две базы данных — dbdev и dbprod, в dbdev мы вносим изменения вручную, а в dbprod изменения попадают с помощью Liquibase.

Я создам в /tmp каталог migration в котором и буду выполнять всю работу, разумеется вы можете использовать тот каталог, который пожелаете. PostgreSQL у меня уже установлен на локальном компьютере, и именно с ним я и буду проводить работу.

Создаём базы данных для работы:

$ mkdir /tmp/migration
$ cd /tmp/migration/
$ createdb dbdev
$ createdb dbprod

Загружаем драйвера JDBC для PostgreSQL, дистрибутивы Liquibase и pgCodeKeeper

$ wget https://jdbc.postgresql.org/download/postgresql-42.1.3.jar
$ wget https://github.com/liquibase/liquibase/releases/download/liquibase-parent-3.4.2/liquibase-3.4.2-bin.tar.gz
$ wget http://pgcodekeeper.ru/cli/release/pgCodeKeeper-cli-3.11.4.201707170702.zip

Разархивируем liquibase и pgcodekeeper в текущий каталог, вы конечно же распаковать их в выделенные каталоги.

$ tar xzvf liquibase-3.4.2-bin.tar.gz
$ unzip pgCodeKeeper-cli-3.11.4.201707170702.zip

В текущем каталоге создайте файл настроек для liquibase — liquibase.properties со следующим содержимым:

driver: org.postgresql.Driver
classpath: ./postgresql-42.1.3.jar
url: jdbc:postgresql:dbprod
username: user
password: topsecret
changeLogFile: db.changelog.xml

Обращаю внимание, что это настройки для Liquibase, т.е. описывайте в нём соединение с БД dbprod, на которую мы будем развертывать наши миграции. Имя пользователя и пароль установите в свои значения, у меня имя пользователя — ags и в дальнейших сообщения вывода команд будет встречаться как раз это имя. В текущем каталоге создаем файл db.changelog.xml со следующим содержимым:




 


Проверяем, готов ли liquibase к работе:

$ ./liquibase status
ags@jdbc:postgresql:dbprod is up to date
Liquibase 'status' Successful

Отлично, половина дела сделано, осталось совсем малость. Проверяем, работает ли pgCodeKeeper.

$ ./pgcodekeeper-cli.sh jdbc:postgresql:dbdev jdbc:postgresql:dbprod

если команда не выдала никакого сообщения — значит всё хорошо. Обратите внимание, если ваш инстанс постгреса настроен на другом хосте или порту или используется доступ по паролю, то вы должны сформировать соответствующую JDBC URL для вашей базы данных. Как правильно его сформировать читаем здесь: jdbc.postgresql.org/documentation/head/connect.html

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

Создадим таблицу в БД dbdev:

[ags@saushkin-ag:/tmp/migration] $ psql dbdev
psql (9.6.3, сервер 9.5.7)
Введите "help", чтобы получить справку.

(ags@[local]:5432) 16:08:43 [dbdev]  =# create table users (id serial primary key, name text);                                                        
CREATE TABLE
Время: 20,708 мс
(ags@[local]:5432) 16:09:16 [dbdev] * =# commit;
COMMIT
Время: 6,913 мс

Проверяем, может ли pgCodeKeeper найти отличия.

$ ./pgcodekeeper-cli.sh jdbc:postgresql:dbdev jdbc:postgresql:dbprod
CREATE SEQUENCE users_id_seq
        START WITH 1
        INCREMENT BY 1
        NO MAXVALUE
        NO MINVALUE
        CACHE 1;

ALTER SEQUENCE users_id_seq OWNER TO ags;

CREATE TABLE users (
        id integer DEFAULT nextval('users_id_seq'::regclass) NOT NULL,
        name text
);

ALTER TABLE users OWNER TO ags;

ALTER TABLE users
        ADD CONSTRAINT users_pkey PRIMARY KEY (id);

ALTER SEQUENCE users_id_seq
        OWNED BY users.id;


Да, всё работает так как и ожидалось. Подготавливаем скрипт создания миграций migrate.sh

#!/bin/bash

FILENAME=${1:-changeset.sql}

# Заголовок файла миграции
echo "--liquibase formatted sql" > $FILENAME
echo "--changeset $USER:$FILENAME" >> $FILENAME
echo "" >> $FILENAME

# Создаем секцию наката
./pgcodekeeper-cli.sh jdbc:postgresql:dbdev jdbc:postgresql:dbprod >> $FILENAME

echo "" >> $FILENAME

# Создаем секцию отката (базы данных идут в обратном порядке)
./pgcodekeeper-cli.sh jdbc:postgresql:dbprod jdbc:postgresql:dbdev | sed -e 's/^/--rollback /' >> $FILENAME

Скрипт принимает один параметр — имя выходного файла, если имя файла не задано, то по умолчанию принимается changeset.sql. Далее формируется заголовок файла SQL, который необходим Liquibase для сохранения информации о выполненных изменениях на целевой БД. Далее идёт формирование собственно файла миграции.

Команда:

./pgcodekeeper-cli.sh jdbc:postgresql:dbdev jdbc:postgresql:dbprod >> $FILENAME

находит различия между базами, формирует файл преобразования структуры объектов БД из dbdev в dbprod и сохраняет в выходном файле.

А команда:

./pgcodekeeper-cli.sh jdbc:postgresql:dbprod jdbc:postgresql:dbdev | sed -e 's/^/--rollback /' >> $FILENAME

ищет различия между этими же базами только в другом направлении, целевой БД теперь становится девелоперская, для того, чтобы можно было выполнить автоматический откат изменений. Секция отката в Liquibase помечается комментариями --rollback.

Проверяем, формирование миграции. Для теста, в качестве выходного файла, я использую /dev/stdout:

$ chmod +x ./migrate.sh
$ ./migrate.sh /dev/stdout 
--liquibase formatted sql
--changeset ags:/dev/stdout

CREATE SEQUENCE users_id_seq
        START WITH 1
        INCREMENT BY 1
        NO MAXVALUE
        NO MINVALUE
        CACHE 1;

ALTER SEQUENCE users_id_seq OWNER TO ags;

CREATE TABLE users (
        id integer DEFAULT nextval('users_id_seq'::regclass) NOT NULL,
        name text
);

ALTER TABLE users OWNER TO ags;

ALTER TABLE users
        ADD CONSTRAINT users_pkey PRIMARY KEY (id);

ALTER SEQUENCE users_id_seq
        OWNED BY users.id;


--rollback ALTER TABLE users
--rollback      DROP CONSTRAINT users_pkey;
--rollback 
--rollback DROP TABLE users;
--rollback 

Отлично, сформирована как секция наката, так и секция отката. А нам не пришлось для этого написать ни одной строки SQL вручную! Вся работа по созданию файла миграции была сделана автоматически.

Формируем реальный файл миграции

$ ./migrate.sh 001_users.sql

Подключаем его к журналу миграций, отредактировав файл db.changelog.xml, добавив в него директиву include с файлом 001_users.sql:




 
    
 



И накатываем изменения на dbprod, перед накатом изменений давайте выставим тег в целевой БД, чтобы мы могли откатиться в дальнейшем.

$ ./liquibase tag 001_before_users
Successfully tagged ags@jdbc:postgresql:dbprod
Liquibase 'tag' Successful

$ ./liquibase migrate
Liquibase Update Successful

Проверяем статус

$ ./liquibase status
ags@jdbc:postgresql:dbprod is up to date
Liquibase 'status' Successful

Откатываемся на состояние перед накатом таблицы

$ ./liquibase rollback 001_before_users
Liquibase Rollback Successful

Проверяем статус повторно

$ ./liquibase status
1 change sets have not been applied to ags@jdbc:postgresql:dbprod
Liquibase 'status' Successful

Возвращаем выполненный предварительно накат

$ ./liquibase migrate
Liquibase Update Successful

Давайте проверим, отличаются ли структуры баз данных сейчас? Теперь, после того как мы «поигрались» с накатами и откатами состояние баз данных dbdev и dbprod должно быть одинаковым. Так ли это?

$ ./pgcodekeeper-cli.sh jdbc:postgresql:dbdev jdbc:postgresql:dbprod
ALTER TABLE databasechangeloglock
        DROP CONSTRAINT pk_databasechangeloglock;

DROP TABLE databasechangeloglock;

DROP TABLE databasechangelog;

pgCodeKeeper говорит, что в dbdev нет двух таблиц — databasechangeloglock и databasechangelog. Эти таблицы были созданы автоматически liquibase и в них он сохраняет информацию о выполненных накатах. Без этих таблиц работа liquibase будет невозможна. Чтобы эти таблицы в дальнейшем не мешали нам при формировании миграций можно или скопировать структуру этих таблиц в девелоперскую базу или использовать возможность списка игнорирования для pgCodeKeeper.

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

$ cat .pgcodekeeperignore 
SHOW ALL
HIDE REGEX "databasechangelog.*"

Теперь, команда

$ ./pgcodekeeper-cli.sh -I .pgcodekeeperignore jdbc:postgresql:dbdev jdbc:postgresql:dbprod

не должна отображать никаких изменений.

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

  1. Вносим изменения в девелоперскую БД
  2. С помощью нашего скрипта формируем миграцию
  3. Инспектируем миграцию и подключаем её в журнал миграций
  4. Деплоим изменения на боевую (тест, стейдж) БД
  5. В случае необходимости, делаем откат

Создание файлов миграций Liquibase теперь стало возможно выполнять автоматически. Миграции описаны на языке SQL и что немаловажно, секция отката создается также без участия человека. Самое сложное что нужно сделать, это придумать имя файла миграции.

PS. У Liquibase есть встроенный механизм формирования чейнджсета различий между двумя БД www.liquibase.org/documentation/diff.html, к сожалению, по своему опыту могу сказать, что он работает не всегда хорошо, заменив этот механизм на код формируемый pgCodeKeeper можно формировать миграции для более сложных изменений в БД.

PPS. pgCodeKeeper распространяется с триальной лицензией на 100 объектов БД, если ваша база содержит больше объектов, свяжитесь с разработчиками (адрес эл. почты и канал Telegram есть на сайте продукта pgcodekeeper.ru ) и вам вышлют лицензию на неограниченное количество объектов БД абсолютно бесплатно.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/333762/


Метки:  

Google планирует представить облачный сервис для квантовых вычислений

Четверг, 20 Июля 2017 г. 11:18 + в цитатник
Google собирается открыть онлайн-доступ к своим квантовым машинам для ученых и исследователей проблем искусственного интеллекта. Этим ИТ-гигант хочет «подстегнуть» разработку новых инструментов для своей технологии. Со временем компания планирует создать мощный облачный сервис с использованием квантовых компьютеров.

/ фото Spiros Vathis CC

По данным Bloomberg, ИТ-гигант сформировал новую лабораторию Embryonic Quantum Data Center, а также готовит проект ProjectQ — open source проект по написанию программного обеспечения для квантовых компьютеров. Иными словами, Google уже рассматривает возможность практического применения квантовых вычислений.

«В компании довольно прямо говорят о создании квантового «железа» и запуске сервиса облачных вычислений на его основе», — отмечает Питер МакМахон (Peter McMahon), специалист по квантовым вычислениям из университета Стэнфорда.

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

Ученые надеются, что полнофункциональные квантовые компьютеры найдут применение в самых разных областях. Технический сотрудник Sandia National Laboratories Робин Блюм-Коут (Robin Blume-Kohout) считает, что квантовые вычисления помогут в улучшении работы солнечных панелей, создании медикаментов и даже удобрений.

Впервые в Google задумались о квантовых вычислениях еще в 2013 году, когда компания купила один из ранних квантовых компьютеров D-Wave. А в 2014 ИТ-гигант уже заявил о начале разработки собственных квантовых машин. По заявлениям разработчиков, система сможет доказать свое превосходство над классическими компьютерами уже к концу этого года.

Однако Google не единственная компания, занимающаяся созданием квантовых компьютеров. IBM уже предлагает доступ к специализированной платформе квантовых вычислений, выведя 16-кубитный квантовый компьютер онлайн. Также компания намерена за следующие 5 лет создать 50-кубитную квантовую систему, которая должна будет «обойти» все современные классические компьютеры. Еще IBM ведет работу над созданием универсального квантового компьютера для корпоративного сегмента. В этой сфере свой интерес имеет и компания Microsoft.

Профессор Сет Ллойд (Seth Lloyd) из Массачусетского технологического института отмечает, что сегодня квантовые стартапы «растут как грибы». Один из них — Rigetti Computing, собравший более $69 млн на создание оборудования и программного обеспечения для квантового компьютера. Его основатель Чад Ригетти (Chad Rigetti) видит, что технология становится такой же горячей, как и ИИ, однако убежден — все еще только начинается.

«Несмотря ни на что эта отрасль еще находится в зачаточном состоянии, — сказал он. — Пока что никто не создал квантовый компьютер, который действительно работает».

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

P.S. Еще несколько материалов из нашего блога:

Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/333688/


Метки:  

Поиск сообщений в rss_rss_hh_new
Страницы: 1437 ... 1058 1057 [1056] 1055 1054 ..
.. 1 Календарь