...

суббота, 2 февраля 2019 г.

Радиомодули для arduino JDY-40

image

Приветствую всех. На просторах aliexpress наткнулся на очередное китайское творение, из раздела "Беспроводные модули для arduino". Ранее подобные модули с аналогичными возможностями за столь малые деньги мне не попадались. Вот я и решил сделать обзор данного модуля. Возможно, кого-то он заинтересует. Речь пойдет о маломощном трансивере JDY-40, работающем на частоте 2,4 Гигагерца. Работать с модулем очень просто, для настройки модуля используются ат команды, которые передаются по USART.

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

Первый режим – это режим последовательного порта


image

Такой режим позволяет обмениваться какими-то данными беспроводным способом между микроконтроллерами, используя USART. Максимальная скорость передачи данных, которую может обеспечить модуль, составляет 19 200 бит в секунду.
При скорости 9 600 бит в секунду расстояние по прямой видимости на максимальной мощности составляет порядка 100 метров. Но если модули поместить в разные комнаты, то устойчивая связь, даже через стены, останется на расстоянии 15 метров.

Второй режим


image

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


Let's block ads! (Why?)

Антирейтинг 2018

Здравствуйте! Хотелось бы прокомментировать данную ситуацию:

Крупнейший российский регистратор REG.RU расторгнул договор с ООО “Бегет”
(г. Санкт-Петербург) из-за систематических нарушений условий договора и Правил регистрации доменных имён, действующих в национальных доменах .RU/.РФ.

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

В действиях ООО “Бегет”, свидетельствующих о злоупотреблении правами посредника аккредитованного регистратора и нарушения законов РФ, были установлены:

— не соблюдение закона о защите персональных данных (ФЗ-152) в части сбора, обработки и хранения;
— массовые грубые систематические нарушения Правил регистрации доменных имен, действующих в национальных доменах .RU/.РФ и условий заключенного между регистратором и партнером договора;
— недобросовестная конкуренция путем введения в заблуждение администраторов доменов.

В связи с возникшей ситуацией мы берём на себя прямое взаимодействие с администраторами по вопросам обслуживания доменных имён, зарегистрированных в REG.RU, как у аккредитованного регистратора (данные изменения затронули порядка 50 тыс.клиентов).

Администраторам доменных имён не требуется производить какие-либо действия — все необходимые операции проведены со стороны REG.RU. Вся необходимая информация направлена на контактные e-mail адреса пользователей.

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

По любым вопросам клиенты могут обратиться по выделенной линии поддержки по электронной почте partners_bgt@reg.ru или телефону +7(499)7025373.

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

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

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

Let's block ads! (Why?)

[Из песочницы] Кастомный виджет googleTranslate для сайта

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

Советуем пользователям переводить веб-страницы с помощью браузеров, имеющих встроенную функцию перевода.

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

Как будет выглядеть наш пример:


Разметка демо-страницы
<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />
    <title>Кастомный виджет googleTranslate для сайта</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="css/style.css">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.min.js"></script>
    <script src="js/google-translate.js"></script>
    <script src="//translate.google.com/translate_a/element.js?cb=TranslateInit"></script>
</head>

<body class="page page_fix">
    <div class="language">
        <img src="images/lang/lang__ru.png" alt="ru" data-google-lang="ru" class="language__img">
        <img src="images/lang/lang__en.png" alt="en" data-google-lang="en" class="language__img">
        <img src="images/lang/lang__de.png" alt="de" data-google-lang="de" class="language__img">
        <img src="images/lang/lang__fr.png" alt="fr" data-google-lang="fr" class="language__img">
        <img src="images/lang/lang__pt.png" alt="pt" data-google-lang="pt" class="language__img">
    </div>
    <section class="content">
        <h1 class="content__title">Машинный перевод сайта</h1>
        <div class="content__desc">
            <p>Перевод сайта на другие языки при помощи Google Translate Widget</p>
            <p>Пример кастомоного виджета</p>
            <p>Hello Мир!!!</p>
        </div>
    </section>
</body>

</html>



Для корректной работы нашего кастомного виджета необходимо подключить файлы:
<link rel="stylesheet" href="css/style.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.min.js"></script>
<script src="js/google-translate.js"></script>
<script src="//translate.google.com/translate_a/element.js?cb=TranslateInit"></script>


Содержимое style.css:
body {
    margin: 0;
    padding: 0;
}

.page {
    display: flex;
    min-height: 100vh;
}

/* Фиксируем позицию body, которую меняет панель гугла*/

.page_fix {
    top: 0 !important;
    position: static !important;
}

/* Прячем панель гугла */

.skiptranslate {
    display: none !important;
}

/* language */

.language {
    position: fixed;
    left: 10px;
    top: 50%;
    transform: translateY(-50%);
    display: flex;
    flex-direction: column;
}

.language__img {
    margin: 2px;
    cursor: pointer;
    opacity: .5;
}

.language__img:hover,
.language__img_active {
    opacity: 1;
}

/* content */

.content {
    text-align: center;
    margin: auto;
}

Используемые флаги:

Разметка кастомного виджета:

<div class="language">
        <img src="images/lang/lang__ru.png" alt="ru" data-google-lang="ru" class="language__img">
        <img src="images/lang/lang__en.png" alt="en" data-google-lang="en" class="language__img">
        <img src="images/lang/lang__de.png" alt="de" data-google-lang="de" class="language__img">
        <img src="images/lang/lang__fr.png" alt="fr" data-google-lang="fr" class="language__img">
        <img src="images/lang/lang__pt.png" alt="pt" data-google-lang="pt" class="language__img">
    </div>

Содержимое google-translate.js:
const googleTranslateConfig = {
    lang: "ru",
};

function TranslateInit() {

    let code = TranslateGetCode();
    // Находим флаг с выбранным языком для перевода и добавляем к нему активный класс
    $('[data-google-lang="' + code + '"]').addClass('language__img_active');

    if (code == googleTranslateConfig.lang) {
        // Если язык по умолчанию, совпадает с языком на который переводим
        // То очищаем куки
        TranslateClearCookie();
    }

    // Инициализируем виджет с языком по умолчанию
    new google.translate.TranslateElement({
        pageLanguage: googleTranslateConfig.lang,
    });

    // Вешаем событие  клик на флаги
    $('[data-google-lang]').click(function () {
        TranslateSetCookie($(this).attr("data-google-lang"))
        // Перезагружаем страницу
        window.location.reload();
    });
}

function TranslateGetCode() {
    // Если куки нет, то передаем дефолтный язык
    let lang = ($.cookie('googtrans') != undefined && $.cookie('googtrans') != "null") ? $.cookie('googtrans') : googleTranslateConfig.lang;
    return lang.substr(-2);
}

function TranslateClearCookie() {
    $.cookie('googtrans', null);
    $.cookie("googtrans", null, {
        domain: "." + document.domain,
    });
}

function TranslateSetCookie(code) {
    // Записываем куки /язык_который_переводим/язык_на_который_переводим
    $.cookie('googtrans', "/auto/" + code);
    $.cookie("googtrans", "/auto/" + code, {
        domain: "." + document.domain,
    });
}



При смене языка добавляется куки с ключом googtrans и значением вида /ru/en
  • /ru — это язык который переводим
  • /en — это язык на который переводим

Это стандартное поведение, поэтому я им и воспользовался для кастомизации виджета. Кликая по флажкам необходимых языков, из атрибута data-google-lang в куки записываются соответствующие значение вида /auto/выбранный_язык. Затем происходит перезагрузка и auto заменяется на язык записанный отдельно в конфиг:

const googleTranslateConfig = {
    lang: "ru",
};

Это сделано для того, чтобы мы не привязывались к одному языку. Если к примеру сайт переведен на 2 языка, русский и английски, то мы можем передать текущий язык в конфиг и правильно обработать его. Все доступные языки и их код стандарта ISO-639-1 можно найти тут.

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

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

Репозиторий с проектом на GitHub

Let's block ads! (Why?)

Паттерн Интерактор (Interactor, Operation)

Данный текст представляет собой адаптацию части руководства фрэймворка Hanami под фрэймфорк Laravel. Чем вызван интерес именно к этому материалу? В нём даётся пошаговое описание с демонстрацией таких общих для языков программирования и фрэймворков вещей как:


  • Использование паттерна "Интеракторы".
  • Демонстрация TDD\BDD.

Сразу стоит отметить, что это не только разные фрэймворки с разной идеологией (в частности, что касается ORM), но и разные языки программирования, каждый из которых имеет свою специфическую культуру и сложившиеся "bests practics" в силу исторических причин. Разные языки программирования и фрэймворки тяготеют к заимствованию друг у друга наиболее удачных решений, поэтому несмотря на различия в деталях, фундаментальные вещи не различаются, если мы конечно не берём ЯП с изначально разной парадигмой. Достаточно интересно сравнить, как одну и туже задачу решают в разных экосистемах.

Итак, исходно мы имеем фрэймворк Hanami (ruby) — достаточно новый фрэймворк, идеологически больше тяготеющий к Symfony, с ORM "на репозиториях". И целевой фрэймворк Laravel\Lumen (php) с Active Record.

В процессе адаптации были срезаны наиболее острые углы:


  • Пропущена первая часть руководства с инициализацией проекта, описанием особенностей фрэймворка и подобных специфичных вещей.
  • ORM Eloquent натянут на глобус и выполняет в том числе роль репозитория.
  • Шаги генерации кода и шаблонов для отправки email.

Сохранено и сделан акцент на:


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

Первая часть оригинального туториала Hanami на которую будет ссылаться текст ниже
Оригинал текста туториала по интеракторам
Ссылка на репозиторий с адаптированным php кодом в конце текста.


Интеракторы


Новая фича: уведомления по электронной почте

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

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

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

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

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

Они используются для изоляции нетривиальной бизнес-логики, следуя принципу единственной ответственности (Single Responsibility Principle).

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


Колбэки? Они нам не нужны!

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

То есть после создания новой записи о книге в базе данных, отправляется email.

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

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

Вместо этого, мы рекомендуем явное, вместо неявного.

Интерактор — это объект который представляет конкретный сценарий использования.

Они позволяют каждому классу иметь единственную ответственность. Единственная ответственность интерактора — объединить объекты и вызовы методов для достижения определённого результата.


Идея

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

Вы должны написать только два публичных метода: __construct и call.
В php реализации интерактора метод call имеет модификатор protected и вызывается через __invoke.

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

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


Подготовка

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


Пишем интерактор

Давайте создадим папку для наших интеракторов и папку для их тестов:

$ mkdir lib/bookshelf/interactors
$ mkdir tests/bookshelf/interactors

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

Добавим интерактор AddBook и напишем новый тест tests/bookshelf/interactors/AddBookTest.php:

# tests/bookshelf/interactors/AddBookTest.php

<?php

use Lib\Bookshelf\Interactors\AddBook;

class AddBookTest extends TestCase
{        
   private function interactor()
   {
       return $this->app->make(AddBook::class);
   }

   private function bookAttributes()
   {
       return [
           "author" => "James Baldwin",
           'title' => "The Fire Next Time",
       ];
   }

   private function subjectCall()
   {
       return $this->interactor()($this->bookAttributes());
   }

   public function testSucceeds()
   {
       $result = $this->subjectCall();
       $this->assertTrue($result->successful());
   }
}

Запуск набора тестов вызовет ошибку Class does not exist, потому, что нет класса AddBook. Давайте создадим этот класс в файле lib/bookshelf/interactors/AddBook.php:

<?php

namespace Lib\Bookshelf\Interactors;

use Lib\Interactor\Interactor;

class AddBook
{
   use Interactor;

   public function __construct()
   {
   }

   protected function call()
   {
   }
}

Есть только два метода, которые должен содержать этот класс: __construct для настройки данных и call для реализации сценария.

Эти методы, особенно call, должны вызывать приватные методы, которые вы напишите.

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

Давайте запустим тест:

$ phpunit

Все тесты должны пройти!

Теперь давайте сделаем так, чтобы наш интерактор AddBook действительно что-то выполнял!


Создание книги

Изменим tests/bookshelf/interactors/AddBookTest.php:

   public function testCreateBook()
   {
       $result = $this->subjectCall();
       $this->assertEquals("The Fire Next Time", $result->book->title);
       $this->assertEquals("James Baldwin", $result->book->author);
   }

Если вы запустите тесты phpunit, то увидите ошибку:

Exception: Undefined property Lib\Interactor\InteractorResult::$book

Давайте заполним наш интерактор, затем объясним, что мы сделали:

<?php

namespace Lib\Bookshelf\Interactors;

use Lib\Interactor\Interactor;
use Lib\Bookshelf\Book;

class AddBook
{
   use Interactor;
   protected static $expose = ["book"];
   private $book = null;

   public function __construct()
   {
   }

   protected function call($bookAttributes)
   {
       $this->book = new Book($bookAttributes);
   }
}

Здесь следует отметить две важные вещи:

Строка protected static $expose = ["book"]; добавляет свойство book в объект результата который будет возвращён при вызове интерактора.

Метод call присваивает модель Book свойству book, которое будет доступно в результате.

Теперь тесты должны пройти.

Мы инициализировали модель Book, но она не сохраняется в базе данных.


Сохранение книги

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

Нам нужно использовать наш BookRepository, чтобы сохранить её.

// tests/bookshelf/interactors/AddBookTest.php

public function testPersistsBook()
{
   $result = $this->subjectCall();
   $this->assertNotNull($result->book->id);
}

Если вы запустите тесты, то увидите новую ошибку с сообщением Failed asserting that null is not null.

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

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

Отредактируйте метод call в файле интерактора lib/bookshelf/interactors/AddBook.php:

protected function call($bookAttributes)
{
   $this->book = Book::create($bookAttributes);
}

Вместо вызова new Book, мы делаем Book::create с атрибутами книги.

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

Если вы запустите тесты сейчас, вы увидите, что все тесты проходят.


Внедрение зависимостей (Dependency Injection)

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

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

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

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

// lib/bookshelf/interactors/AddBook.php

public function __construct(Book $repository)
{
   $this->repository = $repository;
}

protected function call($bookAttributes)
{
   $this->book = $this->repository->create($bookAttributes);
}

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

Прямо сейчас тест проверяет поведение метода create, на то, что его идентификатор заполнен $this->assertNotNull($result->book->id).

Это деталь реализации.

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

Давайте изменим тест testPersistsBook:

// tests/bookshelf/interactors/AddBookTest.php

public function testPersistsBook()
{
   $repository = Mockery::mock(Book::class);
   $this->app->instance(Book::class, $repository);
   $attributes = [
       "author" => "James Baldwin",
       'title' => "The Fire Next Time",
   ];

   $repository->expects()->create($attributes);
   $this->subjectCall($attributes);
}

Теперь наш тест не нарушает границы своей зоны.

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


Уведомление на электронную почту

Давайте добавим уведомление на электронную почту!

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

Мы оставим тело письма пустым, но в поле тема укажем «Book added!».

Создайте тест на уведомление tests/bookshelf/mail/BookAddedNotificationTest.php:

<?php

use Lib\Bookshelf\Mail\BookAddedNotification;
use Illuminate\Support\Facades\Mail;

class BookAddedNotificationTest extends TestCase
{
   public function setUp()
   {
       parent::setUp();
       Mail::fake();
       $this->mail = new BookAddedNotification();
   }

   public function testCorrectAttributes()
   {
       $this->mail->build();
       $this->assertEquals('no-reply@example.com', $this->mail->from[0]['address']);
       $this->assertEquals('admin@example.com', $this->mail->to[0]['address']);
       $this->assertEquals('Book added!', $this->mail->subject);
   }
}

Добавим класс уведомления lib/Bookshelf/Mail/BookAddedNotification.php:

<?php

namespace Lib\Bookshelf\Mail;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;

class BookAddedNotification extends Mailable
{
   use SerializesModels;
   public function build() {
       $this->from('no-reply@example.com')
           ->to('admin@example.com')
           ->subject('Book added!');

       return $this->view('emails.book_added_notification');
   }
}

Теперь все наши тесты проходят!

Но уведомление ещё не отправляется. Нам нужно вызвать отправку из нашего интерактора AddBook.

Отредактируем тест AddBook, чтобы убедиться, что почтовик будет вызван:

public function testSendMail()
{
   Mail::fake();
   $this->subjectCall();
   Mail::assertSent(BookAddedNotification::class, 1);
}

Если запустить тесты, мы получим ошибку: The expected [Lib\Bookshelf\Mail\BookAddedNotification] mailable was sent 0 times instead of 1 times..

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

public function __construct(Book $repository, BookAddedNotification $mail)
{
   $this->repository = $repository;
   $this->mail = $mail;
}

protected function call($bookAttributes)
{
   $this->book = $this->repository->create($bookAttributes);
   Mail::send($this->mail);
}

В результате интерактор отправит уведомление о добавлении книги на электронную почту.


Интеграция с контроллером

Наконец, нам нужно вызвать интерактор из экшена.

Отредактируем экшен файл app/Http/Controllers/BooksCreateController.php:

<?php

namespace App\Http\Controllers;

use Lib\Bookshelf\Interactors\AddBook;
use Illuminate\Http\Request;
use Illuminate\Http\Response;

class BooksCreateController extends Controller
{   
   /**
    * Create a new controller instance.
    *
    * @return void
    */
   public function __construct(AddBook $addBook)
   {
       $this->addBook = $addBook;
   }

   public function call(Request $request)
   {
       $input = $request->all();
       ($this->addBook)($input);
       return (new Response(null, 201));
   }
}

Наши тесты проходят, но есть небольшая проблема.

Мы дважды тестируем код создания книги.

Как правило, это плохая практика, и мы можем исправить это, проиллюстрировав еще одно преимущество интеракторов.

Мы собираемся удалить упоминание на BookRepository в тестах и использовать мок для нашего интерактора AddBook:

<?php

use Lib\Bookshelf\Interactors\AddBook;

class BooksCreateControllerTest extends TestCase
{
   public function testCallsInteractor()
   {
       $attributes = ['title' => '1984', 'author' => 'George Orwell'];       

       $addBook = Mockery::mock(AddBook::class);
       $this->app->instance(AddBook::class, $addBook);
       $addBook->expects()->__invoke($attributes);

       $response = $this->call('POST', '/books', $attributes);
   }
}

Теперь наши тесты проходят и они намного надежнее!

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

Это значительно упрощает экшены и их тесты.

Экшены практически освобождены от бизнес-логики.

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

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

Репозиторий с кодом

Let's block ads! (Why?)

Под капотом у чат-бота: что умеет и как работает RocketBot

RocketBot — это программируемый чат-бот, который интегрируется с VK, Telegram и Bitrix24. Сегодня мы расскажем об инфраструктуре и других технологиях, на которых он построен.


/ фото Darryl Braaten CC BY-SA

Инструментарий


Разрабатывая RocketBot, мы делали упор на скорость разработки и прототипирования. По этой причине система написана на Python, а в качестве базы данных выбрана MySQL.

На сегодняшний день Python занимает третье место в рейтинге TIOBE по популярности. Это означает, что у языка большое комьюнити и нескончаемое количество справочной литературы: книг, сайтов, курсов и исходников. Например, на GitHub можно найти сборники лучших практик по разработке на Python, а на StackOverflow открыто большое число тредов. Множество книг этому языку посвятило издательство O’Reilly, можно выделить «Автостопом по Python» и «Машинное обучение с Python».

Помимо большого количества источников, одним из главных преимуществ Python является разнообразие библиотек и функциональных ML-фреймворков. Примерами могут быть PyTorch и SciKit-learn — это мощные инструменты, которые упрощают обработку естественной речи, диалогов и скриптов.

В частности, для разработки моделей обучения мы использовали PyTorch, так как он обладает широкими возможностями для прототипирования. Дополнительно мы внедрили scikit-learn, который выполняет предварительную обработку данных, а также pymorth2 и gensim (для работы с морфологией и векторизации текстов соответственно). Еще мы испытываем DeepPavlov — оцениваем его возможности.

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

Что умеет наш чат-бот


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

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

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

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

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

Для составления скрипта используются три типа блоков:
  1. Блок вопроса — задает вопрос пользователю и пишет в переменную ответ на него.
  2. Блок условий — реализует ветвление скрипта.
  3. Блок проверки переменных — управляет маршрутом пользователя по скрипту.

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


Пример настроек с выходом из скрипта при ответе «Нет» на вопрос «Вам есть 18 лет?»

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

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

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

Для реализации системы обработки естественной речи пока используется очень простой алгоритм поиска. Со временем мы хотим реализовать новую версию на базе LSTM-сетей, использующую обучение с подкреплением (reinforcement learning). Скорее всего новая реализация будет основана на уже упомянутом фреймворке DeepPavlov.

Еще одной функцией нашего бота является интеграция с CRM-системами. RocketBot умеет автоматически создавать лид и задачу в CRM (Битрикс24) после выполнения скриптов. Бот пересылает все, что написал пользователь, плюс информацию о нем из мессенджера или социальной сети. Все работает по стандартным протоколам и через основной API CRM-систем в виде HTTP-запросов и данных в JSON.

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


/ фото spencer cooper CC BY-ND

Инфраструктура, на которой построен чат-бот


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

Сам бот представляет собой набор из пяти микросервисов, которые взаимодействуют друг с другом по HTTP–JSON (все внутренние коммуникации между сервисами проводятся в защищенном сегменте). Хотя это и приводит к возникновению задержек при ответе на вопрос в одну–две секунды, такая архитектура обладает большим потенциалом к масштабированию и позволяет нам модифицировать отдельные блоки, не затрагивая другие. Например, обновление микросервиса поиска в FAQ не затронет микросервис интеграции с CRM.

Для тестирования и создания моделей машинного обучения и нейронных сетей мы используем Nvidia Tesla M40 16GB. Но даже на ней обучение происходит не очень быстро. Своды данных, которые мы используем для задач обработки естественного языка, исчисляются десятками гигабайт. По этой причине в некоторых случаях (например, для векторизации датасетов) мы использовали виртуальные машины с 64 CPU.



Дополнительное чтение — посты из Первого блога о корпоративном IaaS:
Из нашего Telegram-канала:

Let's block ads! (Why?)

Смотрим фильмы дома: 10 материалов о строительстве домашнего кинотеатра и выборе оборудования

Это — подборка статей из нашего блога «Мир Hi-Fi». Здесь есть материалы, которые помогут вам собрать достойный домашний кинотеатр и подготовить для него помещение. Под катом — обзор 3D-телевизоров, советы по акустической коррекции и правила расстановки колонок.


Фото: PascalSijen / CC BY

Как выбрать аппаратуру для домашнего кинотеатра


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

  • HDMI 2.1 на подходе: что нужно знать. Отвечаем на основные вопросы про HDMI 2.1: зачем нужен новый стандарт, чем он отличается от предшественников и потребуется ли обновить HDMI-кабель, купив телевизор с поддержкой технологии. Среди достоинств новинки — способность передавать 4K-сигнал на скорости до 120 Гц и поддержка мониторов с динамической частотой обновления.

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

  • Руководство по выбору 3D-телевизора. Пошаговая инструкция по выбору 3D-телевизора. Вы узнаете, на каких характеристиках можно сэкономить, а за какие стоит доплатить. Специальная таблица поможет рассчитать оптимальный размер и разрешение телевизора. И, наконец, рассмотрим плюсы и минусы покупки такой техники в интернет-магазинах. В качестве введения — краткий обзор 3D-технологий: от привычных цветных очков до разработок в области безочковых экранов.

Как оформить помещение


  • Инсталляция потолочных колонок для окружающих форматов своими руками. Иллюстрированное руководство по установке потолочных колонок Dolby Atmos. В статье описан весь процесс: от этапа планирования до финальной настройки оборудования. Вы научитесь находить потолочные балки с помощью магнитов, правильно расставлять акустику, а также подбирать и протягивать кабели. Хотя оригинальная статья была написана для американского читателя, обустраивающего частный дом, она будет полезной и тем, кто проживает в квартире. Правда, в этом случае в помещении должен иметься подвесной потолок из гипсокартона.


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

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

  • Советы от THX: как получить от домашнего кинотеатра всё. Рекомендации по установке и настройке домашнего кинотеатра от технического директора THX Скотта Фрэнсиса (Scott Francis). Он рассказал, как выбрать место под колонки, какие ошибки легко допустить при размещении акустической системы и как настроить экран, принимая во внимание освещение. В качестве иллюстраций приводятся разные схемы расстановки колонок: в форматах 5.1, 7.1, Dolby True HD и DTS HD Master Audio.

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


Фото: Bryan Tong Minh / CC BY-SA
  • Строим домашний кинотеатр: акустическая обработка помещения. Выбираем комнату для домашнего кинотеатра. Автор рассматривает особенности и недостатки разных домашних пространств: от акустически подходящего, но неприглядного подвала, до гостиной. Внимание уделяется акустике комнаты и менее очевидным факторам, например накоплению тепла от техники.



О чем мы пишем в Telegram-канале:

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


Let's block ads! (Why?)

[Из песочницы] Ещё один манифест

Эджайл то, эджайл сё. Про эджайл сейчас не говорит только ленивый. Да и ленивый говорит. Все говорят. Из каждого утюга, даже выключенного из сети, топят за эджайл. Такое ощущение, что просто эпидемия какая-то разразилась. И не подумайте, что я только про ИТ. Коучи учат неофитов проводить стендапы с ретроспективами и жить по спринтам в любых бизнес-сферах: от булочных до парикмахерских. А некоторые менеджеры, наслушавшись коучей, так увлекаются, что забывают о природе данного явления, заставляя внедрять гибкие методологии негибкими методами: «Так, с завтрашнего дня мы все становимся гибкими. Что за «хихи»? Гибкими я сказал, а то всех нагну!». Так в чем же природа эджайл, на чем он зиждется?
Как мы знаем, в основе основ лежит так называемый манифест. Мало кто задумывается, что это такое и почему оно такое, воспринимая просто как данность (типа заповеди такие, которые, как ни странно, тоже на горе были записаны). Еще меньше людей пытаются разобраться в том, насколько это применимо к рассматриваемому ими случаю, чтобы не строить свои процессы в режиме натягивания совы на глобус. Ну и есть единицы, которые знают все о гибких методологиях. Они даже о мотивации отцов-основателей AgileAlliance знают больше них самих.

Я не настолько крут, но тем не менее у меня есть своя версия относительно того, как появился эджайл-манифест.

В 2001 году собрались 17 профессионалов-практиков в сфере ИТ (это как раз наши Моисеи, только на этот раз не на Синайском полуострове, а в штате Юта), покататься на лыжах и за одно обсудить проблемы индустрии разработки ПО. И вот начали они рассказывать друг другу, как им живется. Оказалось, что общего у них довольно много. Точнее много схожих проблем. И решили они, что надо с этими проблемами что-то делать (доколе можно терпеть, граждане?). И написали манифест…

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

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

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

И вот глядя на это все, пригорать начало уже у меня. И я подумал: «А чем я хуже? Возьму и напишу свой манифест!» И написал. Он ниже. За основу я брал официальную русскую версию манифеста agile и постарался сохранить общий подход, а где-то и части формулировок. В качестве бонуса я снабдил это дело не в меру вольными комментариями. Сразу скажу, что даже просто понять эту муть будет непросто: серьезность смешивается с иронией, а потоки сюрреалистического сумбура — с каплями квинтэссенции опыта. Ну и потом все это делится на ноль. Два раза. Для надежности. Хотя, если вы дочитали до этих строк, то вам должно быть уже нестрашно. Я в вас верю. Го!

Ценности


1. Контекст важнее лучших практик.

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

2. Общее понимание цели важнее методологических концепций.

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

3. Зафиксированное важнее воображаемого.

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

4. Подвижность ума важнее категоричности.

Любой перечень более, чем из 2-х пунктов (а уж целый манифест так тем паче), как правило, содержит весьма категоричные формулировки. Поэтому люди считают, что надо жестко все принять и жить с этим на уровне установок. Иначе грош цена такому перечню. Но Сократ однажды сказал (да-да, мне нравится ссылаться на вырванные из контекста изречения великих): «Категоричность выдает в человеке скудость ума». «Довольно категоричное утверждение!» скажете вы и, вероятно, будете правы. Только помните: Сократ, кроме того, что был самым умным из людей до Ницше, был еще и боксером, а посему мог отстоять свою точку зрения на разных уровнях. Наемным же работничкам ни один из этих уровней не светит, т.к. они запрещены либо корпоративной этикой, либо уголовным кодексом. Вот и получается быть только жесткими, а не гибкими. А может все же послушать Сократа и попробовать наоборот?

5. Апельсины важнее яблок.

Здесь все понятно.

Принципы


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

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

2. Изменение требований означает, что требования все-таки есть. Если есть требования – ими можно управлять. Управляйте требованиями.

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

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

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

4. На протяжении всего проекта разработчики и представители бизнеса должны ежедневно работать. Для достижения целей проекта.

Комментарий: несмотря на кажущуюся простоту, это самый сложный для понимания пункт. Сложно понять. Сложнее – принять. Еще сложнее – начать действовать. И практически подвиг – жить согласно этому принципу. Но если вы вдруг дойдете до вершины (говорят, что дорога к вершине Эвереста просто усыпана трупами тех, кто не смог и их используют как ориентиры), то вы разорвете и выйдете из круга Сансары хождения на работу. Вы станете над ней, вне ее. И только безграничное сознание собственной всемогущности будет напоминать вам о том, что вы еще существуете. Так, простите, я тут книгу по эзотерике в параллель читаю, так что… ну, вы все поняли.

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

Комментарий: многие думают, что эджайл не подразумевает управляторства. А зачем: продукт оунер задачи хоп и в бэклог записал, потом хопчик – и в сторис расписали, а тут, хоба – спланировали спринт и в разработку с автотестами и за две недели хабас – и в ПРОДас. Бывает и такое, не спорю. А бывает по-другому. И вот в этом «по-другому» без менеджера никак. Многие забывают о том, что вот эти обеспечение поддержки и условий, во многом и есть работа менеджера. А если вы еще хотите планировать, где окажетесь через два-три-шесть месяцев – тут и подавно. А если у вас еще 1-2-5-10 контрагентов, то уж точно. А если у вас и команд 5-10-20, то просто никак по-другому. До сих пор хотите без менеджмента? Видел я таких – ходят потом по собеседованиям, рассказывают, что стартап был годный, но не взлетел, ибо рынок еще не готов.

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

Комментарий: вы, должно быть, устали. Устал и я, т.к. думал, что текста на страничку напишу, а не вышло. Не выйдет и у вас, если будете ориентироваться на интуитивные представления о коммуникациях. Только в случае моей ошибки – потеря невелика, т.к. максимум этот манифест просто никто не дочитает до этих строк. А вот в реальной работе можно очень сильно поплатиться, если ваша коммуникация будет неэффективной. Потери могут быть разные: лишняя работа, испорченные отношения с заказчиком или членами команды, выбор неверного пути развития. В итоге: всегда исходите из ситуации. Иногда один звонок на минуту разговора может быть полезнее, чем гневная переписка с руководством в копии. А иногда без детальных формулировок в письменной форме или без таблицы с графиком просто невозможно передать суть ситуации и очень милые встречи face-to-face тут просто не помогут.

7. Работающий продукт сам по себе не показатель ничего.

Комментарий: а вы разве не знали?

8. Процесс работы должен способствовать устойчивому развитию. Ритм работы должен обеспечивать ее комфорт и эффективность.

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

9. Постоянное внимание к техническому совершенству и качеству проектирования снижает вероятность серьезного рефакторинга при развитии продукта.

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

10. Простота — искусство минимизации лишней работы — крайне необходима, когда она уместна.

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

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

Комментарий: простите, но в манифесте без патетики никуда. Ни в оригинальном, ни в моем.

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

Комментарий: как часто риторически вопрошает одна моя коллега «А не фигню ли мы делаем?». Ответив на ее вопрос отрицательно, я всегда чувствую острую потребность проверить «А не фигово ли мы делаем?», раз она спрашивает. Советую сделать эти два вопроса минимальным чек-листом для непрерывного анализа своей деятельности. Иначе, как у нас в народе говорят, удачи не видать.

13. Подписывайте манифест… и выкидывайте его.

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

Let's block ads! (Why?)

На пути к физическим принципам биологической эволюции

Сокращенный перевод статьи М. Кацнельсона, Ю. Вольфа и Е. Кунина

Возможна ли конвергенция физики и биологии?


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

Towards physical principles of biological evolution
Mikhail I. Katsnelson, Yuri I. Wolf, Eugene V. Koonin

Аннотация


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

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

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

Введение


В чем отличия живых организмов от неживой материи? Существует очевидный ответ на этот вопрос при определении в терминах химического состава и структуры. (По крайней мере, потому, что только единственный подходящий случай, а именно жизни на Земле, относится к этому). Но когда это касается основных процессов эволюции жизни, различие становится менее очевидным. В дарвиновской традиции заманчиво утверждать, что жизнь определяется эволюцией посредством выживания наиболее приспособленного [1-4]. Однако уникальность этого процесса может подвергаться сомнению, так как вся история Вселенной состоит из изменений, которые выдерживают наиболее стабильные (приспособленные) структуры. Более того, процесс репликации (размножения) сам по себе не является уникальным и существует не только в биологии: кристаллы также реплицируют. На макроскопических масштабах времени и пространства, однако, жизнь, несомненно, представляется явным феноменом. Для объективного определения характерных признаков, по которым жизнь отличается от прочих феноменов, существующих во Вселенной, представляется важным исследовать ключевые процессы биологической эволюции в рамках теоретической физики [5, 6].

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

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

И все же возникает еще такой рубежный вопрос: является ли современная физика достаточно наполненной для обслуживания (обеспечения поддержки) биологии? Подобный вопрос, в различных формулировках (в частности, “сводима ли биология к физике”), имеет долгую и весьма драматическую историю (например, [17, 18]).

Не вдаваясь в подробности исторического или философского плана, мы отклоняем любое предположение о том, что жизнь, возможно, следует неким специальным законам “биологической” физики вместо имеющихся общих. Так например, квантовая механика, в общем вполне действенна и приложима к живым организмам, точно также как к любой другой форме материи. Проблема в том, что эта сильная теория, до известной степени, может рассматриваться в качестве “теории всего”, так как привносит немного при объяснении биологических феноменов [19, 20]. Конечно, квантово-механические вычисления могут быть полезны при анализе биохимических реакций, но они никак не могут помочь нам в понимании эволюции. Поэтому предполагается, что физическая концепция, которая могла бы быть основной при теоретическом описании биологических феноменов — это появление (или возникновение, emergency), то есть, коллективное поведение больших совокупностей, которое качественно отличается от поведения составляющих их компонентов. “More is different” так афористично формулирует это Anderson [19-24].

В своей книге, содержащей плодотворные идеи «Что такое жизнь? Физический аспект живой клетки» Шрёдингер высказал несколько основных положений, которые даже по прошествии 70 лет остаются в основе множества обсуждений относительно значимости физики для биологии [25]. Вероятно, наиболее существенным является характеристика (в то время гипотетическая) молекулярных носителей наследственности как “апериодических кристаллов”. Шрёдингер был неточен в таком определении апериодического кристалла, и до сих пор такая метафора охватывает основные свойства, которые были открыты впоследствии (не без влияния Шрёдингера) биологических носителей информации, ДНК и РНК [26-28].

Молекулы нуклеиновых кислот, в частности ДНК, соединяют единообразие (и периодичность) пространственной структуры с эффективностью множественного разнообразия (апериодичностью) основной последовательности. Соединение этих отличительных признаков делает нуклеиновые кислоты единственными из известных молекулами, подходящими для хранения и передачи цифровой информации [29], в полном соответствии с предвидением Шрёдингера. Что касается современной физики, под биологическими “апериодическими кристаллами” иногда подразумеваются “стекла” [19, 20]. На самом деле существуют глубокие аналогии, на различных уровнях, между состоянием стекла и биологическими структурами и обсуждаемыми ниже явлениями. При этом, будет показано, что имеются и существенные различия: в известном смысле, стекла проявляют чрезмерную беспорядочность.

Кросспост

Продолжение следует

Let's block ads! (Why?)

Teamlead Conf 2019 Msk: про ещё один формат общения

Всем привет!

Уже меньше месяца остается до Teamlead Conf 2019 — профессиональной конференции о тимлидах и для тимлидов. Мы определились с финальной программой и отобрали, на наш взгляд, лучшие 32 доклада из почти 140-ти поданных заявок. Да, конкурс в этот раз составил рекордные для нас 4,3 доклада на место, и это, поверьте, та еще проблема для программного комитета. Мы провели очень много времени совещаясь, какие же из заявок принимать в финальную программу, а какие все же оставить за бортом. Было огромное количество качественных докладов, которые не прошли дальше только потому, что у нас в системе были ещё более качественные. Под катом мысли про конференцию и анонс нового трека.
Вообще, когда мы начали думать над этой конференцией, мы сознательно подняли себе планку выше. Мы уже писали о том, что хотим перевалить за отметку 700 участников, для чего даже решили уйти из уютного Инфопространства в более просторную Radisson Slavyanskaya. А чтобы выполнить завышенный план, надо и качество поднимать, не правда ли? Вот отсюда и взялся такой сумасшедший конкурс, сами виноваты :) Но мы все это делаем ради участников, так что не жалуемся.

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

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

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

  • Работа с удалёнными сотрудниками и распределёнными командами — это рабочее название для темы, которая была, пожалуй, самой популярной среди всех заявок на доклады — управление разработкой в распределенных условиях. Это и аутсорс с западными заказчиками, и большие компании с офисами в разных городах, и внештатные фрилансеры. Как управлять людьми и проектами, когда между вами тысячи километров и несколько часовых поясов? Попробуем разобраться вместе.
  • Знают ли ваши сотрудники, кто отвечает за их персональный рост в компании? – тема персонального роста сотрудников крайне важна. Хороший руководитель всегда должен стремиться, чтобы его подчиненные каждый день узнавали что-то новое и прогрессировали. На этом круглом столе попробуем разобраться, кто же все-таки ответственен за их рост и какова роль руководителя в этом процессе.
  • Как тимлидам эффективно взаимодействовать с HR и не сойти с ума – разработка и HR — друзья или враги? Тема очень наболевшая, таящая в себе множество взаимных обид и непониманий. Попытаемся найти общий язык и узнать, где HR может и должен быть другом тимлиду.
  • Управление знаниями в проектных командах – «Байки старичков — лучшая документация» vs «Мы пишем тонну спек и отлично себя чувствуем». Обсудим, как примирить эти две позиции, почему и как можно успешно сочетать самодокументируемый код, устную традицию и документацию as is. Спойлер: мы пока и сами не знаем. Поэтому ждем помощи из зала и живого общения.
  • Workshop «Опыт как игра: управляем конфликтом между командами» – не совсем круглый стол, но тоже крайне интересная активность. Ольга Давыдова и Василий Тарарышкин из ЦФТ попробуют за два часа провести тренинг/workshop, на котором участникам предстоит примерить на себя роль модератора конфликта и найти выход из «горячей» ситуации между командами. В ходе мастер-класса участники смогут обменяться взглядами и подходами к решению конфликтов, попробовать себя в роли ведущего группового обсуждения.
  • У нас есть еще один козырь в рукаве, который мы пока не готовы показать. Тот же формат на 2 часа, но про уникальный навык, который не у всех есть, но который можно развить. Больше ничего не скажу, следите за анонсом.

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

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

Надеемся на лучшее и ждем вас на Teamlead Conf 2019 25-26 февраля в Москве в Radisson Slavyanskaya. Билеты ещё есть, места тоже. Не упустите возможность принять участие в самой крупной тусовке тимлидов.

До встречи!

Let's block ads! (Why?)

[Из песочницы] Modbus на российском микроконтроллере К1986ВЕ92QI

Попал мне в руки российский микроконтроллер К1986ВЕ92QI производства АО "ПКК Миландр" с 32-битным RISC ядром ARM Cortex-M3 128кБ Flash и 32кБ ОЗУ, сразу же захотелось изучить и опробовать его в действии.

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

К микроконтроллеру идет этикетка и протокол отбора продукции, что очень даже приятно.

Для начала нужно было разработать принципиальную схему отладочной платы и определится с компонентами. Остановился на минимуме компонентов: стабилизатор на 3.3в для питания от USB порта, кварцевый резонатор на 8МГц, разъем miniUSB, кнопка сброса, подтягивающие резисторы и sip разъемы. Думаю для начальных опытов с микроконтроллером хватит. Также установил smd переключатель для выбора режима встроенного загрузчика. Микроконтроллер позволяет выбирать метод загрузки программы по одному из двух последовательных интерфейсов UART или JTAG/SWD, при этом JTAG позволяет производить отладку программы в микроконтроллере. Выбор метода загрузки программы определяется логическими уровнями на выходах PF4, PF5, PF6. Все возможные варианты представлены в таблице:

Микроконтроллер представляет из себя микросхему выполненную в пластиковом корпусе LQFP64 с выводами шириной 0.3мм и с расстоянием между ними 0.2мм, что навело на мысль о невозможности создать печатную плату приемлемого качества по технологии ЛУТ, но опыт подтвердил обратное. За пару часов был сделан чертеж печатной платы в Sprint Layout, распечатан на бумаге повышенной плотности Lamond и перенесен на стеклотекстолит. Травление происходило в растворе перекиси и лимонной кислоты на глазок и заняло около часа, на удивление качество проводников оказалось приемлемым с первого раза, что порадовало.

И так плата создана, все компоненты распаяны, остается запрограммировать. Будем использовать среду для разработки от Keil — MDK ARM uVision 5.0, к ней производителем микроконтроллера распространяется библиотека Standard Peripherals Library + software pack. По UART программировать не хотелось, поэтому решил использовать внутрисхемный программатор/отладчик ST-Link v2, а точнее его клон от неизвестного китайского производителя. Keil его поддерживает “из коробки”, а вот микроконтроллер, хоть и в документации сказано, что поддерживает SWD интерфейс, но как и куда что подключать упомянуть забыли. После поисков в интернете по запросу: “JTAG — SWD переходник” было выяснено, что линия SWDIO подключается к JTAG-TMS, а SWCLK к JTAG-TCK и “О чудо!” все заработало, в микроконтроллер прошилась тестовая программа.

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

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

Для создания проектов в Keil на микроконтроллере от Миландр нужно для начала установить software pack. Делается это простым двойным кликом мыши по файлу. Далее Keil все сделает сама.

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

В дереве проекта создаем группу Modbus Slave и добавляем туда следующие файлы из библиотеки Freemodbus:

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

Теперь можно приступить конкретно к портированию библиотеки Freemodbus под наш микроконтроллер с использованием Standard Peripherals Library. Для этого нужно в файле portserial.c прописать функцию инициализации порта UART xMBPortSerialInit

BOOL
xMBPortSerialInit( UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits, eMBParity eParity )
{

        // Включение тактирования порта F
        RST_CLK_PCLKcmd(RST_CLK_PCLK_PORTF, ENABLE); 
        // Объявление структуры для инициализации порта
        PORT_InitTypeDef uart2_port_set;  
        // Инициализация порта F для функции UART
        // Настройка порта по умолчанию
        PORT_StructInit(&uart2_port_set);  
        // Переопределение функции порта
        uart2_port_set.PORT_FUNC = PORT_FUNC_OVERRID;  
        // Установка короткого фронта
        uart2_port_set.PORT_SPEED = PORT_SPEED_MAXFAST;  
        // Цифровой режим работы вывода
        uart2_port_set.PORT_MODE = PORT_MODE_DIGITAL;  
        // Инициализация вывода PF1 как UART_TX (передача)
        uart2_port_set.PORT_Pin = PORT_Pin_1;
        uart2_port_set.PORT_OE = PORT_OE_OUT;
        PORT_Init(MDR_PORTF, &uart2_port_set);
        // Инициализация вывода PF0 как UART_RX (прием)
        uart2_port_set.PORT_Pin = PORT_Pin_0;
        uart2_port_set.PORT_OE = PORT_OE_IN;

        // Процедура инициализации контроллера UART
        // Включение тактирования UART2
        RST_CLK_PCLKcmd(RST_CLK_PCLK_UART2, ENABLE);
        // Объявление структуры для инициализации контроллера UART
        UART_InitTypeDef UART_InitStructure;
        // Делитель тактовой частоты UART = 1
        UART_BRGInit(MDR_UART2,UART_HCLKdiv1);
        // Конфигурация UART
        // Скорость передачи данных – 115200 бод
        UART_InitStructure.UART_BaudRate = ulBaudRate;
        // Количество бит в посылке – 8
        UART_InitStructure.UART_WordLength = UART_WordLength8b;
        // Один стоп-бит
        UART_InitStructure.UART_StopBits = UART_StopBits1;
        // Без проверки четности
        UART_InitStructure.UART_Parity = UART_Parity_No;
        // Выключить работу буфера FIFO приемника и передатчика,
        // т.е. передача осуществляется по одному байту
        UART_InitStructure.UART_FIFOMode = UART_FIFO_OFF;
        // Разрешить прием и передачу данных
        UART_InitStructure.UART_HardwareFlowControl = UART_HardwareFlowControl_RXE | UART_HardwareFlowControl_TXE;
        // Инициализация UART2 с заданными параметрами
        UART_Init(MDR_UART2, &UART_InitStructure);
        // Включить сконфигурированный UART
        UART_Cmd(MDR_UART2, ENABLE);

    return TRUE;
}

функцию записи и чтения:

BOOL
xMBPortSerialPutByte( CHAR ucByte )
{
        //Отправляем байт
            UART_SendData(MDR_UART2,ucByte);

    return TRUE;
}

BOOL
xMBPortSerialGetByte( CHAR * pucByte )
{
            //Читаем байт
    *pucByte = (uint8_t) UART_ReceiveData(MDR_UART2);
    return TRUE;
}

обработчик прерываний UART

    void USART2_IRQHandler(void)
{

  /* Событие при приеме байта ---------------------------------------------------*/
  if((UART_GetITStatus(MDR_UART2,UART_IT_RX)) != RESET)
  { 
         prvvUARTRxISR(  ); 
  }

  /* Событие при передаче байта ------------------------------------------------*/
  if((UART_GetITStatus(MDR_UART2,UART_IT_TX)) !=RESET)
  {
    prvvUARTTxReadyISR(  );
  } 
}

Следом за этим правим файл portimer.c в котором настраивается таймер который формирует временные отчеты для отслеживания конца пакета протокола modbus.

BOOL
xMBPortTimersInit( USHORT usTim1Timerout50us )
{
        MDR_RST_CLK->PER_CLOCK |= (1<<14); // Включение тактирования TIM1
        MDR_RST_CLK->TIM_CLOCK = 0x0;
        MDR_RST_CLK->TIM_CLOCK |= (1<<24); // TIM1_CLK_EN
        MDR_RST_CLK->TIM_CLOCK |= 0x07; // HCLK/8 выбор частоты

        MDR_TIMER1->CNTRL = 0x00000002; //Запись регистра управления
        MDR_TIMER1->CNT = 0x00000000; //Обнуление регистра
        MDR_TIMER1->PSG = 0x2; //f/1 выбор предделителя
        while((MDR_TIMER1->CNTRL & 0x004) != 0) {__NOP();} //ожидание конца записи делителя

        MDR_TIMER1->ARR = usTim1Timerout50us; // установка базы основного счетчика
        while((MDR_TIMER1->CNTRL & 0x004) != 0) {__NOP();} //ожидание записи базы основного счетчика

        MDR_TIMER1->IE = 0x00000002; //(CNT==ARR)->IE выбор действия для срабатывания прерывания
        NVIC->ISER[0] = (1<<14); // Global EN for IRQ14 разрешаем прерывание
        MDR_TIMER1->CNTRL |= (1<<0); //Timer1 ON включаем таймер
    return TRUE;

}

inline void
vMBPortTimersEnable(  )
{
    /* Разрешаем работу таймера */
        MDR_TIMER1->CNTRL |= (1<<0); //Timer1 ON
}

inline void
vMBPortTimersDisable(  )
{
    /* Запрещаем работу таймера */
        MDR_TIMER1->CNTRL &= ~(1<<0); //Timer1 OFF
}

static void prvvTIMERExpiredISR( void )
{
    ( void )pxMBPortCBTimerExpired(  );
}

void Timer1_IRQHandler(void)
{
    //Обработчик прерывания таймера
        MDR_TIMER1->STATUS &= ~0x002; //IE FLAG=0
     prvvTIMERExpiredISR( );
}

В main.c добавим функции обработки регистров modbus, неиспользуемые регистры заглушим заглушками

/* ----------------------- Defines ------------------------------------------*/
#define REG_INPUT_START 1000
#define REG_INPUT_NREGS 4

/* ----------------------- Static variables ---------------------------------*/
static USHORT   usRegInputStart = REG_INPUT_START;
static USHORT   usRegInputBuf[REG_INPUT_NREGS];

eMBErrorCode
eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
{
    eMBErrorCode    eStatus = MB_ENOERR;
    int             iRegIndex;

    if( ( usAddress >= REG_INPUT_START )
        && ( usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS ) )
    {
        iRegIndex = ( int )( usAddress - usRegInputStart );
        while( usNRegs > 0 )
        {
            *pucRegBuffer++ =
                ( unsigned char )( usRegInputBuf[iRegIndex] >> 8 );
            *pucRegBuffer++ =
                ( unsigned char )( usRegInputBuf[iRegIndex] & 0xFF );
            iRegIndex++;
            usNRegs--;
        }
    }
    else
    {
        eStatus = MB_ENOREG;
    }

    return eStatus;
}

eMBErrorCode
eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs,
                 eMBRegisterMode eMode )
{
    return MB_ENOREG;
}

eMBErrorCode
eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils,
               eMBRegisterMode eMode )
{
    return MB_ENOREG;
}

eMBErrorCode
eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
{
    return MB_ENOREG;
}

На этом портирование закончено, осталось только в функции int main(void) инициализировать библиотеку и в цикле вызывать eMBPoll( );

int main (void) 
{

     eMBErrorCode    eStatus;
//Настройки UART не поддерживаются кроме скорости, необходимо в portserial.c в xMBPortSerialInit описать выбор режимов

    eStatus = eMBInit( MB_RTU, 0x0A, 0, 19200, MB_PAR_NONE ); 

        /* Enable the Modbus Protocol Stack. */
    eStatus = eMBEnable(  );

    while(1)
    {
    eStatus = eMBPoll(  );
        //обработчик ошибок
        if (eStatus!= MB_ENOREG){};

        /* Here we simply count the number of poll cycles. */
        usRegInputBuf[0]++;
    }

}

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


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

Ну что же не беда, ищем где происходит начало передачи, в файле mbrtu.c находим строчки кода

/* Activate the transmitter. */
        eSndState = STATE_TX_XMIT;
        vMBPortSerialEnable( FALSE, TRUE );

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

Let's block ads! (Why?)

[Перевод] Почему жульничает дружественный ИИ в Ghost Recon Wildlands

При создании игр разработчики одержимы желанием создать для игроков интересный и увлекательный игровой процесс: поставить их в новые условия или по-новому взглянуть на знакомые. И иногда для этого необходимо немного сжульничать. Разработчики вносят небольшие изменения в системы геймплея или в определённые базовые функции геймдизайна. Это относится и к неигровым персонажам. Ксеноморф из Alien Isolation имел на спине сенсоры ближнего радиуса действия, и «режиссёр» всегда знал, где находится пользователь, враги в Far Cry становились чуть менее точными, когда воевали с игроком, а демоны из DOOM терпеливо ждали своей очереди, чтобы получить шанс разорвать игрока на клочки. Это может казаться контринтуитивным, но ограничивая поведение персонажей или давая им больше знаний и навыков, чем это необходимо, разработчики в некоторых случаях способны сделать игровой процесс более целостным. И это подводит нас к исследованию Ghost Recon Wildlands компании Ubisoft: выпущенной в 2017 году экшн-игры в открытом мире, в которой игроки методично уничтожают наркокартель Санта-Бланка.

В этой статье я расскажу о трёх управляемых ИИ неигровых персонажах, работающих с игроком в офлайновых миссиях: Холте, Мидасе и Уивере. Эта команда призраков должна иметь возможность отвечать на команды игрока и реагировать на окружающий его мир, в то же время поддерживать создаваемую игрой иллюзию, в то время, как вы тайно уничтожаете вражеские командные посты или идёте в лоб на боевом вертолёте, разнося всё на куски. Это интересная задача дизайна. Игра стала одним из выдающихся современных примеров того, как ИИ жульничает не для того, чтобы выполнять то, чего от него ожидают, а потому что мы, игроки, не можем смириться со своим провалом.
Управляемые искусственным интеллектом напарники в серии игр Ghost Recon должны поддерживать игрока и создавать ощущение скрытных оперативников, проникающих в здания и уничтожающих силы противника. В том числе они должны указывать игроку цели, выполнять синхронизированные убийства нескольких врагов по команде, а также постоять за себя, когда становится жарко. Ghost Recon Wildlands берёт все эти элементы и значительно увеличивает их масштаб, что представляет серьёзную проблему для гейм-дизайнеров. В отличие от более старых игр серии, например Ghost Recon: Future Soldier, здесь количество уникальных ситуаций возрастает экспоненциально. Частично это происходит из-за системных элементов геймплея, управляющих погодой, патрулирующими противниками и мятежниками, гражданским населением и многим другим. Игроки могут нападать на лагеря врага под любым углом и использовать при этом множество инструментов. Поэтому системы ИИ для дружественных персонажей должны приспосабливаться, в некоторых случаях игнорировать свои правила, а иногда и попросту жульничать, чтобы поддержать иллюзию, обещаемую Ghost Recon. Теперь для ИИ всех персонажей в Ghost Recon Wildlands используется система деревьев поведений (behaviour tree), при этом дружественный ИИ использует гораздо более сложную систему, чем враги. Сегодня я не буду подробно рассказывать о реализации самих деревьев поведений, а объясню применённые правила дизайна и поддерживающие системы, помогающие в управлении ИИ-напарниками.

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

  • Не перетягивать одеяло на себя: напарники поддерживают игрока, не переключая при этом основное внимание на себя.
  • Поддерживать там, где это нужно: ИИ призрака должен реагировать на окружения и помогать при необходимости.
  • Следовать приказам: делать то, что прикажет игрок, насколько это возможно в текущих обстоятельствах.

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

Как подробно рассказано в докладе Матиаса Ролланда на As GameAI North 2017, управление напарниками состоит из трёх геймплейных систем, направляющих ИИ отряда призраков:

  • Система Smart Recon: находит интересные предметы и персонажей в локальной близости
  • Система Balance of Power: влияет на то, насколько напарники эффективны в бою.
  • И обе эти системы связываются в одну большую под названием Overlord: это набор подсистем, определяющий весь список угроз поблизости от игрока и различную полезную информацию, которую напарники могут максимально эффективно использовать в бою.

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

Допустим, я хочу напасть на базу со скриншота выше. Это плотно заполненная локация, в ней есть враги, транспорт, а также, без всяких сомнений, по окрестностям ходят патрули и расставлены охранные посты. Когда я приближаюсь, вступает в дело система Overlord, которая начинает идентифицировать всех врагов примерно в радиусе 100 метров от меня. Она не только отслеживает, насколько они далеко, но и то, находимся ли я и напарники на их линии видимости. Тем временем Холт, Мидас и Уивер скрытно приближаются за мной к базе. Чтобы знать, куда идти, мой персонаж оставляет метки на навигационном меше, чтобы отряд знал, как ему двигаться. Достигнув лагеря, напарники получают инструкции от Overlord о том, как перемещаться по пространству. Получив всю необходимую информацию о находящихся поблизости персонажах врагов, Overlord знает, в какие области карты не должен двигаться отряд, чтобы его не заметили.

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

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


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

Теперь может возникнуть вопрос: способны ли члены команды промахиваться? На самом деле промахнуться они не могут, потому что не стреляют. Команда разработчиков ИИ в Wildlands называет это «магическим выстрелом» (Magic Shot): отряд притворяется, что стреляет по вашей команде во врага, а все вражеские ИИ просто падают замертво. Благодаря имитации выстрела они не могут промахнуться, а значит вы не провалите миссию таким простым образом.

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


Но проникнув на базу, я решаю пошуметь и начать переполох. В этот момент не только дружественный ИИ поддерживает меня и начинает атаковать врагов, но и система Overlord переключается в режим боя. Поэтому значительно меняется информация о приоритетах целей, а также о местах для перемещения по миру. Кроме того, в дело вступает система Balance of Power. По сути, эта система — инструмент балансировки в реальном времени, который делает отряд призраков в процессе развития боя более или менее эффективным: он влияет на урон от их выстрелов, частоту атак и общую стойкость напарников. Эффективность отряда зависит от того, как игрок проявляет себя в избегании урона и уничтожении врагов. Плюс напарники в начале боя получают дополнительный бонус, чтобы помочь игроку избежать смерти, когда начинается хаос. Возвратимся к основам дизайна: они не только часто целятся, чтобы поддержать, но и стремятся находиться поблизости от игрока, чтобы тот знал об их поддержке. После завершения перестрелки система Smart Recon по-прежнему работает, и они продолжают находить цели, например, снайперов, о которых игрок забыл, или другие боевые вертолёты.

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


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

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


Создание персонажей поддержки для игр наподобие Ghost Recon Wildlands никогда не было простой задачей. Игроки часто бывают… ненадёжны. Поэтому необходимо разрабатывать системы, способные вести себя как положено в скрытном проникновении, серьёзных перестрелках и просто при блужданиях по карте. Мне, как разработчику игр, очень отрадно видеть, как такая AAA-игра идёт на большие уступки для обеспечения качественного игрового процесса. В статье я часто использовал слово «жульничать», но оно не означает, что игрок отклоняется от задуманного дизайнерами геймплея. Подобные трюки просто сглаживают серьёзные проблемы реализации, которые запросто могут возникнуть в игре подобного масштаба. Делать умный ИИ для игр в открытом мире намного сложнее, чем можно представить, поэтому если занимаешься этим, то вполне можно срезать углы. Даже если это означает, что ИИ сможет телепортироваться на летящий вертолёт.
  • Mathias Rolland, Teammates AI in the systemic open world of Ghost Recon Wildlands, Game AI North 2017

Let's block ads! (Why?)