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

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

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

 

 -Статистика

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

Habrahabr/New








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

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

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

[Из песочницы] Любопытная особенность языка Java и коварные ошибки, которые она может повлечь

Понедельник, 11 Сентября 2017 г. 14:06 + в цитатник
Fisfis сегодня в 14:06 Разработка

Любопытная особенность языка Java и коварные ошибки, которые она может повлечь

Привет, Хабр! Представляю вашему вниманию перевод статьи A Curious Java Language Feature and How it Produced a Subtle Bug автора Lukas Eder.

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

package p;
 
import static p.A.x;
 
class A {
    static String x = "A.x";
}
 
class B {
    String x = "B.x";
}
 
class C {
    String x = "C.x";
 
    class D extends B {
        void m() {
            System.out.println(x);
        }
    }
}
 
public class X {
    public static void main(String[] args) {
        new C().new D().m();
    }
}

Будет выведено:

B.x

Потому, что:

Члены суперкласса B скрывают все вложенные элементы класса C, которые, в свою    очередь, перекрывают статический импорт класса A.

Каким же образом все это может привести к ошибкам?


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

package p;
 
import static p.A.x;
 
class A {
    static String x = "A.x";
}
 
class B {
    private String x = "B.x"; // Здесь изменен модификатор доступа
}
 
class C {
    String x = "C.x";
 
    class D extends B {
        void m() {
            System.out.println(x);
        }
    }
}
 
public class X {
    public static void main(String[] args) {
        new C().new D().m();
    }
}

Теперь, как ни странно, B.x больше не видим для метода m(), в данном случае применяется уже другое правило. А именно:

Вложенные элементы (классы) скрывают статический импорт

И в итоге мы получаем следующий результат:

C.x

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

package p;
 
import static p.A.x;
 
class A {
    static String x = "A.x";
}
 
class B {
    private String x = "B.x";
}
 
class C {
    String xOld = "C.x"; // Здесь внесены изменеия
 
    class D extends B {
        void m() {
            System.out.println(x);
        }
    }
}
 
public class X {
    public static void main(String[] args) {
        new C().new D().m();
    }
}

Как все мы знаем 50% переменных, которые более не будут использоваться переименовываются и получают приставку “old”.

В этом финальном варианте кода остается единственное возможное значение x в при вызове метода m() и это статически импортированный A.x. Таким образом, вывод будет следующим:

A.x

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


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

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

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

Заключение


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

https://habrahabr.ru/post/337648/


Метки:  

15 лет в ISDEF: опыт старейшего участника

Понедельник, 11 Сентября 2017 г. 13:37 + в цитатник
Spbwriter сегодня в 13:37 Маркетинг

15 лет в ISDEF: опыт старейшего участника

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

    Ассоциация ISDEF – это полузакрытый клуб IT-предпринимателей, дающий возможность отсеивать незнакомых членам клуба бизнесменов, что делает обмен опытом более откровенным. Так сказать, “междусобойчик”. Мы решили представить вам подробное интервью с Павлом Козловским, участником Ассоциации, автором старейших в нише приложений для учета личных финансов и ведения семейного бюджета “Домашняя Бухгалтерия” (успешно развивается с 1998 года), в котором он делится своим опытом участия в ISDEF. Павел в нашем клубе уже 15 лет и старается не пропускать его мероприятия ни весной, ни осенью.

    image

    Оргкомитет: Павел, что такое ISDEF для тебя?

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

    Оргкомитет: Как давно ты состоишь в Ассоциации? Как в нее попал?

    Павел Козловский: Наверное, лет 15 назад. Я попал на конференцию буквально на второй или третий год, поскольку ассоциация тогда только образовалась. Так как мы всегда общались с коллегами через Интернет, узнал про ISDEF, мне стало интересно, что это такое. Приехал посмотреть в первый раз и с тех пор ни одной конференции больше не пропустил – ни осенней, ни весенней. Собираюсь продолжать в том же духе!

    Оргкомитет: Чем именно зацепила конференция?

    Павел Козловский: Зацепило, что в одном месте собирается большое число людей, которые занимаются одним и тем же делом. То есть ты попадаешь в среду, где все разговаривают на одном языке, имеют одинаковые проблемы, ищут их решения. Общение происходит в профессиональном сообществе, которого в свое время не было вообще. [“Речь о русскоязычном сообществе владельцев ИТ-бизнесов на собственных программных продуктах” — примечание оргкомитета]. Уже позже, когда новые люди начали появляться, конечно, стали больше обмениваться опытом. Я нанимал сотрудников с ISDEF. И вообще ISDEF – это что-то вроде энергетической накачки и проверки боем. Если люди какое-то время в ассоциации состоят, то с ними можно иметь дело.

    PR: Оргкомитет: А поменялось вообще что-нибудь за время существования конференции?

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

    PR: Оргкомитет: Какую ты видишь ценность для себя в участии в ISDEF?

    Павел Козловский: Уже довольно много существует таких конференций и собраний. ISDEF – небольшая ассоциация (300 человек членов и активных помощников), это не тысяча людей. В ней я практически всех знаю, со всеми лично знаком. Одна из приятных сторон – ты приезжаешь один-два раза в год на конференцию, видишься с друзьями, общаешься — это очень полезно, позитивно. И, опять же, те же самые друзья, люди, с которыми ты уже знаком, могут рассказать тебе такие вещи, о которых ты не услышишь в другом месте. Cекреты, достижения свои, лайфхаки – довольно много можно вынести ценной информации. ISDEF – всегда небольшой эмоциональный взрыв. То есть после нее рождаются новые планы, идеи, ты что-то пересматриваешь — что ты делал не так, что делают другие, смотришь, сравниваешь. И тем самым ты перенимаешь опыт у других.

    image

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

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

    Оргкомитет: Твой топ спикеров на осенней конференции ISDEF 2017?

    Павел Козловский: Мне всегда очень интересно (если судить по рейтингу и количеству слушателей) слушать топ-менеджеров, которые добились больших результатов, смогли развить свою компанию, перейти на новый уровень. Слушать людей, у которых что-то получилось, у них можно набраться опыта и в принципе это интересные докладчики. Можно выделить Александра Лысковского, Сергея Рыжикова и др. Очень интересно рассказывает Дима Калаев. Мне интересно в общем-то все. Так как я руководитель в своей небольшой компании, мне интересны все темы — поверхностно, не углубляясь, познакомиться и быть в курсе всего. То есть выделить что-то конкретное сложно. Единственное, что отличает меня от многих членов ISDEF – то, что мои клиенты в сегменте B2C работают, то есть на консьюмеров обращено все. И у меня 95% рынка – это Россия, не заграница, то есть мне больше интересно развитие рынка и маркетинга в России.
    image

    PS: Наша ежегодная осенняя конференция ISDEF 2017 пройдет 29-30 сентября в Виноградово (это еще Москва, но в километре от подмосковного Долгопрудного) и соберет традиционно 150-250 участников из разных ниш ИТ-бизнеса (сейчас зарегистрировано 100 участников, но 30-50 членов ISDEF обычно регистрируются перед самой конференцией, пользуясь своей льготой на участие, так что мы рассчитываем на комфортную “посещаемость” в 150-200 человек). И все это в уютной “ламповой” атмосфере без пафоса и излишеств.

    PPS: Сегодня, 11 сентября, последний день, когда можно зарегистрироваться со скидкой за 12000 рублей или $200, цена без скидки составит уже $300 (18000 рублей), и регистрация будет закрыта через 2 недели, 25 сентября. Посмотрите всех спикеров и примите решение, но наш совет: смотреть нужно всех зарегистрированных;)
    Original source: habrahabr.ru (comments, light).

    https://habrahabr.ru/post/337458/


    Метки:  

    tig — улучшаем продуктивность работы с git

    Понедельник, 11 Сентября 2017 г. 13:29 + в цитатник
    imrobot2002 сегодня в 13:29 Разработка

    tig — улучшаем продуктивность работы с git

      Всем привет,


      хочу рассказать о консольной утилите, которая значительно увеличила мою продуктивность работы с Git, и, надеюсь, ускорит и вашу также. Называется она tig и была написана канадским программистом Джонасом Фонсека (Jonas Fonseca) ещё в далёком 2006-м году, но по настоящий день она активно развивается и поддерживается в великолепном состоянии. Я хочу показать её функционал (внимание, есть относительно тяжелые gif-ки внутри) и поделиться самыми удобными способами использования.



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


      Установка


      Установка подробно описана в документации на главной странице проекта.
      Если вы работаете в MacOS, то tig доступен через Homebrew:


       brew install tig

      В Linux она тоже доступна для всех основных репозиториев:


      apt-get install tig
      yum install tig

      Для остальных вариантов, стандартная схема — скачать исходный код (из релизов или через git clone и выполнить make && make install. Это подробно описано в ссылке выше.


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


      Вот коротенькое демо того, как выглядит интерфейс при запуске команды tig из директории репозитория:



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


      Главная клавиша это — h: показать окно помощи :)



      Как видим, есть несколько режимов (views) — главный, режим просмотра diff-ов, режим лога, режим просмотра дерева файлов, blame режим, просмотр текущего статуса и т.д.


      Между всеми этими режимами переключаться довольно просто, обычно достаточно стрелочками (или j/k) выбрать нужную запись в логе или файл и нажать Enter, либо, как, например, в случае с blame — соответствующую клавишу (b).


      Режимы отображаются либо на весь экран либо в dual-split режиме. Последний бывает либо горизонтальный, либо вертикальный — программа сама выбрает его в зависимости от соотношения сторон терминала, и умеет обновлять на лету. Чтобы закрыть текущий режим (и вернуться к предыдущему) — просто нажимаем q (quit). Чтобы, наоборот, развернуть окно с текущим режимом на полный экран — O. Переключаться между режимами в dual-split режиме — Tab.


      В режиме просмотра diffочень удобно увеличивать количество строк сверху и снизу изменённой строки с помощью [ и ] (уменьшить и увеличить, соответственно):



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


      Drop-in замена git


      Для некоторых команд tig может спокойно работать как drop-in замена git.


      tig status
      tig log
      tig show
      tig blame file
      tig grep pattern
      tig refs
      tig stash
      tig status

      Также, в режиме pager-а:


      git show | tig

      Конфигурация


      tig достаточно гибкий в плане настройки — у него есть файл конфигурации (путь к которому также можно конфигурировать через TIGRC_USER) — ~/.tigrc и поддержка readline.


      Можно создавать свои собственные команды. Например, следующая команда копирует ID коммита в буфер обмена на MacOS X:


      bind generic 5 !@sh -c "echo %(commit) | pbcopy"


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


      Заключение


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


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


      Ссылки


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

      https://habrahabr.ru/post/337644/


      Метки:  

      PDF отчеты по дашбордам Kibana

      Понедельник, 11 Сентября 2017 г. 12:55 + в цитатник
      Crait сегодня в 12:55 Администрирование

      PDF отчеты по дашбордам Kibana


        Вот ты собрал свой модный мониторинг. ElasticSearch принимает данные от чего бы то ни было, а кибана их рисует. Ты смотришь на графики один день, второй, третий и через некоторое время под грузом новых задач ты забываешь об этом. Вспоминаешь когда нужно показать начальникам какую-то отчетность, заходишь в кибану, делаешь скриншоты, и думаешь, что неплохо было бы иметь средство, которое это делало за тебя.
        Да, это умеет делать X-Pack, но он стоит денег. Да, это умеет делать sentinl, но чтобы его настроить нужно будет повозиться, а пдф рисовать он так и не научился. А нужно всего ничего: сделать пару скриншотов, собрать из них PDF и отправить на почту, повторить через неделю.
        Мы сделали это за тебя. Все, что нужно сделать – склонировать репозиторий, описать желаемый отчет в конфиге, вписать данные о почте ( откуда и куда отправлять ) и вот, отчеты уже у вас. Летят по расписанию, ага.

        Допустим, у вас есть развернутая кибана и три дашборды, которые вы хотели бы показать в отчете. Тогда вы описываете эти дашборды в разделе pages конфиг файла ( урл дашборды, заголовок и описание для отчета ). Выглядеть это будет примерно вот так:
        "pages":[
          {
            "url": "http://0.0.0.0:5601/app/kibana#/dashboard/ca460a50-8cb0-11e7-a2bb-9b97b18ab1d8?embed=true&_g=()",
            "title": "Заголовок 1",
            "description": "За неделю"
          },
          {
            "url": "http://0.0.0.0:5601/app/kibana#/dashboard/e05c6b70-8cb2-11e7-a2bb-9b97b18ab1d8?embed=true&_g=()",
            "title": "Заголовок 2 ",
            "description": "За неделю"
          },
          {
            "url": "http://0.0.0.0:5601/app/kibana#/dashboard/233acc20-8cb3-11e7-a2bb-9b97b18ab1d8?embed=true&_g=()",
            "title": "Заголовок 3",
            "description": "За неделю"
        }
        ]


        После этого осталось только вписать данные о почте, и желаемый временной промежуток ( как часто будут лететь отчеты ) в секундах:
        
        "smtp_server": "smtp.yandex.ru",
          "email_subject": "Регулярный отчет",
          "email_text": "Регулярный отчет со статистикой по",
          "email_from": "email@fr.om",
          "email_password":"password",
          "time_interval": 120,
        "email_to": "email@t.o",
        

        После конфигурирования осталось только запустить Reporter и он сам начнет работать:
        docker-compose up -d

        Все, теперь у Вас есть не только красивые графики, но и отчеты по расписанию, которые можно использовать, например в связке с мониторингом настроек TLS в роще доменов.
        github.com/AverageS/kibanareports — вот здесь лежит исходный код, и простая, в три строчки инструкция настройки и запуска.
        Original source: habrahabr.ru (comments, light).

        https://habrahabr.ru/post/337576/


        Метки:  

        [Из песочницы] Learnopengl. Урок 2.5 — Источники света

        Понедельник, 11 Сентября 2017 г. 12:44 + в цитатник

        Метки:  

        Кто все эти люди? Давайте спросим К50

        Понедельник, 11 Сентября 2017 г. 12:37 + в цитатник
        i-cat сегодня в 12:37 Разработка

        Кто все эти люди? Давайте спросим К50



          Привет, Хабр. Не будем лить воду до ката, сразу приступим к делу. Оптимизатор ставок в контекстной рекламе платформа К50 предлагает своим клиентам инструменты для увеличения эффективности рекламы. Большая часть имеет отношение к онлайн-среде, что вполне логично, ведь речь идет о сетевых технологиях. Для компаний, у которых обращения по телефону составляют 30% (а в некоторых тематиках – до 70-80%) от общего числа входящих обращений, данных для анализа рекламы было недостаточно. Именно для таких клиентов К50 решили разработать сервис, чтобы получить детальную информацию по каждому звонку, включая его длительность, запись, ключевое слово и цепочку событий-визитов, которая и привела клиента. Звучит сложно, но реализовано это было достаточно оперативно благодаря готовым компонентам Voximplant (ну, чуть-чуть себя похвалили, простите).


          Динамичный конструктор для динамического колл-трекинга


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

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

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

          Испытание Voximplant в полевых условиях


          К50 арендует у нас пул виртуальных номеров. Если их клиенты подключили статический колл-трекинг, то виртуальных номеров нужно немного: достаточно по одному на каждый канал. В динамическом колл-трекинге номер-«маска» “подменяется” для каждого пользователя, поэтому количество номеров рассчитывается в зависимости от количества юзеров и длительности сеанса. К50 предлагают своим клиентам номера для 60 городов России и 30 стран (столько же, сколько и мы предлагаем всем разработчикам Voximplant).

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


          После звонка Voximplant отдает все данные в K50: время, длительность и запись разговора, номер подмены, номер переадресации и прочее. Собранные данные К50 анализирует и ранжирует для каждого из пользователей отдельно, в соответствии с данными, которые уже собраны: цепочка визитов, источник и ключевое слово.

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



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

          И обратно


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

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

          Еще картинка:


          И что в итоге?


          Для того чтобы начать отслеживать звонки, клиент К50 должен установить код счетчика на свой сайт. Ничего сложного.

          Трекер синхронизирован с аналитикой К50, Google Analytics и CRM клиента, и поэтому клиенты могут проследить всю воронку продаж – и узнать, какой именно звонок привел к покупке. На основе данных от Трекера (просмотр страниц, звонил ли за консультацией), можно в режиме реального времени настраивать рекламные кампании и показывать новые сообщения – для этого есть специализированные сервисы К50.

          К50 работают на нас с ноября 2015 года. Ну и для того, чтобы вы оценили масштаб сотрудничества наших платформ, укажем объемы обрабатываемых звонков – 180 тысяч ежемесячно, с определением источника каждого звонка и получением детализированной информации об абоненте. Вроде неплохо, как считаете? Если нужно больше технической информации, с удовольствием предоставим, спрашивайте.

          Картинка до ката взята с сайта The Irish Time.
          Original source: habrahabr.ru (comments, light).

          https://habrahabr.ru/post/336522/


          Метки:  

          Монетизация приложений в iOS 11: таргетируем встроенные покупки в новом App Store

          Понедельник, 11 Сентября 2017 г. 11:34 + в цитатник
          Groozze сегодня в 11:34 Разработка

          Монетизация приложений в iOS 11: таргетируем встроенные покупки в новом App Store



            На WWDC’17 Apple показала обновленный интерфейс App Store и представила ряд нововведений. Среди них были продвигаемые встроенные покупки, которые с выходом iOS 11 будут выводится прямо в поиске и редакторских подборках наряду с приложениями.

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

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

            - (BOOL)paymentQueue:(SKPaymentQueue *)queue 
            shouldAddStorePayment:(SKPayment *)payment 
                      forProduct:(SKProduct *)product;

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

            Для того чтобы встроенную покупку сделать продвигаемой, необходимо заполнить специальные метаданные, недавно появившиеся в iTunes Connect: рекламное изображение, заголовок и краткое описание. После прохождения review изменений покупка появится в новом разделе «Продвижение в App Store», где можно в любой момент поменять значения видимости по умолчанию для всех пользователей и их порядок отображения на странице приложения в App Store. Так можно продвигать до 20 встроенных покупок одновременно и неограниченное количество покупок держать в режиме готовности к включению.



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

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

            А конкретнее?


            Рассмотрим новые методы API, предоставляемые Apple для совершения данных манипуляций.

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


            Чтобы изменить порядок и видимость этих покупок, нам нужно получить объекты покупок по их sku через SKProductsRequest:

            - (void)requestProducts
            {
                SKProductsRequest* productRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObject:@"gold.iap.example.com"]];
                productRequest.delegate = self;
                [productRequest start];
            }
            
            - (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
            {
                NSArray* products = response.products;
                // do some stuff
            }

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

            - (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
            {
                if (@available(iOS 11.0, *)) {
                    NSArray* products = response.products;
                    [[SKProductStorePromotionController defaultController] updateStorePromotionOrder:products completionHandler:^(NSError * _Nullable error) {
                        if(error != nil) {
                            NSLog(@"Update store promotion order failed with error: %@", [error description]);
                        } else {
                            NSLog(@"Success");
                        }
                    }];
                } else {
                    // Fallback on earlier versions
                }
            }

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


            Порядок изменился. Данным вызовом мы установили приоритет для товара gold.iap.example.com. Теперь он показывается первым.

            Если бы мы передали несколько товаров, они бы отображались в том порядке, в котором мы их передали. Далее идут остальные товары в их порядке по-умолчанию (то есть заданном в iTunes Connect). Если в качестве списка товаров передать nil, переопределение сбросится и все товары вернутся в первоначальное положение. Получить текущий установленный порядок можно вызовом:

            - (void)fetchPromotionOrder
            {
                if (@available(iOS 11.0, *)) {
                    [[SKProductStorePromotionController defaultController] fetchStorePromotionOrderWithCompletionHandler:^(NSArray * _Nonnull storePromotionOrder, NSError * _Nullable error) {
                        if(error != nil) {
                            NSLog(@"Fetch store promotion order failed with error: %@", [error description]);
                        } else {
                            NSMutableString* productIds = [NSMutableString string];
                            for (SKProduct* product in storePromotionOrder) {
                                [productIds appendString:product.productIdentifier];
                                [productIds appendString:@"; "];
                            }
                            NSLog(@"Got promotion order: %@", productIds);
                        }
                    }];
                } else {
                    // Not supported
                }
            }

            Метод вернет только те товары, порядок которых был переопределен, в порядке их переопределения.

            Другая доступная пара методов взаимодействует с видимостью товаров. Выполнив следующий код мы переопределим видимость переданного товара gold.iap.example.com (в этих методах передается только один товар):

            - (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
            {
                if (@available(iOS 11.0, *)) {
                    SKProduct* product = [response.products objectAtIndex:0];
                    [[SKProductStorePromotionController defaultController] updateStorePromotionVisibility:SKProductStorePromotionVisibilityHide forProduct:product completionHandler:^(NSError * _Nullable error) {
                        if(error != nil) {
                            NSLog(@"Update store promotion visibility failed with error: %@", [error description]);
                        } else {
                            NSLog(@"Success");
                        }
                    }];
                } else {
                    // Fallback on earlier versions
                }
            }

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


            Другим методом можно получить текущую установленную видимость товара:

            - (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
            {
                if (@available(iOS 11.0, *)) {
                    SKProduct* product = [response.products objectAtIndex:0];
                    [[SKProductStorePromotionController defaultController] fetchStorePromotionVisibilityForProduct:product completionHandler:^(SKProductStorePromotionVisibility storePromotionVisibility, NSError * _Nullable error) {
                        if(error != nil) {
                            NSLog(@"Fetch store promotion visibility failed with error: %@", [error description]);
                        } else {
                            NSLog(@"Promotion visibility %ld", (long)storePromotionVisibility);
                        }
                    }];
                } else {
                    // Fallback on earlier versions
                }
            }

            Enum SKProductStorePromotionVisibility имеет следующие доступные значения: Show (товар виден), Hide (товар скрыт), Default (значение видимости берется из iTunes Connect).

            Таким образом, список встроенных покупок можно подстраивать для каждого конкретного пользователя как угодно. Инструмент — в руках разработчика, остается самое главное: продумать правила показа, ведь именно от них зависит успех продаж тех или иных встроенных покупок и доход от приложения в целом. Все это демонстрирует желание Apple сделать App Store настоящим местом для покупок, а не банальным сервисом для хранения и поиска приложений.

            Ссылка на документацию от Apple: developer.apple.com/app-store/promoting-in-app-purchases
            Original source: habrahabr.ru (comments, light).

            https://habrahabr.ru/post/337482/


            STM32 без HAL и SPL

            Понедельник, 11 Сентября 2017 г. 11:19 + в цитатник
            sanders1967 сегодня в 11:19 Разработка

            STM32 без HAL и SPL

              В свое время, более 5 лет, при поиске информации о 32-разрядных микроконтроллерах, обратил внимание, что практически все примеры для STM32 подразумевали использование SPL (Standard Peripherals Library). Цитата из Википедии:
              STM32F10x Standard Peripherals Library (сокр. STM32F10x SPL) — библиотека, созданная компанией STMicroelectronics на языке Си для своих микроконтроллеров семейства STM32F10x. Содержит функции, структуры и макросы для облегчения работы с периферией микроконтроллера."

              В настоящее время, для снижения порога вхождения и ускорения разработки предлагается использовать STM32CUBE. Цитата с сайта STM:
              STM32Cube embedded software libraries, including:
              The HAL hardware abstraction layer, enabling portability between different STM32 devices via standardized API calls
              The Low-Layer (LL) APIs, a light-weight, optimized, expert oriented set of APIs designed for both performance and runtime efficiency
              A collection of Middleware components, like RTOS, USB library, file system, TCP/IP stack, Touch sensing library or Graphic Library (depending on the MCU series)

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

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

              Инициализация периферии.


              Порты

              .
              Для многих проектов нужно просто включать или выключать соответствующие ноги контроллера и считывать аналоговые значения.

              Включение порта: 1 строчка кода:
              //инициализация порта A*************************
              RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;

              Перевод 0 пина порта A в аналоговый режим 2 строчки:
              //PA0 - PA0/ADC1_ADC2_ADC3_IN0
              // GPIO_Pin_0 порта A аналоговый вход
              GPIOA->MODER |= GPIO_MODER_MODER0_0;
              GPIOA->MODER |= GPIO_MODER_MODER0_1;

              Перевод 2 пина порта A в режим выхода (пуш-пулл) 1 строчка:
              GPIOA->MODER |= GPIO_MODER_MODER2_0;

              Использование альтернативных функций тоже не очень сложно.
              Часто микроконтроллер используется для управления полумостовым преобразователем. Для этого нужно соответствующие пины порта сконфигурировать, как комплементарные выходы ШИМ.
              Определение выхода 8 порта А, как ШИМ выход CH1 счетчика TIM1 (3 строчки):
              //PA8/TIM1_CH1
              // Alternate function mode
              GPIOA->MODER &= ~GPIO_MODER_MODER8_0; //0
              GPIOA->MODER |= GPIO_MODER_MODER8_1; //1
              //GPIO alternate function high register (GPIOx_AFRL)
              //AFR8[3:0] = 0001: AF1
              GPIOA -> AFR[1] |= 0x00000001;

              Определение выхода 13 порта B, как ШИМ выход CH1N счетчика TIM1:
              //PB13/TIM1_CH1N
              // Alternate function mode
              GPIOB->MODER &= ~GPIO_MODER_MODER13_0; //0
              GPIOB->MODER |= GPIO_MODER_MODER13_1; //1
              //GPIO alternate function high register (GPIOx_AFRL)
              //AFR13[3:0] = 0001: AF1
              GPIOB -> AFR[1] |= 0x00100000;


              Закономерный вопрос: где взять обозначения нужных регистров и битов? Ответ: в 3-ех документах (на примере 746).
              1. Reference manual STM32F7.pdf
              2. STM32F745xx.pdf
              3. stm32f746xx.h
              Этих 3 файлов полностью хватает для того, чтобы правильно обращаться ко всем регистрам микроконтроллера.

              АЦП

              .
              Пример инициализации АЦП для работы в режиме DMA. В этом режиме 4 канала АЦП2 автоматически переключаются по кругу и передают данные контроллеру DMA, который складывает данные в массив.
              void init_ADC1(void)
              {
              RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; //подаем тактирование АЦП
              ADC1->CR2 |= ADC_CR2_ADON; //включить АЦП
              ADC1->CR1 |= ADC_CR1_EOCIE;
              ADC1->CR1 |= ADC_CR1_SCAN; // Bit 8 SCAN: Scan mode
              ADC1->CR2 |= ADC_CR2_EOCS; //Bit 10 EOCS: End of conversion selection
              ADC1->CR2 |= ADC_CR2_DMA; //Bit 8 DMA: Direct memory access mode (for single ADC mode)
              ADC1->CR2 |= ADC_CR2_DDS; //Bit 9 DDS: DMA disable selection (for single ADC mode

              //Bits 23:20 L[3:0]: Regular channel sequence length (4)
              //0003: 4 conversion
              ADC1->SQR1 |= ADC_SQR1_L_0; //1
              ADC1->SQR1 |= ADC_SQR1_L_1; //1
              ADC1->SQR1 &= ~ADC_SQR1_L_2; //0
              ADC1->SQR1 &= ~ADC_SQR1_L_3; //0

              //Bits 4:0 SQ1[4:0]: 1st conversion in regular sequence PC0/ADC1_ADC2_ADC3_IN10
              ADC1->SQR3 &= ~ADC_SQR3_SQ1_0; //0
              ADC1->SQR3 |= ADC_SQR3_SQ1_1; //1
              ADC1->SQR3 &= ~ADC_SQR3_SQ1_2; //0
              ADC1->SQR3 |= ADC_SQR3_SQ1_3; //1
              ADC1->SQR3 &= ~ADC_SQR3_SQ1_4; //0

              //Bits 4:0 SQ2[4:0]: 2st conversion in regular sequence PC1/ADC1_ADC2_ADC3_IN11
              ADC1->SQR3 |= ADC_SQR3_SQ2_0; //1
              ADC1->SQR3 |= ADC_SQR3_SQ2_1; //1
              ADC1->SQR3 &= ~ADC_SQR3_SQ2_2; //0
              ADC1->SQR3 |= ADC_SQR3_SQ2_3; //1
              ADC1->SQR3 &= ~ADC_SQR3_SQ2_4; //0

              //Bits 4:0 SQ3[4:0]: 3st conversion in regular sequence PC2/ADC1_ADC2_ADC3_IN12
              ADC1->SQR3 &= ~ADC_SQR3_SQ3_0; //0
              ADC1->SQR3 &= ~ADC_SQR3_SQ3_1; //0
              ADC1->SQR3 |= ADC_SQR3_SQ3_2; //1
              ADC1->SQR3 |= ADC_SQR3_SQ3_3; //1
              ADC1->SQR3 &= ~ADC_SQR3_SQ3_4; //0

              //Bits 4:0 SQ4[4:0]: 4st conversion in regular sequence PC3/ADC1_ADC2_ADC3_IN13
              ADC1->SQR3 |= ADC_SQR3_SQ4_0; //1
              ADC1->SQR3 &= ~ADC_SQR3_SQ4_1; //0
              ADC1->SQR3 |= ADC_SQR3_SQ4_2; //1
              ADC1->SQR3 |= ADC_SQR3_SQ4_3; //1
              ADC1->SQR3 &= ~ADC_SQR3_SQ4_4; //0

              NVIC_EnableIRQ (ADC_IRQn);
              }

              ПДП

              .
              Инициализация одного потока ПДП для передачи данных из АЦП в массив (см. выше)
              //Тактирование DMA2
              RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN;

              //Stream3 Channel 1 DMA2 - в массив ADC2_array 2 каналa

              //Bits 27:25 CHSEL[2:0]: Channel selection (1)
              DMA2_Stream3->CR |= DMA_SxCR_CHSEL_0; //1
              DMA2_Stream3->CR &= ~DMA_SxCR_CHSEL_1; //0
              DMA2_Stream3->CR &= ~DMA_SxCR_CHSEL_2; //0

              //Bits 14:13 MSIZE[1:0]: Memory data size (16 bit)
              DMA2_Stream3->CR |= DMA_SxCR_MSIZE_0; //1
              DMA2_Stream3->CR &= ~DMA_SxCR_MSIZE_1; //0

              //Bits 12:11 PSIZE[1:0]: Peripheral data size (16 bit)
              DMA2_Stream3->CR |= DMA_SxCR_PSIZE_0; //1
              DMA2_Stream3->CR &= ~DMA_SxCR_PSIZE_1; //0

              //Bits 10 MINC: Memory increment mode
              DMA2_Stream3->CR |= DMA_SxCR_MINC;

              //Bits 7:6 DIR[1:0]: Data transfer direction (00: Peripheral-to-memory)
              DMA2_Stream3->CR &= ~DMA_SxCR_DIR_0; //0
              DMA2_Stream3->CR &= ~DMA_SxCR_DIR_1; //0

              //Bits 4 TCIE: Transfer complete interrupt enable
              DMA2_Stream3->CR |= DMA_SxCR_TCIE;

              //Bits 15:0 NDT[15:0]: Number of data items to transfer
              //1000 point x 4 channel
              DMA2_Stream3-> NDTR = 4000;

              //Bits 31:0 PAR[31:0]: Peripheral address
              DMA2_Stream3->PAR = (uint32_t) &(ADC2->DR);

              //Bits 31:0 M0A[31:0]: Memory 0 address
              DMA2_Stream3->M0AR = (uint32_t) ADC2_array;

              //Bits 0 EN: Stream enable / flag stream ready when read low
              DMA2_Stream3->CR |= DMA_SxCR_EN;

              NVIC_EnableIRQ (DMA2_Stream0_IRQn);


              Таймеры

              .
              Пример конфигурации таймера с комплементарными 12-разрядными ШИМ выходами для управления 3 полумостами (3-фазный инвертор)
              // TIM1 PWM
              RCC -> APB2ENR |= RCC_APB2ENR_TIM1EN; //тактирование TIM1

              TIM1->CR1 |= TIM_CR1_CMS_0; //Center-aligned mode 1
              TIM1->CR1 |= TIM_CR1_ARPE;

              //частота ШИМ
              //прескалер 8 и период 4000 - 3000 Гц
              //частота шины 108 МГц

              TIM1->PSC = 8;
              TIM1->ARR = 4000;

              TIM1->CCR1 = 1000; //начальные значения
              TIM1->CCR2 = 1000;
              TIM1->CCR3 = 1000;

              TIM1->CCMR1 &= ~TIM_CCMR1_OC1M_0;
              TIM1->CCMR1 |= TIM_CCMR1_OC1M_1;
              TIM1->CCMR1 |= TIM_CCMR1_OC1M_2; //110: PWM mode 1

              TIM1->CCMR1 &= ~TIM_CCMR1_OC2M_0;
              TIM1->CCMR1 |= TIM_CCMR1_OC2M_1;
              TIM1->CCMR1 |= TIM_CCMR1_OC2M_2; //110: PWM mode 1

              TIM1->CCMR2 &= ~TIM_CCMR2_OC3M_0;
              TIM1->CCMR2 |= TIM_CCMR2_OC3M_1;
              TIM1->CCMR2 |= TIM_CCMR2_OC3M_2; //110: PWM mode 1

              TIM1->CCER |= TIM_CCER_CC1E; // Capture/Compare 1 output enable
              TIM1->CCER |= TIM_CCER_CC1NE; // Capture/Compare 1 complementary output enable
              TIM1->CCER |= TIM_CCER_CC2E; // Capture/Compare 2 output enable
              TIM1->CCER |= TIM_CCER_CC2NE; // Capture/Compare 2 complementary output enable
              TIM1->CCER |= TIM_CCER_CC3E; // Capture/Compare 3 output enable
              TIM1->CCER |= TIM_CCER_CC3NE; // Capture/Compare 3 complementary output enable

              //DTG[7:0]: Dead-time generator setup 1 mks
              TIM1->BDTR |= TIM_BDTR_DTG_0;
              TIM1->BDTR |= TIM_BDTR_DTG_1;
              TIM1->BDTR |= TIM_BDTR_DTG_2;
              TIM1->BDTR |= TIM_BDTR_DTG_3;
              TIM1->BDTR |= TIM_BDTR_DTG_4;
              TIM1->BDTR |= TIM_BDTR_DTG_5;
              TIM1->BDTR |= TIM_BDTR_DTG_6;
              TIM1->BDTR |= TIM_BDTR_DTG_7;

              TIM1->DIER |= TIM_DIER_CC1IE; //Capture/Compare 1 interrupt enable
              //TIM1->DIER |= TIM_DIER_CC2IE; //Capture/Compare 2 interrupt enable
              //TIM1->DIER |= TIM_DIER_CC3IE; //Capture/Compare 3 interrupt enable

              TIM1->CR1 |= TIM_CR1_CEN; //Bit 0 CEN: Counter enable
              TIM1->BDTR |= TIM_BDTR_MOE; //MOE: Main output enable

              NVIC_EnableIRQ (TIM1_CC_IRQn); //разрешить прерывания от таймера


              Пример конфигурации таймера для формирования прерываний по времени.
              Прерывания от этого таймера, как правило, используются для обновления данных в
              интерфейсах. В этом режиме внешние выходы таймера не используются.
              // TIM3 100 мсек
              RCC -> APB1ENR |= RCC_APB1ENR_TIM3EN; //TIM3 Timer clock enable

              TIM3->CR1 |= TIM_CR1_CEN; //Bit 0 CEN: Counter enable
              TIM3->CR1 |= TIM_CR1_ARPE; //Bit 7 ARPE: Auto-reload preload enable
              TIM3->DIER |= TIM_DIER_UIE; //Bit 0 UIE: Update interrupt enable

              TIM3->PSC = 2000;
              TIM3->ARR = 5400;
              NVIC_EnableIRQ (TIM3_IRQn); //разрешить прерывания от таймера

              Эти файлы конфигурации используются практически без изменения длительное время. Начиналось это все еще на 103 контроллере, сейчас используется на 7 серии. :)
              Конечно инициализация АЦП, таймеров и ПДП чуть сложнее, чем портов, но тоже простая задача.
              При этом не используются внешние библиотеки, более компактный код, более предсказуемое поведение контроллера.
              Original source: habrahabr.ru (comments, light).

              https://habrahabr.ru/post/337622/


              Метки:  

              Быстрый рендеринг океанских волн на мобильных устройствах

              Понедельник, 11 Сентября 2017 г. 11:16 + в цитатник
              SSul сегодня в 11:16 Разработка

              Быстрый рендеринг океанских волн на мобильных устройствах



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


                В этой статье мы хотели поговорить о моделировании волн в открытом море и представить алгоритм, который позволил достичь достаточно интересные результаты при приемлемых 25-30Fps на среднем китайфоне.


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


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


                Генерация волн


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


                Простое, но неестественное море

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



                Тот же алгоритм, но издали наблюдается периодичность.



                Более оптимально использовать шум Перлина, пример генерации которого на шейдерах представлен ниже (код для Cg, для GLSL требует косметических изменений):


                float rand(float2 n) {
                    return frac(sin(dot(n, float2(12.9898, 4.1414))) * 43758.5453);
                }
                
                float noise(float2 n) {
                    const float2 d = float2(0.0, 1.0);
                    float2 b = floor(n), f = smoothstep(0, 1, frac(n));
                return lerp(lerp(rand(b), rand(b + d.yx), f.x), lerp(rand(b + d.xy), rand(b + d.yy), f.x), f.y);
                }

                rand — генерирует псевдослучайное значение, а noise интерполирует четыре случайный числа в углах квадрата на любую точку внутри него.


                Шум перлина

                Периодичности не наблюдается



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


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


                $h = 1- 2|h|$



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




                Фазовое распределение и анимация


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


                float amp = maxHeight / 2;
                for (int i = 0; i < count; ++i){
                    h += amp * phase(pos + v[i]*t);
                    pos *= sp;
                    amp /= sa;
                }

                Хорошие результаты получаются при выборе sp, sa равным 2, но мы вольны выбирать любые значения, обеспечивающие приемлемые результаты. Подбор этих параметров позволяет получить разнообразные типы волн и управлять их изменением вплоть до полного штиля.


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


                Оптимизация


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


                • Шум Перлина: Для каждого вертекса требуется 4 случайных значения, т.е 4 sin, 4 fract и прочие более простые операции.
                • Расчет для 7 волн — 28 sin.
                • Расчет нормалей к поверхности: Кроме высоты самой точки нам необходимо знать высоты 2 соседних точек. Соответственно, количество расчетов увеличивается в 3 раза — до 84! операций вычисления sin.

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


                • Попробовать сократить число фаз, но как упоминалось ранее, желательно иметь порядка 7 фаз для приемлемого отображения. А меньшее число значительно ухудшает "качество" волн.
                • Попробовать заменить затратную операцию вычисления шума на выборку из готовой текстуры. Вместо 84 sin мы получаем уже 21 выборку (т.к. для шума Перлина требуется 4 sin).

                Карта высот-нормалей


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


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


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


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


                Пример карты высот с нормалями

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


                Дополнительная оптимизация


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


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


                Разогнанная карта высот

                Это решает проблему генерации множества волн небольшим количество проходов, однако при анимации становится заметно, что часть волн движется с одной скоростью. Для уменьшения этого эффекта можно сохранять в текстуру волны с большей разницей фаз, например 1 — 3 — 5, а при рендеринге мы получим 1-1'-3-3'-5-5'. Также мы использовали подход при котором первые две фазы из четырех использовали одну текстуру, а последние две уже другую с иным распределением и количеством фаз. Именно этим способом получено изображение, приведенное в начале поста


                Недостатки метода


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

                Еще немного про оптимизацию


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


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


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


                Линия горизонта


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


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


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


                Проецируемая сетка


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


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

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


                Этот метод имеет несколько преимуществ:


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

                Расчет освещения


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


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


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

                $1-cos(a)$


                . В то же время замена формулы на

                $R_0+(1-R_0)(1-cos(a))^5, R_0=0.04$


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

                Результаты


                Приведенный способ симуляции воды мы реализовали в Unity3D. Для расчета освещения и создания формы волн мы использовали явные вертексные и фрагментные шейдеры (можно было реализовать и на поверхностных шейдерах, но это не играет принципиальной роли). При тестах на андроид смартфонах мы получили от 25 к/c (Adreno 405 + MediaTek MT6735P) до 45 (Adreno 505 + Snapdragon 430). На части смартфонах, как и ожидалось, приложение на заработало из-за отсутствия поддержки чтения из текстуры в вершинном шейдере. При этом интересно отметить, что расчет освещения в результате оказался сопоставим со сложностью c генерацией волн. При необходимости можно поднять fps за счет использования других моделей освещения или отключения части элементов как карта окружения, блики и т.д


                Итоговое изображение+анимация

                Анимации с 7 фазами волн



                Ютуб


                Анимации с 4 фазами



                Ютуб

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

                https://habrahabr.ru/post/336998/


                Метки:  

                Pygest #17. Релизы, статьи, интересные проекты из мира Python [29 августа 2017 — 11 сентября 2017]

                Понедельник, 11 Сентября 2017 г. 10:35 + в цитатник
                andrewnester сегодня в 10:35 Разработка

                Pygest #17. Релизы, статьи, интересные проекты из мира Python [29 августа 2017 — 11 сентября 2017]

                  image Всем привет! Это уже семнадцатый выпуск дайджеста на Хабрахабр о новостях из мира Python.

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

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


                  Статьи


                  Что за чёрт, Python
                  Занимательна статья о «необычностях» в Python

                  PyTorch — ваш новый фреймворк глубокого обучения
                  Хорошая «разборная» статья о фреймворке PyTorch

                  The Incredible Growth of Python
                  О росте популярности Python

                  Orchestrating a Background Job Workflow in Celery for Python
                  О том, как управлять выполнением Celery-задач

                  Sound Pattern Recognition with Python
                  Отличная статья о распознавании звуковых паттернов с помощью Python

                  A Complete Beginner's Guide to Django — Part 1
                  Туториал для начинающих разрабатывающих на Django

                  Intro to Threads and Processes in Python
                  О потоках и процессах в Python

                  Monkey-patching is Bad
                  Почему monkey patching — плохо.

                  A Brief Analysis of “The Zen of Python”
                  Анализ Дзен Python.

                  Python Magic Methods and __getattr__
                  О магических методах в Python

                  Asyncio Coroutine Patterns: Errors and cancellation
                  Статья о паттернах обработки ошибок при использовании asynаcio

                  Monitoring Road Traffic with Python
                  Статья-пример мониторинга пробок с помощью Python

                  How Python does Unicode
                  Как Python работает с Unicode

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


                  Hatch
                  Инструмент для управления проектами, пакетами и виртуальными окружениями

                  background
                  Инструмент для запуска задач в «бэкграунде»

                  setup.py
                  Отличный шаблон setup.py файла для ваших проектов

                  Seq2Seq Chatbot
                  Чат-бот в 200 строк

                  janus
                  Простая библиотека для парсинга параметров командной строки

                  Видео


                  DjangoCon US 2017
                  Запись видео с DjangoCon US 2017

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

                  Pygest #16. Релизы, статьи, интересные проекты из мира Python [15 августа 2017 — 28 августа 2017]

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

                  https://habrahabr.ru/post/337628/


                  Метки:  

                  Использование системных функций D-Bus в Sailfish OS

                  Понедельник, 11 Сентября 2017 г. 10:17 + в цитатник
                  osanwe сегодня в 10:17 Разработка

                  Использование системных функций D-Bus в Sailfish OS

                  • Tutorial

                  Введение


                  Данная статья является продолжением материала об использовании системного API в Sailfish OS и посвящена функциям D-Bus в данной операционной системе. Подробно будет разобрано взаимодействие со стандартным календарём и вспышкой. Список остальных основных функций D-Bus системы представлен в конце статьи.

                  Для понимания изложенного материала необходимо знание основ разработки для Sailfish OS и принципов взаимодействия с D-Bus в рамках операционной системы. Хорошей стартовой точкой являются соответствующие статьи от FRUCT:
                  [1] Начало разработки для Sailfish OS;
                  [2] Разработка для Sailfish OS: работа с D-Bus.

                  Теория


                  Имеется два способа получить информацию о доступных интерфейсах и функциях D-Bus. Первый подход заключается в изучении зарегистрированных в системе интерфейсов с помощью специальных утилит (например, Visual D-Bus и D-Bus Inspector) или командной строки (рисунок 1). Второй подход использует описанную в предыдущей статье методологию изучения исходного кода.


                  [Рисунок 1 — Пример получения списка интерфейсов D-Bus.]

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

                  Техника


                  Функции D-Bus могут быть вызваны (или определены) из кода на языке C++ (который в системе недоступен), из QML-кода и из desktop-файлов приложений. Соответственно, при поиске информации об интерфейсах необходимо иметь представление, во-первых, о модуле org.nemomobile.dbus; во-вторых, о способе обращения к D-Bus из desktop-файлов.

                  QML-модуль org.nemomobile.dbus предоставляет два основных компонента для работы с D-Bus: DBusAdaptor и DBusInterface. Первый позволяет создать приложению свой интерфейс, второй — использовать существующий. При общем поиске информации интерес представляют оба компонента, так как позволяют узнать, как можно взаимодействовать с приложением извне, и как приложение использует сторонние интерфейсы соответственно.

                  Например, чтобы узнать какие интерфейсы D-Bus использует приложение настроек, требуется перейти в каталог /usr/share/jolla-settings и выполнить проверку на использование D-Bus:
                  grep -i -H 'dbus' * && grep -A 5 'DBusAdaptor' ./settings.qml
                  $ cd /usr/share/jolla-settings/
                  $ grep -i -H 'dbus' *
                  settings.qml:import org.nemomobile.dbus 2.0
                  settings.qml:    DBusAdaptor {
                  $ grep -A 5 'DBusAdaptor' ./settings.qml
                      DBusAdaptor {
                          service: "com.jolla.settings"
                          path: "/com/jolla/settings/ui"
                          iface: "com.jolla.settings.ui"
                  
                          function showSettings() {



                  В то же время, при анализе desktop-файлов необходимо помнить, что, во-первых, desktop-файлы хранятся в каталоге /usr/share/applications; во-вторых, использование описанных функций запускает экземпляр приложения; в-третьих, при описании взаимодействия с D-Bus используются поля с префиксом X-Maemo:
                  • X-Maemo-Service — сервис, или местоположение приложения на пользовательской или системной шине;
                  • X-Maemo-Object-Path — путь, или наименование объекта;
                  • X-Maemo-Method — наименование вызываемого метода.

                  Интересно знать
                  Префиксы X-Maemo появились в Sailfish OS как наследство от операционной системы Maemo (рисунок 2), ранее разрабатываемой компанией Nokia. Они позволяют объявить функции D-Bus таким образом, что к ним можно обращаться без предварительного запуска программы. Эти функции позволяют осуществить запуск программы с осуществлением перед её открытием некоторой предварительной работы.

                  image
                  [Рисунок 2 — Зависимость Sailfish OS от других операционных систем (Википедия).]

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


                  Таким образом, чтобы получить список всех приложений, поддерживающих запуск с использованием D-Bus, требуется перейти в каталог /usr/share/applications и выполнить поиск по одному из ключевых слов:
                  grep -H 'X-Maemo-Service' *
                  $ cd /usr/share/applications/
                  $ grep -H 'X-Maemo-Service' *
                  jolla-calendar-import.desktop:X-Maemo-Service=com.jolla.calendar.ui
                  jolla-calendar.desktop:X-Maemo-Service=com.jolla.calendar.ui
                  jolla-camera-viewfinder.desktop:X-Maemo-Service=com.jolla.camera
                  jolla-clock.desktop:X-Maemo-Service=com.jolla.clock
                  jolla-contacts-import.desktop:X-Maemo-Service=com.jolla.contacts.ui
                  jolla-email.desktop:X-Maemo-Service=com.jolla.email.ui
                  jolla-gallery-openfile.desktop:X-Maemo-Service=com.jolla.gallery
                  jolla-gallery-playvideostream.desktop:X-Maemo-Service=com.jolla.gallery
                  jolla-mediaplayer-openfile.desktop:X-Maemo-Service=com.jolla.mediaplayer
                  jolla-mediaplayer.desktop:X-Maemo-Service=com.jolla.mediaplayer
                  jolla-messages-openurl.desktop:X-Maemo-Service=org.nemomobile.qmlmessages
                  jolla-messages.desktop:X-Maemo-Service=org.nemomobile.qmlmessages
                  jolla-notes-import.desktop:X-Maemo-Service=com.jolla.notes
                  jolla-notes.desktop:X-Maemo-Service=com.jolla.notes
                  jolla-settings.desktop:X-Maemo-Service=com.jolla.settings
                  new-mail.desktop:X-Maemo-Service=com.jolla.email.ui
                  open-url.desktop:X-Maemo-Service=org.sailfishos.browser.ui
                  ovpn-import.desktop:X-Maemo-Service=com.jolla.settings
                  sailfish-office-openfile.desktop:X-Maemo-Service=org.sailfish.office
                  sailfish-office.desktop:X-Maemo-Service=org.sailfish.office
                  simkit.desktop:X-Maemo-Service=org.sailfish.simkit
                  voicecall-ui-openurl.desktop:X-Maemo-Service=com.jolla.voicecall.ui
                  voicecall-ui.desktop:X-Maemo-Service=com.jolla.voicecall.ui



                  Сводная таблица основных системных функций API и D-Bus приведена в конце статьи.

                  Практика


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

                  Создадим компонент, позволяющий открыть расписание на текущий день. Для этого требуется перейти в каталог /usr/share/jolla-calendar (принципы именования директорий описывались в предыдущей статье) и узнать, в каких файлах имеется обращение к D-Bus:
                  grep -r -i -H 'dbus' *
                  $ cd /usr/share/jolla-calendar/
                  $ grep -r -i -H 'dbus' *
                  DbusInvoker.qml:import org.nemomobile.dbus 2.0
                  DbusInvoker.qml:DBusAdaptor {
                  calendar.qml:import org.nemomobile.dbus 2.0
                  calendar.qml:    DbusInvoker {}



                  Из результата выполнения команды видно, что определение интерфейсов производится в файле DbusInvoker.qml, который содержит только определения интерфейса и функций D-Bus:
                  cat ./DbusInvoker.qml -n
                  $ cat ./DbusInvoker.qml -n
                   1  import QtQuick 2.0
                   2  import Sailfish.Silica 1.0
                   3  import org.nemomobile.dbus 2.0
                   4  import Calendar.dateParser 1.0
                   5
                   6  DBusAdaptor {
                   7      service: "com.jolla.calendar.ui"
                   8      path: "/com/jolla/calendar/ui"
                   9      iface: "com.jolla.calendar.ui"
                  10
                  11      function viewEvent(id, recurrenceId, startDate) {
                  12          var occurrence = DateParser.parseTime(startDate)
                  13          if (isNaN(occurrence.getTime())) {
                  14              console.warn("Invalid event start date, unable to show event")
                  15              return
                  16          }
                  17
                  18          if (pageStack.currentPage.objectName === "EventViewPage") {
                  19              pageStack.currentPage.uniqueId = id
                  20              pageStack.currentPage.recurrenceId = recurrenceId
                  21              pageStack.currentPage.startTime = occurrence
                  22          } else {
                  23              pageStack.push("pages/EventViewPage.qml",
                  24                             { uniqueId: id, recurrenceId: recurrenceId, startTime: occurrence },
                  25                             PageStackAction.Immediate)
                  26          }
                  27          requestActive.start()
                  28      }
                  29
                  30      function viewDate(dateTime) {
                  31          var parsedDate = new Date(dateTime)
                  32          if (isNaN(parsedDate.getTime())) {
                  33              console.warn("Invalid date, unable to show events for date")
                  34              return
                  35          }
                  36
                  37          if (pageStack.currentPage.objectName === "DayPage") {
                  38              pageStack.currentPage.date = parsedDate
                  39          } else {
                  40              pageStack.push("pages/DayPage.qml", { date: parsedDate }, PageStackAction.Immediate)
                  41          }
                  42          requestActive.start()
                  43      }
                  44
                  45      function importFile(fileName) {
                  46          if (pageStack.currentPage.objectName === "ImportPage") {
                  47              pageStack.currentPage.fileName = fileName
                  48          } else {
                  49              pageStack.push("pages/ImportPage.qml", { "fileName": fileName }, PageStackAction.Immediate)
                  50          }
                  51          requestActive.start()
                  52      }
                  53
                  54      function activateWindow(arg) {
                  55          app.activate()
                  56      }
                  57  }



                  Из кода адаптера видно, что в создаваемом компоненте необходимо подключиться к сервису com.jolla.calendar.ui и использовать путь /com/jolla/calendar/ui и интерфейс com.jolla.calendar.ui (строки 7-9). После этого станут доступными объявленные функции, из которых, в рамках поставленной задачи, интерес представляет только viewDate (строки 30-43), принимающая в качестве аргумента одно из представлений даты, распознаваемое объектом Date. Полученные результаты позволяют реализовать свой компонент для работы с календарём:
                  CalendarController.qml
                  import QtQuick 2.0
                  import Sailfish.Silica 1.0
                  
                  import org.nemomobile.dbus 2.0
                  
                  
                  Item {
                      id: calendarControl
                  
                      /* Открыть календарь для текущей даты.
                       */
                      function showAgenda() {
                          calendar.call('viewDate', Date.now())
                      }
                  
                      DBusInterface {
                          id: calendar
                          service: 'com.jolla.calendar.ui'
                          path: '/com/jolla/calendar/ui'
                          iface: 'com.jolla.calendar.ui'
                      }
                  }



                  По такому же принципу формируются и другие компоненты, взаимодействующие с функциями D-Bus системы.

                  Рассмотрим процесс управления вспышкой. Для этого, согласно анализу каталога /usr/share/jolla-settings/pages/flashlight, необходимо подключиться к сервису com.jolla.settings.system.flashlight и использовать путь /com/jolla/settings/system/flashlight и интерфейс com.jolla.settings.system.flashlight. После этого, вызывая функцию toggleFlashlight без параметров, становится возможным включать и выключать вспышку.

                  Однако, в некоторых задачах может потребоваться получить информацию о текущем состоянии вспышки — включена она или выключена. Для этого используется функция getProperty с передаваемым в неё параметром "flashlightOn". В данном случае возвращается булево значение.
                  grep -i -H 'dbus' ./pages/flashlight/* && grep -A 5 -i -H 'DBusInterface' ./pages/flashlight/Flashlight.qml
                  $ cd /usr/share/jolla-settings
                  $ grep -i -H "dbus" ./pages/flashlight/*
                  ./pages/flashlight/Flashlight.qml:import org.nemomobile.dbus 2.0
                  ./pages/flashlight/Flashlight.qml:        flashlightDbus.call("toggleFlashlight", undefined, handleToggle, handleError)
                  ./pages/flashlight/Flashlight.qml:    property QtObject flashlightDbus: DBusInterface {
                  ./pages/flashlight/Flashlight.qml:        flashlight.flashlightOn = flashlightDbus.getProperty("flashlightOn")
                  $ grep -A 5 -i -H "DBusInterface" ./pages/flashlight/Flashlight.qml
                  ./pages/flashlight/Flashlight.qml:    property QtObject flashlightDbus: DBusInterface {
                  ./pages/flashlight/Flashlight.qml-        signalsEnabled: true
                  ./pages/flashlight/Flashlight.qml-        service: "com.jolla.settings.system.flashlight"
                  ./pages/flashlight/Flashlight.qml-        path: "/com/jolla/settings/system/flashlight"
                  ./pages/flashlight/Flashlight.qml-        iface: "com.jolla.settings.system.flashlight"
                  ./pages/flashlight/Flashlight.qml-        function flashlightOnChanged(newOn) {



                  Учитывая вышенаписанное, реализуется компонент для взаимодействия со вспышкой:
                  FlashlightController.qml
                  import QtQuick 2.0
                  import Sailfish.Silica 1.0
                  
                  import org.nemomobile.dbus 2.0
                  
                  Item {
                      id: flashlightControl
                  
                      // Состояние вспышки.
                      property bool flashlightOn
                  
                      // Включает или выключает вспышку.
                      function toggleFlashlight() {
                          flashlightOn = !flashlightOn;
                          flashlight.call("toggleFlashlight", undefined);
                      }
                  
                      DBusInterface {
                          id: flashlight
                          service: "com.jolla.settings.system.flashlight"
                          path: "/com/jolla/settings/system/flashlight"
                          iface: "com.jolla.settings.system.flashlight"
                          signalsEnabled: true
                          function flashlightOnChanged(newOn) {
                              flashlightControl.flashlightOn = newOn
                          }
                      }
                  
                      Component.onCompleted: {
                          flashlightControl.flashlightOn = flashlight.getProperty("flashlightOn")
                      }
                  }



                  Заключение


                  В данной статье указаны два способа поиска информации о функциях D-Bus в Sailfish OS, и подробно разобран один из них — поиск в исходном коде. С его использованием разработаны и прокомментированы примеры компонентов для взаимодействия со вспышкой и стандартным календарём. Код этих и других модулей доступен на GitHub.

                  Однако не стоит забывать, что решение части задач возможно простым запуском интересующей программы с требуемыми аргументами. Например, запуск стандартного браузера с открытием сайта может быть осуществлён с помощью команды sailfish-browser https://google.com/. Но это выходит за рамки описываемого в статье материала.
                  sailfish-browser https://google.com/
                  $ sailfish-browser https://google.com/
                  [D] unknown:0 - Using Wayland-EGL
                  greHome from GRE_HOME:/usr/bin
                  libxul.so is not found, in /usr/bin/libxul.so
                  Created LOG for EmbedLite
                  [D] onCompleted:103 - ViewPlaceholder requires a SilicaFlickable parent
                  Loaded xulDir:/usr/lib/xulrunner-qt5-38.8.0/libxul.so, appDir:/usr/bin
                  EmbedLiteExt virtual nsresult EmbedChromeManager::Observe(nsISupports*, const char*, const char16_t*):82: obj:(nil), top:app-startup
                  EmbedLiteExt virtual nsresult EmbedTouchManager::Observe(nsISupports*, const char*, const char16_t*):86: obj:(nil), top:app-startup
                  EmbedLiteGlobalHelper app-startup
                  EmbedLiteSyncService app-startup
                  PREFS SERVICE INITAILIZED
                  EmbedPrefService app-startup
                  EmbedliteDownloadManager initialized
                  UserAgentOverrideHelper app-startup
                  1505073762747   addons.manager  DEBUG   Application has been upgraded
                  1505073762892   addons.manager  DEBUG   Loaded provider scope for resource://gre/modules/addons/XPIProvider.jsm: ["XPIProvider"]
                  1505073762912   addons.manager  DEBUG   Loaded provider scope for resource://gre/modules/LightweightThemeManager.jsm: ["LightweightThemeManager"]
                  1505073762942   addons.manager  DEBUG   Loaded provider scope for resource://gre/modules/addons/GMPProvider.jsm
                  1505073762961   addons.manager  DEBUG   Loaded provider scope for resource://gre/modules/addons/PluginProvider.jsm
                  1505073762968   addons.manager  DEBUG   Starting provider: XPIProvider
                  1505073762973   addons.xpi      DEBUG   startup
                  1505073762982   addons.xpi      DEBUG   checkForChanges
                  1505073762993   addons.xpi      DEBUG   Loaded add-on state from prefs: {}
                  1505073763000   addons.xpi      DEBUG   getInstallState changed: false, state: {}
                  1505073763009   addons.xpi      DEBUG   Empty XPI database, setting schema version preference to 16
                  1505073763012   addons.xpi      DEBUG   No changes found
                  1505073763015   addons.manager  DEBUG   Registering shutdown blocker for XPIProvider
                  1505073763021   addons.manager  DEBUG   Provider finished startup: XPIProvider
                  1505073763022   addons.manager  DEBUG   Starting provider: LightweightThemeManager
                  1505073763024   addons.manager  DEBUG   Registering shutdown blocker for LightweightThemeManager
                  1505073763029   addons.manager  DEBUG   Provider finished startup: LightweightThemeManager
                  1505073763032   addons.manager  DEBUG   Starting provider: GMPProvider
                  1505073763046   addons.manager  DEBUG   Registering shutdown blocker for GMPProvider
                  1505073763050   addons.manager  DEBUG   Provider finished startup: GMPProvider
                  1505073763052   addons.manager  DEBUG   Starting provider: PluginProvider
                  1505073763055   addons.manager  DEBUG   Registering shutdown blocker for PluginProvider
                  1505073763059   addons.manager  DEBUG   Provider finished startup: PluginProvider
                  1505073763060   addons.manager  DEBUG   Completed startup sequence
                  Created LOG for EmbedPrefs
                  [D] QMozWindowPrivate::setSize:71 - Trying to set empty size:  QSize(-1, -1)
                  Attempting load of libEGL.so
                  EmbedLiteExt virtual nsresult EmbedTouchManager::Observe(nsISupports*, const char*, const char16_t*):86: obj:0xb225a130, top:domwindowopened
                  EmbedLiteExt void EmbedChromeManager::WindowCreated(nsIDOMWindow*):91: WindowOpened: 0xb225a140
                  EmbedLiteExt void EmbedTouchManager::WindowCreated(nsIDOMWindow*):95: WindowOpened: 0xb225a140
                  EmbedLiteExt void EmbedTouchManager::WindowCreated(nsIDOMWindow*):108: id for window: 1
                  ###################################### SelectAsyncHelper.js loaded
                  ###################################### embedhelper.js loaded
                  ### ContextMenuHandler.js loaded
                  ### SelectionPrototype.js loaded
                  ### SelectionHandler.js loaded
                  Init Called:[object Object]
                  JavaScript warning: https://www.google.ru/xjs/_/js/k=xjs.mhp.en_US.2vKAz7DqmvI.O/m=sb_mobh,hjsa,d,csi/am=AAAD/rt=j/d=1/t=zcms/rs=ACT90oFx8AHVqc9lMfPQBwURKXyQ4qaFiA, line 7: mutating the [[Prototype]] of an object will cause your code to run very slowly; instead create the object with the correct initial [[Prototype]] value using Object.create



                  Основные системные API функции:
                  Описание Необходимые данные
                  Создать атмосферу
                  import Sailfish.Ambience 1.0
                  
                  var previousAmbienceUrl = Ambience.source
                  Ambience.setAmbience(url, function(ambienceId) {
                      pageStack.push(ambienceSettings, {
                          'contentId': ambienceId,
                          'previousAmbienceUrl': previousAmbienceUrl
                      })
                  })
                  
                  Настройка яркость экрана
                  import org.nemomobile.systemsettings 1.0
                  
                  DisplaySettings { id: displaySettings }
                  
                  maximumValue: displaySettings.maximumBrightness
                  minimumValue: 1
                  value: displaySettings.brightness
                  
                  displaySettings.brightness = Math.round(value)
                  
                  Настройка ориентации экрана
                  import org.nemomobile.systemsettings 1.0
                  
                  DisplaySettings { id: displaySettings }
                  
                  displaySettings.orientationLock = "dynamic" // Динамическая ориентация
                  displaySettings.orientationLock = "portrait" // Портретная ориентация
                  displaySettings.orientationLock = "landscape" // Альбомная ориентация
                  
                  Автоматическая настройка яркости экрана
                  import org.nemomobile.systemsettings 1.0
                  
                  DisplaySettings { id: displaySettings }
                  
                  checked: displaySettings.ambientLightSensorEnabled && displaySettings.autoBrightnessEnabled
                  
                  if (checked) {
                      displaySettings.autoBrightnessEnabled = false
                  } else {
                      displaySettings.autoBrightnessEnabled = true
                      displaySettings.ambientLightSensorEnabled = true
                  }
                  
                  Настройка времени включения спящего режима
                  import org.nemomobile.systemsettings 1.0
                  
                  DisplaySettings { id: displaySettings }
                  
                  displaySettings.dimTimeout = VALUE_IN_SECONDS
                  
                  Настройка состояния дисплея во время зарядки
                  import org.nemomobile.systemsettings 1.0
                  
                  DisplaySettings { id: displaySettings }
                  
                  displaySettings.inhibitMode = DisplaySettings.InhibitOff // Выключать дисплей во время зарядки
                  displaySettings.inhibitMode = DisplaySettings.InhibitStayOnWithCharger // Не выключать дисплей во время зарядки
                  
                  Настройка системного размера шрифта
                  import org.nemomobile.configuration 1.0
                  
                  ConfigurationValue {
                      id: fontSizeCategory
                      key: "/desktop/jolla/theme/font/sizeCategory"
                      defaultValue: "normal"
                  }
                  
                  fontSizeCategory.value = "normal" // Стандартный размер шрифта
                  fontSizeCategory.value = "large" // Большой размер шрифта
                  fontSizeCategory.value = "huge" // Огромный размер шрифта
                  
                  Настройка системной громкости
                  import org.nemomobile.systemsettings 1.0
                  
                  ProfileControl { id: profileControl }
                  
                  maximumValue: 100
                  minimumValue: 0
                  
                  profileControl.ringerVolume = value
                  profileControl.profile = (value > 0) ? "general" : "silent"
                  
                  Настройка вибрации
                  import org.nemomobile.systemsettings 1.0
                  
                  ProfileControl { id: soundSettings }
                  
                  soundSettings.vibraMode = ProfileControl.VibraAlways // Вибрация активирована всегда
                  soundSettings.vibraMode = ProfileControl.VibraSilent // Вибрация активирована в бесшумном режиме
                  soundSettings.vibraMode = ProfileControl.VibraNormal // Вибрация активирована в обычном режиме
                  soundSettings.vibraMode = ProfileControl.VibraNever // Вибрация не активирована
                  
                  Включить/выключить звуки на системные события
                  import org.nemomobile.systemsettings 1.0
                  
                  ProfileControl { id: soundSettings }
                  
                  soundSettings.systemSoundLevel = false // Выключить
                  soundSettings.systemSoundLevel = true // Включить
                  
                  Включить/выключить WLAN
                  import MeeGo.Connman 0.2
                  import com.jolla.settings 1.0
                  import com.jolla.connection 1.0
                  
                  TechnologyModel {
                      id: wifiListModel
                      name: "wifi"
                  }
                  
                  NetworkManagerFactory { id: networkManager }
                  
                  NetworkTechnology {
                      id: wifiTechnology
                      path: networkManager.instance.technologyPathForType("wifi")
                  }
                  
                  ConnectionAgent { id: connectionAgent }
                  
                  checked: wifiListModel.available && wifiListModel.powered && !wifiTechnology.tethering
                  
                  if (wifiTechnology.tethering) connectionAgent.stopTethering(true)
                  else wifiListModel.powered = !wifiListModel.powered
                  
                  Включить/выключить общий доступ к интернету
                  import Sailfish.Telephony 1.0
                  import Sailfish.Silica.private 1.0
                  import MeeGo.Connman 0.2
                  import MeeGo.QOfono 0.2
                  import com.jolla.connection 1.0
                  
                  ConnectionAgent { id: connectionAgent }
                  
                  NetworkManagerFactory { id: networkManager }
                  
                  NetworkTechnology {
                      id: wifiTechnology
                      path: networkManager.instance.technologyPathForType("wifi")
                  }
                  
                  SimManager {
                      id: simManager
                      controlType: SimManagerType.Data
                  }
                  
                  OfonoNetworkRegistration {
                      id: networkRegistration
                      modemPath: simManager.activeModem
                  }
                  
                  OfonoConnMan {
                      id: connectionManager
                      modemPath: simManager.activeModem
                  }
                  
                  function roamingDataAllowed() {
                      return networkRegistration.valid && connectionManager.valid
                          && !(networkRegistration.status === "roaming" && !connectionManager.roamingAllowed)
                  }
                  
                  enabled: !networkManager.instance.offlineMode && (roamingDataAllowed() || wifiTechnology.tethering)
                  
                  if (wifiTechnology.tethering) {
                      delayedTetheringSwitch.start()
                      connectionAgent.stopTethering()
                  } else {
                      delayedTetheringSwitch.start()
                      connectionAgent.startTethering("wifi")
                  }
                  
                  Включить/выключить режим полёта
                  import MeeGo.Connman 0.2
                  
                  NetworkManagerFactory { id: connMgr }
                  
                  connMgr.instance.offlineMode = true // Включить
                  connMgr.instance.offlineMode = false // Выключить
                  
                  Включить/выключить Bluetooth
                  import MeeGo.Connman 0.2
                  import Sailfish.Bluetooth 1.0
                  import org.kde.bluezqt 1.0 as BluezQt
                  
                  TechnologyModel {
                      id: btTechModel;
                      name: "bluetooth"
                  }
                  
                  btTechModel.powered = !btTechModel.powered // Переключение
                  


                  Основные системные D-Bus функции:
                  Описание Необходимые данные
                  Просмотр события в календаре Сервис:
                  com.jolla.calendar.ui
                  Путь:
                  /com/jolla/calendar/ui
                  Интерфейс:
                  com.jolla.calendar.ui
                  Функция:
                  viewEvent(id, recurrenceId, startDate)
                  Просмотр дня в календаре Сервис:
                  com.jolla.calendar.ui
                  Путь:
                  /com/jolla/calendar/ui
                  Интерфейс:
                  com.jolla.calendar.ui
                  Функция:
                  viewDate(dateTime)
                  Открытие камеры в последнем состоянии Сервис:
                  com.jolla.camera
                  Путь:
                  /
                  Интерфейс:
                  com.jolla.camera.ui
                  Функция:
                  showViewfinder()
                  Открытие фронтальной камеры Сервис:
                  com.jolla.camera
                  Путь:
                  /
                  Интерфейс:
                  com.jolla.camera.ui
                  Функция:
                  showFrontViewfinder()
                  Создание будильника Сервис:
                  com.jolla.clock
                  Путь:
                  /
                  Интерфейс:
                  com.jolla.clock
                  Функция:
                  newAlarm()
                  Просмотр контакта Сервис:
                  com.jolla.contacts.ui
                  Путь:
                  /com/jolla/contacts/ui
                  Интерфейс:
                  com.jolla.contacts.ui
                  Функция:
                  showContact(int contactId)
                  Редактирование контакта Сервис:
                  com.jolla.contacts.ui
                  Путь:
                  /com/jolla/contacts/ui
                  Интерфейс:
                  com.jolla.contacts.ui
                  Функция:
                  editContact(int contactId)
                  Импортирование контактов Сервис:
                  com.jolla.contacts.ui
                  Путь:
                  /com/jolla/contacts/ui
                  Интерфейс:
                  com.jolla.contacts.ui
                  Функция:
                  importWizard()
                  Воспроизвести аудиофайл по URL Сервис:
                  com.jolla.mediaplayer
                  Путь:
                  /com/jolla/mediaplayer/ui
                  Интерфейс:
                  com.jolla.mediaplayer.ui
                  Функция:
                  openUrl(url)
                  Создание новой заметки Сервис:
                  com.jolla.notes
                  Путь:
                  /
                  Интерфейс:
                  com.jolla.notes
                  Функция:
                  newNote()
                  Просмотр настроек Сервис:
                  com.jolla.settings
                  Путь:
                  /com/jolla/settings/ui
                  Интерфейс:
                  com.jolla.settings.ui
                  Функция:
                  showSettings()
                  Просмотр списка загрузок Сервис:
                  com.jolla.settings
                  Путь:
                  /com/jolla/settings/ui
                  Интерфейс:
                  com.jolla.settings.ui
                  Функция:
                  showTransfers()
                  Просмотр списка аккаунтов Сервис:
                  com.jolla.settings
                  Путь:
                  /com/jolla/settings/ui
                  Интерфейс:
                  com.jolla.settings.ui
                  Функция:
                  showAccounts()
                  Просмотр настройки записи телефонных разговоров Сервис:
                  com.jolla.settings
                  Путь:
                  /com/jolla/settings/ui
                  Интерфейс:
                  com.jolla.settings.ui
                  Функция:
                  showCallRecordings()
                  Включить/выключить поддержку Android Сервис:
                  com.jolla.apkd
                  Путь:
                  /com/jolla/apkd
                  Интерфейс:
                  com.jolla.apkd
                  Функция:
                  controlService(true/false)
                  Включить/выключить вспышку Сервис:
                  com.jolla.settings.system.flashlight
                  Путь:
                  /com/jolla/settings/system/flashlight
                  Интерфейс:
                  com.jolla.settings.system.flashlight
                  Функция:
                  toggleFlashlight()
                  Перезагрузить устройство Сервис:
                  com.nokia.dsme
                  Путь:
                  /com/nokia/dsme/request
                  Интерфейс:
                  com.nokia.dsme.request
                  Функция:
                  req_reboot()
                  Выключить устройство Сервис:
                  com.nokia.dsme
                  Путь:
                  /com/nokia/dsme/request
                  Интерфейс:
                  com.nokia.dsme.request
                  Функция:
                  req_shutdown
                  Позвонить Сервис:
                  com.jolla.voicecall.ui
                  Путь:
                  /
                  Интерфейс:
                  com.jolla.voicecall.ui
                  Функция:
                  dial(number)
                  Открыть изображения в галерее Сервис:
                  com.jolla.gallery
                  Путь:
                  /com/jolla/gallery/ui
                  Интерфейс:
                  com.jolla.gallery.ui
                  Функция:
                  showImages(array_of_urls)
                  Открыть видео в галерее Сервис:
                  com.jolla.gallery
                  Путь:
                  /com/jolla/gallery/ui
                  Интерфейс:
                  com.jolla.gallery.ui
                  Функция:
                  playVideoStream(url)
                  Создать новое письмо Сервис:
                  com.jolla.email.ui
                  Путь:
                  /com/jolla/email/ui
                  Интерфейс:
                  com.jolla.email.ui
                  Функция:
                  mailto()
                  Поиск WLAN-сетей Сервис:
                  com.jolla.lipstick.ConnectionSelector
                  Путь:
                  /
                  Интерфейс:
                  com.jolla.lipstick.ConnectionSelectorIf
                  Функция:
                  openConnectionNow('wifi')



                  Возникающие по ходу разработки вопросы и идеи всегда можно обсудить в Telegram-чате и в группе ВКонтакте.
                  Original source: habrahabr.ru (comments, light).

                  https://habrahabr.ru/post/337618/


                  Метки:  

                  [recovery mode] Индия приняла закон о «выключении» интернета

                  Понедельник, 11 Сентября 2017 г. 10:00 + в цитатник
                  VASExperts сегодня в 10:00 Администрирование

                  Индия приняла закон о «выключении» интернета

                  В конце августа жители Индии из штатов Харьяна и Пенджаб обнаружили, что 2G, 3G, 4G, CDMA и GPRS перестали работать. Были отключены и СМС-сообщения. На несколько дней 50 млн человек остались без доступа к мобильному интернету. С учетом, что 77% городских и 92% сельских жителей Индии пользуются мобильными телефонами для выхода в Сеть, почти все цифровые каналы распространения информации для жителей оказались перекрыты.

                  Это не первый раз, когда власти страны прибегли к такой мере: с начала 2017 года в разных районах производилось 20 частичных отключений. После случая с Харьяном и Пенджабом СМИ обратили внимание на документ, который был выпущен правительством Индии в начале августа. В нем описываются правила и процесс отключения интернета в стране.


                  / Flickr / Field Engineer / CC

                  Право на блэкаут


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

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

                  Приказы передаются операторам связи либо в письменной форме, либо по защищенным каналам.

                  Почему блокируют?


                  По данным доклада IMRB, общее распространение интернета в Индии в марте 2017 года составляло 31%. В городской черте этот показатель возрастает вдвое. С учетом объема цифровой экономики, согласно исследованию Института Брукингса, в 2015 году Индия потеряла почти миллиард долларов из-за остановок интернета. Это больше, чем любая другая страна за тот же период.

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

                  В 2017 году большая часть блокировок пришлась на штат Кашмир, территория которого имеет спорный статус. Блокировки также совершались в Харьяне, Раджастхане, Уттар-Прадеше, Мадхья-Прадеше, Западной Бенгалии и Махараштре.

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

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

                  «Инвесторы больше не будут закрывать глаза на финансовые потери, вызванные приостановкой обслуживания, — считает Питер Мисек (Peter Micek), юрисконсульт в Access Now. — Отключение напрямую вредит крупнейшим мультинациональным компаниям и самым маленьким стартапам, препятствуя мобильным транзакциям и блокируя доступ к рынкам».

                  Институт Брукингса пришел к выводу, что в период с 1 июля 2015 года по 30 июня 2016 года страны мира понесли ущерб в размере $2,4 млрд в связи с локальными отключениями.

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

                  P.S. О чем еще мы пишем в нашем блоге VAS Experts:

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

                  https://habrahabr.ru/post/337584/


                  Метки:  

                  Новый VPU Myriad X от Intel обучит дронов самостоятельности

                  Понедельник, 11 Сентября 2017 г. 09:38 + в цитатник
                  1cloud сегодня в 09:38 Разработка

                  Новый VPU Myriad X от Intel обучит дронов самостоятельности

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

                    28 августа компания Intel представила визуальный процессор (VPU) Myriad X, который разработан специально для автономных интеллектуальных устройств. Главная особенность чипа — встроенный аппаратный ускоритель для нейросетей (Neural Compute Engine). Он отвечает за обучение искусственного интеллекта на периферийных устройствах, имея при этом низкое энергопотребление. Среди предложенных Intel сфер применения чипа числятся дроны, системы безопасности и наблюдения, VR/AR и другие устройства.


                    / Flickr / Bidgee / CC

                    По словам разработчиков, Myriad X — первая в мире однокристальная система, специально «заточенная» под ускоренное глубокое обучение. Neural Compute Engine помогает устройствам видеть, интерпретировать и реагировать на окружающую среду в реальном времени. С ускорителем производительность Myriad X достигает триллиона операций в секунду (TOPS).

                    «Мы близки к тому, чтобы машинное зрение и глубокое обучение вошли в число стандартных требований к миллиардам ежедневно окружающих нас устройств», — сказал Реми Эль-Уаззани (Remi El-Ouazzane), вице-президент и генеральный менеджер Movidius, компании-разработчика чипов семейства Myriad.

                    Архитектура VPU-чипа Movidius Myriad X VPU состоит из нескольких специализированных вычислительных устройств. Это несколько процессоров общего назначения, наряду с 16 процессорами SHAVE (Streaming Hybrid Architecture Vector Engine). Последние работают совместно с нейронным вычислительным движком.

                    Процессоры SHAVE состоят из шестнадцати программируемых 128-битных векторных процессоров VLIW, конфигурируемых шин MIPI, аппаратных ускорителей и централизованной архитектуры встроенной памяти.

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

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

                    Применение VPU


                    Однако наиболее вероятной сферой применения нового чипа в Intel видят беспилотники. Дроны становятся умнее. Например, Spark — мини-дрон от DJI — оборудован набором из камер и датчиков и процессором Vision Movivius Myriad 2, который помогает интеллектуальной системе бортового зрения обнаруживать и избегать столкновения с объектами, создавать 3D-карты, распознавать лица и жесты.

                    И достигнутый уровень развития — не предел. По словам Кормака Брика (Cormac Brick), руководителя по бортовым системам искусственно интеллекта в Movidius, дроны учатся думать и реагировать.

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

                    Movidius видят применение своим чипам и в сфере безопасности. В этом году их процессор Myriad 2 уже был интегрирован в камеры видеонаблюдения Dahua. Эти камеры далеко шагнули от традиционных технологий мониторинга и записи. Они обладают расширенными функциями анализа видео: мониторят плотность толпы, распознают лица, имеют стереоскопическое зрение, могут обнаруживать неправильно припаркованные автомобили.

                    Есть и еще одно применение VPU нового поколения. В июле Intel представили мобильный модуль Movidius Neural Compute Stick с разъемом USB 3.0. Его задача — обучение искусственного интеллекта на различных устройствах. Характеристики и особенности те же: низкое энергопотребление при высокой производительности, компактность, офлайн-режим работы, нацеленность на приложения машинного зрения.

                    Акцент на AI


                    По данным Accenture, рынок AI в 12 развитых странах удвоит темпы роста к 2035 году. Например, только в Китае к 2020 году собираются установить 450 млн новых камер видеонаблюдения с системами распознавания лиц. К слову, компания Dahua Technology, которая уже экспериментировала с процессором Myriad 2, занимает второе место на рынке камер наблюдения и базируется в Ханчжоу.

                    На AI-рынке у Intel до выхода Myriad X было несколько серьезных противников: Qualcomm Neural Processing Engine, процессор Google TPU 2.0, предназначенный для обучения нейронных сетей, и NVIDIA Tesla V100. По мнению аналитиков Seeking Alpha, самую серьезную конкуренцию Intel на рынке машинного обучения, который достигнет $5 млрд к 2021 году, составляет именно NVIDIA.

                    Однако вскоре могут появиться и другие сильные конкуренты. В августе компания Microsoft представила проект Brainwave. Это платформа для глубокого обучения AI в реальном времени с низкой задержкой в обработке запросов. Архитектура Brainwave поддерживает выполнение более 130 тыс. вычислений за цикл. Работа в этом направлении вскоре позволит применять нейронные сети для выполнения бытовых задач.

                    О компании Movidius

                    Компания Movidius разрабатывает визуальные процессоры для интернета вещей. Штаб-квартира располагается в Сан-Матео, Калифорния. В сентябре 2016 года была приобретена компанией Intel.

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

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

                    https://habrahabr.ru/post/337612/


                    Метки:  

                    [Перевод] Погружение в CSS: метрики шрифтов, line-height и vertical-align

                    Понедельник, 11 Сентября 2017 г. 09:23 + в цитатник

                    Метки:  

                    Зачем мы сделали VOD на WebRTC

                    Понедельник, 11 Сентября 2017 г. 08:23 + в цитатник
                    flashphoner сегодня в 08:23 Разработка

                    Зачем мы сделали VOD на WebRTC


                      VOD — это про video on demand, т.е. проигрывание обычных роликов, как это делается на YouTube или другом стриминговом сервисе. WebRTC — это видео реалтайм с низкой задержкой. Вы спросите — как эти две вещи могут быть связаны? Заходите под кат за подробностями.

                      Сапорт и багфикс


                      Все началось, как обычно, с сапорта. К нам обратилась девушка-программист, предположительно из аутсорсинговой компании в Индии, которая участвовала в разработке мобильного приложения для телемедицины. Одной из хотелок клиента была запись WebRTC видеочата с iOS приложения, с последующим воспроизведением в этом же iOS приложении. Такая запись работала, но при воспроизведении стандартными средствами iOS SDK, обнаружились зеленые артефакты. Точнее даже не артефакты, а вполне четкие прямоугольные области зеленого цвета, занимающие 3/4 экрана. Конечно же это никуда не годилось, и мы приступили к изучению проблемы.


                      Воспроизведение записанного WebRTC видео через AVPlayerViewController

                      В мобильном приложении для воспроизведения видео, мы использовали стандартные компоненты MPMoviePlayer или AVPlayerViewController, которые могут играть mp4 ролик если указать его http URL, например http://host/sample.mp4. Эти компоненты отыгрывали MP4 видео нормально, но в случае с трансляциями, записанными с iOS приложения, зеленая область никуда не исчезала и все портила.

                      WebRTC динамически меняет разрешение потока


                      Оказалось, что зеленые артефакты в записи были связаны с тем, что для WebRTC нормально менять разрешение видео на лету. При этом, в файле записи mp4 мы имеем чудесные фреймы разного размера, точнее сначала последовательность одного размера 640x480, потом другого 320x240, и т.д. Такие фокусы замечательно отыгрывает например VLC, без каких либо артефактов, а встроенные компоненты воспроизведения видео в iOS по HTTP дают зеленые артефакты при изменении разрешения видео в битстриме.

                      Давайте запустим трансляцию с iOS-приложения и убедимся, что это действительно так. Для тестирования можно воспользоваться нашим мобильным приложением для iOS — Two Way Streaming на базе iOS SDK и демо-сервером WCS5-EU.

                      Так выглядит приложение, которое стримит поток на сервер:


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


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

                      WebRTC VOD, как решение


                      Выходом из сложившейся ситуации стал бы рескейлинг с транскодингом, т.е. декодирование фреймов, приведение к одному разрешению, например 640x480 и запись в этом разрешении. Но если делать так с каждым публикуемым на сервер стримом, ресурсы CPU быстро иссякнут на 10-20 видеопотоках. Поэтому нам требовалось какое-то решение, не задействующее транскодинг.

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

                      Осталось реализовать зачитку записанного mp4 и проброс в движок Web Call Server для дальнейшей конвертации в WebRTC. Первые же тесты показали хорошие результаты — зеленые прямоугольники исчезли.

                      Так мы получили VOD с воспроизведением не только по WebRTC, но и по всем поддерживаемым протоколам и технологиям: RTMP, RTMFP, RTSP, HTML5 Canvas, Media Source, HLS, WebRTC.

                      WebRTC VOD — Live трансляция


                      Дальше возник вопрос — “А вдруг пользователи захотят транслировать ролик как поток, всем сразу и одновременно?”.

                      В результате, пришлось сделать два типа VOD.

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

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

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

                      Для VOD мы ввели следующие схемы:

                      Если нужно проиграть ролик персонально, передаем имя потока так:

                      vod://sample.mp4

                      Если же требуется устроить из ролика полноценную онлайн-трансляцию, то имя потока будет таким:

                      vod-live://sample.mp4

                      Сам файл sample.mp4 должен лежать в папке сервера WCS_HOME/media и иметь формат MP4 / H.264 + AAC.

                      Что же стало с iOS приложением? — спросите вы.

                      Все хорошо. iOS приложение играет VOD ролик по WebRTC без зеленых прямоугольников.

                      WebRTC VOD в Web плеере


                      А теперь посмотрим, как WebRTC VOD выглядит в вебе. Для этого, на стороне сервера скопируем mp4-файл в папку /usr/local/FlashphonerWebCallServer/media. Пусть это будет всем известный Big Buck Bunny, sample.mp4.

                      Открываем страницу с тестовым плеером, указываем название потока vod://sample.mp4 и нажимаем Test Now.


                      Плеер начинает играть поток через WebRTC. В chrome://webrtc-internals можно видеть графики воспроизведения:


                      В итоге история закончилась хорошо. Мы пофиксили баг с зеленым экраном при воспроизведении mp4-записи трансляции в iOS приложении и сделали WebRTC-VOD-функцию для веб-браузеров и мобильных устройств под управлением iOS и Android.

                      Ссылки


                      1. Тестовое iOS приложение Two Way Streaming для трансляций
                      2. Web плеер — пример плеера для воспроизведения VOD — WebRTC потоков
                      3. Сервер Web Call Server 5, раздающий mp4 ролики по WebRTC
                      4. WebRTC SDK для iOS — библиотека для разработки стриминг-приложений для iOS
                      Original source: habrahabr.ru (comments, light).

                      https://habrahabr.ru/post/337560/


                      [Перевод] Создание языка программирования с использованием LLVM. Часть 10: Заключение и другие вкусности LLVM

                      Понедельник, 11 Сентября 2017 г. 04:55 + в цитатник
                      32bit_me сегодня в 04:55 Разработка

                      Создание языка программирования с использованием LLVM. Часть 10: Заключение и другие вкусности LLVM

                      • Перевод
                      • Tutorial
                      Оглавление:
                      Часть 1: Введение и лексический анализ
                      Часть 2: Реализация парсера и AST
                      Часть 3: Генерация кода LLVM IR
                      Часть 4: Добавление JIT и поддержки оптимизатора
                      Часть 5: Расширение языка: Поток управления
                      Часть 6: Расширение языка: Операторы, определяемые пользователем
                      Часть 7: Расширение языка: Изменяемые переменные
                      Часть 8: Компиляция в объектный код
                      Часть 9: Добавляем отладочную информацию
                      Часть 10: Заключение и другие вкусности LLVM



                      9.1. Заключение


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

                      Интересно видеть, как далеко мы зашли, и насколько мало кода это потребовало. Мы построили полный лексический анализатор, парсер, AST, генератор кода, интерактивное исполнение (с JIT!) и генерацию отладочной информации в самостоятельный исполняемый файл — всё это меньше 1000 строк уода (без учёта пустых строк и комментариев).

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

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

                      глобальные переменные — хотя ценность глобальных переменных в современной программной инженерии находится под вопросом, они часто используются для маленьких быстрых хаков, таких, как сам по себе компилятор Калейдоскопа. К счастью, в нашу программу добавить глобальные переменные очень легко: просто проверяем для каждой переменной, есть ли она в глобальной таблице символов. Для того. чтобы создать новую глобальную переменную, создайте экземпляр класса LLVM GlobalVariable.
                      типизированные переменные — сейчас Калейдоскоп поддерживает только переменные типа double. Это делает язык очень элегантным, потому что поддержка только одного типа означает, что вам не нужно указывать типы переменных. Различные языки имею разные способы решения этой проблемы. Самый простой путь — потребовать от пользователя указывать тип для каждого определения переменной, и записывать типы переменных в таблицу символов вместе с их Value*.
                      массивы, структуры, вектора, и т.п. Если вы вводите типы, вы можете начать расширять систему типов в разных интересных направлениях. Простые массивы сделать очень просто и полезно для разных видов приложений. Добавьте их в качестве упражнения, для изучения того, как работает инструкция LLVM getelementptr: она настолько элегантна и необычна, что имеет свой собственный FAQ!
                      стандартный рантайм — в текущем виде язык даёт пользователю возможность доступа к произвольным внешним функциям, и мы используем это для таких вещей, как «printd» и «putchard». Вы можете расширить язык так, чтобы добавить конструкции более высокого уровня, часто имеет смысл приводить такие конструкции к функциям рантайма, чем делать их в виде inline-последовательностей команд.
                      управление памятью — сейчас в языке Калейдоскоп есть доступ только к стеку. Также будет полезно выделять память в куче, либо путём вызова стандартных интерфейсов libc malloc/free, либо с помощью сборщика мусора. Если вы предпочтёте сборщик мусора, заметим, что LLVM полностью поддерживает точную сборку мусора (Accurate Garbage Collection), включая алгоритмы перемещения объектов, и необходимые для сканирования/обновления стека.
                      поддержка исключений — LLVM поддерживает генерацию исключений с нулевой стоимостью и с возможностью взаимодействия с кодом, скомпилированным в других языках. Вы можете также генерировать код, который подразумевает, что каждая функция возвращает значение ошибки, и проверяет это. Также можно реализовать исключения явным использованием setjmp/longjmp. В общем, существует много разных способов.
                      ООП, обобщённые типы, доступ к базам данных, комплексные числа, геометрическое программирование,… на самом деле, нет конца безумным штукам, которые можно добавить в язык.
                      необычные применения — мы говорили о применении LLVM в области, которой интересуются многие: построение компилятора для специфического языка. Однако, существует много других областей, для которых применение компилятора, на первый взгляд, не рассматривается. Например, LLVM используется для ускорения графики OpenGL, трансляции кода C++ в ActionScript, и множества других интересных вещей. Возможно, вы будете первым, кто построит JIT-компилятор в нативный код для регулярных выражений с помощью LLVM?
                      удовольствие — пробуйте сделать что-то безумное и необычное. Сделать язык, такой же, как все остальные, не так весело, как сделать что-то безумное. Если вы хотите поговорить об этом, не стесняйтесь писать в рассылку llvm-dev: там много людей, которые интересуются языками и часто желают помочь.

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

                      10.2. Свойства LLVM IR


                      Есть пара вопросов насчёт кода в форме LLVM IR, давайте рассмотрим их сейчас.

                      10.2.1. Независимость от целевой платформы


                      Калейдоскоп является примером «переносимого языка»: любая программа, написанная на Калейдоскопе будет работать одинаково на любой целевой платформе, на которой будет запущена. Многие другие языки имеют такое же свойство, например, Lisp, Java, Haskell, Javascript, Python и т.п. (отметим, что, хотя эти языки являются переносимыми, не все их библиотеки переносимы).

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

                      Тот факт, что LLVM предоставляет компактное, платформенно-независимое представление кода, очень привлекает. К сожалению, люди часто думают только о компиляции С или С-подобных языков, когда они спрашивают о переносимости языка. Я сказал «к сожалению», потому что на самом деле нельзя (в общем случае) сделать С-код переносимым, т.к., конечно же, сам по себе исходный код на С не является переносимым в общем случае, даже в случае портирования приложения с 32 на 64 бита.

                      Проблема с С (опять же, в общем случае) в том, что он очень полагается на платформеннозависимые допущения. В качестве простого примера, препроцессор сделает код платформеннозависимым, если он обрабатывает следующий текст:
                      #ifdef __i386__
                        int X = 1;
                      #else
                        int X = 42;
                      #endif
                      

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

                      Но подмножество С можно сделать переносимым. Если вы сделаете примитивные типы фиксированного размера (например, int = 32 бита, long = 64 бита), не будете беспокоиться насчёт совместимости ABI с существующими бинарными файлами, и откажетесь от некоторых других возможностей, то вы можете получить переносимый код. Это имеет смысл для некоторых особых случаев.

                      10.2.2. Гарантии безопасности


                      Многие из упомянутых языков также являются «безопасными»: для программы, написанной на Java невозможно испортить адресное пространство и уронить процесс (подразумевая, что JVM не имеет багов). Безопасность — это интересное свойство, требующее комбинации проектирования языка, поддержки рантайма, и, зачастую, поддержки ОС.

                      Определённо возможно реализовать безопасный язык в LLVM, но LLVM IR сам по себе не гарантирует безопасности. LLVM IR допускает небезопасные преобразования указателей, использование памяти после её освобождения, переполнение буферов, и различные другие проблемы. Безопасность должна быть реализована на уровне выше, чем LLVM и, к счастью, несколько групп занимались исследованием этого вопроса. Спрашивайте в списке рассылки llvm-dev, если вам интересны детали.

                      10.2.3. Оптимизации, специфичные для языка


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

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

                      Первое, это правда, LLVM теряет информацию. Например, невозможно различить на уровне LLVM IR, было ли SSA-значение порождено из типа С «int» или «long» на ILP32-машине (кроме как из отладочной информации). Оба компилируются в значение типа «i32», и информация об исходном типе теряется. Более общая проблема в том, что система типов LLVM считает эквивалентными типы с одинаковой структурой, не с одинаковыми именами. Это ещё одна вещь, которая удивляет людей, что если у вас есть два типа в высокоуровневом языке, имеющие одинаковую структуру, (например, две разных структуры, имеющие по одному полю int): эти типы будут скомпилированы в один тип LLVM, и будет невозможно сказать, какой исходной структуре принадлежали переменные.
                      Второе, хотя LLVM и теряет информацию, он не имеет фиксированной целевой платформы: мы продолжаем расширять и улучшать его в разных направлениях. Мы добавляем новые возможности (LLVM не всегда поддерживал исключения или отладочную информацию), мы расширяем IR, чтобы захватывать важную для оптимизации информацию (был ли аргумент расширен нулями или знаковым битом, информацию об аласинге указателей и т.п.). Многие улучшения инициированы пользователями: люди хотят, чтобы LLVM имел какие-либо специфические возможности, и мы идём им навстречу.
                      В-третьих, возможно легко добавлять специфические для языка оптимизации, и есть ряд способов сделать это. Как тривиальный пример, легко добавить проход оптимизации, который «знает» разные вещи о исходном коде. В случае С-подобных языков, такой проход оптимизации «знает» о функциях стандартной библиотеки С. Если вы вызываете функцию «exit(0)» в main(), он знает, что вызов можно безопасно конвертировать в «return 0», потому что стандарт С описывает, что должна делать функция «exit».

                      Вдобавок к простым знаниям о библиотеке, возможно встроить другую различную специфическую для языка информацию в LLVM IR. Если у вас есть специфические нужды, пожалуйста, напишите в список рассылки llvm-dev. В худшем случае, вы можете рассматривать LLVM как если бы он был «тупым кодогенератором» и реализовывать высокоуровневые оптимизации, какие вам угодно, в вашем фронтенде, в специфичном для вашего языка AST.

                      10.3. Приёмы и хитрости


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

                      10.3.1. Реализация переносимых offsetof/sizeof


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

                      10.3.2. Стековые кадры сборщика мусора


                      Некоторые языки хотят явно управлять кадрами стека, часто из=за наличия сборщика мусора или для того, чтобы проще реализовать замыкания. Часто есть лучшие способы реализации этих возможностей, чем явное управление кадрами стека, но LLVM поддерживает это, если вы хотите. Для этого нужно, чтобы ваш фронтенд конвертировал код в Continuation Passing Style и использовал хвостовые вызовы (которые LLVM также поддерживает).
                      Original source: habrahabr.ru (comments, light).

                      https://habrahabr.ru/post/337240/


                      Метки:  

                      PHP-Дайджест № 116 – свежие новости, материалы и инструменты (27 августа – 10 сентября 2017)

                      Понедельник, 11 Сентября 2017 г. 01:47 + в цитатник
                      pronskiy сегодня в 01:47 Разработка

                      PHP-Дайджест № 116 – свежие новости, материалы и инструменты (27 августа – 10 сентября 2017)



                        Свежая подборка со ссылками на новости и материалы. В выпуске: PHP 7.2.0 RC 1, Laravel 5.5 LTS, чистый код на PHP, предложения из PHP Internals, видео с конференций и митапов, и многое другое.
                        Приятного чтения!



                        Новости и релизы


                        • PHP 7.2.0 RC 1 — Стартовал цикл релиз-кандидатов ветки 7.2. Ожидается всего не менее 6 выпусков для стабилизации. Тем временем можно почитать что нового в PHP 7.2: тут habr и тут.
                        • PHP 7.0.23, PHP 7.1.9
                        • Laravel 5.5 LTS — Под капотом filp/whoops для ошибок, автообнаружение пакетов, улучшения очереди задач, улучшения исключений, фронтенд пресеты для React, и многое другое.
                        • Behat 3.4.0 — Обновление популярного BDD-фреймворка.
                        • NGINX Unit — Анонсирован сервер приложений от команды Nginx с поддержкой PHP.


                        PHP Internals


                        • RFC: Operator functions — Для всех операторов, кроме присваивания, предлагается добавить одноименные функции, чтобы их можно было использовать в качестве аргументов функций высшего порядка:
                          // Суммирует элементы массива (Эквивалент array_sum())
                          $sum = array_reduce($terms, '+', 0);
                          
                        • Add Fiber (sackful coroutine) support — Интересное улучшение генераторов в PHP, которое позволило бы упростить асинхронный код. Пока не оформлено в виде формального RFC, но уже имеется черновой пул-реквест.


                        Инструменты


                        • Botman 2.0.0 — Фреймворк для создания чат-ботов. Из коробки поддерживает: Slack, Telegram, Nexmo, HipChat, Facebook Messenger, WeChat. Туториалы Laravel + Botman: Telegram, FB Messenger, Slack.
                        • nkkollaw/zubr — Инструмент призван исправить проблемы встроенных функций PHP: добавлены неймспейсы, консистентное именование и порядок аргументов.
                        • Prooph — Инструменты для реализации CQRS и Event Sourcing на PHP. Туториал. Что такое Event Sourcing и почему это круто.
                        • parpalak/rose — Встраиваемый поисковый движок с поддержкой русского языка.
                        • spatie/fractalistic — Обертка над thephpleague/fractal добавляющая короткий текучий интерфейс.


                        Материалы для обучения




                        Аудио и видеоматериалы




                        Занимательное



                        Спасибо за внимание!

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

                        Прислать ссылку
                        Быстрый поиск по всем дайджестам
                        <- Предыдущий выпуск: PHP-Дайджест № 115

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

                        https://habrahabr.ru/post/337616/


                        Метки:  

                        Контроль на рабочем месте: новое постановление Европейского Суда

                        Понедельник, 11 Сентября 2017 г. 01:26 + в цитатник
                        iou-iou сегодня в 01:26 Управление

                        Контроль на рабочем месте: новое постановление Европейского Суда

                          Фабула дела

                          10 лет назад заявитель — Богдан Барбулеску был уволен из частной компании за то, что переписывался в рабочее время с невестой и братом в Yahoo Messanger.
                          Он работал в румынской частной компании в отделе по поддержке продаж. В его обязанности входило отвечать на запросы клиентов и для этого он использовал Yahoo Messanger, который установил по просьбе работодателя и в котором завел специальный аккаунт.
                          В компании существовали внутренние правила, которыми очень строго запрещалось использование ресурсов компании (в том числе интернета) для личных нужд. Заявитель был ознакомлен с ними под расписку. Через год после этого в компании был разослан документ, в котором напоминалось о запрете использовать оборудование компании и интернет в целях, не связанных с работой. Там также было указано, что компания может контролировать работников на предмет того, как они используют оборудование и интернет на рабочем месте. Также был описан случай увольнения сотрудницы за то, что она пользовалась для личных целей интернетом, факсом и ксероксом, не справлялась со своими обязанностями и халатно относилась к работе. Заявитель также был ознакомлен с этим документом под роспись. 
                          В июле 2007 года заявителя вызвали к начальству и попросили дать объяснения, почему его активность в интернете намного выше, чем у его коллег. На обвинение в использовании интернета в личных целях Богдан Барбулеску написал письменное заявление, что он не использует интернет в личных целях.  Через час начальство предъявило ему распечатку его переписки в Yahoo Messanger на 45 страницах за неделю, предшествовавшую его вызову к начальству. Из этой распечатки было ясно видно, что он переписывался по личным вопросам с братом и невестой. Через 2 недели его уволили. Заявитель проиграл в румынских судах спор с работодателем относительно его увольнения. Он обратился в Европейский Суд с жалобой на вторжение в его право на частную жизнь (статья 8 Европейской Конвенции). Дело рассматривалось с точки зрения обязательств государства охранять права от нарушения другими лицами, в данном случае бывшим работодателем заявителя. Сначала Суд сначала не нашел нарушения. После пересмотра дела в Большой Палате было установлено нарушение.

                          Что решил Европейский Суд

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

                          1. Работник должен быть заранее уведомлен о том, что работодатель может его контролировать и о сути такого контроля.
                          2. Содержание мониторинга и степень вторжения в частную жизнь работника. В решении отмечается, что имеется разница между просмотром переписки и чтением содержания переписки. Во втором случае вторжение в частную жизнь намного серьезнее.
                          3. Основания для контроля должны быть законные и обоснованные.
                          4. При проведении контроля при возможности должны быть использованы методы, при которых не проводится оценка всего содержания переписки работника.
                          5. Должна проводиться оценка последствий контроля для работника и насколько результаты контроля используются для тех целей, для которых такой контроль установлен.
                          6. При контроле работнику должны предоставляться адекватные способы защиты его частной жизни: компания не может читать никакие сообщения работников до тех пор, пока они не предупреждены о том, что компания может это делать. 
                           
                          Основной вопрос, который анализировал Суд в данном деле – насколько национальные суды взвесили конкурирующие интересы сторон: с одной стороны — право на частную жизнь и неприкосновенность переписки, предусмотренные статьей 8 Конвенции; с другой стороны – интерес компании в эффективности ее бизнеса и ее безопасности. И соответственно насколько румынские суды учли перечисленные выше факторы, когда рассматривали спор заявителя с его компанией.
                            
                          1. Предупреждение о мониторинге:
                          Суд отметил, что национальные суды исходили из того, что заявитель был предупрежден о том, что его переписка будет просматриваться его работодателем. В частности, он был уведомлен под расписку о том, что в компании запрещено использовать ее ресурсы, в том числе интернет, для личных целей, и что другой работник был уволен за использование ресурсов компании для личных целей. Однако, по мнению ЕСПЧ, они не исследовали вопрос о том, было ли заявитель уведомлен об объеме и характере такого мониторинга. По мнению ЕСПЧ компания, которая собирается контролировать переписку работника, должна уведомить его об этом перед началом мониторинга, особенно, когда контроль производится в отношении содержания переписки. 

                          2. Объем вмешательства:
                          Также Суд отметил, что национальные суды не проводили анализа объема мониторинга и степени вмешательства компании в личную среду их работника.

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

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

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

                          6. Момент, в который компания узнала содержание переписки 
                          Румынские суды не изучали вопрос о том, когда же компания прочла содержание переписки. По всей вероятности эти произошло до того, как заявителя вызвали, чтобы спросить об использовании интернета в личных целях. Тот факт, что компания могла получить доступ к содержанию переписки в любой момент дисциплинарного производства противоречит требованию прозрачности, закрепленному в рекомендациях Комитета Министров (CM/Rec(2015)5).

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

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

                          https://habrahabr.ru/post/337614/


                          Метки:  

                          Работа и жизнь в Болгарии. Часть вторая

                          Воскресенье, 10 Сентября 2017 г. 23:47 + в цитатник
                          slamon вчера в 23:47 Управление

                          Работа и жизнь в Болгарии. Часть вторая



                            18-ое ноября 2010-го года, Москва, 6 утра. На улице промозглый холодный ветер с мелким моросящими дождиком, заставляющий ёжиться в ожидании машины до Шереметьево. Регистрация, осмотр, паспортный контроль, небольшое ожидание, и вот уже в 8.20 самолет отрывается от полосы и несёт нас вдаль, в Софию. Два с половиной часа полёта, пустой встречающий аэропорт, небольшая очередь на паспортном контроле… И вот мы уже за дверьми аэропорта. Нас встречает яркое болгарское солнышко, ласково обогревающими своими лучами, и теплый легкий ветерок приятно пахнет свежестью и переменами…

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

                            Приезд




                            Из аэропорта мы взяли такси на ресепшн одной из таксомоторных фирм, и поехали в уже заранее арендованное жилье (без договора аренды вам не выдадут визу Д). Маленький совет приезжим: если вы приехали один и у вас нет кучи багажа, то вы можете воспользоваться метро, которое следует непосредственно от самого аэропорта и до центра города. Проезд на метро вам обойдется всего в 0.8 евро вместо ориентировочных 7 евро на такси.

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

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

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

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



                            Дело в том, что в Болгарии договора чтут и блюдут. И если вы подписали договор на 1 год, то будьте добры весь год и оплачивать. И если примерно за месяц до окончания договора вы не изъявили желание договор разорвать, то он будет автоматом продлен ещё на год (а то и на три). Пользуетесь ли вы при этом интернетом / сотовой связью, или нет — это никого не интересует. Если вы при этом решили забить на оплату, то не удивляйтесь, если затем на вас могут подать в суд из-за копеечных 50 евро. Так вот, интернет с ТВ нам подключили спустя 2 недели, оказался он паршивым, и я сменил провайдера на м-тел. Что не помешало blizoo затем заваливать меня бумажками «немедленно оплатите счет».

                            В Болгарии есть аналог нашей большой тройки. Это компании Vivacom, M-tel и Telenor, более известный как Globul. Любопытные читатели могут заглянуть на сайты этих операторов, чтобы увидеть тарифные планы (ищите слово «планове», это «тариф» по-болгарски). По большей части все услуги являются пост-оплатными, хотя есть и предоплатные симки. Для заключения договора иностранцам нужен или паспорт, или лична карта (если вы её уже получили).

                            Интернет и ТВ от М-Тел весьма качественные, быстрые, в общем — я доволен. На ТВ сотни каналов, включая и русские (ну, если вы вдруг соскучились по «Братки в законе-17», то НТВ вам поможет наверстать упущенное). Большая часть каналов идет на болгарском языке, многие на оригинальном языке, но с болгарскими субтитрами. И тут я хотел бы немного рассказать о самом болгарском языке.

                            Болгарский язык


                            Болгарский язык для русского человека может показаться удивительным. Для неподготовленного русского человека, который никогда не сталкивался с болгарским языком, не составит проблем с лету прочитать текст, написанный на болгарском. Скажем так, процентов 80 вы сможете понять с лёту. Это и неудивительное: славянский язык, общие корни, старая добрая кириллица без добавления латинских букв. И даже если болгарское слово на письме содержит в себе «неправильный» порядок букв, ваш мозг легко сможет конвертировать слово в «правильное». Можете проверить: прочитайте фразу «Строителни работници оставиха четири столични квартала без ток». Уверен, что ни у одного читателя не вызовет проблем прочитать и понять эту фразу.

                            Но совсем другое дело, когда вы впервые слышите болгарскую речь вживую. И понимаете, что нифига не понимаете :-)

                            И причин этому много, и одна из них — ударения. Попробуйте прочитать слова «Родина» с ударением на выделенную «и», и вы поймете, что это слово внезапно стало для вас совершенно непонятным и чужеродным. Ударения — это одна из ключевых особенностей, которая отличает болгарский язык от русского. Если честно, то я за 5 лет так и не научился правильно по-болгарски произносить банальное телефонное «ало».

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

                            Ещё одно интересное отличие: произношение буквы "Ъ". Если вы когда-нибудь сталкивались с болгарским письмом (на болгарский сайт, например, забредали), то наверняка удивились обилию рассыпанных по словам твердых знаков. И вот теперь внимание — это вовсе не твердый знак, а гласная буква, близкая в первом приближении по произношению к русскому "Ы". Произносится она, разумеется, не прямо как русское Ы, но аналог очень близкий. Другая необычная буква — "Щ". Произносится приблизительно как слитное «ШТ». И напоследок: буква "Е" в болгарском практически всегда читается как русское «Э».
                            Для особо любопытных читателей даю домашнее задание: потренируйтесь в произношении слова «КЪЩА» («дом» в переводе на русский).

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

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

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

                            Бизнес


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

                            В Болгарии вести бизнес не просто, а очень просто. Нет никаких ограничений на открытие фирмы иностранцами, открытие новой фирмы занимает около недели, расчетный счет открывается в банке за 10 минут на месте, бухгалтерия прозрачна и проста. Минимальный уставной капитал фактически отсутствует (1 евро). В абсолютом большинстве случае действует налоговый режим 10% от прибыли (доход минус расход). Это всё касается ЕООД/ООД — фактически полный аналог российскому ООО. Есть ещё АД (акционерно дружество), аналог АО в РФ), тут уставной капитал составляет уже 25 000 евро. Многие лицензируемые деятельности вроде кредитных/банковских/платежных также требуют минимальный уставной капитал не ниже особо установленных законом.

                            Бумажная волокита сведена к минимуму, все документы в электронном виде доступны через Търговски регистър (аналог ЕГРЮЛ), там же любой человек может просмотреть все данные по вашей фирме. У вас есть на руках «дружествен договор» (в качестве аналога можно рассмотреть российский «Устав фирмы»), «решение за вписване в търговски регистър» и ЕИК — уникальный номер вашей фирмы. По факту, в повседневной жизни управления фирмой вам нужен только знать свой ЕИК. За исключением редчайший случаев при заключении сделок никто тут в здравой уме не будет просить от вас копии копий всяких там ИНН и прочего бумажного барахла. Есть ЕИК, есть реестр — этого более чем достаточно на практике. Ах да, при определенном обороте фирме необходимо будет зарегистрироваться на выплату ДДС (аналог НДС), он составляет сегодня 20%, возврат ДДС осуществляется раз в год.

                            Практически все небольшие фирмы (а они составляют абсолютное большинство фирм в Болгарии) отдают всю бухгалтерию на аутсорс таким же небольшими бухгалтерским компаниям. Стоимость ведения фирмы разное и обычно стартует от размера минимальной заработной платы в месяц. Эта цифра каждый год корректируется правительством страны, и на 2017-ый год составляет 460 лева (примерно 230 евро).

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

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

                            Медицина


                            Никто из нас не железный, и наступают иногда моменты, когда приходится обращаться за квалифицированной медицинской помощью. Как иностранцу, доступ до бесплатной государственной медицины вам тут будет закрыт (по крайней мере, пока не получите ПМЖ, хотя и тут я не уверен, лучше эту информацию проверить). Это не касается вызовов скорой помощи: в случае необходимости скорая приедет, и даже не попросит вас показать какой-нибудь там документ или паспорт. Мы вызывали пару раз скорую: один раз, когда брату жены стало плохо во время прогулки, другой раз — для дочери, когда у неё подскочила температура до 39 с лихом. В первый раз скорая приехала спустя минут 10, другой же раз мы ждали скорую несколько часов (как нам потом сказали, к детям обязан выезжать педиатр, а их в Софии крайне мало и все были заняты на других вызовах). Врачи на скорой помощи были крайне вежливые, что-либо оплачивать не пришлось (даже намека не видел).

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

                            В Болгарии есть понятие «семейного доктора». Это что-то вроде нашего терапевта из прикрепленной поликлиники. Именно этот доктор будет выписывать вам рецепты на лекарства, проводить первичные осмотры и направлять к другим врачам. Да, кстати, имейте ввиду, что очень многие лекарства, которые есть в России, в Болгарии отсутствуют в принципе. Особенно выпадают в осадок аптекари, когда ты им пытаешься объяснить, что такое «зелёнка» :-)

                            При оформлении ВНЖ вы в обязательном порядке должны будете делать медицинскую страховку с покрытием до 30 000 евро. Если вы делаете эту страховку для отмазки (как это делали мы), то стоимость такой страховки будет не выше 30-50 евро. Но я советую вам сделать нормальную страховку в проверенной фирме. Дело в том, что по этой страховке вы сможете отбивать многие расходы в платных клиниках, что поможет здорово сэкономить на визитах к врачам. Мы про этот лайфхак узнали достаточно поздно от своих знакомых. Даже сами болгары очень часто предпочитают ходить в платные поликлиники, используя эти же страховки.

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

                            Образование



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

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

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

                            В Болгарии есть как государственные школы, так и частные. Для иностранцев обучение детей в государственной школе ранее было платным, сегодня же эту плату отменили. Не могу рассказать подробно об обучении в государственной школе, ибо мы свою дочь отдали по окончанию детского сада в платную школу под названием Образователни технологии, куда вместе с нами ушло в первый класс почти половина группы из детского сада. Стоимость обучения в школе составляет 350 евро в месяц (если оплачивать по-месячно) или 3550 евро при оплате сразу за год. Учатся дети с утра и до обеда (затем у нас была продленка с играми и прогулками), профессионально оборудованные классы, углубленное изучение английского языка. Учеба продолжается вплоть до 8-го класса, после чего идет уже так называемое профессиональное обучение либо в обычной, либо в специализированной школе. Суммарно в болгарских школах 12 классов, система оценок — 6-ти бальная. Стартует учеба 15-го сентября, и продолжается вплоть до июня. Таких каникул, как в России, в школах нет, исключение только одно — рождественские каникулы, которые длятся с 25-го декабря по 4-5 января. Кстати, для взрослых новогодних каникул тоже нет, уже 2-го января все выходят на работу.

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

                            P.S. Меня тут просили кота показать, ловите:

                            P.P.S. Продолжение следует :-)
                            Original source: habrahabr.ru (comments, light).

                            https://habrahabr.ru/post/337602/


                            Метки:  

                            Дайджест свежих материалов из мира фронтенда за последнюю неделю №279 (4 — 10 сентября 2017)

                            Воскресенье, 10 Сентября 2017 г. 23:41 + в цитатник
                            alexzfort сегодня в 23:41 Разработка

                            Дайджест свежих материалов из мира фронтенда за последнюю неделю №279 (4 — 10 сентября 2017)

                              Предлагаем вашему вниманию подборку с ссылками на новые материалы из области фронтенда и около него.


                                  Медиа    |    Веб-разработка    |    CSS    |    Javascript    |    Браузеры    |    Занимательное


                              Медиа


                              podcast Подкаст «Пятиминутка React» #34: Moscow Frontend Conference 2017 и BEM React Core
                              podcast Подкаст «devschacht»: Ночной фронтенд #3
                              podcast Подкаст «Фронтенд Юность (18+)» #18 Как Лёха не попал в Booking: Прокрастинация, собеседование в Booking, Приватные данные классов ES6, async_hooks
                              podcast Подкаст «Drinkcast», Выпуск #7 — «Все фронтендеры попадают в Питер»
                              video .getInstance: «Промисы в JavaScript»
                              video Видео докладов с конференции ChernivtsiJS #3, прошедшей 10 июня, 2017
                              video en Свежий выпуск шоу «Supercharged» о новом свойстве Font-Display, позволяющим улучшить скорость загрузки веб-шрифтов
                              video en Свежий выпуск шоу «Totally Tooling Tips» об инструменте Lighthouse

                              Веб-разработка


                              en confs.tech — сайт, где можно ознакомиться с грядущими международными конференциями по фронтенду
                              en Руководство по виртуальной реальности для веб-разработчиков
                              en Об особенностях и огранизации фронтенда на HealthCare.gov
                              en Примеры того, что я делаю каждый день в качестве разработчика фронтенда. Блог разработчика из IoT-компании
                              en Как в сервисе каршеринга car2go выбирали себе фреймворк
                              en Ленивое асинхронное растрирование SVG. Jake Archibald показывает способ растрирования SVG с помощью createImageBitmap
                              Еженедельная подборка красивых эффектов на CSS/SVG/JS #52




                              CSS


                              habr Сокращённые свойства. Зачем задавать картинку через background-image, если можно просто написать background?
                              en codepen Сборник советов по организации интерфейсов от Steve Schoger, на HTML и CSS
                              en Онлайн-генератор Critical Path CSS
                              en Цзен просто писать CSS. Заметка от Rich Harris, где он рассказывает, как самые большие проблемы с CSS могут быть решены без CSS-in-JS


                              JavaScript


                              video 8 Ошибок при изучении JavaScript — видео на канале Web Developer Blog
                              JavaScript и SEO: сканирует ли Google JavaScript?
                              [[][[]]+[]][+[]][++[+[]][+[]]] — это «n» в JavaScript
                              7 советов по обработке «undefined» в JavaScript
                              Базовый набор JavaScript алгоритмов: для начинающих
                              en Javascript: любопытный случай с Null >= 0
                              en Ироничный рассказ о руковостве каждого JavaScript фреймворка, написанного более чем 5 минут назад
                              en Как я убедил нашего технического директора перейти с CoffeeScript на ES6
                              en React vs Angular: подробное сравнение







                              Браузеры


                              Chrome Выпуск web-браузера Chrome 61
                              Firefox en 9 вещей в Firefox Dev Tools, о которых вы не знали
                              Chrome habr Обзор всех инструментов разработчика Chrome DevTools
                              Chrome en Как отлаживать JavaScript с помощью Chrome DevTools
                              Chrome В Chrome 63 появятся средства информирования о попытках перехвата HTTPS
                              Создатель Opera обвинил Google в препятствовании работе Opera и Vivaldi

                              Занимательное


                              Мэтт Мулленвег описал проблемы, связанные с Gutenberg, и подтвердил, что новый редактор появится в WordPress 5.0
                              Компания-владелец Trello и Jira запустила корпоративный мессенджер Stride
                              Facebook запустил сервис для встреч с друзьями в духе Badoo и Tinder
                              Криптовалюта: текущее состояние и перспективы развития
                              Наставничество в IT: что делать, если вам поручили джуниора
                              Как защитить веб-приложение: основные советы, инструменты, полезные ссылки
                              Как Google в тайне финансирует академические исследования. Себе на пользу
                              Ради всего святого, напишите на главной сайта, что делает ваша компания

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



                              Дайджест за прошлую неделю.
                              Материал подготовили dersmoll и alekskorovin.
                              Original source: habrahabr.ru (comments, light).

                              https://habrahabr.ru/post/337610/



                              Поиск сообщений в rss_rss_hh_new
                              Страницы: 1437 ... 1137 1136 [1135] 1134 1133 ..
                              .. 1 Календарь