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

Поиск сообщений в 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 ленты.
По всем вопросам о работе данного сервиса обращаться со страницы контактной информации.

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

Canvas — почти как SVG

Понедельник, 03 Июля 2017 г. 16:03 + в цитатник

Ссылка на канвас ниндзю в конце.

Конкретно речь пойдёт об элементе Path и как его реализовать на canvas.

Как мы помним path в svg умеет рисовать кривые безье, сплайны из этих кривых, а так же окружности. У канваса в этом плане возможностей куда меньше, так что будем работать с ним. Для начала научимся рисовать кривые. В svg как и в canvas кривые ограничены лишь 3-мя степенями, это сделано ради оптимизации, мы же будем использовать каноничное уравнение для их вычисления, так что кривые у нас будут любого порядка.

Ничего сложного в расчёте кривых нет. Ниже код функции, которая возвращает массив вида [x,y] — это точка на кривой. Входные параметры для функции: массив контрольных точек и коэффициент смещения относительно начала кривой. Смещение — это значение в процентах от 0% до 100% (0 — начало кривой, 100 — конец), надеюсь этот момент понятен.

// так же понадобится найти факториал
function factorial (number) {
        var result = 1;
        while(number){
            result *= number--;
        }
        return result;
}

function getPointOnCurve (shift, points) {
        var result = [0,0];
        var powerOfCurve = points.length - 1;
        shift = shift/100;
        for(var i = 0;points[i];i++){
            var polynom = (factorial(powerOfCurve)/(factorial(i)*factorial(powerOfCurve - i))) *
                Math.pow(shift,i) *
                Math.pow(1-shift,powerOfCurve - i);
            result[0] += points[i][0] * polynom;
            result[1] += points[i][1] * polynom;
        }
        return result;
}

getPointOnCurve(60, [[0,0],[100,0],[100,100]]); // -> [84, 36]

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

Следующая остановка — сплайны.

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

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

[[0,0],[100,0],[100,100,true],[200,100],[200,0]]

Точки с флагом true — опорные.

Код функции
function getCenterToPointDistance (coordinates){
    return Math.sqrt(Math.pow(coordinates[0],2) + Math.pow(coordinates[1],2));
}

function getLengthOfCurve (points, step) {
    step = step || 1;
    var result = 0;
    var lastPoint = points[0];
    for(var sift = 0;sift <= 100;sift += step){
        var coord = getPointOnCurve(sift,points);
        result += getCenterToPointDistance([
            coord[0] - lastPoint[0],
            coord[1] - lastPoint[1]
        ]);
        lastPoint = coord;
    }
    return result;
};

function getMapOfSpline (points, step) {
    var map = [[]];
    var index = 0;
    for(var i = 0;points[i];i++){
        var curvePointsCount = map[index].length;
        map[index][+curvePointsCount] = points[i];
        if(points[i][2] && i != points.length - 1){
            map[index] = getLengthOfCurve(map[index],step);
            index++;
            map[index] = [points[i]];
        }
    }
    map[index] = getLengthOfCurve(map[index],step);
    return map;
};

function getPointOnSpline (shift, points, services) {
    var shiftLength = services.length / 100 * shift;
    if(shift >= 100){
        shiftLength = services.length;
    }
    var counter = 0;
    var lastControlPoint = 0;
    var controlPointsCounter = 0;
    var checkedCurve = [];
    for(; 
        services.map[lastControlPoint] && 
        counter + services.map[lastControlPoint] < shiftLength; 
        lastControlPoint++
    ){
        counter += services.map[lastControlPoint];
    }
    for(
        var pointIndex = 0; 
        points[pointIndex] && controlPointsCounter <= lastControlPoint; 
        pointIndex++
    ){
        if(points[pointIndex][2] === true){
            controlPointsCounter++;
        }
        if(controlPointsCounter >= lastControlPoint){
            checkedCurve.push(points[pointIndex]);
        }
    }
    return getPointOnCurve(
        (shiftLength - counter) / (services.map[lastControlPoint] / 100),
        checkedCurve
    );
};

var points = [[0,0],[100,0],[100,100,true],[200,100],[200,0]];
var services = {};
services.map = getMapOfSpline(points);

services.length= 0;
for(var key in services.map){
    services.length += services.map[key];
}

getPointOnSpline(60, points, services); // -> [136, 95.(9)]


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

Для дуги в path SVG предусматривает 7 параметров, что на мой взгляд излишне, вот эти параметры:
A rx ry x-axis-rotation large-arc-flag sweep-flag x y

Расшифровка:

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

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

Для дуги нам нужно знать:
  • полуоси эллипса
  • углы начала и конца дуги
  • наклон эллипса


Всего 5 параметров.

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

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

[
    [x1,y1],
    [x2,y2],
    [x3,y3],
    [radiusX,radiusY,startRadian,endRadian,tilt], // tilt - optional
    [x5,y5],
    ...
    [xN,yN]
]

Код
function getPointOnEllipse (radiusX,radiusY,shift,tilt,centerX,centerY){
        tilt    = tilt || 0;
        tilt    *= -1;
        centerX = centerX || 0;
        centerY = centerY || 0;

        var x1  = radiusX*Math.cos(+shift),
            y1  = radiusY*Math.sin(+shift),
            x2  = x1 * Math.cos(tilt) + y1 * Math.sin(tilt),
            y2  = -x1 * Math.sin(tilt) + y1 * Math.cos(tilt);

        return [x2 + centerX,y2 + centerY];
 }

function getLengthOfEllipticArc (radiusX, radiusY, startRadian, endRadian, step) {
    step = step || 1;
    var length = 0;
    var lastPoint = getPointOnEllipse(radiusX,radiusY,startRadian);
    var radianPercent = (endRadian - startRadian) / 100;
    for(var i = 0;i<=100;i+=step){
        var radian = startRadian + radianPercent * i;
        var point = getPointOnEllipse(radiusX,radiusY,radian);
        length += getCenterToPointDistance([point[0]-lastPoint[0],point[1]-lastPoint[1]]);
        lastPoint = point;
    }
    return length;
};

function getMapOfPath (points, step) {
    var map = [[]];
    var index = 0;
    var lastPoint = [];
    for(var i = 0;points[i];i++){
        var point = points[i];
        if(point.length > 3){
            map[index] = getLengthOfEllipticArc(point[0], point[1], point[2], point[3], step);
            if(!points[i+1]){continue}
            var centerOfArc = getPointOnEllipse(point[0], point[1], point[2] + Math.PI, point[4], lastPoint[0], lastPoint[1]);
            var endOfArc = getPointOnEllipse(point[0], point[1], point[3], point[4], centerOfArc[0], centerOfArc[1]);
            index++;
            map[index] = [endOfArc];
            lastPoint = endOfArc;
            continue;
        }
        map[index].push(point);
        if(point[2] === true || (points[i+1] && points[i+1].length > 3)){
            map[index] = getLengthOfCurve(map[index],step);
            index++;
            map[index] = [point];
        }
        lastPoint = point;
    }
    if(typeof map[index] !== 'number'){map[index] = getLengthOfCurve(map[index],step);}
    return map;
};

function getPointOnPath (shift, points, services) {
    var shiftLength = services.length / 100 * shift;
    if(shift >= 100){
        shiftLength = services.length;
    }
    var counter = 0;
    var lastControlPoint = 0;
    var controlPointsCounter = 0;
    var checkedCurve = [];
    for(; services.map[lastControlPoint] && counter + services.map[lastControlPoint] < shiftLength; lastControlPoint++){
        counter += services.map[lastControlPoint];
    }
    var lastPoint = [];
    for(var pointIndex = 0; points[pointIndex] && controlPointsCounter <= lastControlPoint; pointIndex++){
        var point = points[pointIndex];
        if(point.length > 3){
            var centerOfArc = getPointOnEllipse(point[0], point[1], point[2] + Math.PI, point[4], lastPoint[0], lastPoint[1]);
            if(controlPointsCounter === lastControlPoint){
                var percent = (shiftLength - counter) / (services.map[lastControlPoint] / 100);
                var resultRadian = point[2] + ((point[3] - point[2])/100*percent);
                return getPointOnEllipse(point[0], point[1], resultRadian, point[4], centerOfArc[0], centerOfArc[1]);
            }
            lastPoint = getPointOnEllipse(point[0], point[1], point[3], point[4], centerOfArc[0], centerOfArc[1]);
            controlPointsCounter++;
            if(controlPointsCounter === lastControlPoint){
                checkedCurve.push(lastPoint);
            }
            continue
        }
        if(point[2] === true || (points[pointIndex+1] && points[pointIndex+1].length > 3)){
            controlPointsCounter++;
        }
        if(controlPointsCounter >= lastControlPoint){
            checkedCurve.push(point);
        }
        lastPoint = point;
    }
    return getPointOnCurve(
        (shiftLength - counter) / (services.map[lastControlPoint] / 100),
        checkedCurve
    );
};

var points = [[0,0],[100,0],[100,100],[20,20,0,Math.PI],[200,100],[200,0]];
var services = {};
services.map = getMapOfPath(points);

services.length= 0;
for(var key in services.map){
    services.length += services.map[key];
}

getPointOnPath(60, points, services); // -> [96.495, 98.036]


Ну вот теперь мы крутые чуваки, много чего умеем.
Ссылка на примеры вот.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/332192/


Метки:  

Сказ о том, как Android-разработчика спамеры задолбали, и что и из этого вышло

Понедельник, 03 Июля 2017 г. 15:49 + в цитатник
Привет, Хабр. Экономить воду нужно, это знают все. Дело это полезное. И чтобы граждан простимулировать в этом добром деле, у нас повсеместно ставят водосчетчики. Причем без счетчика платишь в несколько раз больше.

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

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



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

Часть первая — Воинственная


Вот поставили вы себе счётчики, опломбировали и подали информацию в службу Единого Окна. Живёте себе спокойно, передаёте данные по показаниям, и в ус не дуете. И тут через год или два раздаётся звонок, от Единого Расчетного Центра/Управы/Городского Центра Метрологии/Самой Управляющей Компанией (нужное подчеркнуть). В трубке воинственная барышня/юноша сообщают, что срок службы счётчика вашего истёк — и быстрее ставьте новый – и когда наш мастер приедет?

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

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

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

Диалог со спамером - У меня есть сосед
(С) -спамер, (Я) — Я
(С) – (и даже не поздоровался, хамло) РосКосмосВодоНаноКанал имени Святой Метрологии. Вы должны поменять счетчики на воду! У вас заканчивается срок службы!
(Я) – (в голосе паника) Ой! Что же делать!
(С) – (довольный, рыбка-то попалась) Мы пришлем вам мастера. Когда сможете принять?
(Я) – А что мастер сделает?
(С) – Он поменяет вам счетчики на новые!
(Я) – А зачем менять то?
(С) – (сердится) Потому, что так положено! Говорите адрес!
(Я) – Погодите. У меня сосед, он профессиональный строитель. Он мне сказал, что детальку меняют, и не надо счетчик снимать!
(С) – (уже с душой) Ваш сосед ничего не понимает! Это же метрология!
(Я) — (праведный гнев) Вы обманываете меня! Мой сосед ПРОФЕССИОНАЛЬНЫЙ строитель!!! Он лучше всех знает!!!
(С) – (раздражение и злость, смешалось в этом голоске) Ах так!!! Ну тогда вам пришлют письменное извещение!!! И платить вы будете по повышенному тарифу!!! (гудки....)

Часть вторая – Размышления.


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

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

Хорошо, заведу-ка я таблицу в Excel, табличку и буду записывать всё там. Но опять же, не потащу я компьютер в ванную и туалет, чтобы записать показания. Иначе мы опять возвращаемся к бумажке и ручке.

ОК. Буду использовать планшет. Но всё что мог на тот момент предоставить Маркет – либо платное, либо не отвечающее моему представлению о прекрасном. Да и в конце-то концов я Android – разработчик, или где?

Диалог со спамером - Подумай о душе, Мария
(С) – Добрый день, мы хотим предложить вам перейти на новый интернет, от лучшего провайдера. У нас самый выгодный…
(Я) – Простите, представьтесь пожалуйста.
(С) – Ээээ… Мария. Так вот…
(Я) – (торжественно) Мария! Я хочу поговорить с вами о Боге!
(С) — …
(Я) – Вы хотите поговорить со мной о Боге? Мария, я не слышу вас!
(С) — … Мы вообще-то…
(делает попытку вернуть все в русло первоначальной беседы)
(С) – Послушайте, мы хотим предложить вам выгодные условия…
(Я) – (добавив, щепотку праведного гнева) Мария! О чем вы?!!! Что может быть важнее разговора о Боге?!!!
(С) – Как понимаю, в не хотите разговаривать. (гудки...)

Часть третья – Подготовительная


Итак, составим план, в котором перечислив всё, что нам нужно.

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

Второе – удобный инструмент для занесения ежемесячных показаний, а также какой-то простейший инструмент анализа.

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

Четвёртое – если понравится в использовании, не быть жадиной и поделиться с миром.

Диалог со спамером - Ориентируемся на личность
(С) – Добрый день (и называет, гад, мое имя). Меня зовут Виталий. Я хочу предложить вам выгодное предложение, по управлению вашими капиталами.
(Я) – Виталька!!! Это ты?!!! Сколько лет!!! Сколько зим!!!
(С) – (слегка обалдев) Я…
(Я) – Блин!!! Я ж твоего звонка ждал!!! Как сам?!!! Как жена?! Как дети?!!!
(С) – (охреневая глубже) Я вообще-то не женат…
(Я) – Ну что ж ты балбес. Мужик без жены, как гусеница без дерева!
(С) – Ну, я как понимаю вас достали со звонками. До свидания…

Часть четвёртая – Эксперименты.


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


Старый дизайн

Главное, что приложение работало. Велась статистика (кстати пригодилось, когда пришлось пободаться с Мосэнерго).

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

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

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

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

Поменял полностью дизайн:


Новый дизайн

Добавил настройки, и возможность сохранить/загрузить данные в/из файла:



Перерисовал иконки в векторе, исправил кучу глюков и ошибок, добавил счётчик тепла, и написал инструкцию. В общем, почти с нуля переделал.

Диалог со спамером - Говорящий с Богами
(С) – Добрый день. Я говорю с (мое имя). Мы из банка-партнёра от банка «Тинкофф». Вы хотите взять кредит?
(Я) – Нет
(С) – Можно узнать почему?
(Я) – Боги запретили мне делать это.
(С) – (пауза....) Простите, что?
(Я) – Боги запретили мне брать кредиты.
(С) – А может всё-таки…
(Я) – (возмущённо) Вы хотите поспорить с Богами?!!!
(С) – Ээээ… нет… До свидания…

Часть 5. Трюки разработчика


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

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


Диалог для ввода данных

Всё было нормально для обычных, однотарифных счётчиков, но для многотарифных началась ерунда. Вот так я победил это. Заводим адаптер (amountList)

ListView lvAmounts = (ListView)mView.findViewById(R.id.lv_newAmount_Amount);        insertAmountAdapter insertAmountAdapter = new insertAmountAdapter(getActivity(), amountList);        
lvAmounts.setAdapter(insertAmountAdapter);

Класс адаптера (также есть класс следящий за введёнными показаниями AmountTextWatcher):

Класс адаптера
public class insertAmountAdapter extends BaseAdapter {

    Context mContext;
    ArrayList amountList;
    LayoutInflater mLayoutInflater;
    EditText etAmount, etTariff;
    TextView tvTariffTitle;


    public insertAmountAdapter(Context mContext, ArrayList amountList) {
        this.mContext = mContext;
        this.amountList = amountList;
        mLayoutInflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    @Override
    public int getCount() {
        return amountList.size();
    }

    @Override
    public Object getItem(int position) {
        return amountList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View view = convertView;
        if(view == null){
            view = mLayoutInflater.inflate(R.layout.item_insertamount, parent, false);

            etTariff = (EditText)view.findViewById(R.id.et_amount_tariffInfo);
            etTariff.addTextChangedListener(new AmountTextWatcher(view, etTariff, amountList));

            etAmount = (EditText)view.findViewById(R.id.et_amount_Amount);
            etAmount.addTextChangedListener(new AmountTextWatcher(view, etAmount, amountList));
        }
        etAmount.setTag(position);
        etAmount.setText(String.valueOf(amountList.get(position).getAmount()));
        etAmount.setFilters(new InputFilter[]{new DigitalFilter(3)});

        tvTariffTitle = (TextView)view.findViewById(R.id.tv_amount_tariffTitle);
        tvTariffTitle.setText(amountList.get(position).getTariffTitle()+", "+amountList.get(position).getUnit());

        etTariff.setTag(position);

        etTariff.setText(amountList.get(position).getTariffValue());
        etTariff.setFilters(new InputFilter[]{new DigitalFilter(2)});
        return view;
    }
}

class AmountTextWatcher implements TextWatcher {

    private View view;
    private EditText editText;
    private ArrayList amountList;

    public AmountTextWatcher(View view, EditText editText, ArrayList amountList) {
        this.view = view;
        this.editText = editText;
        this.amountList = amountList;
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {

    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {

    }

    @Override
    public void afterTextChanged(Editable s) {
        if(editText.equals(view.findViewById(R.id.et_amount_Amount))){
            amountList.get(Integer.parseInt(editText.getTag().toString())).setAmount(Double.valueOf(s.toString().isEmpty()?"0":s.toString()));
        } else if(editText.equals(view.findViewById(R.id.et_amount_tariffInfo))){
            amountList.get(Integer.parseInt(editText.getTag().toString())).setTariffValue(s.toString().isEmpty()?"0":s.toString());
        }
        return;
    }
}


Как видите, отслеживание рабочей строки идёт, через setTag и getTag.

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

Создаём инструкцию в strings.xml:

Строковая переменная

        



Добавляем картинки, под такими же именами, которые прописаны в инструкции, в папку drawables (у меня это: add_btn_instruction.png и open_btn_instruction.png).

В требуемом месте создаём строку, TextView и ImageGetter:

String instructionHTML = getString(R.string.instructionText);
TextView tvInstruction = (TextView)findViewById(R.id.tv_instruction);
tvInstruction.setText(Html.fromHtml(instructionHTML, htmlImageGetter, null));
Html.ImageGetter htmlImageGetter = new Html.ImageGetter() {
        public Drawable getDrawable(String source) {
            int resId = getResources().getIdentifier(source, "drawable", getPackageName());
            Drawable ret = InstructionActivity.this.getResources().getDrawable(resId);
            ret.setBounds(0, 0, ret.getIntrinsicWidth(), ret.getIntrinsicHeight());
            return ret;
        }
    };

Диалог со спамером - Время спать, и все в кровать
(С) – Это квартира или фирма?!
(Я) – В чем вопрос?
(С) – Мы проводим социологический опрос…
(Я) – Женщина, вы вообще на часы смотрите? Время уже десять вечера!
(С) – (праведное возмущение) Ну если вы спать хотите, то выключать телефон надо! (гудки...)

Часть 6. Реклама и все-все-все.


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

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

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

Вот собственно и вся история написания моего самого первого приложения.

Диалог со спамером - Немного Булгакова
(С) – Здравствуйте. Как мне удобно обращаться к вам?
(Я) – Зови меня, Добрый Человек, Добрый Человек.
(гудки....)

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

https://habrahabr.ru/post/332190/


Метки:  

Три дня как все кассы в стране должны стать онлайн (на самом деле нет)

Понедельник, 03 Июля 2017 г. 15:33 + в цитатник

Теперь так делать нельзя

Старая логика такая: внутри кассы есть некая постоянная write-only память, в которую касса пишет каждый пробитый чек. Это реализовано в виде ЭКЛЗ — электронной контрольной защищённой ленты, которая уже давно не лента, а плата. Это устройство требует много геморроя — там целый квест с заменой, заведением новой кассы и так далее.

В цифровом мире такие проблемы очень давно решаются сертификатами. Именно эту плюшку даёт нам ФЗ-54, который описывает онлайн-отправку чеков. Он же запрещает с 1 февраля 2017 заводить новые кассы старого типа, а с 1 июля 2017 (то есть уже) — вообще использовать такие кассы. То есть если в феврале планировалось открытие нового магазина, то в нём уже должна быть онлайн-касса. С 1 июля 2017 все кассы должны быть онлайн.

Мелкие бизнесы (ИП, ЕНВД и патентное налогообложение) могли перетоптаться до 1 июля вообще без кассы, но потом даже для торговых автоматов они стали обязательными. На самом деле это нереально круто для страны, но…

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


Как теперь выстроен процесс передачи данных о чеке


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

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



На каждом бумажном носителе чека есть QR-код, который можно отсканировать и получить себе этот чек в личный кабинет Госуслуг или в приложение налоговой службы.

Вместо сканирования можно вбить параметры с чека руками:



И получить вот такой результат:



Если в течение 30 дней касса пробивает, но не передаёт чеки в онлайн, она автоматически блокируется (и потом налагается штраф). Блокировка в наших модулях реализована на уровне прошивки устройства.

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

Апгрейд


Чтобы всё это заработало, нужно:
  1. Обновить кассы аппаратно
  2. Получить ЭЦП для налоговой, чтобы регистрировать кассу
  3. Выбрать оператора фискальных данных.
  4. Снять кассу с учёта и поставить её на учёт.

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

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


Модуль связи — касса отдаёт данные через Ethernet. Есть похожие выходные интерфейсы с 3G-модемом.

У нас «Штрихи». Соответственно, было два варианта — либо подключить к уже имеющейся кассе модуль доработки с блоком ФН и комплектом активации ККТ ШТРИХ-М-02Ф (17 тысяч рублей), либо купить новую модель кассы — от 27 тысяч рублей. На новые модели мы заменили только старые кассы. К «Штриху» вопроса нет, они крутые и очень грамотно сработали.

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

Немного прошлого


Объяснять новый ФЗ начали в сентябре, наши спецы 1С ездили на конференцию. На тот момент на стендах конференции присутствовали новые кассы, но был только предзаказ, модули не продавались. Сроки рассказали приблизительно. Чёткой рабочей инструкции и тестового экземпляра Штрих не давал — но не потому что они злые гады, а потому что, по всей видимости, не пускали железо в серию до появления окончательных уточнений по реализации закона.

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

Мы решили сделать всё заранее к февралю, потому что февраль и март — это много выездных ярмарок, мы не хотели заморачиваться с новыми ЭКЛЗ на короткий срок до замены, плюс надо было иметь кассы для открытия точек в феврале. Опять же, не было уверенности, что 1С обновит всё как надо, и мы сможем за две недели взять и перепрыгнуть сразу.

ИТ-команда ещё в январские праздники поставила кассу в офиса, и начала торговать играми сама себе. Было много доработок — например, чтобы чек нормально отправлялся в ОФД, чтобы 1С сам проверял соединение и предупреждал продавцов, если чеки не грузятся онлайн.

Нужно было обновить чеки, в т.ч. добавить печать QR-кода и имя кассира. Оно теперь обязательно. И вот за такое как на картинке сверху (снято в Волгограде) теперь будут бить ногами, если, конечно, в паспорте не так же.

По разработке и тестам — 3 месяца мы медленно изобретали велосипеды, потому что внятных best practice не было. Нормально кассы начали продавать только с этого года.

Наше время


В апреле-мае мы не могли в нужном количестве закупиться устройствами модернизации, потому что их тупо нет, все ушли в продуктовые сети. Например, у Пятёрочки и Перекрёстка тоже «Штрихи-М». Полтора месяца назад примерно на семинаре «ONLINE РЕВОЛЮЦИЯ: все чеки в облаках» сказали, что зарегистрированных кассовых аппаратов в стране более миллиона, а перешло на новую схему только 250 тысяч (это ещё без учёта тех парней, которые раньше не били чеки, а теперь должны будут торговать с кассой).

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

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


То есть если есть предзаказ (договор поставки и совершённая оплата) на новые кассы, но их ещё не привезли, а в старых не кончилась ЭКЛЗ — можно печатать старые чеки, пока не приедут кассы.

Штрафы


  • Старая касса, но чек выбит — 10 тысяч рублей.
  • Чек не отправлен покупателю — 10 тысяч рублей.
  • Нет кассы, а она должна быть — 30 тысяч рублей.

И вот очень хороший сайт с FAQ с кучей деталей.

Резюме


Это всё очень круто, потому что мы в стране наконец-то отказались от устаревшего носителя, плюс получили возможность проверять всё онлайн. Да, проблемы при внедрении есть, но в целом — оно того стоит.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/332188/


Метки:  

4 популярные ошибки в дизайне визиток

Понедельник, 03 Июля 2017 г. 15:30 + в цитатник
В этой статье мы наглядно рассмотрим самые частые ошибки, которые совершаются при создании визиток, и научим вас, как их избежать. Эта статья будет полезна не только дизайнерам, но и тем, кто планирует завести или уже имеет собственные визитки.

Проблемы с версткой


Задача верстки — правильно расставить акценты на визитке. В случае с плохой версткой, получатель не поймет, куда смотреть и что читать в первую очередь.

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

image

image

Плохое обращение со шрифтами


Вот краткий список принципов, которыми можно руководствоваться при работе со шрифтами:

  1. Важно правильно подобрать сочетающиеся друг с другом шрифты, поэтому лучше не использовать больше двух шрифтов на одной визитке — меньше шанс промахнуться;
  2. Эффекты к шрифтам неприменимы (за очень редким исключением);
  3. Деформировать (растягивать) шрифт нельзя — буквы должны выглядеть так, как они задуманы.

image

image

Проблемы с читаемостью


В погоне за количеством «ДИЗАЙНА» на квадратный сантиметр на визитке не следует применять как можно больше доступных в фотошопе эффектов.

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

image

image

Неправильное оформление визитки


Под финальным пунктом объединены часто встречающиеся ошибки на этапе наполнения визитки:

1. Оформление ссылок. В первую очередь, избавьтесь от «https://». Эта часть не обязательна для ввода и выглядит как мусор на пути к полезной информации. Также постарайтесь, чтобы «id» ваших сообществ и страниц выглядели как «/logomachine», а не «/id32754081»;

2. Оформление номера телефона. Мобильные имеют формат «8 911 123 44 55», а городские — «111 22 33». В скобках пишутся только необязательные для набора цифры (код города, например);

3. Оформление почты. Почта на @rambler.ru, а также «zaychik777» в качестве логина — плохая идея (или “под запретом”). Лучше всего — использовать почту на домене своей компании;

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

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

image

image

Как итог:


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

https://habrahabr.ru/post/332186/


Метки:  

Как обеспечить безопасность в эпоху AI и облачных платформ. Интервью с профессором Малковым

Понедельник, 03 Июля 2017 г. 15:15 + в цитатник
В начале XX века аптеки мира были завалены «чудодейственными» препаратами. Женщины с удовольствие посещали спа-радио-центры, дети пили радиоактивную воду. И лишь когда через несколько лет у многих выпали волосы, зубы или появились еще более серьезные «побочки», пришло понимание, что новинка не такая уж и безопасная. Сегодня риски, связанные с облачными технологиями и искусственным интеллектом, еще даже не осознаются. Но их уже должны учитывать разработчики, создавая программные продукты для облачных платформ и интернета вещей. О том, как сделать виртуальные среды безопасными, чего ожидать от искусственного интеллекта, и как при этом остаться программистом, рассказал Константин Малков, технический директор 5nine Software. Этим интервью мы продолжаем серию публикаций об облачных технологиях Microsoft. В первой мы сравнили «облака» с «новым электричеством» и пришли к оптимистичным выводам. Читать далее

https://habrahabr.ru/post/332010/


Метки:  

Как быстро удалить множество строк из большой базы в MySQL

Понедельник, 03 Июля 2017 г. 14:25 + в цитатник
Как известно, все системные администраторы делятся на две категории. Те, кто уже делают бэкапы и те, кто ещё нет.

Подобно им, администраторы БД также делятся на две категории, те, кто уже запускал процедуру удаления на большой БД с типом таблиц InnoDB, и те, кому это ещё предстоит.



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

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

Как сделать так, чтобы не было мучительно больно? Добро пожаловать под кат!

1. Если вы УЖЕ запустили удаление и теперь хотите приблизительно оценить, сколько уже сделано и сколько ещё осталось, используйте SHOW ENGINE INNODB STATUS;
Получите длинный вывод. Ищите в нём вашу команду и смотрите undo log entries, это и будет количество уже обработанных записей.

---TRANSACTION 1 4141054098, ACTIVE 191816 sec, OS thread id 36004918272 updating or deleting, thread declared inside InnoDB 84
mysql tables in use 1, locked 1
686063 lock struct(s), heap size 88520688, undo log entries 229144332
MySQL thread id 56087872, query id 2202164550 1.1.1.2 database updating
DELETE
FROM table
WHERE UNIX_TIMESTAMP(moment) < 1498712335 - 365 * 86400
AND UNIX_TIMESTAMP(moment) > 0


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

2. Если вы только планируете начать удаление, используйте LIMIT.
Количество записей подбирается эмпирически, скажем на не особо мощном сервере я использовал LIMIT 5000, на более мощном LIMIT 50000.
Начните с небольших значений и увеличивайте их по необходимости.

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

3. Используйте pt-archiver из комплекта percona-tools.

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

Пример:
pt-archiver --source h=127.0.0.1,D=build4,t=b_iblock_element \
    --optimize s --purge --where 'TAGS LIKE "%САПР%"' \
    --limit 1000 --commit-each --progress 500 --charset "CP1251"
В принципе, ключи довольно очевидны, тем не менее, пройдусь по ним:
--source — описывает подключение. Хост, база и таблица. При необходимости можно дописать логин и пароль (в примере я использую креды из ~/.my.cnf);
--optimize — оптимизирует исходную таблицу, либо ту, в которую переносятся данные. Поскольку в данном случае я не переношу, а удаляю данные, оптимизирую именно исходную (s) таблицу. В принципе, делать это необязательно;
--purge — изначально утилита предназначена для переноса данных в другую таблицу (или в файл). Но можно и просто удалять строки;
--where — обычное SQL-условие, по которому будут отбираться строки для удаления;
--limit 1000 — обрабатывать за раз 1000 строк (можно больше, зависит от производительности вашего сервера);
--commit-each — делать коммит после количества строк, указанного в --limit;
--progress 500 — выводить прогресс каждые 500 строк (опять же, имеет смысл подобрать этот параметр индивидуально);
--charset — кодировка. Если будет использоваться только ASCII-кодировка, проще указать --no-check-charset. Отдельно упомяну, что необходимо чтобы локаль консоли совпадала с указанным charset'ом, иначе ошибка не выведется, но и строки обработаны не будут.

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

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

https://habrahabr.ru/post/332182/


Метки:  

Как искать людей в числе Пи и причем тут Python

Понедельник, 03 Июля 2017 г. 13:59 + в цитатник
Коллеги, привет! Недавно передо мной встала задача розыграть бесплатные места на нашем курсе по Python разработке. Вообще говоря, разыграть пару бесплатных мест — это просто. Можно сделать буквально в две строчки, если уже есть готовый список участников:
emails = pandas.read_csv("emails.csv")
emails.sample(NUM_WINNERS, random_state=SEED)

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

Хотелось бы сделать робота, который сам выбирает реальные шары из корзины, распознает номера и отправляет в чатик по API (это весело!), но это не очень быстро. Решение должно быть бессмысленным, беспощадным и не особо времязатратным. Так в голову пришло число Пи. Вообще у нас с коллегами есть inside joke про идеальный Пи-архиватор. Суть проста: чтобы сжать любые данные нужно лишь найти то место в числе Пи, где они начинаются и запомнить позицию (+длину, конечно). Непревзойденное сжатие! Получается, что также можно искать устаников, в частности их emai’ы в числе Пи, и считать победителем тех, кто найдется первым. Если хотите сразу к сути, то можно тут же перейти в notebook.
Непродолжительный поиск в интернетах выдал множество решений по генерации цифр числа Пи, в том числе на Python (также в процессе находится этот прекрасный ресурс: www.angio.net/pi, — не могу не поделиться). Я, честно говоря, не знал, что человечество до такой степени обеспокоено этой проблемой. Самые популярные решения: Gauss–Legendre algorithm, Chudnovsky algorithm, BBP formula.
Я же выбрал тот вариант, который позволяет генерировать цифры числа бесконечно, а не выдает заранее определенное количество цифр
def pi_digits():
    """generator for digits of pi"""
    q, r, t, k, n, l = 1, 0, 1, 1, 3, 3
    while True:
        if 4 * q + r - t < n * t:
            yield n
            q, r, t, k, n, l = (10*q, 10*(r-n*t), t, k, (10*(3*q+r))/t-10*n, l)
        else:
            q, r, t, k, n, l = (q*k, (2*q+r)*l, t*l, k+1, (q*(7*k+2)+r*l)/(t*l), l+2)

Это Spigot algorithm товарища Гиббонcа, который вычисляет цифры числа Пи в потоковом режиме. Все подробности есть в research paper, которая особенно понравится любителям Haskell.
Остается только связать email’ы участников с какими-то числами. Сначала я хотел брать md5 от почты и потом делить по модулю, чтобы получить число не больше заданной длины. Но это как-то не очень случайно, тем более что можно подобрать и зарегистрировать почту, которая окажется достаточно близко к началу числа Пи. Поэтому расчехляем старый добрый ПГСЧ:
np.random.seed(SEED)
emails["num"] = np.random.randint(10 ** (NUM_DIGITS - 1), 10 ** NUM_DIGITS - 1, size=len(emails))

Длина чисел задается заранее, чем длиннее число, тем, соответственно, сложнее найти его в Пи. Осталось только написать функцию поиска.
class _Num(object):
    def __init__(self, n):
        self.n = n
        self.s = str(n)
        self.p = 0 # pointer in number string representation
        self.l = len(self.s)
 
    def move_p(self, d):
        if d == self.s[self.p]:
            self.p += 1
        else:
            self.p = 0
 
    
def find_nums_in_pi(nums, first_n=None):
    MAX_POS = 10 ** 6
    pi_gen = pi_digits()
    first_n = first_n if first_n is not None else len(nums)
    _nums = [_Num(n) for n in nums]
    nums_pos = {}
    for pos in itertools.count():
        if pos % 1000 == 0:
            print "Current Pi position: %s. Nums found: %s" % (pos, len(nums_pos))
        if pos == MAX_POS:
            raise RuntimeError("Circuit breaker!")
        d = str(pi_gen.next())
        for cur_num in _nums:
            cur_num.move_p(d)
            # whole number found
            if cur_num.p == cur_num.l:
                nums_pos[cur_num.n] = pos - cur_num.l + 1
                # found enough numbers
                if len(nums_pos) == first_n:
                    return nums_pos
                # create new search array without found number
                _nums = [num for num in _nums if num.n != cur_num.n]
                break

Тут я решил пойти простым путем. Кастую числа в строки, устанавливаю указатили в их начала, генерирую цифры Пи, если данная цифра есть в данном числе, то сдвигаю указатель вперед, если нет, то возвращаю назад. Когда число найдено, запоминаю его и позицию, удаляю из массива поиска. На всякий случай добавляю ограничитель, чтобы не ходить дальше миллионной цифры и делаю какое-то логирование прогресса.
Найти двух победителей, email’ам которых сопоставлены шестизначные числа, заняло около минуты на моей машине. Профит!
Как водится, “в бою” все пошло не совсем так гладко. Розыгрыш запускался в live режиме, с компа одновременно транслировалось видео, он немного поднапрягся и поиск занял уже 5 минут, вместо одной. Но чтобы еще более накалить обстановку я ненароком (честно!) перезапустил в notebook’е выполнение cell’а с поиском чисел после его успешного выполнения в первый раз. А notebook ошибок не прощает, старые значения не запоминает, выполняет ячейки синхронно. Нервы натянулись, как канаты. К счастью, все закончилось хорошо, победители были выявлены, награждены, справедливость восторжествовала. Слава роботам, слава числу Пи!
Кстати, впереди еще один розыгрыш мест на курсе 5 июля в 20-00. Хотите прикоснуться к прекрасному? Проходите тест и регистрируйтесь на День открытых дверей, время есть!
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/332180/


Метки:  

Как компьютерные профи раскалывают хакеров

Понедельник, 03 Июля 2017 г. 13:52 + в цитатник


В последнее время, на фоне всевозможных вирусов Wanna Cry и Petya, тема кибербезопасности не сходит с первых полос СМИ. В этой связи показалась примечательной заметка найденная на одном из заморских сайтов. Под катом рассказ Роджера Краймса о том, как одни профессионалы доставляют неприятности другим и наоборот. Суть статьи сводится к тому, что если хотите познакомиться с действительно толковым хакером, поговорите со специалистом по защите от кибератак. Эти талантливые люди каждый день работают над тем, чтобы совершать киберпреступления становилось труднее и наименее прибыльно. Кстати, с удивлением узнал, что любимое развлечение специалистов по информационной безопасности, «ломать» компы соседей на профессиональных конференциях.

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



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

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

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

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

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

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

Командный файл должен был переформатировать его жесткий диск и уничтожить на нем всё, если бы Рик перезагрузил компьютер. Я предварительно «закоментил» губительные строки своего сценария, с тем, чтобы программа была пока-что безвредной. Но удали я буквально три знака (то есть rem), и этот пока еще безвредный сценарий превратился бы в погибельный, по крайней мере, для его компьютера.

DDoS-атака тут же прекратилась. Присмиревший хакер вернулся в чат-канал и недоверчиво спросил: «Старик, а как ты это сделал?» Наконец-то он начал разговаривать человеческим языком, когда с него сошла вся эта фальшивая развязность. Я ответил: «Рик, есть много хакеров лучше тебя. Бросай свое вредное занятие и направь свои таланты на что-то хорошее. Проводи больше времени со своей красавицей женой. Когда-нибудь ты замутишь не с тем парнем или не с тем агентством. Это тебе был предупредительный звоночек».

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



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

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

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


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

Попробуй ограбить настоящий банк, и есть шанс, что возьмешь меньше 8000 долларов и, возможно, будешь пойман (по последней статистике ФБР 55% банковских грабителей было опознано и арестовано за 2014 год) и сядешь в тюрьму на годы. Негативный фактор риска/награды является причиной того, что в США происходит менее 4000 ограблений банков в год.

Сравните это с киберпреступлениями. Каждый месяц в ФБР поступает более 22 000 заявлений о киберпреступлениях, и, скорее всего, будет совершаться еще большее число преступлений. Средний заявленный ущерб составляет почти 6500 долларов, а из 269 000 заявлений только 1500 были переданы в правоохранительные органы. Хотя большинство последних ежегодных отчетов ФБР не включали в себя сведений об обвинительных приговорах, отчет 2010 года с похожим количеством жалоб и случаев указывает только на шесть судебных приговоров. Это значит, что на каждые 50 635 жертв приходится только один осужденный киберпреступник. И это только случаи, заявленные в ФБР.

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

Секрет хакерства


Секрет хакерства в том, что здесь нет секрета. Хакерство — это как обычная профессия, сантехник или электрик, где надо научиться владеть какими-то инструментами или методами, а остальное — лишь практика и упорство. Большинство хакеров находят недостающие программные патчи, ошибки в конфигурации, уязвимости или применяют социальную инженерию. Если это сработает хоть раз, оно будет эффектным тысячи раз. Это настолько легко и срабатывает настолько регулярно, что многие профессиональные пентестеры (им платят за разрешенное хакерство) бросают эту работу через несколько лет, потому что она больше не вызывает у них интереса.

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

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

Люди, взламывающие хакеров


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

Брайан Кребс


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

Брюс Шнайер


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

Доктор Дороти Деннинг


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

Кевин Митник


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

Майкл Ховард


Ховард с друзьями создали метод безопасного написания программного обеспечения известный, как Цикл разработки безопасного программного обеспечения (SDL, Security Development Lifecycle), которым повсеместно пользуются тысячи компаний, чтобы сократить количество багов и уязвимостей в продуктах. Недавние критики этого метода теперь пользуются им, увидев, насколько хорошо он работает в течение многих лет.

Джоанна Рутковская


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

Ланс Спитцнер


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

Кормак Херли


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

Майкл Дубинский


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

Все эти специалисты — часть огромной армии «белых» хакеров, создающих с каждым годом всё больше и больше трудностей для хакерства. Критическая масса растёт, и в течение следующего десятилетия онлайн-киберпреступления станут таким же редким явлением, как ограбление банка. Они будут совершаться, но их будет всё меньше, за них будет гораздо легче наказать. Кстати, а кого из русских «белых» хакеров знаете вы?
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/332178/


Метки:  

Конкурс по программированию: JSDash

Понедельник, 03 Июля 2017 г. 13:25 + в цитатник
Компания Hola объявляет долгожданный летний конкурс по программированию! Победителей ожидают призы:

  1. Первое место: 3000 USD.
  2. Второе место: 2000 USD.
  3. Третье место: 1000 USD.
  4. Если Вы отправите кому-то ссылку на этот конкурс, поставив наш адрес в CC, и этот человек займёт призовое место, Вы получите половину суммы приза (разумеется, не в ущерб награде победителя). За одного победителя такую награду может получить только один человек — тот, кто отправил ссылку первым.

Авторы интересных решений будут приглашены на собеседования.



Правила



Условия конкурса на английском языке размещены на GitHub. Ниже — перевод на русский язык.

  • Отправляйте решения с помощью этой формы. По электронной почте решения не принимаются.
  • Решения принимаются до 31 июля 2017, 23:59:59 UTC.
  • Предварительные результаты будут опубликованы 7 августа 2017, а окончательное объявление победителей — 15 августа 2017.
  • Можно отправлять решения многократно, но от каждого участника будет рассмотрено только самое последнее решение, отправленное до окончания срока приёма работ.
  • Для тестирования мы будем использовать Node.js v8.1.3 (текущая версия на момент публикации). Можно использовать любые возможности языка, поддерживаемые интерпретатором в стандартной конфигурации.
  • Весь код решения должен находиться в единственном файла на JS.
  • Решение должно быть на JS. Если Вы предпочитаете CoffeeScript или подобные языки, необходимо оттранслировать решение в JS перед отправкой.
  • Если Ваш JS-файл — продукт генерации, минификации и/или компиляции с других языков вроде CoffeeScript, пожалуйста, приложите архив с исходниками, а также, желательно, описанием подхода. Содержимое этого архива будет опубликовано, но мы не будем его тестировать.
  • Нельзя загружать никаких модулей, даже тех, что входят в стандартный комплект Node.js.
  • Нам нужно знать Ваше полное имя, но если Вы хотите, мы опубликуем вместо него псевдоним. Мы сохраним Ваш адрес электронной почты в тайне.
  • Задавайте вопросы по условию задачи в комментариях к этой публикации или по электронной почте.

JSDash


Поиграем в текстовую игру! Несомненно, вы распознаете в ней клон классической видеоигры, впервые изданной в 1984 году.

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

Мы рекомендуем запустить скрипт game/jsdash.js и сыграть в игру несколько раз перед тем, как читать дальше. (Примечание: мы разрабатывали и тестировали игру под xterm в Linux. В других системах может работать, а может и не работать.)

Игра


Клавишами-стрелочками можно перемещаться в четырёх направлениях. Зелёная буква A — это вы. Можно перемещаться через пустое пространство или землю (:), толкать камни (O) по горизонтали в пустое пространство и собирать алмазы (*). Через кирпичи (+) и сталь (#) пройти невозможно. Камни и алмазы падают, когда остаются без опоры, а также скатываются вбок друг с друга и с кирпичей. Падающие предметы убивают игрока. Бабочки (анимация /|\-) взрываются при соприкосновении с игроком, от удара падающим предметом, а также будучи запертыми без возможности передвижения. Взрыв бабочки поглощает любые материалы, кроме стали, и может убить игрока. После взрыва образуются алмазы, которые можно собрать.

За каждый взятый алмаз начисляется 1 очко. Если собрать 3 алмаза с промежутками не более 2 секунд, в дополнение к очкам за каждый из них, начисляется 3 призовых очка. Если продолжать быстро собирать алмазы, не делая промежутков длиннее 2 секунд, то начисляется 5 очков после пятого алмаза, 7 очков после седьмого (в дополнение ко всем предыдущим премиям), и так далее для каждого простого числа. За убитую бабочку начисляется 10 очков при условии, что игрока не убило взрывом.

Ограничение времени игры — 2 минуты. Можно прервать игру раньше, нажав Q, Esc или Ctrl-C; набранные очки при этом не теряются. Клавиша P позволяет приостановить игру.

Остаток времени, очки и сообщения о призовых цепочках (hot streak) отображаются в строке состояния под игровым полем.

Механика нашей игры в целом соответствует образцу 1984 года (она известна благодаря подробному описанию на фан-сайте Boulder Dash), однако для простоты мы решили использовать не все типы объектов. Самое большие отличия — описанная выше система начисления очков и то, что на уровне нет выхода. Цель игры — набрать как можно больше очков, прежде чем игра закончится смертью персонажа или по истечению времени. Если вас интересуют подробности игровой механики, читайте исходный код модуля game.js.

Решения


Решение представляет собой модуль Node.js без зависимостей. Модуль должен экспортировать одну функцию:
play(screen)

Игра загрузит модуль и вызовет функцию play один раз, передав начальное состояние игры в качестве параметра screen. Оно представляет собой массив строк, по одной на каждую строку экрана с верхней до нижней, включая строку состояния. Строки будут содержать в точности то, что вы видите на экране, только без раскраски в ANSI-цвета (игру можно увидеть в таком режиме на консоли, если запустить её с параметром --no-color). Функция play должна быть генератором. Чтобы сделать ход, она должна сгенерировать (yield) значение 'u', 'd', 'r' или 'l' для шага вверх, вниз, вправо или влево соответственно. Ещё можно сгенерировать 'q' или просто завершить работу генератора (return), чтобы окончить игру досрочно (набранные очки при этом не теряются). Если сгенерировать любое другое значение, это означает ход «остаться на месте». Пытаться идти в направлении, в котором двигаться невозможно (например, в стену) не запрещено: персонаж просто останется на месте. После каждого yield содержимое массива screen обновляется, и ваш код может снова его проанализировать для принятия дальнейших решений.

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

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

Состояние игры обновляется раз в 100 мс. Если функция play будет генерировать команды быстрее, то персонаж будет двигаться 10 раз в секунду. После каждой команды генератор будет блокироваться на инструкции yield до конца рануда длиной в 100 мс. Если функция «думает» над ходом дольше, чем 100 мс, она начинает пропускать ходы, и тогда персонаж будет оставаться на месте в те раунды, когда функция не успела сделать ход. В этом случае генератор также не увидит некоторых промежуточных состояний экрана. Например, если скрипт «задумается» на 250 мс между двумя инструкциями yield, то не увидит двух состояний экрана, а персонаж останется неподвижным на два раунда; таким образом, будут упущены две возможности сделать ход, которые были бы, если бы программа работала быстрее. После этого генератор будет заблокирован на 50 мс до конца раунда, и сгенерированная им команда будет выполнена.

Очень простой пример работающего скрипта искусственного интеллекта приведён в файле game/example.js. Каждый раунд он находит все возможные ходы (направления, в которых по соседству с позицией игрока находятся пустое пространство, земля, камень, который можно сдвинуть, или алмаз) и выбирает один из них случайным образом. Обычно этот скрипт убивается вскоре после начала игры.

Тестирование


Скрипт jsdash.js, который мы предоставляем на GitHub, — это не только интерактивная игра, но и мощный инструмент для тестирования. Запустите его с параметром --help, чтобы узнать обо всех его возможностях.

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

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

jsdash.js --ai=submission.js --log=log.json

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

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

jsdash.js --replay=log.json

Отправка решений


Для отправки решений пользуйтесь формой на нашем сайте. По электронной почте решения не принимаются!

Поскольку код решений часто бывает сгенерированным, минимизированным или оттранслированным с другого языка, форма содержит также поле для отправки архива с исходными тестами. Если код сгенерирован, включите туда генератор; если он минимизирован, включите исходную версию; если код переведён с CoffeeScript или другого языка, включите код на том языке, на котором он написан. Желательно также включить в архив файл README с кратким описанием подхода к решению (по-английски). Архив должен быть в формате tar.gz, tar.bz2 или zip. Содержимое архива будет опубликовано, но не будет протестировано (мы тестируем только JS-файл, который вы отправляете вне архива).

Максимальный размер JS-файла установлен в 64 МиБ. Это произвольно выбранная цифра, которая существует в основном для того, чтобы чьё-нибудь «решение» одномоментно не заполнило нам диск. Если ваше решение правда больше 64 МиБ, напишите нам, и мы увеличим ограничение.

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

Желаем удачи всем участникам!
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/332176/


[Из песочницы] Обновление document.title в фоновой вкладке

Понедельник, 03 Июля 2017 г. 13:00 + в цитатник
Предположим, что у нас есть сайт по продаже билетов, на котором мы хотим в document.title показывать цену, чтобы увеличить удовлетворённость пользователей и дать им знать, что в какой вкладке у них открыто (т.к. мы не знаем, будет ли меняться место отправления/прибытия, дата, любимый перевозчик и так далее, а цена, напротив, для различных комбинаций практически всегда разная). При этом мы знаем, что, начиная с версии 56, Chrome проводит политику блокировки фоновых вкладок. Что это означает для данного функционала?

Согласно документации, rAF (requestAnimationFrame) обычно вызывается 60 раз в секунду. Для экранов, у которых частота обновления выше, это значение будет также выше (хотя вы можете и не замечать это глазом).

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

Проведём эксперимент. В коде под спойлером по requestAnimationFrame простейшим образом обновляется тайтл:

requestAnimationFrame страница




  
  


tab




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

Chrome


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

IE11
Чтобы не ходить в настройки и не разрешать выполнение скриптов на локальных сайтах, воспользуемся комбинацией команд http-server и lt -p 8080:



* Edge работает аналогично

Safari


Firefox

, где e10s — это Electrolysis

Результат — только Firefox выполняет rAF в фоновой вкладке. Казалось бы удивительно, что даже IE11 не выполняет rAF в фоне, однако, Per the documentation, Chrome does not call requestAnimationFrame() when a page is in the background. This behavior has been in place since 2011. С 2011, Карл!, что означает, что таким поведением никого не удивить. Не удивить, даже если в бэкграунде играет музыка (через или что бы то ни было ещё), rAF, в фоне, при любых условиях, в любом браузере, отличным от FF, выполняться не будет.

Поэтому, отвечая на изначальный вопрос «Как показать цену в тайтле», ответ достаточно прост — показывать её не в момент отображения компонента, а в момент получения данных из API. Вторым решением был бы вынос из функции, которая используется для анимации страницы при возврате данных с API (большой лоадер на весь экран красиво убираем просто)), функции-инициализатора. К сожалению, так сложилось, что таких функций почему-то больше чем одна, поэтому этот вариант влечёт за собой большие перестановки и от него решено было отказаться. К слову, setTimeout/setInterval, выполняются корректно, через них возможен третий вариант решения проблемы.

На этом стори можно доделывать и закрывать, а теперь перейдём к тому, что происходит на самом деле, используя исходный код requestAnimationFrame из WebKit:

int Document::requestAnimationFrame(Ref&& callback)
{
    if (!m_scriptedAnimationController) {
#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
        m_scriptedAnimationController = ScriptedAnimationController::create(*this, page() ? page()->chrome().displayID() : 0);
#else
        m_scriptedAnimationController = ScriptedAnimationController::create(*this, 0);
#endif
        // It's possible that the Page may have suspended scripted animations before
        // we were created. We need to make sure that we don't start up the animation
        // controller on a background tab, for example.
        if (!page() || page()->scriptedAnimationsSuspended())
            m_scriptedAnimationController->suspend();

        if (page() && page()->isLowPowerModeEnabled())
            m_scriptedAnimationController->addThrottlingReason(ScriptedAnimationController::ThrottlingReason::LowPowerMode);

        if (!topOrigin().canAccess(securityOrigin()) && !hasHadUserInteraction())
            m_scriptedAnimationController->addThrottlingReason(ScriptedAnimationController::ThrottlingReason::NonInteractedCrossOriginFrame);
    }

    return m_scriptedAnimationController->registerCallback(WTFMove(callback));
}

Первый if довольно понятен, подробнее по suspendScriptedAnimations и setIsVisibleInternal.

Во втором if, значение функции isLowPowerModeEnabled, у каждой ОС будет браться из разных источников; в iOS, вероятно, оно берётся из _didReceiveLowPowerModeChange.

Третий if наиболее интересен; topOrigin это просто SecurityOrigin документа верхнего уровня; сам метод находится здесь, в комментариях в этом методе достаточно подробно расписано, что в нём происходит. Этот метод возвращает true, если два скрипта с разных origin могут общаться между собой (на чтение или на запись). В то же время, у пользователя остаётся место для манёвра при помощи NonInteractedCrossOriginFrame.

Таким образом, webkit-браузеры будут получать блокировку rAF каждый раз, когда они заходят в один из трёх if.

Вернёмся к Firefox. Преобразуем исходную функцию, меняющую заголовок страницы, на следующую:

Меняем тайтл на каждый animationFrame
    requestAnimationFrame(function handler() {
      document.title += 'R'
      requestAnimationFrame(handler);
    });


Результат


Как можно заметить, в Firefox/Gecko всё происходит немного иначе, чем в webkit. Если найти реализацию request_animation_frame, то можно заметить, что:

  1. // TODO: Should tick animation only when document is visible — что означает, что когда-нибудь поведение будет соответствовать поведению остальных браузеров, поэтому на том, что происходит сейчас, можно особо не зацикливаться.
  2. Существует is_faking_animation_frames где оказывается, что ребята из Gecko, в случае, если у вас много фейковых анимаций, выбрасывают вас на FakeRequestAnimationFrameCallback.

Даже не знаю, кто круче.

Хорошие ссылки:

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

https://habrahabr.ru/post/332174/


Метки:  

Многопользовательская игра на Go через telnet

Понедельник, 03 Июля 2017 г. 12:53 + в цитатник
Всем привет! Меня зовут Олег и я SRE. В какой-то момент мне захотелось улучшить свои навыки программирования на Go и написать маленькую многопользовательскую игру.

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

Вот что получилось:

image

Выбор технологий


Telnet


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

telnet towel.blinkenlights.nl

Но, почему telnet, спросите Вы? Ведь netcat намного круче и современнее добавят другие. Не все знают, но telnet — это не только утилита для установления TCP-соединения. Это целый протокол, который позволяет, например, отправлять на сервер введённые данные без нажатия Enter (line feed ANSII).

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

Как вариант можно было использовать

stty -icanon && nc  

но это, прямо скажем, костыль.

Go


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

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

Game design


Игровой процесс


Игра представляет собой мультиплеер до 5 человек в раунде. Если количество игроков будет меньше — оставшиеся слоты будут представлены ботами.

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

Система повреждений


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

Скорость может варьироваться. При ударе она сбрасывается до 1. При безаварийной езде через некоторое время она увеличивается до 5.

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

if player.Car.Borders.intersects(&opponent.Car.Borders) {
	switch player.Car.Borders.nextTo(&opponent.Car.Borders, 0) {
	case LEFT:
		// Игрок слева
		switch player.Car.Direction {
		...
		case RIGHT:
			// Удар сзади
			player.Health -= DAMAGE_BACK * (maxSpeed - player.Car.Speed)
			...
	case RIGHT:
		// Игрок справа
		switch player.Car.Direction {
		case RIGHT:
			// Удар спереди
			player.Health -= DAMAGE_FRONT * player.Car.Speed
			...
	...
}

То есть если игрок А двигался со скоростью 4 и его догнал игрок Б со скоростью 5, игрок А потеряет 2*(5-4) = 2. Однако, атакующий игрок потеряет 4*5 = 20.

Самым же сильным повреждением окажется удар сбоку DAMAGE_SIDE = 6 и может доходить до 24.

Разработка


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

Исходный код находится на github, но давайте пробежимся по основным моментам:

Telnet


Как я уже упомянул, нам требуется поддержка telnet-протокола. Для этого на стороне приложения нам требуется «поздороваться» с клиентом при помощи последовательности байт:

telnetOptions := []byte{
	255, 253, 34, // IAC DO LINEMODE
	255, 250, 34, 1, 0, 255, 240, // IAC SB LINEMODE MODE 0 IAC SE
	255, 251, 1, // IAC WILL ECHO
}
_, err := conn.Write(telnetOptions)

и считать ответ (начинается с 250).

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

Данные взяты из RFC854.

Раунды


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

type Round struct {
	Players         []Player
	FrameBuffer     Symbols
	...
}

Если недостаточно игроков — добавляем ботов.

Каналы


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

func (p *Player) checkBestRoundForPlayer(compileRoundChannel chan Round) {
	foundRoundForUser := false
	for i := 0; i < len(compileRoundChannel); i++ {
		select {
		case r := <-compileRoundChannel:
			// Есть ожидающий раунд
			if len(r.Players) < maxPlayersPerRound && !p.searchDuplicateName(&r) {
				...
				r.Players = append(r.Players, *p)
				compileRoundChannel <- r
				foundRoundForUser = true
				break
			} else {
				compileRoundChannel <- r
			}
		default:
		}
	}
	if !foundRoundForUser {
		// Создаём новый раунд
		...
		r := Round{...}
		r.Players = append(r.Players, *p)
		compileRoundChannel <- r
	}
}

Заметьте, что не требуется использование Mutex, несмотря на то, что данная функция выполняется в отдельных Goroutine. Каналы в Go не позволят Вам вычитать объект несколько раз, так что модификация одного объекта исключена в этом случае.

FrameBuffer


Все игроки без исключения должны получать полную информацию о происходящем в игре. Так давайте же отправлять всем одно и то же изображение. Изначально тип FrameBuffer был просто []byte, но в какой-то момент мы решили добавить Emoji, чтобы сделать игру красочнее. А поскольку каждый такой символ занимает больше 1го байта — по факту Symbols — это массив массивов байт.

type Symbol struct {
	Color int
	Char  []byte
}
type Symbols []Symbol

Итак, вот примерный алгоритм генерации содержимого FrameBuffer:

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

Боты


Искусственного интеллекта тут, конечно же нет. Но каким-то базовым действиям боты обучены:

  • Преследовать игроков (не ботов)
  • Если рядом есть бонус — собрать
  • Если на пути препятствие (другой игрок) — объехать

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

Визуализация


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



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

Одно из основных кредо Go тут полностью соблюдено:

Don't communicate by sharing memory, share memory by communicating.

Как поиграть?


К сожалению, на Windows какие-то проблемы с emoji в терминале. У меня не было достаточно мотивации разбираться, так как я пользуюсь MacOS и Linux. Но если кто-то знает режим совместимости или ещё что-то — буду рад совету.

Для всех остальных:

telnet protury.info 4242


Итог


  • Goroutine — отличный инструмент XXI века. Реализация параллельного исполнения функций не несёт практически никаких накладных расходов для разработчика
  • Визуализация Goroutine — красивая абстракция. К сожалению, не очень хорошо работает на приложениях, чуть сложнее «Hello, World!» и завязана на старой версии Go 1.5 в контейнере
  • Даже древние протоколы, такие как Telnet, могут удивлять своей продуманностью в 2017 году
  • Go — прекрасно подходит не только для веб-приложений. Он ещё более хорош для написания backend-сервисов
  • Даже в текстовом режиме терминала можно отображать красочные объекты — нужно лишь использовать символы из расширенного ASCII или Emoji

Бонус


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



Поиграть:

telnet protury.info 4243

Спасибо


Хотелось бы сказать спасибо компании InnoGames, которая предоставляет InnoDay — целый день в неделю, когда можно заниматься подобными вещами, также моим коллегам, которые мне всячески помогали — Павел Усов и Kajetan Staszkiewicz. А также всем, кто прочел до конца!
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/330512/


Метки:  

Цифровой датчик температуры TSic: адреса, пароли, явки

Понедельник, 03 Июля 2017 г. 12:10 + в цитатник

Как мы унифицируем аналитическую деятельность в CUSTIS

Понедельник, 03 Июля 2017 г. 12:02 + в цитатник

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


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


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


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

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


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


Начинаем работу


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


  1. Методический трек. Создаем методическую основу для проведения работ на разных проектах. По итогам испытаний и внедрения вносим в результаты этого трека корректировки.
  2. Испытания. Проверяем разработанные методы на реальных проектах. Собрав качественные и количественные показатели, возвращаемся к методическому треку и дорабатываем методики.
  3. Внедрение. Принимаем успешно апробированные наработки и делаем их обязательными для всех аналитиков. Это этап, когда методика становится официальной практикой для всей компании.

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


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

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


Определяем типы проектов


Мы выделили четыре типа проектов в компании, на которых нам важно уметь перемещать аналитиков:


  1. Доработка существующих систем  — корректировки, выделяемые в отдельные проекты. Трудозатраты: от 200 до 1500 человеко-часов. Длительность: до полугода. К таким проектам относится, например, разработка нескольких визуальных форм с отчетами, алгоритмов их заполнения, нескольких таблиц базы данных, фильтрации, выгрузки данных из отчетов в xlsx, pdf.
  2. Новый проект (автоматизация «с нуля») — разработка автоматизированных систем, когда у клиента нет «предыдущего» решения либо нужно полностью заменить существующую систему. Трудозатраты: от 1500 до 10 000 человеко-часов. Длительность: от полугода до года.
  3. Анализ request for information (RFI), предпроект, ведение бизнес-тем — бизнес-анализ процессов заказчиков. Реализация таких проектов может привести к запуску проектов автоматизации с нуля либо доработок существующих систем.
  4. Реинжиниринг существующих систем — полная переработка имеющейся системы.

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


Описываем концепты аналитической деятельности


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


Схема состоит из следующих элементов:


  • голубые прямоугольники — концепты;
  • пунктирные прямоугольники — типы диаграмм;
  • прямоугольники со сплошным контуром — папки в шаблоне проекта в Enterprise Architect, где содержатся диаграммы.


Подробно остановимся на основных концептах.


  1. Процесс — бизнес-процесс заказчика. Он может включать как автоматизируемые, так и не автоматизируемые функции в рамках разрабатываемой системы.
    • Описывается в нотации BPMN. Объекты на такой диаграмме могут быть типа Business Process — для диаграммы верхнего уровня и Activity — для диаграммы, описывающей процесс до элементарных операций.
    • Описание должно быть шире, чем автоматизируемый процесс, чтобы при чтении диаграммы был понятен контекст.
  2. Роль — роль пользователя в системе или организационная единица.
    • Роль, исполняющая процесс или операцию, визуализируется на BPMN-диаграмме с помощью Pool и Lane, а на диаграмме Use Case — с помощью Actor.
  3. Операции — операции, выполняемые в рамках локального процесса (локальные операции), или используемые в других процессах (глобальные).
    • Создаются на BPMN-диаграммах элементом Activity.
  4. Автоматизируемая операция — элементарная операция, неделимая в рамках разрабатываемой системы.
    • На BPMN-диаграммах обозначается элементом типа Activity. Для него нужно устанавливать тип выполнения операции Manual, Script, User. Manual означает, что перация выполняется пользователем в нформационной системе, Script — операция выполняется внутри системы, User — пользователи выполняют действия вручную. При описании бизнес-процессов для функций первых двух типов необходимо создавать требования для их выполнения.
  5. Информационный ландшафт — все системы и подсистемы, которые задействованы в рамках бизнес-процесса, и передаваемые между ними данные.
    • При описании используется диаграмма потоков данных.
  6. Объект данных — класс объектов реального мира.
    • Создается на диаграммах классов в нотации UML.
  7. Автоматизируемая задача — задача, сформулированная заказчиком либо аналитиком.
    • Отображается элементом Feature. Он присутствует на BPMN- и Use Case-диаграммах. На BPMN-диаграммах он связывается с операциями, на Use Case —с элементами типа Use Case. Таким образом получается связь между бизнес-моделью и автоматизируемыми задачами.
  8. Функция — описание поведения системы, когда она взаимодействует с кем-то или чем-то. Описание может совпадать с тем, как сформулирована автоматизируемая задача, или обобщать несколько задач.
    • Отображается на Use Case-диаграммах элементами типа Use Case. Они состоят из шагов — атомарных неделимых действий. К функциям привязываются элементы типа Requirement.
  9. Требование — условие, которое должно быть удовлетворено.
    • Отображается элементом Requirement. Может присутствовать на диаграммах трех типов: BPMN, Use Case, диаграммах требований.
    • На диаграмме требований можно создавать иерархию требований, задавать в объектах название и описание. Для приоритизации требований устанавливается модальность: может, должен, обязан.
  10. Таблица — таблица базы данных.
    • На ER-диаграммах отображаются не только таблицы, но и  связи между ними. Несколько таблиц могут быть связаны с несколькими классами реализации.
  11. Класс — классы объектов реализации, которые создает разработчик при проектировании.
    • Классы реализации отображаются на диаграмме классов в нотации UML.
  12. GUI — описание пользовательского интерфейса.
    • Создается на диаграмме типа Dialog Wireframe Diagram. Обязательные элементы диаграммы: Use Case и макет экранной формы, факультативные: компонент, класс, таблица.
  13. Компонент — это часть системы, выполняющая какую-то функцию.
    • Компонентную диаграмму создают на этапе проектирования системы архитекторы или разработчики, чтобы отразить ее состав.

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


Выбираем аналитические инструменты


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


Наша компания много лет использовала гибкие методики разработки DDD (Domain Driven Design) [7] и инструменты Wiki [6]. Мы опирались на этот опыт и искали новые рыночные методики и инструменты аналитической деятельности.


Мы выписали возможные кейсы использования инструмента, опробовали их на нескольких проектах [9], пообщались с коллегами из других компаний и в итоге остановили выбор на Enterprise Architect.


Для нас были критичными такие параметры, как:


  • поддержка нотации BPMN и UML, ArchiMate 3.0;
  • ведение версионности проектов и диаграмм;
  • функции экспорта и импорта моделей;
  • выгрузки документации на основе диаграмм без привлечения разработчиков для создания шаблонов выгрузок документов;
  • возможность коллективно работать с диаграммами;
  • низкая стоимость и гибкая лицензионная политика;
  • наличие действующего сообщества пользователей и разработчиков.

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


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


Разрабатываем шаблон проекта в Enterprise Architect


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


Существует несколько вариантов описаний требований. Узнать о них подробнее вы можете из материалов, указанных в списке литературы в конце статьи [1–4]. Мы постарались взять только варианты, необходимые для решения наших задач, и оставили те артефакты, которые используют в работе два и более человек в проекте с учетом жизненного цикла разработки системы.


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


Набор артефактов в шаблоне меняется в зависимости от типа проекта.


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


  1. Доработка существующих систем.
  2. Новый проект (автоматизация «с нуля»).
  3. Анализ request for information (RFI), предпроект, ведение бизнес-тем.
  4. Реинжиниринг существующих систем.

Заключение


Еще раз напомню, для чего все мы здесь сегодня собрались.


Представленный методический трек — часть большой работы по унификации аналитической деятельности в компании CUSTIS. На момент написания статьи мы уже испытали методику на некоторых типах проектов.


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


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


На проектах по доработке существующих и разработке новых систем время создания аналитических артефактов «по-новому» оказалось меньше времени их разработки «по-старому» на 25–40%.


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


Это продемонстрировано на диаграмме:



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


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


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


Полезная литература


  1. К. Вигерс. Разработка требований к программному обеспечению. 2004.
  2. А. Левенчук. Системноинженерное мышление.
  3. Jacobson, I. Spence, K. Bittner. Use-Case 2.0: The Guide to Succeeding with Use Cases
  4. An Introduction to the ArchiMate 2 Modeling Language
  5. ArchiMate 3.0 Specification
  6. М. Цепков. Модель системы — архитектура для Agile-разработки (презентация с выступления на Agile Days, 4–5 марта 2011).
  7. М. Цепков. Domain Driven Design: модель вместо требования (презентация с выступления на ЛАФ, 25–26 июня 2011).
  8. М. Цепков. Как выбрать для проекта практики проектирования и работы с требованиями (презентация с выступления на Analyst Days, 21–22 апреля 2017).
  9. П. Музыка. Практика применения Enterprise Architect и T4-шаблонов для разработки системы на Microsoft SQL Server (презентация с выступления на Desktop UI & Business Applications, 11 апреля 2015).
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/332018/


Метки:  

[Из песочницы] Три года успешного предоставления услуг публичного сервиса аренды виртуальных машин с Apache CloudStack

Понедельник, 03 Июля 2017 г. 11:57 + в цитатник
В середине 2014 года мы в приняли решение о необходимости переноса услуг публичного сервиса аренды виртуальных машин (далее сервис VPS) с платформы OpenQRM, которая была выбрана на тот момент без должного анализа потребностей клиентов и не отвечала требованиям как к управляемости так и к философии поведения (надо сказать, что разработчики OpenQRM вообще странно подошли к разработке, создав продукт из кучи bash-скриптов, кода на PHP и кучи костылей). В общем, наши пользователи были несчастливы, сервис был так себе и приносил скорее убытки, чем прибыль. Необходимо отметить, что наша дочерняя компания, которая как раз оказывает операторские услуги — небольшая региональная компания и мы не рассматривали создание большого сервиса VPS в тот момент, а основной задачей виделось переход на стабильный и надежный продукт, который бы отвечал следующим требованиям:

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

Размер инфраструктуры не планировался большим — на тот момент мы рассчитывали использовать 512 — 1024 ГБ RAM, 128 — 256 ядер Xeon E5-2670, 10 — 20 ТБ хранилища, 200+ виртуальных машин. Сервис предполагал предоставление виртуальных машин с непосредственным присвоением публичных IPv4, о поддержке IPv6 речь не шла. В качестве технологии виртуализации мы ориентировались на KVM. Хранилище — классическое NFSv3.

Мы провели сравнительный анализ (читайте — попробовали развернуть по мануалам) несколько продуктов — Apache CloudStack, OpenStack, Eucalyptus и выбрали Apache CloudStack (далее ACS) для предоставления услуг. Мы не рассматривали для использования системы без API. Сейчас уже достаточно сложно ретроспективно восстановить процесс выбора, могу лишь заметить, что функционирующую инфраструктуру с использованием ACS мы получили за 1-2 дня. На тот момент это был ACS версии 4.3, который мы до сих пор и используем в данном облаке (обновление до текущих версий не имеет смысла, поскольку инфраструктура стабильна, адекватно реагирует на добавление и замену различных ее частей и позволяет обеспечивать потребности пользователей). В момент написания статьи к выпуску планируется ACS 4.10, данный релиз включает не так много изменений, которые предоставляют новую функциональность. Тут необходимо сделать небольшое отступление — ACS предоставляет большое количество различных сервисов, конечным выбором которых получается то или иное облако — можно с балансировкой нагрузки или без, с использованием NAT или прямым назначением IP, с внешними шлюзами безопасности или без поддержки безопасности и т.п. В общем, может оказаться, что в рамках одних топологий развертывания, гипервизоров, хранилищ, сетевых топологий почти нет изменений между релизами 4.3 и 4.10, в то время как в рамках других топологий этих изменений может быть существенное количество.

Мы используем самый простой вариант развертывания — публичное облако с общим адресным пространством без специальных сетевых услуг (это называется ACS с базовыми зонами (basic zones) без групп безопасности (security groups)). В рамках данной модели развертывания что-то новое изобрести достаточно сложно, поэтому в рамках ACS 4.10 мы ждем только поддержку IPv6.

Дело в том, что ACS часто используется для предоставления комплексных виртуальных услуг и развивается в данном направлении быстрее (это так называемые продвинутые зоны (advanced zones)), поэтому для продвинутых зон поддержка IPv6 существует достаточно давно, а для базовых зон появляется только сейчас. В том случае, если облако будет использоваться для предоставления услуг крупным клиентам в B2B или просто как приватное облако для внедрения в организации, то необходимо смотреть какие возможности требуются и, возможно, что с релиза 4.3 до 4.10 произошли какие-то существенные изменения в наборе возможностей. Мы в настоящий момент не видим в рамках нашего бизнеса предоставлять региональным клиентам такие услуги (точнее, они не готовы их покупать или мы не умеем их продавать), поэтому ACS с базовыми зонами — наше все.

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

Доступность


Итак, начнем с аптайма — у нас есть серверы с аптаймом более 1 года, никаких нестабильных моментов из-за которых ACS уходит “в пике” за три года не обнаружено. Подавляющее количество поломок системы происходило из-за проблем с электроснабжением. За время эксплуатации компенсацию за нарушение SLA 99.9% мы производили 1 раз.

Виртуальный маршрутизатор


Самый плохой, сложный, непрозрачный компонент ACS — виртуальный маршрутизатор. Роль его заключается в предоставлении услуг DHCP, прямой и обратной зоны DNS, маршрутизации, балансировке, статическом NAT, поддержки паролей и ssh-ключей шаблонов VM (cloud-init), пользовательских данных. В нашем облаке он используется только для DHCP, прямой и обратной зоны DNS, поддержки паролей и ssh-ключей шаблонов VM (cloud-init), пользовательских данных. Данный компонент может быть отказоустойчивым, но в рамках нашего развертывания это не имеет большого смысла, поскольку ACS автоматически поднимает его при аварии и на функциональность это не влияет.

Если бы мы использовали продвинутые зоны с нетривиальными сетевыми функциями, то виртуальный маршрутизатор выполнял бы критическую роль. В общем, с виртуальным маршрутизатором в ACS 4.3 есть ряд проблем, часть из которых дожила до 4.9 и в 4.10 наконец-то должны быть внесены изменения, которые их решат. Первая проблема, которую мы обнаружили — проблема c DHCP сервером в Debian — он не выдает DHCP информацию из-за бага, который описан (например, здесь). Далее, у нас были проблемы с ротацией логов, из-за чего происходило переполнение файловой системы виртуального маршрутизатора и он переставал работать. В итоге, мы внесли в саму виртуальную машину существенное количество изменений, поправили скрипты, возможно сломали совместимость с другими функциями, но добились чтобы он работал как надо. В настоящее время мы выполняем перезагрузку данного компонента один раз в 1-2 месяца, поскольку облако находится на финальном этапе жизненного цикла, когда внесение изменений не имеет практического смысла. Стоит отметить, что для больших инфраструктур с десятками тысяч VM с виртуальным маршрутизатором имеются другие проблемы, например, описанная здесь. Я еще не проводил анализ того решена ли данная проблема в 4.10, но энтузиазм коммитеров на ее решение вроде высокий (в форке Cosmic она точно уже решена). Стоит отметить, что вместо виртуального маршрутизатора на базе Debian Linux можно использовать Juniper SRX, Citrix NetScaler. В настоящее время есть инициатива реализации виртуального маршрутизатора с использованием VyOS (думаю, что она не будет реализована, поскольку за ней не стоит серьезного игрока, которому это решение необходимо).

Сценарий задания правил iptables, ebtables на хосте виртуализации


При запуске виртуальной машины агент ACS, размещенный на хосте, выполняет конфигурирование правил iptables и ebtables, с помощью которых производится ограничение сетевых возможностей виртуальных машин (изменение MAC, присвоение чужих IP, нелегальные DHCP серверы). По непонятным причинам в ACS 4.3 данный сценарий не работал корректно — правила терялись, к машинам переставал идти трафик. Стоит отметить, что в текущем тестовом облаке ACS 4.9.2 эта проблема решена и не доставляет неудобств. В общем, мы переписали python-сценарий и добились его корректной работы. Касательно данной проблемы, есть подозрение, что в силу экспериментального режима развертывания мы “сломали” ACS, и из-за этого наблюдалось такое поведение, возможно, что при осознанном конфигурировании проблема бы не проявила себя.

Несколько первичных хранилищ NFS для одного кластера


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

Интерфейс самообслуживания пользователя ACS


Интерфейс ACS достаточно консервативный и ориентирован на администраторов, а пользователя, который не использовал ранее комплексные инструменты администрирования VM, он однозначно пугает и требуется существенная работа по описанию его функций и способов выполнения различных задач. В этом смысле, интерфейсы, которые предоставляют AWS, DO и другие ведущие провайдеры сервисов VPS, предоставляют пользователю лучший UX. Как итог, время от времени, служба поддержки вынуждена объяснять пользователю каким образом выполнить ту или иную нетривиальную операцию достаточно продолжительное время по телефону (например, как создать шаблон из выполняющейся VM).

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


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

В настоящее время мы планируем развертывание нового облака на 288 ядер Xeon E5-2670, 1536 GB RAM и 40 TB хранилища SSD с использованием ACS 4.10 (Basic Zones, Security Groups). Для того, чтобы предоставлять нашим пользователя более качественный сервис мы так же инициировали создание альтернативного интерфейса именно для такого развертывания, который создается как открытый продукт CloudStack-UI и учитывает тот опыт, который мы приобрели в результате эксплуатации текущего облака.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/332168/


Метки:  

Стартап дня (июнь 2017-го)

Понедельник, 03 Июля 2017 г. 11:48 + в цитатник

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


Yext


Yext помогает бизнесу быть лучше представленным на картах. В идеале, как только у банка открывается новое отделение, оно должно сразу появиться в десятках мест: от очевидных карт Google и Яндекса (Google и Bing в американских реалиях) до местного аналога banki.ru и, например, сайта Western Union. В реальности десятками мест никто, конечно, не занимается: везде, кроме самых крупных и раскрученных источников, надолго остается неправильная или неполная информация; клиенты идут не туда, деньги теряются.


image


И тут на сцену выходит Yext. За суммы, начинающиеся с $4 в неделю, он дает бизнесам единую точку управления своими локациями на всех релевантных площадках: один клик — и данные обновились везде. В одиночку такой сервис не работает: жадный покупатель мог бы включать его только ради каких-то изменений, но для большинства клиентов это событие довольно редкое, можно заметно сэкономить, поэтому стартап «заодно» предлагает и постоянные услуги. Для популярных сетей это мониторинг отзывов на всех тех сайтах, данные на которых Yext приводит в порядок, а для маленьких, кому это неактуально, есть функция геостраниц. Красивые, правильно сверстанные и SEO-оптимизированные страницы про каждую локацию один раз встраиваются в основной сайт и дальше управляются из общего дашборда вместе с внешними ресурсами.


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


August Home


image


Американский August Home делает для обычных домов и квартир электронные дверные замки, управляемые через приложение на смартфоне, и эта идея куда глубже, чем может показаться: всё, что связано с доставкой, сейчас в тренде, а проект во многом именно про неё. Основной продвигаемый бонус — отсутствие необходимости встречать курьеров и других людей, которым на самом деле нужно место, а не человек. Дверь можно открыть откуда угодно, где есть интернет, не надо никого ждать. Курьер может приехать, когда ему удобно, а вы быть там, где удобно вам. Восьмичасовой интервал доставки становится вполне комфортным, логистические услуги дешевеют, ВВП растет, благолепие… У жителя России может возникнуть вопрос про воровство, но в Штатах ответ настолько очевиден, что даже в промоматериалах не упоминается: с одной стороны, и воровать в современных квартирах особенно нечего, а с другой, курьера при входе фотографируют, откуда он взялся — более-менее известно. Возможное преступление просто идеально для раскрытия, люди не до такой степени идиоты.


Остальные возможные сценарии кажутся куда более надуманными. Ну да, можно отобрать ключ у бывшего парня одним нажатием кнопки и быть уверенным, что он дубликат не сделал. Но заботиться о такой ситуации заранее и ставить для этого специальный замок?.. Разве что в квартирах под посуточную аренду это актуально. Или, например, возможность для уборщицы заходить в дом только по средам с 10 до 12 — а зачем? Потому что можем? А уж логирование входов и push-уведомления о них кажутся вообще вредными для нормальной семейной жизни.


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


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


Grammarly


image


Насколько я могу судить, я пишу по-русски достаточно грамотно; постоянным читателям блога, конечно, виднее, но самооценка у меня такая. И такая же самооценка была про английский язык: я понимал, что мои тексты очень упрощенные, без сложных конструкций и ярких идиом, но думал, что явных ошибок в них мало, тем более что и браузер с Word’ом подчеркивали что-то редко. Ха! Стоило установить себе плагин от Grammarly, и иллюзии развеялись как дым.


Это всего лишь проверка грамотности текста, но проверка хорошая. Grammarly не проверяет слова по словарю, а действительно знает английскую (только английскую) орфографию с пунктуацией, видит пропущенные запятые, несогласование времен, неправильные артикли, понимает, что player должен обязательно has, а не have, и замечает ещё огромную кучу разных проблем. Меня правит практически в каждом абзаце, при том, что, повторюсь, стандартные средства не подчеркивают почти ничего. Важно, что ошибки не просто отмечаются, но и полноценно разъясняются. В общем, действительно полезное применение технологий AI.


Технически в Grammarly есть три варианта реализации: плагин к Chrome/Safari/Firefox/IE, плагин к MS Office и самостоятельный текстовый редактор. Работоспособным кажется только вариант в браузере — менять привычный редактор, даже ради проверки английского, это чересчур, а в Word’е он почему-то ломает возможность Undo через Ctrl-Z (как?? кто так программирует??), что, конечно, полностью убивает возможность использования.


Модель монетизации, естественно, основана на подписке: бесплатно можно видеть только явные ошибки, а премиум-пользователи за примерно 20 долларов в месяц получают ещё и стилистические рекомендации в духе «a lot of тут не подходит, используйте лучше much». Платит за такое, скорее всего, очень маленький процент аудитории, но при текущих 7 миллионах DAU это должно быть несколько сот тысяч человек (то есть десятки миллионов годовой выручки).


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


LoveCrafts


image


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


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


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


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


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


Английский рынок стартап занял практически без инвестиций, ради американского поднял порядка 30 миллионов долларов и сейчас в США примерно половина его бизнеса. В апреле был очередной раунд в 33 миллиона — хотят организовывать новые категории и выходить в новые страны.


Oberlo


image


Идея этого стартапа — автоматизация прямой перепродажи с AliExpress. Интернет-бизнесмен со своим аккаунтом на Shopify подключается к Oberlo, выбирает в веб-интерфейсе те товары с AliExpress, которые нужно показывать на новой площадке, и вуаля, магазин готов. Осталось только описания на нужном языке поправить и правило для новых цен установить, +20 или +50 процентов к оригинальным, например. Всё равно ведь дешево останется.


Когда конечный покупатель закажет что-то на этой витрине, Oberlo автоматически создаст и оплатит заказ на AliExpress сразу с финальным адресом. Если что-то изменится на странице товара на Ali, цена увеличится или товар вообще пропадет, то Oberlo поправит и витрину. Владельцу магазина остается только привлекать клиентов и разбираться с претензиями: диспуты, увы, пока автоматически не проксируются.


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


В дополнение к очевидной SaaS-подписке и потенциальному использованию маркетингового бюджета AliExpress, Oberlo ещё и берет комиссию за часть товаров. Идея состоит в том, что кроме обычных магазинов с Ali они в том же режиме предлагают перепродавать товары неких «проверенных» поставщиков, работающих напрямую с Oberlo. При настройке экспорта эта часть ассортимента всегда подсовывается повыше, и, конечно, регулярно попадает в финальные витрины. Не знаю, насколько это действительно прямые договоры: было бы очень красиво и вполне соответствовало духу проекта, если «проверенными» назывались бы просто обычные товары с Ali с измененными описаниями и увеличенной ценой.


Придумали эту замечательную модель совсем недалеко от России, в Литве. Стартап недавно куплен Shopify за 15 миллионов долларов.

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

https://habrahabr.ru/post/332022/


Метки:  

Pygest #12. Релизы, статьи, интересные проекты из мира Python [20 июня 2017 — 03 июля 2017]

Понедельник, 03 Июля 2017 г. 11:31 + в цитатник
image Всем привет! Это уже двенадцатый выпуск дайджеста на Хабрахабр о новостях из мира Python.

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

А теперь к делу!


Релизы


Python 3.6.2rc1
Jython 2.7.1 RC3

Статьи


Автоэнкодеры в Keras, Часть 1: Введение
Автоэнкодеры в Keras, Часть 2: Manifold learning и скрытые (latent) переменные
Автоэнкодеры в Keras, Часть 3: Вариационные автоэнкодеры (VAE)
Автоэнкодеры в Keras, Часть 4: Conditional VAE
Автоэнкодеры в Keras, Часть 5: GAN(Generative Adversarial Networks) и tensorflow
Автоэнкодеры в Keras, часть 6: VAE + GAN
Серия статей от iphysic о auto-encoders в глубоком обучении на Python.

Compiling Python syntax to x86-64 assembly for fun and (zero) profit
Занимательная статья о том, как скомпилировали синтаксис Python в x86-64 ассемблерный код и что из этого вышло

Stock Trading Analytics and Optimization in Python with PyFolio, R’s PerformanceAnalytics, and backtrader
Большая статья о использовании связки Python + R в анализе и оптимизации финансовых данных

Memory use in CPython and MicroPython
О различиях в использовании памяти в CPython и MicroPython

Django vs Flask
Сранение 2 популярных Python фреймворков

Linked Lists in Python
О связанных списках в Python

How to Use Static Type Checking in Python 3.6
Заметка о том, как правильно использовать статическую проверку типов, введённую в Python 3.6

Using Docker for Flask Application Development (not just Production!)
Туториал о том, как использовать Flask + Docker при разработке Python приложений.

Why did Pinterest move from Django to Flask.
Интересное обсуждение на Reddit о том, почему Pinterest перешёл с Django на Flask

GraphQL in the Python World
Отличная статья о том, как использовать GraphQL в Python коде

Neurally Embedded Emojis
Занимательная статья о том, как использовать нейронную сеть для подборка «эмоджи»

Experienced python programmers: are there any standard features of the language that you still don't regularly use?
Ещё одно интересное обсуждение на Reddit о том, какие стандартные «фичи» языка используются реже всего.

Интересные проекты


Visualization-of-popular-algorithms-in-Python
Примеры визуализаций некоторых популярных алгоритмов

logzero
Отличный инструмент для простого логирования.

DeepLearning
Подборка примеров по глубокому обучению на TensorFlow и Keras

Предыдущий выпуск дайджеста ищете здесь:

Pygest #11. Релизы, статьи, интересные проекты из мира Python [6 июня 2017 — 19 июня 2017]

Спасибо за внимание! Присылайте Ваши предложения для публикации в дайджесте!
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/332114/


Метки:  

Классификация текста с помощью нейронной сети на JAVA

Понедельник, 03 Июля 2017 г. 10:19 + в цитатник
– Наша Лена уходит в декрет, – сообщил начальник, – поэтому нам надо искать замену на время ее отсутствия. Часть задач мы распределим, а вот как быть с задачей перенаправления обращений пользователей?

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

– Давай я напишу программу, которая это будет делать автоматически! – ответил я.

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



Формализуем задачу


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

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

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

Выбор инструментов


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

В качестве СУБД использовал SQLite.

Отсюда взял готовую реализацию нейронной сети (Encog Machine Learning Framework). Я решил в качестве классификатора использовать именно нейронную сеть, а не, например, наивный байесовский классификатор, потому что, во-первых, теоретически, нейронная сеть должна быть точнее. Во-вторых, мне просто хотелось поиграться с нейронными сетями.

Для чтения Excel-файла с данными для обучения понадобились некоторые библиотеки Apache POI.

Ну, и для тестов традиционно использовал JUnit 4.

Чуть-чуть теории


Не буду подробно описывать теорию по нейронным сетям, так как ее предостаточно (тут неплохой вводный материал). Вкратце и по-простому: у сети есть входной слой, скрытые слои и выходной слой. Количество нейронов в каждом слое определяется разработчиком заранее и после обучения сети изменению не подлежит: если добавили/убавили хоть один нейрон, то сеть нужно переобучать заново. На каждый нейрон входного слоя подается нормализованное число (чаще всего от 0 до 1). В зависимости от набора этих чисел на входном слое, после определенных вычислений, на каждом выходном нейроне тоже получается число от 0 до 1.



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

Переходим к практике


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

Способов построения словаря много. Можно, например, тупо взять все слова русского языка и это будет наш словарь. Но такой подход не годится, потому что размер входного слоя будет настолько огромным, что для создания нейронной сети не хватит ресурсов простой рабочей станции. Для примера представим, что у нас словарь состоит из 100 000 слов, тогда имеем 100 000 нейронов во входном слое; допустим, 80 000 в скрытом слое (ниже описан способ определения размерности скрытого слоя) и 25 в выходном. Тогда просто для хранения весов связей потребуется ~60 Гб оперативки: ((100 000 * 80 000) + (80 000 * 25)) * 64 бита (тип double в JAVA). Во-вторых, такой подход не годится, потому что в текстах может использоваться специфичная терминология, отсутствующая в словарях.

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

Один из способов «выдергивания» слов/фраз (даже точнее сказать, фрагментов) из текста называется построением N-грамм. Наиболее популярными являются униграммы и биграммы. Бывают так же символьные N-граммы – это когда текст дробится не на отдельные слова, а на отрезки символов определенный длины. Трудно заранее сказать, какая из N-грамм окажется эффективнее в конкретной задаче, поэтому нужно экспериментировать.
Текст Униграмма Биграмма 3-символьная N-грамма
Этот текст должен быть разбит на части [«этот», «текст», «должен», «быть», «разбит», «на», «части»] [«этот текст», «текст должен», «должен быть», «быть разбит», «разбит на», «на части»] [«Это», «т т», «екс», «т д», «олж», «ен », «быт», «ь р», «азб», «ит », «на », «час», «ти»]

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

Класс Unigram
class Unigram implements NGramStrategy {
  @Override
  public Set getNGram(String text) {
    if (text == null) {
      text = "";
    }

    // get all words and digits
    String[] words = text.toLowerCase().split("[ \\pP\n\t\r$+<>№=]");

    Set uniqueValues = new LinkedHashSet<>(Arrays.asList(words));
    uniqueValues.removeIf(s -> s.equals(""));

    return uniqueValues;
  }
}


В результате, после обработки ~10 000 текстов, я получил словарь размером ~32 000 элементов. Проанализировав по диагонали полученный словарь, я понял, что в нем очень много лишнего, от чего надо бы избавиться. Для этого сделал следующее:

  1. Убрал все небуквенные символы (числа, знаки препинания, арифметические операции и т.д.), так как никакой смысловой нагрузки они, как правило, не несут.
  2. Прогнал слова через процедуру стемминга (использовал Стеммер Портера для русского языка). Кстати, полезным побочным эффектом этой процедуры является «унисексация» текстов, то есть «сделал» и «сделала» будут преобразованы в «сдела».
  3. Сначала я хотел определять и исправлять опечатки и грамматические ошибки. Начитался про Алгоритм Оливера (функция similar_text в PHP) и Расстояние Левенштейна. Но задача решилась гораздо проще, хоть и с погрешностью: я решил, что если элемент N-граммы встречается меньше, чем в 4 текстах из обучающей выборки, то мы этот элемент в словарь не включаем как бесполезный в будущем. Таким образом я избавился от большинства опечаток, слов с грамматическими ошибками, «слепленныхСлов» и просто очень редких слов. Но надо понимать, что если в будущих текстах будут часто встречаться опечатки и грамматические ошибки, точность классификации таких текстов будет ниже и тогда все-таки придется реализовывать механизм исправления опечаток и грамматических ошибок. Важно: такой «финт» с выкидыванием редко-встречающихся слов допустим при большом объеме данных для обучения и построения словаря.

Все это реализовано в классах FilteredUnigram и VocabularyBuilder.

Класс FilteredUnigram
public class FilteredUnigram implements NGramStrategy {
  @Override
  public Set getNGram(String text) {
    // get all significant words
    String[] words = clean(text).split("[ \n\t\r$+<>№=]");

    // remove endings of words
    for (int i = 0; i < words.length; i++) {
      words[i] = PorterStemmer.doStem(words[i]);
    }

    Set uniqueValues = new LinkedHashSet<>(Arrays.asList(words));
    uniqueValues.removeIf(s -> s.equals(""));

    return uniqueValues;
  }

  private String clean(String text) {
    // remove all digits and punctuation marks
    if (text != null) {
      return text.toLowerCase().replaceAll("[\\pP\\d]", " ");
    } else {
      return "";
    }
  }
}


Класс VocabularyBuilder
class VocabularyBuilder {
  private final NGramStrategy nGramStrategy;

  VocabularyBuilder(NGramStrategy nGramStrategy) {
    if (nGramStrategy == null) {
      throw new IllegalArgumentException();
    }

    this.nGramStrategy = nGramStrategy;
  }

  List getVocabulary(List classifiableTexts) {
    if (classifiableTexts == null ||
        classifiableTexts.size() == 0) {
      throw new IllegalArgumentException();
    }

    Map uniqueValues = new HashMap<>();
    List vocabulary = new ArrayList<>();

    // count frequency of use each word (converted to n-gram) from all Classifiable Texts
    //

    for (ClassifiableText classifiableText : classifiableTexts) {
      for (String word : nGramStrategy.getNGram(classifiableText.getText())) {
        if (uniqueValues.containsKey(word)) {
          // increase counter
          uniqueValues.put(word, uniqueValues.get(word) + 1);
        } else {
          // add new word
          uniqueValues.put(word, 1);
        }
      }
    }

    // convert uniqueValues to Vocabulary, excluding infrequent
    //

    for (Map.Entry entry : uniqueValues.entrySet()) {
      if (entry.getValue() > 3) {
        vocabulary.add(new VocabularyWord(entry.getKey()));
      }
    }

    return vocabulary;
  }
}


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

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

Класс Bigram
class Bigram implements NGramStrategy {
  private NGramStrategy nGramStrategy;

  Bigram(NGramStrategy nGramStrategy) {
    if (nGramStrategy == null) {
      throw new IllegalArgumentException();
    }

    this.nGramStrategy = nGramStrategy;
  }

  @Override
  public Set getNGram(String text) {
    List unigram = new ArrayList<>(nGramStrategy.getNGram(text));

    // concatenate words to bigrams
    // example: "How are you doing?" => {"how are", "are you", "you doing"}

    Set uniqueValues = new LinkedHashSet<>();

    for (int i = 0; i < unigram.size() - 1; i++) {
      uniqueValues.add(unigram.get(i) + " " + unigram.get(i + 1));
    }

    return uniqueValues;
  }
}


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

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

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

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

Итак, сеть мы создали. Теперь нужно определиться с тем, как будем конвертировать текст в цифры, пригодные для «скармливания» нейронной сети. Для этого нам нужно преобразовать текст в вектор текста. Предварительно нужно каждому слову в словаре присвоить уникальный вектор слова, размер которого должен быть равен размеру словаря. После обучения сети менять вектора для слов нельзя. Вот как это выглядит для словаря из 4 слов:
Слово в словаре Вектор слова
привет 1 0 0 0
как 0 1 0 0
дела 0 0 1 0
тебе 0 0 0 1

Процедура преобразования текста в вектор текста подразумевает под собой сложение векторов используемых в тексте слов: текст «как тебе привет?» будет преобразован в вектор «1 1 0 1». Этот вектор мы уже можем подавать на вход нейронной сети: каждое отдельное число на каждый отдельный нейрон входного слоя (число нейронов как раз равно размеру вектора текста).

Метод, вычисляющий вектор текста
private double[] getTextAsVectorOfWords(ClassifiableText classifiableText) {
  double[] vector = new double[inputLayerSize];

  // convert text to nGram
  Set uniqueValues = nGramStrategy.getNGram(classifiableText.getText());

  // create vector
  //

  for (String word : uniqueValues) {
    VocabularyWord vw = findWordInVocabulary(word);

    if (vw != null) { // word found in vocabulary
      vector[vw.getId() - 1] = 1;
    }
  }

  return vector;
}


Тут и тут можно дополнительно почитать про подготовку текста к анализу.

Точность классификации


Поэкспериментировав с разными алгоритмами формирования словаря и с разным количеством и размерностью скрытых слоев, я остановился на таком варианте: используем FilteredUnigram с отсеканием редкоиспользуемых слов для формирования словаря; делаем 2 скрытых слоя размерностью 1/6 от размера словаря – первый слой и 1/4 от размера первого слоя – второй слой.

После обучения на ~20 000 текстов (а это очень мало для сети такого размера) и на прогоне сети по 2 000 эталонных текстов имеем:
N-грамма Точность Размер словаря
(без редкоиспользуемых слов)
Униграмма 58% ~25 000
Отфильтрованная униграмма 73% ~1 200
Биграмма 63% ~8 000
Отфильтрованная биграмма 69% ~3 000

Это точность для одной характеристики. Если нужна точность для нескольких характеристик, то формулы расчета такие:

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


Пример:

Допустим, точность определения одной характеристики равна 65%, второй характеристики – 73%. Тогда точность определения сразу обеих равна 0,65*0,73 = 0,4745= 47,45%, а точность определения хотя бы одной характеристики равна 1-(1-0,65)*(1-0,73) = 0,9055= 90,55%.

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

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

Итоговая программа


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

Общий алгоритм работы программы:

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


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




В планах:
  • Добавить другие типы классификаторов (например, сверточную нейронную сеть и наивный байесовский классификатор);
  • Попробовать использовать словарь, состоящий из комбинации униграмм и биграмм.
  • Добавить механизм устранения опечаток и грамматических ошибок.
  • Добавить словарь синонимов.
  • Исключать слишком часто-встречающиеся слова, так как они, как правило, являются информационным шумом.
  • Добавить веса к отдельным значимым словам, чтобы их влияние в анализируемом тексте было больше.
  • Немного переделать архитектуру, упростив API, чтобы можно было вынести основную функциональность в отдельную библиотеку.

Немного об исходниках


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

  • Паттерн «Стратегия». Интерфейс NGramStrategy и классы, его реализующие.
  • Паттерн «Наблюдатель». Классы LogWindow и Classifier, реализующие интерфейсы Observer и Observable.
  • Паттерн «Декоратор». Класс Bigram.
  • Паттерн «Простая фабрика». Метод getNGramStrategy() интерфейса NGramStrategy.
  • Паттерн «Фабричный метод». Метод getNgramStrategy() класса NGramStrategyTest.
  • Паттерн «Абстрактная фабрика». Класс JDBCDAOFactory.
  • Паттерн (антипаттерн?) «Одиночка». Класс Config. Наверное, это один из немногих случаев, когда использование одиночки оправдано.
  • Паттерн «Шаблонный метод». Метод initializeIdeal() класса NGramStrategyTest. Правда, тут не совсем классическое его применение.
  • Паттерн «DAO». Интерфейсы CharacteristicDAO, ClassifiableTextDAO и т.д.

Полный исходный код: https://github.com/RusZ/TextClassifier.

Конструктивные предложения и критика приветствуются.

P.S.: За Лену не переживайте – это вымышленный персонаж.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/332078/


Метки:  

The incredible machine или мой самый лучший тест

Понедельник, 03 Июля 2017 г. 09:38 + в цитатник
Добрый день.

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

image

Тем не менее, есть хорошая новость: incredible machine все-таки может быть полезна. Например, для тестирования программных систем.

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

Самым подходящим вариантом для теста будет тестирование посредством обратной функции:
image
на вход подаются случайные данные, преобразуются функцией $f$, затем к результату применяется функция $f^{-1}$, обратная к $f$ и сравнивается выход с исходными данными. Тестируются сразу две функции с бронебойным доказательством правильности работы (не алгоритмов, конечно, а реализации).

Обратной функцией к рендерингу штрихкода очевидно будет распознавание изображения штрихкода. Сказано — сделано. Взяли еще одну open source библиотеку zbar. Инегрировали — заработала.
image
Теперь схема тестирования оформилась вполне четко: входные данные это — текстовое представление штрихкода и его стандарт (ean-13, ean-8, upc-a, code-39, qr и т.п.). Это представление преобразуется в изображение, которое тут же распознается и в результате мы получаем, опять же, текстовое представление и стандарт.
Таким образом мы протестировали следующие компоненты:
  • Библиотеку zint
  • Библиотеку libpng (при выводе и распознавании кода в формате png)
  • Библиотеку zlib (она используется libpng и множеством иных подсистем)
  • Библиотеку libjpeg (при выводе и распознавании кода в формате jpeg)
  • Библиотеку zbar
  • Собственную инфраструктуру, которая все это интегрирует и связывает


Нам остался еще один шаг: zint умеет выводить штрихкод в векторном формате svg, однако же zbar своими средствами этот формат не понимает, но у нас есть собственная инфраструктура для чтения и рендеринга svg-изображения. Добавим в нашу схему еще один узелок и включим в тест. Все работает.
image
Теперь к списку протестированных компонентов можем добавить:
  • Модуль чтения svg-файлов и преобразования их во внутренний векторный формат
  • Модуль рендеринга векторных изображений

    Краткое итого


    Описанный тест примечателен тем, что использует значительное число модулей различного назначения, реализованных независимо друг от друга. Еще одним его ценным свойством является преобразование данных между качественно различными формами (текст — векторное изображение — растровое изображение — текст).
    И ложка дегтя: такой тест, имея великолепную демонстративность, не является достаточным. Он верифицирует функционал компонентов в весьма узком диапазоне областей определения каждого из них. То есть, рассчитывать на полноту тестирования методом «incredible machine» (интересно, ранее кто-нибудь использовал этот термин в таком контексте?), увы, нельзя. Детальные тесты отдельных функций он не отменяет.

    Спасибо за внимание.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/331230/


Метки:  

FinWin-2017: конкурс финтех-проектов и последние тенденции в банковской сфере

Понедельник, 03 Июля 2017 г. 09:14 + в цитатник
22 июня в Москве, в центре Digital October во второй раз состоялся ежегодный форум-выставка экосистем и маркетплейсов для финансовой и смежных индустрий FinWin 2017.

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

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



Конкурс проектов


Одним из самых интригующих событий форума FinWin стал конкурс проектов. Целью соревнования был отбор нескольких самых перспективных проектов, обладающих значительным потенциалом для сотрудничества с банками. В состав жюри вошли ведущие финтех-эксперты из крупнейших банков России – «Открытие», «Райффайзенбанк», «Тинькофф», «Альфа-Банк», «Сбербанк» и «ВТБ-24». Участники конкурса представили свои проекты, раскрывая преимущества сервисов, которые могли бы способствовать развитию банковских экосистем.

Победителями стали проекты «Мой Капитал», «Мой Брокер» «iQChannels» и «Altcraft». Остановимся на презентациях компаний-победителей подробнее:



Мой Капитал

Проект «Мой Капитал» и представляет собой мобильный маркетплейс финансовых инструментов. Экосистема состоит из более чем 10 мобильных и десктопных приложений, реализованных для операционных систем iOS, Android, Windows и Mac.

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

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

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


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

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

Видео доклада

Мой Брокер

За первым победителем следует другой призер — давно утвердившийся на рынке продукт от ветерана в финансовом секторе, компании БКС – интеллектуальное приложение «Мой Брокер», которое позиционируется создателями как «биржа в смартфоне». В отличие от проекта «Мой Капитал», это не совсем экосистема приложений, а скорее одиночный продукт с максимально широкими возможностями для инвестирования на бирже.

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

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

Аналитики БКС в режиме онлайн могут предложить готовые решения для инвестирования или проконсультировать пользователя. Созданный пользователем персональный финансовый портфель представляет собой своеобразный виджет с наглядными показателями роста. Разработчики гарантируют безопасность всех финансовых операций.

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

Видео доклада

Altcraft

Компания «Altkraft» специализируется на создании продуктов в сфере digital-маркетинга. Ребята оказались единственными представителями этого направления на конкурсе. Проект, презентованный на выставке, представляет собой синтезированную платформу для автоматизации маркетинга и коммуникаций в цифровых каналах. Безопасность данных обеспечивается клиентским firewall: платформа позиционируются как on-premise software. Устанавливается платформа на оборудование клиента, что позволяет выполнять требование закона «О персональных данных» № 152-ФЗ.

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

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

Видео доклада

iQChannels

Замыкает список победителей проект компании iQStore – экосистема инструментов для взаимодействия бизнеса с клиентом под названием iQChannels.

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

Видео доклада



Помимо четырёх представленных проектов в конкурсе также приняли участие «Технософт», «Арт-Банк», Freedom24.ru, BrainySoft, 7 Seconds, Оператор Кредитных Заявок, Деньги в дело, VentureClub. Каждое из решений вызывало интерес аудитории и жюри. К примеру, специалисты из BrainySoft создали агрегатор добавленной стоимости для разных типов финансовых организаций: интернет-магазинов, банков, микрофинансовых организаций. Платформа дает обширный набор готовых интеграций для предоставления кредитов на покупку товара в реальном времени и последующей работы с клиентами.

Собственно конференция


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

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

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

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

Такие меры позволяют банкам:

  • Повышать лояльность клиентов;
  • вторгнуться на территорию ритейла и маркетплейсов вроде Яндекс Маркета;
  • получать дополнительный доход за счет комиссий.




В ходе сессий выступали отечественные и зарубежные топ-менеджеры банков и финтех-специалисты высокого класса. Например, Михаил Ломтадзе, представитель правления казахского банка Kaspi, член совета директоров «Бинбанка» Александр Филатов, руководитель проекта Tarantool Data Grid Mail.ru Group Денис Аникин, руководитель отдела Центра технологических инноваций Сбербанка Андрей Аристархов и другие. Подробный обзор презентаций представлен в статье «В банк как в магазин, или Чего хотят клиенты».

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

Интересным как по содержанию, так и по формату подачи оказался доклад Николая Адеева, представителя компании Artsofte на тему «Заблуждения при формировании маркетплейсов или с чего начинается экосистема».

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

  • Убеждение банков в том, что они «владеют» клиентами и могут без проблем допродать им что угодно.
  • Понимание маркетплейса как аналога отдельного портала/витрины/e-commerce.
  • Убеждение, что сайтами должны заниматься маркетинг и реклама, ДБО – IT-специалисты, в то время как маркетплейсы олицетворяют собственно бизнес.

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

Совместный доклад члена совета директоров «Бинбанка» Александра Филатова и директора по развитию бизнеса банка «Бинбанк Диджитал» Игоря Гайдаржи касался как вопросов управления, так и технологических нюансов. В презентации прозвучали советы, как съесть 10 банков и не стать неуклюжим, как перекроить всю систему управления (спойлер: не обошлось без Грефа), ну и, конечно, не обделили вниманием и вездесущий Agile.

И, наконец, Сбербанк. Руководитель отдела Центра технологических инноваций Сбербанка Андрей Аристархов рассказал о частном опыте применения open API для развития организации. Внедрение открытых API представляет собой поэтапный процесс. В общем виде оно происходит по следующей схеме: появление open API стимулирует приток внешних разработчиков со свежими идеями финтех-продуктов, а затем и приложений, выполненных их силами (формирование маркетплейсов происходит как раз на этом, зрелом этапе развития проекта), что, в свою очередь, приводит к расширению бизнеса. Чтобы обезопасить данные и репутации компании, Сбербанк распределяет партнеров, работающих с Open API, по нескольким уровням доверия, каждому из которых соответствует определенный пул прав и привилегий.



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

https://habrahabr.ru/post/332162/


Docker 17.06 и Kubernetes 1.7: ключевые новшества

Понедельник, 03 Июля 2017 г. 08:30 + в цитатник

Прошлая неделя подарила два «вкусных» релиза из Open Source-мира контейнеров: практически одновременно обновились Docker (версия 17.06) и Kubernetes (версия 1.7). Какие возможности они принесли? В статье представлена информация из анонсов и release notes этих релизов с небольшими уточнениями по некоторым из ключевых изменений.

Docker CE 17.06


28 июня был представлен Docker CE (Community Edition) 17.06 — первый выпуск контейнерной системы, собранный с помощью проекта Moby, анонсированного в апреле. Подробнее о Moby мы уже писали.

Сборка в несколько этапов


Главной фичей релиза стала поддержка многоэтапных сборок (multi-stage builds), суть которой заключается в возможности описывать в одном Dockerfile несколько этапов сборки образа для того, чтобы в конечный образ не попадали промежуточные данные, которые не требуются. Очевидный пример, который приводят в Docker: Java-разработчики обычно используют Apache Maven для компиляции своих приложений, однако Maven не нужен в конечном контейнере (образе) для запуска этих приложений. Теперь можно оформить Dockerfile таким образом, что сам Maven будет использоваться в промежуточном образе (для сборки), но не попадёт в конечный (для запуска).

Вот вариант Dockerfile для простого приложения на Java Spring Boot:

FROM node:latest AS storefront
WORKDIR /usr/src/atsea/app/react-app
COPY react-app/package.json .
RUN npm install
COPY . /usr/src/atsea/app
RUN npm run build

FROM maven:latest AS appserver
WORKDIR /usr/src/atsea
COPY pom.xml .
RUN mvn -B -f pom.xml -s /usr/share/maven/ref/settings-docker.xml dependency:resolve
COPY . .
RUN mvn -B -s /usr/share/maven/ref/settings-docker.xml package -DskipTests

FROM java:8-jdk-alpine
WORKDIR /static
COPY --from=storefront /usr/src/atsea/app/react-app/build/ .
WORKDIR /app
COPY --from=appserver /usr/src/atsea/target/AtSea-0.0.1-SNAPSHOT.jar .
ENTRYPOINT ["java", "-jar", "/app/AtSea-0.0.1-SNAPSHOT.jar"]
CMD ["--spring.profiles.active=postgres"]


Как видно, две подготовительные стадии здесь используют Node.js и Apache Maven для сборки приложения, однако результирующий образ будем компактным, не имея в своём составе ни Node.js, ни Maven.

Примечание: До настоящего времени у себя в компании мы для этих целей использовали фичу под названием артефакты в собственной Open Source-утилите dapp (её обзор см. здесь).

Логи и метрики


Метрики Docker теперь могут использоваться в плагинах. Для демонстрации приводится пример плагина, который проксирует запросы на метрику, доступную в нём:
$ docker plugin install --grant-all-permissions cpuguy83/docker-metrics-plugin-test:latest
$ curl http://127.0.0.1:19393/metrics

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

Плагины теперь также могут использоваться и для логов (т.е. для реализации logging drivers), а вывод списка всех драйверов журналирования добавлен в docker info. Кроме того, реализацию docker service logs, которая с прошлого релиза (17.05) может показывать и логи индивидуальных заданий (/task/{id}/logs в REST), перенесли из ветки Edge в Stable, поэтому теперь легко получить обобщённые логи для всего сервиса, запущенного в Swarm.

Сеть


Стала возможной привязка сервисов к сетям внутри узла (node-local): Host, Macvlan, IPVlan, Bridge, local-scope. Приводимый для Macvlan пример — это создание специфичных для узла сетевых конфигураций на рабочих узлах и сети на управляющем узле, которая будет их применять:
[Wrk-node1]$ docker network create --config-only --subnet=10.1.0.0/16 local-config
[Wrk-node2]$ docker network create --config-only --subnet=10.2.0.0/16 local-config
[Mgr-node2]$ docker network create --scope=swarm --config-from=local-config -d macvlan
mynet
[Mgr-node2]$ docker service create --network=mynet my_new_service

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

Swarm


Ряд новшеств получил режим Swarm, а в частности:
  • объекты конфигурации (Configuration Objects), позволяющие безопасно передавать информацию о конфигурации по аналогии с тем, как это делалось для секретов:
    $ echo "This is a config" | docker config create test_config -
    $ docker service create --name=my-srv --config=test_config …
    $ docker exec -it 37d7cfdff6d5 cat test_config
    This is a config

  • функция ротации CA-сертификатов в системе public key infrastructure (PKI), применяемой для безопасного деплоя системы оркестровки контейнеров (docker swarm ca --rotate);
  • поддержка событий (ранее были доступны вне Swarm) для получения в реальном времени данных о сервисах, узлах, сетях, секретах;
  • новый флаг --datapath-addr для docker swarm init, указывающий сетевой интерфейс для изоляции заданий управления (control traffic) от данных приложений (data traffic) — полезно в случае приложений, производящих большую нагрузку на ввод/вывод;
  • возможность указывать место хранения секрета в контейнере (вместо традиционного /var/run).

Более подробный лог изменений в Docker 17.06 вместе с ссылками на коммиты можно найти в Docker CE release notes. А для любителей смотреть и слушать есть 8-минутное видео с рассказом и демонстрацией основных новшеств.

Kubernetes 1.7


29 июня был представлен Kubernetes 1.7, главными нововведениями которого названы улучшения в безопасности, поддержке stateful-приложений, расширяемости платформы. Что за этим стоит?

Безопасность


  • Объявлен стабильным Network Policy API, позволяющий настраивать правила, определяющие (и ограничивающие) взаимодействие между подами.
  • Node authorizer, позволяющий ограничивать API-запросы kubelet (к секретам, подам и другим объектам узла).
  • Альфа-версия шифрования секретов и других ресурсов, хранимых в etcd.
  • В kubelet TLS bootstrapping добавлена поддержка ротации сертификата клиента и сервера
  • Логи Audit, хранимые сервером API, стали более настраиваемыми и расширяемыми с поддержкой фильтрации событий и webbooks, а также стали предоставлять больше данных для аудита системы.

Поддержка stateful-приложений


  • Бета-версия функции автоматических обновлений StatefulSet, используемых для деплоя stateful-приложений. Стратегия обновлений определяется полем spec.updateStrategy, поддерживающим сейчас два значения: OnDelete и RollingUpdate.
  • Поддержка в StatefulSets более быстрого масштабирования и запуска приложений, не требующих строгой очередности, настраиваемой теперь через Pod Management Policy. Такие приложения теперь могут запускаться параллельно и без ожидания получения подом определённых статусов (Running, Ready).
  • Альфа-версия локального хранилища (Local Storage): в StorageClasses внутри StatefulSets теперь можно получить доступ к локальному хранилищу через стандартный интерфейс PVC/PV.
  • Умный откат (и история изменений) при обновлениях DaemonSets.
  • Новый плагин StorageOS Volume, реализующий постоянные томы хранения высокой доступности во всём кластере (из локального или подключённого к узлу хранилища).

Расширяемость


  • Агрегация API позволяет расширять возможности Kubernetes собственными API. Прослойка агрегации работает вместе с kube-apiserver и ничего не делает, пока не зарегистрирован ни один ресурс для расширения API. Регистрация API выполняется через объект APIService, который реализуется через extension-apiserver внутри пода, работающего в кластере Kubernetes.
  • В Container Runtime Interface (CRI) добавлены новые RPC-вызовы для получения метрик контейнера. Добавлена альфа-версия интеграции с containerd, поддерживающая базовый жизненный цикл пода и управления образами.

Другое


  • Альфа-версия поддержки внешних контроллеров Dynamic Admission, позволяющих добавлять API-серверу бизнес-логику при модификации объектов.
  • Альфа-версия Policy-based Federated Resource Placement, что позволяет определять основанные на политиках решения по федеративным ресурсам (с использованием внешнего движка политик, например, основываясь на требованиях к цене или производительности).
  • На смену Third Party Resource (TPR) пришли Custom Resource Definitions (CRD), которые предлагают «более ясный API» и решают ряд проблем, зафиксированных во время бета-тестирования TPR. Полностью TPR будут убраны в Kubernetes 1.8 (доступно руководство по миграции).
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/332160/


Метки:  

Поиск сообщений в rss_rss_hh_new
Страницы: 1437 ... 1034 1033 [1032] 1031 1030 ..
.. 1 Календарь