Новости web-panda https://web-panda.ru Авторский блог @CatOstrovsky. Только все самое интересное о JavaScript, PHP, NodeJS... ru Стань первым в Slovar.IO https://web-panda.ru/post/slovario-beta

✌Добро пожаловать в увлекательный мир Slovario! Это замечательная игра в жанре "головоломка" с интересными подсказками, улучшениями и бустами. 🧠Игра не только позволит Вам расслабиться и отвлечься, но и отлично способствует развитию внимания и позволяет расширить словарный запас.


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

👻 FREE OF ADS 100%;

✌ MULTIPLAYER;

💥 IT'S COMPLETELY FREE;

📈 GREAT WORKING WITHOUT INTERNET;

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

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

Зарабатывай монеты и открывай новые миры!

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

]]>
Tue, 11 Jun 2019 12:53:33 +0000 ООП Konstantin Ostrovsky
Алгоритм шифрования base64 https://web-panda.ru/post/base-64 Кодировка Base64 используется для преобразования двоичных данных в текстовый формат, который позволяет транспортировать их в средах, которые могут безопасно обрабатывать только текст. Варианты использования - это кодирование UID для использования в URL-адресах HTTP, кодирование ключей шифрования и сертификатов, позволяющих безопасно переносить их по электронной почте, отображать их на страницах HTML и использовать для копирования и вставки.

Base64 иногда также упоминается как PEM, которая выступает за P rivacy повышенной E lectronic M аила. Там Base64 использовался для создания печатного текста снова после двоичных данных электронной почты, которые были сгенерированы в процессе шифрования электронной почты.

Как это устроено


Кодирование Base64 берет исходные двоичные данные и оперирует ими, разделяя их на токены по три байта. Байт состоит из восьми битов, поэтому Base64 занимает всего 24 бита. Эти 3 байта затем преобразуются в четыре печатных символа из стандарта ASCII.

Первый шаг - взять три байта (24 бита) двоичных данных и разделить их на четыре числа по шесть бит. Поскольку стандарт ASCII определяет использование семи битов, Base64 использует только 6 битов (что соответствует 2 ^ 6 = 64 символа), чтобы обеспечить возможность печати закодированных данных и не использовать ни один из специальных символов, доступных в ASCII. Название алгоритма Base64 происходит от использования этих 64 символов ASCII. Символами ASCII, используемыми для Base64, являются цифры 0-9, алфавиты 26 строчных и 26 прописных символов, а также два дополнительных символа «+» и «/».

Таблица кодирования / декодирования Base64
AВСDЕFгЧАСяJКLMNОп
0123456789101112131415
 
QрSTUВWИксYZaбсdее
16171819202122232425262728293031
 
гчасяJКLмNопQрsTUv
32333435363738394041424344454647
 
весИксYZ0123456789+/
48495051525354555657585960616263
 

В наших программах мы можем просто определить эту таблицу как массив символов. Например, в «C» мы будем делать:

/ * ---- Таблица кодирования / декодирования Base64 --- * /
char b64 [] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 + /";

Технически, используется 65-ый символ «=», но об этом подробнее ниже.

Преобразование ASCII 3-байтовых 24-битных групп повторяется до тех пор, пока не будет закодирована вся последовательность исходных байтов данных. Чтобы обеспечить правильную печать закодированных данных и не превышать ограничение длины строки на любом почтовом сервере, вставляются символы новой строки, чтобы длина строк не превышала 76 символов.

Что происходит, когда последняя последовательность байтов данных для кодирования имеет длину не более 3 байтов? Если размер исходных данных в байтах не кратен трем, мы можем получить только один или два оставшихся (8-битных) байта. Решение состоит в том, чтобы добавить недостающие байты, используя значение байта «0» для создания окончательной 3-байтовой группы. Поскольку эти искусственные конечные «0» не могут быть закодированы с использованием таблицы кодирования, мы вводим 65-й символ: «=» для представления «0». Естественно, этот символ может появляться только в конце закодированных данных.

Пример


Допустим, мы хотим преобразовать три байта 155, 162 и 233. Соответствующий 24-битный поток - 100110111010001011101001.

155 -> 10011011
162 -> 10100010
233 -> 11101001

Разделение этих битов на 4 группы по 6 бит создает следующие 4 десятичных значения: 38, 58, 11 и 41.

100110 -> 38
111010 -> 58
001011 -> 11
101001 -> 41

Преобразование их в символы ASCII с использованием таблицы кодирования Base64 переводит их в последовательность ASCII «m6Lp».

38 -> м
58 -> 6
11 -> L
41 -> р
]]>
Tue, 11 Jun 2019 12:31:52 +0000 JavaScript Konstantin Ostrovsky
Массовое заражение серверов Linux (CVE-2019-10149) https://web-panda.ru/post/exim-important-information-2019 Exim (v4) - это агент пересылки почты. exim4-config предоставляет инфраструктуру конфигурации для служб exim4. Она была вынесена в отдельный пакет для упрощения замены конфигурационной схемы собственной (без изменения файлов относящихся к основным пакетам exim4).

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

Выявлена критическая уязвимость в почтовом сервере Exim, которая позволяет выполнить код на сервере с правами root.

Данная уязвимость (CVE-2019-10149) https://security-tracker.debian.org/tracker/CVE-2019-10149 может привести к выполнению кода на сервере с правами root, который осуществляется во время обработки специального запроса. Ошибка была найдена в версиях Exim 4.87 до 4.91 (включительно). Неправильная проверка адреса получателя в функции delivery_message () в /src/deliver.c может привести к удаленному выполнению команды.
Узнайте больше о CVE-2019-10149 из словаря MITER CVE и NIST NVD . Эксплуатация данной угрозы возможна в версиях с 4.87 по 4.91 включительно или при сборке с опцией EXPERIMENTAL_EVENT.

Для исправления прошлых версий, применяющихся в дистрибутивах, можно использовать патч, доступный по ссылке: https://git.exim.org/exim.git/commit/d740d2111f189760593a303124ff6b9b1f83453d

Exim широко распространен. На момент публикации результаты поиска Shodan показали, что более 4,1 миллиона систем используют версии Exim, которые считаются уязвимыми (4.87-4.91), а 475 591 - последняя исправленная версия (4.92). Другими словами, почти 90% систем с Exim уязвимы для локальной эксплуатации и потенциально для удаленной эксплуатации в зависимости от конфигурации.


 

Как понять, что сервер взломан?


Проверьте запущенные процессы командой top.
На заражённых серверах наблюдается 100%-я нагрузка, создаваемая процессом [kthrotlds]. Также в планировщике cron добавляется задание с ограничением прав на редактирование.

 

>>>Лечение описано здесь <<<

 

Обновление до безопасной версии

Обновления для пакетов, поставляющих версию 4.92, в которой не проявляется данная проблема, можно найти по ссылкам:

Для Debian: https://security-tracker.debian.org/tracker/CVE-2019-10149

Для Ubuntu: https://people.canonical.com/~ubuntu-security/cve/2019/CVE-2019-10149.html

Для OpenSUSE: https://bugzilla.novell.com/show_bug.cgi?id=CVE-2019-10149

Для Arch Linux: https://www.archlinux.org/packages/community/x86_64/exim/

Для Fedora: https://bodhi.fedoraproject.org/updates/FEDORA-2019-7b741dcaa4

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

Некоторую информацию о CVE-2019-10149 в дистрибутивах Linux можно найти здесь:

Отслеживание безопасности Debian: CVE-2019-10149
База данных Red Hat CVE: CVE-2019-10149
Ubuntu CVE Tracker: CVE-2019-10149
Gentoo Bugzilla: CVE-2019-10149
Центр безопасности Amazon Linux: ALAS-2019-1221

Источник: Habr

Подробнее об особенностях и принципе действия уязвимости можно прочитать по ссылке: http://www.opennet.ru/opennews/art.shtml?num=50819

]]>
Tue, 11 Jun 2019 09:52:11 +0000 Linux Konstantin Ostrovsky
Случайности - не случайны. Random с учетом веса https://web-panda.ru/post/random-with-weight Наверно, каждый из Вас, так или иначе сталкивался с генераторами псевдослучайных чисел. Эти функции активно используются в играх, веб-сайтах и сложных информационных системах. Чаще всего функция rand уже входит в базовый набор функций языка. В JS - это Math.random, C# - System.Random, Cpp - std::rand, PHP - rand и тд.

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

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

Генератор псевдослучайных чисел (ГПСЧ, англ. pseudorandom number generator, PRNG) — алгоритм, порождающий последовательность чисел, элементы которой почти независимы друг от друга и подчиняются заданному распределению (обычно равномерному). Современная информатика широко использует псевдослучайные числа в самых разных приложениях — от метода Монте-Карло и имитационного моделирования до криптографии. При этом от качества используемых ГПСЧ напрямую зависит качество получаемых результатов. Это обстоятельство подчёркивает известный афоризм математика ORNL Роберта Кавью (англ.)русск.: «генерация случайных чисел слишком важна, чтобы оставлять её на волю случая». Wikipedia

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

Для примера предлагаю написать алгоритм генерации букв алфавита с учетом их частотности. 

Частотность — термин лексикостатистики, предназначенный для определения наиболее употребительных слов. Расчёт осуществляется по формуле: , где Freqx — частотность слова «x», Qx — количество словоупотреблений слова «x», Qall — общее количество словоупотреблений. В большинстве случаев частотность выражается в процентах. В словарях частотность слов может отражаться пометками — употребительное, малоупотребительное и т. д. Аналогичным образом определяется частотность для букв. Бо́льшая частотность согласных на данном отрезке текста (например, в стихотворениях) получила название аллитерации. Высокие показатели частотности гласных называются ассонансом. Частотный анализ используется в криптографии для выявления наиболее частотных букв того или иного языка. Частотность слов и букв являлась важнейшим инструментов криптоанализа в эпоху до повсеместного распространения блочных шифров. Не следует путать термины частотность и частота.Wikipedia

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

 

#БУКВАУПОТРЕБЛЕНИЙЧАСТОТНОСТЬ
1о5541448110.97%
2е426912138.45%
3а404870088.01%
4и371531427.35%
5н338388816.70%
6т316209706.26%
7с276270405.47%
8р239168254.73%
9в229307194.54%
10л222301744.40%
11к176534693.49%
12м162030603.21%
13д150521182.98%
14п142015722.81%
15у132457122.62%
16я101390852.01%
17ы95959411.90%
18ь87846131.74%
19г85646401.70%
20з83299041.65%
21б80517671.59%
22ч73001931.44%
23й61062621.21%
24х49041760.97%
25ж47469160.94%
26ш36787380.73%
27ю32207150.64%
28ц24388070.48%
29щ18224760.36%
30э16101070.32%
31ф13357470.26%
32ъ1854520.04%
33ё1849280.04%

 

Как мы видим, лидером по употреблению в словах в русском языке, является буква "О". Её частотность более 10%!

Для работы приведем эти данные в формат JSON. Структура будет следующая: [ { буква, вес } , ...].

В итоге получаем следующий JSON:

[
    { "word": "о", "weight": 10.97 },
    { "word": "е", "weight": 8.45 },
    { "word": "а", "weight": 8.01 },
    { "word": "и", "weight": 7.35 },
    { "word": "н", "weight": 6.70 },
    { "word": "т", "weight": 6.26 },
    { "word": "с", "weight": 5.47 },
    { "word": "р", "weight": 4.73 },
    { "word": "в", "weight": 4.54 },
    { "word": "л", "weight": 4.40 },
    { "word": "к", "weight": 3.49 },
    { "word": "м", "weight": 3.21 },
    { "word": "д", "weight": 2.98 },
    { "word": "п", "weight": 2.81 },
    { "word": "у", "weight": 2.62 },
    { "word": "я", "weight": 2.01 },
    { "word": "ы", "weight": 1.90 },
    { "word": "ь", "weight": 1.74 },
    { "word": "г", "weight": 1.70 },
    { "word": "з", "weight": 1.65 },
    { "word": "б", "weight": 1.59 },
    { "word": "ч", "weight": 1.44 },
    { "word": "й", "weight": 1.21 },
    { "word": "х", "weight": 0.97 },
    { "word": "ж", "weight": 0.94 },
    { "word": "ш", "weight": 0.73 },
    { "word": "ю", "weight": 0.64 },
    { "word": "ц", "weight": 0.48 },
    { "word": "щ", "weight": 0.36 },
    { "word": "э", "weight": 0.32 },
    { "word": "ф", "weight": 0.26 },
    { "word": "ъ", "weight": 0.04 },
    { "word": "ё", "weight": 0.04 }
]

Данные подготовлены, настало время разобрать наш алгоритм. Алгоритм будет оперировать 4-мя переменными:

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

Разберем алгоритм. Для этого разделим его работу на несколько этапов:

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

Вот такая простая, но очень полезная функция теперь у Вас в арсенале!

Реализация алгоритма на языке JavaScript

/**
    Генерация случайного элемента с учетом веса
    @param array values [{word, weight}, ...]
    @return string word
**/
function randomWithWeight ( values )
{    
    
    // Создаем переменные
    let total = 0,
    currentWeight = 0,
    rndWeight = 0;

    // Вычисляем общий вес
    for(let item of values) total += item.weight;

    // Находим случайный вес
    rndWeight = Math.floor(Math.random() * total)
    
    // Перебираем все элементы, пока не достигнем нужного веса
    for (let item of values)
    {
        currentWeight += item.weight; // Прибавляем вес текущего элемента массива к временной переменной
        if ( currentWeight >= rndWeight ) // Прерываем генерацию и возвращаем букву
            return item.word;
    }
}

var words = [{ "word": "о", "weight": 10.97 }, { "word": "е", "weight": 8.45 }, { "word": "а", "weight": 8.01 }, { "word": "и", "weight": 7.35 }, { "word": "н", "weight": 6.70 }, { "word": "т", "weight": 6.26 }, { "word": "с", "weight": 5.47 }, { "word": "р", "weight": 4.73 }, { "word": "в", "weight": 4.54 }, { "word": "л", "weight": 4.40 }, { "word": "к", "weight": 3.49 }, { "word": "м", "weight": 3.21 }, { "word": "д", "weight": 2.98 }, { "word": "п", "weight": 2.81 }, { "word": "у", "weight": 2.62 }, { "word": "я", "weight": 2.01 }, { "word": "ы", "weight": 1.90 }, { "word": "ь", "weight": 1.74 }, { "word": "г", "weight": 1.70 }, { "word": "з", "weight": 1.65 }, { "word": "б", "weight": 1.59 }, { "word": "ч", "weight": 1.44 }, { "word": "й", "weight": 1.21 }, { "word": "х", "weight": 0.97 }, { "word": "ж", "weight": 0.94 }, { "word": "ш", "weight": 0.73 }, { "word": "ю", "weight": 0.64 }, { "word": "ц", "weight": 0.48 }, { "word": "щ", "weight": 0.36 }, { "word": "э", "weight": 0.32 }, { "word": "ф", "weight": 0.26 }, { "word": "ъ", "weight": 0.04 }, { "word": "ё", "weight": 0.04 }];

// Генерируем 50 случайных элементов
for (var i = 50; i >= 0; i--)
    console.log(randomWithWeight(words));

 

Реализация алгоритма на языке C#

using System.Collections.Generic;
using System.Collections;
using System;

[Serializable]
// Вспомогательная структура данных для хранения элементов массива
public class WordInsert
{
  public string word;
  public float weight;
}

/**
    Генерация случайного элемента с учетом веса
    @param array data [{word, weight}, ...]
**/
public class RandomWeight
{
  private WordInsert[] WordsList = null;

  RandomWeight(WordInsert[] data) {
        WordsList = data;
  }


  public string GetRandom() {
    // Создаем переменные
    float total = 0;
    float currentWeight = 0;
    float rndWeight = 0;

    // Вычисляем общий вес
    foreach(WordInsert i in WordsList) total += i.weight;

    // Находим случайный вес
    rndWeight = UnityEngine.Random.Range(1, total);

    // Перебираем все элементы, пока не достигнем нужного веса
    foreach (WordInsert word in WordsList)
    {
        currentWeight += word.weight;  // Прибавляем вес текущего элемента массива к временной переменной
        if ( currentWeight >= rndWeight )  // Прерываем генерацию и возвращаем букву
            return word.word;
    }

    return ""; // Подстраховка
  }
}
]]>
Wed, 08 May 2019 10:59:58 +0000 JavaScript Konstantin Ostrovsky
Словари и работа с ними https://web-panda.ru/post/words-and-db

 

Что такое словарь?

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

С развитием компьютерной техники всё большее распространение получают электронные словари и онлайн-словари.

Источник https://ru.wikipedia.org

 

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

 

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

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

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

Вы даже можете использовать словари для тренировки искусственных нейронных сетей. К примеру создать ИНС, которая будет генерировать Lorem Ipsum.

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

 

Где взять?

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

Мой выбор пал на использование SQLite для работы с словарем. Для конвертации был написан небольшой скрипт на NodeJS. Он работает достаточно примитивно, просто загоняет в базу записи из массива, который он строит на основе словаря из файла *txt. Я думаю, что Вам будет не трудно модифицировать скрипт для работы с CSV, XML и другими форматами данных. Время работы с 65 000 записей ~ 5секунд. Все записи добавляются одной транзакцией. Честно говоря, я не проверял какую нагрузку сможет выдержать скрипт, поэтому в случае необходимости, Вы можете модифицировать его и разбить на несколько транзаций. Скачать скрипт+словарь можно по этой ссылке.

Если база будет в формате sql, то Вы с легкостью можете перегнать ее в SQLite3 при помощи простой команды:

sqlite3 database.sqlite3 < db.sql

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

  1. http://www.speakrus.ru/dict/
  2. https://shra.ru/2017/03/baza-dannykh-russkikh-slov-sushhestvitelnye/
  3. https://github.com/danakt/russian-words
  4. http://ivanov-portal.ru/slovari/slovari.html
  5. http://blog.harrix.org/article/3334

 

Как использовать SQLite в Unity?

Существует много реализаций библиотек и готовых решений, которые Вы можете найти на https://assetstore.unity.com.

В своем последнем проекте я использовал https://github.com/rizasif/sqlite-unity-plugin.

Плагин *.dll поддерживает компиляцию под х64, которую с недавних пор так любит Google Play.  

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

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Data;
using Mono.Data.Sqlite;
using System.IO;
using UnityEngine.Networking;

public class DB : MonoBehaviour
{ 
    [HideInInspector]
    public IDbConnection dbcon;
    
    [HideInInspector]
    public static string wordsTable = "words";

    public static bool connected = false;
    private string DBFilename = "db.sqlite";

    void Start()
    {
      Connect();
    }

    // Подключение к базе данных
    void Connect() {

      if (System.IO.File.Exists(Application.persistentDataPath + "/" + DBFilename))
      {
        string connection = "URI=file:" + Application.persistentDataPath + "/" + DBFilename;
        dbcon = new SqliteConnection(connection);
        dbcon.Open();
        Debug.Log("DB exists");
        connected = true;

      }else{
        StartCoroutine(DownloadDB(DBFilename));
      }

    }

    // Загружаем базу данных из внешнего источника
    IEnumerator DownloadDB(string file_name)
    {
        Debug.Log("Download database...");
        string url = "https://example.com/" + file_name;
        using (UnityWebRequest www = UnityWebRequest.Get(url))
        {
            yield return www.SendWebRequest();
            if (www.isNetworkError || www.isHttpError)
            {
                Debug.Log(www.error);
            }
            else
            {
                string savePath = string.Format("{0}/{1}", Application.persistentDataPath, file_name);
                System.IO.File.WriteAllBytes(savePath, www.downloadHandler.data);
                Connect();
            }
        }
    }

    // Получаем все таблицы и ищем в них нужную. Если нет - создаем
    bool CheckExistsTable(string table) {
      var tables = GetTable(table);
      var exists = false;
      while(tables.Read()) if(tables[0].ToString() == table) exists = true;
      if(exists == false) CreateTables(table);

      return exists;
    }

    // Создать таблицу, если она не создана
    void CreateTables(string table) {
      var dbcmd = dbcon.CreateCommand();
      string q_createTable =
        "CREATE TABLE IF NOT EXISTS " + table + " (" +
        "id" + " INTEGER PRIMARY KEY, " +
        "val" + " STRING )";

      dbcmd.CommandText = q_createTable;
      dbcmd.ExecuteReader();
    }

    // Добавить запись
    void InstertWord(string word, string table) {
      var dbcmd2 = dbcon.CreateCommand();
      dbcmd2.CommandText = "INSERT INTO "+table+" (val) VALUES ('"+word+"')";
      dbcmd2.ExecuteNonQuery();
    }

    // Получить все записи
    IDataReader GetRows(string table) {
      var dbcmd3 = dbcon.CreateCommand();
      string query ="SELECT * FROM "+table;
      dbcmd3.CommandText = query;
      var reader = dbcmd3.ExecuteReader();

      return reader;
    }

    // Найти запись в базе
    public IDataReader Find(string name, string table) {
      var dbcmd3 = dbcon.CreateCommand();
      string query ="SELECT * FROM "+table+" WHERE val='"+name+"'";
      dbcmd3.CommandText = query;
      var reader = dbcmd3.ExecuteReader();

      return reader;
    }

    // Получить таблицу из базы
    IDataReader GetTable(string name) {
      var dbcmd3 = dbcon.CreateCommand();
      string query ="SELECT name FROM sqlite_master WHERE type='table' AND name='"+name+"';";
      dbcmd3.CommandText = query;
      var reader = dbcmd3.ExecuteReader();

      return reader;
    }

    // Закрыть соединение
    void Close() {
      dbcon.Close();
      connected = false
    }

}

]]>
Wed, 08 May 2019 08:11:19 +0000 JavaScript Konstantin Ostrovsky
Возрождение легенды! Gravity Tracks Android https://web-panda.ru/post/gravity-defied-beta 🏁Возрождение популярнейшего хита с мобильных устройств! 
🎮Испытай себя на более чем 30 трассах с различным уровнем сложности.

💪🏻Вам доступны 7 персонажей, 6 байков и 15 видов колес с различными характеристиками.

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

 

 

]]>
Mon, 06 May 2019 09:33:07 +0000 Project Konstantin Ostrovsky
Быстрый старт с Unity 3D https://web-panda.ru/post/the-car-and-the-ball Игровая индустрия не стоит на месте и 3D игры уже стали обыденностью. Unity предоставляет огромный набор инструментов для создания 3D игр. Сегодня я ознакомлю Вас с самыми полезными компонентами и приведу примеры их использования.

Хотелось бы сразу сообщить Вам что статья не претендует на пособие по работе с Unity 3D, в статье лишь рассмотрены наиболее полезные аспекты.

Unity - бесплатная платформа для создания кроссплатформенных игр. Код пишется на языке C#, который после TS не должен Вас пугать. Скачать Unity можно с официального сайта: https://unity.com/ru
Так же советую Вам сразу зарегистрироваться на сайте, так как магазин дополнений и программа требует авторизации.

В качестве редактора по умолчанию будет установлен VS Code, но этот редактор платный. Если Вы не желаете платить за IDE, то советую связку Atom и IDE-CSharp.

Я опущу установку компонентов, думаю тут и так все понятно. Если у Вас возникнут вопросы - пишите в комментарии.

 

Начало работы

Любое создание игры начинается с создания проекта. Откройте Unity и он сразу предложит Вам открыть существующий проект или создать новый. При создании необходимо указать тип приложения: 2D, 3D и др. Это не сильно на что-либо влияет, но лучше указать. Аналитику подключать необязательно.

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

 

Основные термины

Идеология Unity достаточно проста и мало отличается от Unreal Engine или Cocos Creator. Если Вы уже знакомы с этими движками, то эту часть статьи можно пропустить. 

Важно понимать что все элементы, которые Вы видите в игре Unity являются инстансами класса GameObject, соответственно имеют все его методы и свойства. Создать новый  игровой объект Вы можете в редакторе структуры сцены, либо при помощи метода Instantiate() в коде. Сами по себе объекты не несут никакого функционала. Что бы "прицепить" логику к игровому объекту, мы должны добавить к нему компонент

Компонент - это код, написанный на языке C#. Все компоненты наследуются от базового класса MonoBehaviour. Для создания нового компонента рекомендую воспользоваться навигацией по файлам. Как можно заметить, компоненты могут иметь переменные, значения которых мы должны устанавливать прямо в редакторе. Что бы свойство компонента отображалось в редакторе, достаточно просто сделать это свойство публичным. Визуальный компонент автоматически меняется в зависимости от типа переменной.

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

UI или же Canvas. Важно понимать что все игровые элементы, которые созданы вне элемента Canvas будут смещаться при изменении позиции камеры. Canvas служит для хранения HUD-элементов и подобного. К сожалению, на Canvas есть ограничения. Он не отображает 3D-объекты. 

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

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

Shader. Шейдеры чаще всего используют для визуализации различных графических эффектов. Среди этих эффектов блики воды, размытие и еще много. Шейдеры устроены достаточно просто, но дают безграничные возможности. Шейдер - функция, в которую передается вектор позиции пикселя и вектор его цвета. Функция должна вернуть новый цвет пикселя. В один проход рендера вывается шейдер для каждого пикселя. Для монитора 1920х1080 - это 2073600 вызова на кадр. Можно представить как напрягается GPU в это время. Поэтому, крайне не рекомендуется злоупотреблять шейдерами, а их оптимизация - это вообще отдельная история... Провести эксперименты и написать свой шейдер Вы можете на сайте https://www.shadertoy.com/.

Я опущу такие термины как Camera, HUD, Sprite, Tile. Эти понятия были рассмотрены в цикле статей по Phaser 3.

 

Разные плюшки

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

Particle System

Больше всего мне всегда было интересно как же делают дым и туман в играх, потому что дым или туман - это очень сложный физический и химический процесс, который зависит от множества факторов окружающей среды и состоит из миллионов частиц. Да и все олды помнят потрясающие GTA V, NFS, TDU. Если у Вас не очень мощный ПК, то каждый раз когда в игре отображался дым из под колес - ПК ловил жестокие тормоза. Для создания таких вещей, в Unity существует компонент Particle System (пер. система частиц).  Компонент имеет очень много настроек отображения. Все они отлично описаны здесь. Ниже Вы можете увидеть результаты некоторых моих наработок:

Physics

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

Light

Он же - свет. Позволяет создавать потрясающие сцены, которые поражают своей реалистичностью. Существует несколько компонентов для освещения. Основные, которые Вам точно пригодятся - Direction Light(Направленный свет) и Point Light(Точка света). Вот лишь несколько примеров реализации освещения:

 

Подводя итоги

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

Как обещал, ссылки на сорцы:

- The Ball - отличная аркада, созданная с использованием только встроенных возможностей движка. Цель игры - пройти как можно дальше и открыть все скины персонажа. В игре присутствуют Coins, которые можно поднять в ходе прохождения уровней. Реализованы самые популярные аркадные бусты и что не мало важно, отсутствует реклама! Игра скомпилирована под Android, скачать apk можно здесь.

- Simple Car - удобнейший шаблон для гоночной игры. Реализована вся физика, доступно 4 машины на выбор. Это лишь скелет игры и только от Вас зависит что получится в результате.  Игра скомпилирована под Android, скачать apk можно здесь.

 

Бонус

В качестве бонуса предоставляю Вам возможность самостоятельно пройти экскурсию по лаборатории WebPanda в виртуальном мире:

]]>
Thu, 28 Mar 2019 14:09:17 +0000 Пример Konstantin Ostrovsky
Поиск и очистка толстых папок в Linux https://web-panda.ru/post/fat-linux-folders Свободное место на диске (df)

Для просмотра свободного и занятого места на разделах диска в Linux можно воспользоваться командой df.

Ввод команды df без параметров дает вполне наглядный вывод свободного и занятого месте в разделах. Но вывод является не очень понятным для большинства пользователей, потому что размеры выводятся в КБайтах (1К-блоках).

df

Filesystem     1K-blocks    Used Available Use% Mounted on
udev              240964       0    240964   0% /dev
tmpfs              50424    5508     44916  11% /run
/dev/vda1       10303764 8054728   1802840  82% /
tmpfs             252104       0    252104   0% /dev/shm
tmpfs               5120       0      5120   0% /run/lock
tmpfs             252104       0    252104   0% /sys/fs/cgroup
tmpfs              50420       0     50420   0% /run/user/1001

Примечание: df не отображает информацию о не смонтированных дисках.

Опция -h

Опция -h (или —human-readable) позволяет выводить данные в человеко-понятном формате. Размер теперь будет выводиться в GB.

df -h

Filesystem      Size  Used Avail Use% Mounted on
udev            236M     0  236M   0% /dev
tmpfs            50M  5.4M   44M  11% /run
/dev/vda1       9.9G  7.7G  1.8G  82% /
tmpfs           247M     0  247M   0% /dev/shm
tmpfs           5.0M     0  5.0M   0% /run/lock
tmpfs           247M     0  247M   0% /sys/fs/cgroup
tmpfs            50M     0   50M   0% /run/user/1001

Размер конкретного диска

Команде df можно указать путь до точки монтирования диска, размер которого вы хотите вывести:

df -h /dev/vda1

Filesystem      Size  Used Avail Use% Mounted on
/dev/vda1       9.9G  7.7G  1.8G  82% /

Размер папок на диске (du)

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

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

Если нужно просмотреть размеры без рекурсивного обхода всех папок, то используется опция -s (--summarize). Также как и с df, добавим опцию -h (--human-readable).

du — утилита суммирует статистику для каждого файла с каталогами.

Ключи:
-s — показывать уже итог для каждого аргумента;
-c — выводит сумарный итог;
-k — использовать блоки размером 4K (синоним —block-size=4K);
-h — Выводить все размеры в удобном для  чтения и понимания (для примера, 4K 2M 8G);

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

du -sh /var/

2.1G    /var/

Размеры файлов и папок внутри конкретной папки:

du -sh /var/*

2.0M    /var/backups
409M    /var/cache
597M    /var/lib
4.0K    /var/local
0       /var/lock
71M     /var/log
8.0K    /var/mail
4.0K    /var/opt
0       /var/run
14M     /var/softaculous
4.0K    /var/softtmp
20K     /var/spool
1.1G    /var/swap.1
28K     /var/tmp
28K     /var/www

Сортировка результатов:

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

du -sh /etc/* | sort -rn
840K    /etc/php
812K    /etc/ssl
724K    /etc/apache2
672K    /etc/fail2ban
580K    /etc/ssh
264K    /etc/ImageMagick-6
248K    /etc/exim4
232K    /etc/roundcube

sort — утилита для сортировки и  вывода файлов на экран.

Ключи:
-r — (reverse) — обратить результаты сравнения;
-n — сортировать по размеру.

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

]]>
Thu, 14 Mar 2019 10:23:29 +0000 Linux Konstantin Ostrovsky
Создание HTML5-игр для самых маленьких(Phaser) Часть 4 https://web-panda.ru/post/phaser-3-released-4 В прошлой статье мы ознакомились с основными терминами разработки игр, получили представление о структуре проекта и написали небольшое ТЗ к нашей игре. Давайте же приступим к ее написанию!

Весь код игры я поместил в репозиторий GitHub. Демо результата Вы можете посмотреть здесь.

Откройте папку с проектом при помощи bash или другого доступного терминала. В случае если у Вас Windows - запустите командную строку и перейдите в папку с проектом, который мы приготовили в первой статье

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

npm run start или yarn start если Вы используете yarn

Чем отличается сборка под developer(разработку) от сборки для production(релиз-версия)?

В dev-версии все скрипты не минифицированны и Вам будет удобно производить отладку, так же после сборки автоматически запускается отслеживание изменений в файлах. Если Вы измените файл скрипта, то проект будет автоматически собран заново и страница в браузере обновится. Это очень удобно во время разработки. Production-версия же минифицирована и не включает в себя скрипт отслеживания изменений файлов.

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

В базовом шаблоне размер canvas равен 700x400 px. Что бы изменить размер canvas измените параметры width и height в файле /src/const/config.ts.

Начнем мы пожалуй с основной сцены меню. По умолчанию приложение запускает сцену Welcome. Что бы ее отредактировать откройте файл /src/scenes/Welcome.ts.

Как мы видим, в файле находится класс, который наследуется от базового класса сцены Phaser.Scene. Соответственно класс наследует все свойства и методы объекта Phaser.Scene.

В Phaser 3 нам доступны следующие методы жизненного цикла сцены:

  • preload - предварительная загрузка ресурсов сцены(аудио, спрайты и тд.)
  • create - вызывается сразу после того как сцена была инициализирована
  • update - вызывается при каждом рендеринге сцены

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

Если ресурсы используются на множестве сцен, более логично будет загружать их при старте игры в сцене Boot по пути /src/scenes/Boot.ts. Где загружать ресурсы - решать только Вам, главное помнить что пользователь не должен ощущать "тормозов" из за загрузки ресурсов. Я считаю, что лучше заранее подгрузить ресурсы в Boot и заставить человека подождать один раз, чем заставлять его ожидать при смене сцен многократно. 

Графику, шрифты и аудио Вы можете взять из репозитория на GitHub и разместить в своем проекте.

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

Поместите и отредактируйте код в метод preload:

this.load.audio('<имя аудио-спрайта в игре>', ['<путь к файлу>']); - загрузка аудио. Вы можете передать больше разнообразных форматов аудио для корректной работы в различных браузерах. Необходимый минимум: ogg, mp3;

this.load.image('<имя изображения в игре>', '<путь к файлу>') - загрузка изображения. Поддерживаются все наиболее распространенные форматы изображений, кроме SVG, но над этим ведется работа и вскоре ситуация изменится;

this.load.bitmapFont('<имя>', '<спрайт png>', '<шрифт xml-fnt>') -  загрузка шрифта. Может показаться странным, что шрифты загружаются не из файлов .ttf или подобных, но это наиболее правильное решение для игровых шрифтов. png - спрайт хранит все буквы шрифта, а файл с расширением .fnt очень похож на .xml и служит описанием карты для изображения .png. Если Вам необходимо конвертировать .ttf шрифт в .fnt, вы можете воспользоваться сервисом littera.

Что бы узнать какие еще файлы Вы можете загружать при помощи this.load, следует обратиться к документации класса Phaser.Loader.LoaderPlugin.

Вот что у Вас должно получиться:

...
preload() {
    this.load.audio('bump', ['assets/audio/bump.mp3']);
    this.load.audio('bump-1', ['assets/audio/bump-1.mp3']);
    this.load.audio('cash', ['assets/audio/cash.mp3']);
    this.load.audio('select', ['assets/audio/select.mp3']);
    this.load.audio('auch', ['assets/audio/auch.mp3']);
    this.load.audio('lose', ['assets/audio/lose.mp3']);
    this.load.audio('win', ['assets/audio/win.mp3']);

    this.load.image('coin', 'assets/images/coin.png');
    this.load.image('sofa', 'assets/images/sofa.png')
    this.load.image('sofa_1', 'assets/images/sofa_1.png')
    this.load.image('sofa_2', 'assets/images/sofa_2.png')
    this.load.image('sofa_3', 'assets/images/sofa_3.png')
    this.load.image('sofa_4', 'assets/images/sofa_4.png')
    this.load.image('ball', 'assets/images/ball.png')
    this.load.image('arrow', 'assets/images/arrow.png')
    this.load.bitmapFont('joystix', 'assets/fonts/joystix.png', 'assets/fonts/joystix.fnt')
}
....

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

  
  preload() {
    let audios = [
      {name: "bump", link: "assets/audio/bump.mp3"},
      {name: "bump-1", link: "assets/audio/bump-1.mp3"},
      {name: "cash", link: "assets/audio/cash.mp3"},
      {name: "select", link: "assets/audio/select.mp3"},
      {name: "auch", link: "assets/audio/auch.mp3"},
      {name: "lose", link: "assets/audio/lose.mp3"},
      {name: "win", link: "assets/audio/win.mp3"}
    ]
    for(let audio of audios) this.load.audio(audio.name, audio.link);
    
    let images = [
      {name: 'coin', link: 'assets/images/coin.png'},
      {name: 'sofa', link: 'assets/images/sofa.png'},
      {name: 'sofa_1', link: 'assets/images/sofa_1.png'},
      {name: 'sofa_2', link: 'assets/images/sofa_2.png'},
      {name: 'sofa_3', link: 'assets/images/sofa_3.png'},
      {name: 'sofa_4', link: 'assets/images/sofa_4.png'},
      {name: 'arrow', link: 'assets/images/arrow.png'},
      {name: 'sofa_4', link: 'assets/images/sofa_4.png'}
    ]
    for(let image of images) this.load.image(image.name, image.link);
    
    this.load.bitmapFont('joystix', 'assets/fonts/joystix.png', 'assets/fonts/joystix.fnt')
  }

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

 

После того как все изображения были загружены, Вы можете отобразить их на сцене.  Очистите содержимое метода create у сцены Welcome.Вывод текста bitmap осуществляется при помощи метода dynamicBitmapText.

this.add.dynamicBitmapText(, , '<имя шрифта - string>', 'Название игры', );
this.add.dynamicBitmapText(0, 0, 'joystix', 'Название игры', 30);

В результате текст должен отобразиться в верхнем левом углу. Так произошло потому что начало координат в Phaser находится в верхнем левом углу. Вот наглядный пример расположения осей координат XY:

Давайте переместим надпись в центр холста. Для этого нам нужно сместить ее на половину всей высоты и половину всей ширины холста. Размеры холста хранятся в классе systems и он доступен нам в текущем контексте по ссылке this.sys.

Ширина холстаthis.sys.canvas.width

Высота холстаthis.sys.canvas.height

this.add.dynamicBitmapText(this.sys.canvas.width / 2, this.sys.canvas.height / 2, 'joystix', 'Название игры', 30);

Текст сместился, но не совсем туда куда мы планировали, это происходит потому что центр смещения объекта изначально находится в левом верхнем углу. Изменить его позицию можно при помощи метода setOrigin(float), который в качестве агрумента принимает два числа для каждой оси координат(XY) или одно число для установки сразу на обе оси. Число обычно указывают в диапазоне от 0 до 1. Соответственно если указать значение 0.5, то смещение будет производиться относительно центра объекта.

this.add.dynamicBitmapText(this.sys.canvas.width / 2, this.sys.canvas.height / 2, 'joystix', 'Название игры', 30).setOrigin(0.5);

Теперь когда Вы знаете как правильно позиционировать объекты на сцене, предлагаю Вам самостоятельно расположить на сцене кнопки меню: Игра, Магазин, Настройки. Размер текста сделать чуть меньше заголовка, приблизительно 20px. В результате у Вас должно получиться следующее:

this.add.dynamicBitmapText(this.sys.canvas.width / 2, this.sys.canvas.height / 2 - 100, 'joystix', 'Название игры', 30).setOrigin(0.5);

this.add.dynamicBitmapText(this.sys.canvas.width / 2, this.sys.canvas.height / 2, 'joystix', 'Игра', 20).setOrigin(0.5);
this.add.dynamicBitmapText(this.sys.canvas.width / 2, this.sys.canvas.height / 2 + 50, 'joystix', 'Магазин', 20).setOrigin(0.5);
this.add.dynamicBitmapText(this.sys.canvas.width / 2, this.sys.canvas.height / 2 + 100, 'joystix', 'Настройки', 20).setOrigin(0.5);

Давайте отобразим HUD - элементы в верхней части сцены. Так как эти элементы будут присутствовать на всех сценах, предлагаю вынести их в отдельный класс что бы не дублировать код. Воспользуемся классом Helper в папке /src/classes/Helper.ts.

Добавим туда два метода - один для отображения количества монет, а другой для отображения лучшего счета пользователя. Данные о счете и количестве монет мы будем хранить в LocalStorage. Метод должен получать значение из LocalStorage и выводить его на сцену. Методы следует сделать статическими, так как они никак не будут привязаны к контексту класса. В качестве аргумента мы будем принимать объект сцены типа Phaser.Scene, для того что бы иметь возможность с ней взаимодействовать (добавлять изображения и текст). Назовем эти методы drawCoins и drawBestScore:


const STORAGE_COINS = 'coins',
STORAGE_BEST_SCORE = 'best-score';

export default class Helper {

	static drawCoins(context: Phaser.Scene) : void {
		let coinsCount = window.localStorage.getItem(STORAGE_COINS);
		if(!coinsCount) coinsCount = "0";

		context.add.image(25, 25, 'coin').setDisplaySize(30,30);
		context.add.dynamicBitmapText(50, 11, 'joystix', coinsCount, 20);
	}

	static drawBestScore(context: Phaser.Scene) : void {
		let bestScore = window.localStorage.getItem(STORAGE_BEST_SCORE);
		if(!bestScore) bestScore = "0";

		context.add.dynamicBitmapText(context.sys.canvas.width - 25, 11, 'joystix', bestScore, 20).setOrigin(1, 0);
	}
}

Теперь эти методы можно использовать в сцене меню, для этого импортируйте класс Helper из папки ./scr/classes/ и вызовите методы в методе create, передав параметром объект this.

import Helper from "../classes/Helper"
....
Helper.drawCoins(this);
Helper.drawBestScore(this);

В результате Вы должны увидеть следующее:

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

По умолчанию все элементы сцены - статические и не реагируют на нажатия. Что бы это исправить необходимо вызвать метод setInteractive, поле чего можно добавлять слушателей на события нажатия на элемент. Давайте попробуем это сделать. Для этого добавим кнопке "игра" обработчик, который будет выводить alert "Игра начинается...". События нажатия на элемент называется pointerdown. С списком всех событий Phaser Вы можете ознакомиться на  этой странице.


let startButton = this.add.dynamicBitmapText(this.sys.canvas.width / 2, this.sys.canvas.height / 2, 'joystix', 'Игра', 20).setOrigin(0.5);
startButton.setInteractive(); // Разрешаем кнопке реагировать на нажатия и другие события
startButton.on(Phaser.Input.Events.POINTER_DOWN, (event) => {
  alert("Игра начинается...")
})

За работу с сценами отвечает класс SceneManager. Благодаря этому классу Вы можете запускать/сменять сцены, смещать и делать многое другое, но в настоящее время нас интересует механизм смены сцены. По нажатию на кнопку "игра", сцена должна меняться на основную сцену игры. Это можно реализовать при помощи метода start:

this.scene.start("<название сцены>")

Самое время создать три новые сцены пунктов меню. Назовем их: Game - игра, Shop - магазин, Settings - настройки.

Что бы добавить сцену, необходимо добавить файл в папку /src/scenes  с именем соответствующим названию сцены и расширением .ts. В этом файле необходимо создать класс, описывающий сцену, который унаследован от Phaser.Scene. Название класса , файла и сцены должны совпадать.

После того как Вы создали сцену, необходимо добавить ее в нашу игру. Для этого откройте файл /src/game.ts и добавьте сцену по аналогии с другими сценами игры.

Базовый шаблон сцены выглядит следующим образом:


DemoScene.ts


export class DemoScene extends Phaser.Scene {

  constructor() {
    super({
      key: "DemoScene",
    });
  }
  
  preload() {
    // Preload all files here
  }

  create() : void {
    // Main method
  }

  update() : void {
    // Callback of update every frame
  }

}

 

Подведем итоги

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

Задание

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

Скачать архив с примерами из этой статьи

 

Другие части статьи:

]]>
Thu, 07 Mar 2019 14:32:01 +0000 JavaScript Konstantin Ostrovsky
Создание HTML5-игр для самых маленьких(Phaser) Часть 3 https://web-panda.ru/post/phaser-3-released-3 В первой статье мы успешно развернули базовое окружение для написания игры на Phaser 3. В этой статье предлагаю Вам написать свою первую игру и выполнить несколько самостоятельных заданий для закрепления материала.

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

Анализ

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

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

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

 Сложность игры должна иметь три вариации:

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

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

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

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

Прямые конкуренты:

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

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

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

  • Главное меню;
  • Выбор уровня сложности;
  • Магазин;
  • Игра;

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

Heads-Up Display, аббр. HUD (англ. head-up — предназначенный для просмотра без наклона головы, display — индикация) — часть визуального интерфейса игрока, отображающаяся на фоне виртуального игрового пространства в видеоигре. Название происходит от аналогичного в английском языке обозначения ИЛС.

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

Немного забегая вперед, хочу познакомить Вас с таким понятием как ScrollFactor. Как можно заметить этот термин состоит из двух слов scroll (прокрутка) и factor(коэффициент). Другими словами это коэффициент прокрутки. В Phaser 3 у каждого объекта есть свойство ScrollFactor, которое Вы можете задать одноименной функцией. Если указать ему значение ноль - элемент не будет реагировать на прокрутку сцены или смещение камеры, таким образом он всегда будет находиться в одном положении. Это аналогично тому что Вы зададите position:fixed в css.

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

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

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

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

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

Метод update

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

Tweens

Много примеров реализации этой анимации Вы можете найти здесь. Этот класс реализует множество всевозможных способов анимации объектов и является встроенным функционалом Phaser 3 для анимации. Полагаю это отличный и наиболее правильный метод анимации объектов, но у него есть ограничения и порой Вам может не хватить его гибкости. Этот метод можно сравнить с методом animate в jQuery. При помощи параметров, переданных в функцию Вы можете создать свою анимацию и запускать ее в нужные моменты времени.

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

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

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

В случае если игрок A пропустил мяч - игроку B начисляется очко и наоборот. Когда количество очков достигает 10 - определяется победитель и игра завершается. 

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

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

Структура проекта

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

  1. assets
  2. src
  3. typescript
  4. index.html
  5. package.json
  6. tsconfig.json
  7. webpack.config.js

1)  assets. Эта папка должна содержать игровые ресурсы, такие как: спрайты, аудио, стили, тайлы и  прочее. Папка не участвует в компиляции проекта и проходит через webpack. Данные остаются в таком виде, в котором Вы их туда загрузили. Каждый тип ресурсов должен находиться в соответствующей под-директории:

  • Изображения - images;
  • Шрифты - fonts;
  • Звуки - audio;
  • Тайлы - tilemaps;
  • Стили - css;

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

  • classes - вспомогательные классы для работы с игровыми элементами и прочим. Здесь вы найдете класс Helper, который имеет один статический метод для сложения. Конечно, этот класс вряд ли Вам пригодиться, он служит лишь примером реализации классов в этой папке. Можете вынести в этот класс методы для отрисовки HUD что бы не дублировать код в каждой сцене;
  • const - константы приложения. В этой папке изначально находится один файл конфигурации для Phaser, который используется в game.ts. Вы можете использовать эти константы не только для определения параметров игры, но и к примеру для проведения расчетов и позиционирования игровых элементов;

  • objects - игровые объекты. Игровым объектом можно считать к примеру противника, мяч, игрока. Каждый из этих объектов имеет свою логику работы и логично будет вынести их в отдельный файл. Большинство разработчиков предпочитают наследовать игровые объекты от уже существующих объектов Phaser. К примеру мяч - это изображение, значит можно наследовать класс Phaser.GameObjects.Image и расширить его, добавив своей логики;
  • scenes - игровые сцены. После создания сцены ее необходимо добавить в соответствующую функцию в файле game.ts для того что бы игра знала про нее. Классы в этой директории наследуются от базового класса Phaser.Scene и расширяют его в случае необходимости.
  • game.ts - основной класс, инициализирующий Phaser.

3) typescript.  TypeScript - отличный язык, но для его правильной работы необходимы заголовочные файлы, которые объяснят интерпретатору какие классы и методы есть у объекта Phaser. В это папке Вы найдете один заголовочный файл для TypeScript. В случае необходимости сюда Вы можете помещать заголовочные файлы других библиотек.

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

5) package.json. NPM зависимости проекта.

6) tsconfig.json. Конфигурация для компилятора TypeScript

7) webpack.config.js.  Конфигурация для webpack

 

Другие части статьи:

]]>
Wed, 06 Mar 2019 12:42:25 +0000 JavaScript Konstantin Ostrovsky
Создание HTML5-игр для самых маленьких(Phaser) Часть 2 https://web-panda.ru/post/phaser-3-released-2 Продолжая цикл статей по созданию игр для новичков, хочу заметить что за прошедший период Phaser 3 получил сильное развитие. В нем появилось множество новых типов объектов и функций, благодаря которым программировать с Phaser 3 стало еще легче, быстрее и удобнее. Прощу прощения если в момент прочтения данной статьи, принятые мною решения проектирования игры будут не самыми актуальными. Ссылка на часть 1

В прошлом уроке мы познакомились с HTML 5, Canvas, Flash и Phaser 3, а так же узнали о таких языках программирования как ActionScript, JavaScript и TypeScript. Настало время провести параллели о между этими языками и аргументировать почему мой выбор пал именно на TypeScript.

Java/Action/Type - все это Script

JavaScript, вероятно, является самым популярным и гибким языком программирования сейчас и еще долго будет им оставаться. Благодаря быстрому росту веба, JavaScript стал популярен и получил всеобщее признание. Но так было не всегда. Что бы лучше почувствовать "ветер перемен", давайте вернемся в 90-е и оценим качество веб-контента, а так же постараемся понять что послужило столь мощным толчком к развитию языка. Полагаю, перемещаясь во времени, мы обязательно увидим так же зарождение и погибель ActionScript и появление TypeScript.

Веб в 90-е

Язык HTML (т.е. HyperText Markup Language) появился в 1991 году. Его создал учёный-физик Тим Бернерс-Ли, работавший в ту пору, в ЦЕРН (том самом, который создал Большой Адронный Коллайдер). Тим также является автором первого браузера, который носил название World Wide Web, и он же придумал концепцию Всемирной паутины.

World Wide Web. Первый в мире браузер!

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

По мере того, как HTML и CSS обрастали новыми возможностями, мужали и крепли, браузеры тоже эволюционировали. Самым распространенным в конце 90-х был браузер Internet Explorer (к 1999 году актуальной его версией была 5.01). Согласно статье в "Wikipedia" со ссылкой TheCounter.com, в 2000 году этим браузером пользовались более 79% пользователей.

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

Игровой ПК начала 90-х

22 апреля 1993 года был выпущен первый веб-браузер для ОС Windows с графическим интерфейсом пользователя — Mosaic, исходный код которого лёг в основу Netscape Navigator и Internet Explorer. Решили вспомнить, как это было и показать несколько скриншотов браузеров эпохи становления Интернета.

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

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

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

События, в результате которых появился JavaScript, разворачивались в течение шести месяцев, с мая по декабрь 1995 года. Компания Netscape Communications уверенно прокладывала себе путь в области веб-технологий. Её браузер Netscape Communicator успешно отвоевывал позиции у NCSA Mosaic, первого популярного веб-браузера. Netscape была создана людьми, принимавшими участие в разработке Mosaic в ранние 90-е. Теперь, с деньгами и независимостью, у них было всё необходимое для поиска способов дальнейшего развития веб-технологий. Именно это послужило толчком для рождения JavaScript.

Основатель Netscape Communications и бывший участник команды Mosaic Марк Андриссен считал, что веб должен стать более динамичным. Анимации, взаимодействие с пользователями и другие виды интерактивности должны стать неотъемлемой частью интернета будущего. Веб нуждался в лёгком скриптовом языке (или языке сценариев — прим.ред.), способном работать с DOM, который в те дни не был стандартизирован. Существовало одно «но», являвшееся на тот момент серьёзным вызовом: этот язык не должен был предназначаться для крупных разработчиков и прочих людей, имевших отношение к инженерной стороне вопроса. Java в те дни уже активно развивалась и твёрдо заняла эту нишу. Таким образом, новый скриптовый язык должен был предназначаться для совершенно иной аудитории — дизайнеров. Очевидно, что веб был статичным, а HTML был достаточно молод и прост в освоении даже для тех, кто не имел ничего общего с программированием. Следовательно, всё, что должно было стать частью браузера и сделать веб более динамичным, должно быть максимально понятным для далёких от программирования людей. Из этого предположения родилась идея Mocha, который должен был стать тем самым простым, динамичным и доступным скриптовым языком.

Прототип JavaScript был написан всего за десять дней в мае 1995 года Бренданом Эйхом. Первоначально он был завербован для внедрения среды выполнения Scheme для Netscape Navigator, но команда управления настояла на языке C-стиля, который будет дополнять недавно выпущенную Java.

JavaScript дебютировал в версии 2 Netscape Navigator в декабре 1995 года. В следующем году Microsoft провела реверс инжиниринг JavaScript для создания собственной версии, назвав его JScript. JScript поставляется с версией 3 браузера Internet Explorer и почти идентичен JavaScript — даже включая все те же ошибки и причуды — но у него были некоторые дополнительные возможности Internet Explorer.

Последующие версии JavaScript уже были основаны на стандарте ECMAScript. Проще говоря, ECMAScript — стандарт, а JavaScript — самая популярная реализация этого стандарта. Необходимость обеспечения того, чтобы JScript (и любые другие варианты) оставались совместимыми с JavaScript, мотивировала Netscape и Sun Microsystems к стандартизации языка. Они сделали это с помощью Европейской ассоциации производителей компьютеров, которая принимает стандарты. Стандартизованный язык назывался ECMAScript, чтобы не нарушать товарный знак Sun’s Java — шаг, вызвавший путаницу. В конечном итоге ECMAScript использовался для обозначения спецификации, и JavaScript был (и до сих пор) использован для обозначения самого языка.

 

Обратно в нулевые (2000)

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


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

Выход был один — одна из компаний создателей векторной графики объединится с гигантом анимации и станет доминирующей на рынке векторной анимации. Такими компаниями стали FutureSplash Animator и Macromedia. Джонатан Гай, основатель компании FutureSplash Animator пытался сначала договориться с одним из гигантов — Adobe. Но сделка с этой компанией не состоялась. По-настоящему продуктом Джонатана заинтересовались после того, как FutureSplash Animator был использован такими компаниями, как Microsoft и Disney Online. В ноябре 1996 г. Джонатан Гай и его коллеги присоединились к компании Macromedia, и FutureSplash Animator превратился Macromedia Flash 1.0. На сегодняшний момент компания Adobe все-таки объединилась с Macromedia Flash. 

Технология flash основана на использовании векторной графики в формате Shockwave Flash (.swf) разработанная компанией Macromedia®. Это далеко не первый векторный формат, но именно его создателям удалось найти наиболее удачное сочетание между изобразительными возможностями графики, инструментальными средствами для работы с ней, а также механизмом включения результата в web-страницы. Основным преимуществом flash-технологии является его межплатформенность, т.е. этот формат может использоваться на любой аппаратно-программной платформе (в частности, как на компьютерах Macintosh, работающих под управлением операционной системы MacOS, так и на компьютерах IBM с ОС Windows).


К концу XX в. возможности web-анимации достигли уровня обычных видеороликов, и ограничивались лишь скоростными возможностями Интернета, что, по сути, и сдерживает графическое развитие flash-технологий. Но в Macromedia Flash внедрены такие возможности, о которых не могут и мечтать создатели видеофильмов — это диалог, участие пользователя в анимации. Первоначально это были банальные кнопочки, от нажатия которых происходили те или иные графические изменения. Но очень быстро Macromedia Flash превратилось в среду разработки профессиональных приложений: сайтов, справочников, игр, интернет-казино. Появление встроенного языка программирования ActionScript, позволило разработчикам создавать ggi-программы, полнофункциональные http-приложения.

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

У каждой медали — две стороны. И в случае с flash есть свои «ложки дегтя» — проблемы, ограничивающие возможности его использования.

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

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

Решить эту проблему можно было 2-мя способами:

  • встроить flash в движок браузера;
  • изобрести новый более легковесный инструмент на базе JavaScript.

Критика и зависимость от Adobe подтолкнуло разработчиков создать нечто новое, бесплатное и более доступное для пользователя. Таким образом появился Canvas. 

В 2005 году изначально была предложена со стороны Apple для поддержки некоторых приложений внутри движка WebKit (на данный момент его используют браузеры Safari и Chrome). Рабочая группа W3C включила Canvas в Web Applications 1.0, который вошел в готовящийся стандарт HTML 5.0.

Сейчас встроенная поддержка Canvas реализована в том или ином виде во всех современных браузерах. В IE версии 8 и ниже она эмулируется при помощи отдельного VML-документа.

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

Хотелось бы сказать что на мой взгляд, ActionScript был лучшей реализацией чем JavaScript по нескольким причинам:

  • Возможность отладки кода в момент компиляции (не стоит забывать что AS - компилируется, а JS - интерпритируется);
  • Качественные, проработанные инструменты для разработчиков;
  • Строгая типизация;
  • Приватность (конечный файл sfw достаточно сложно раскодировать и получить исходники приложения).

Наше время (+/- 10 лет)

JavaScript - на пике популярности. Все, кто имеет отношение к вебу обязательно знают и работают с этим языком. Огромным толком к развитию языка послужило появление программной платформы NodeJS, которая позволяет работать на привычном многим языке так же на стороне сервера. Нет, он конечно же не вытеснил такие языки программирования как PHP, Ruby, GO, С# и прочие, но занял почетное место на нише популярных серверных языков.

И все бы хорошо, но...

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

Вдохновившись этим, MicroSoft в 2012 году представила TypeScript, позиционируемый как средство разработки веб-приложений, расширяющее возможности JavaScript.Разработчиком языка TypeScript является Андерс Хейлсберг (англ. Anders Hejlsberg), создавший ранее Turbo Pascal, Delphi и C#.

TypeScript является обратно совместимым с JavaScript и компилируется в последний. Фактически, после компиляции программу на TypeScript можно выполнять в любом современном браузере или использовать совместно с серверной платформой Node.js. Код экспериментального компилятора, транслирующего TypeScript в JavaScript, распространяется под лицензией Apache. Его разработка ведётся в публичном репозитории через сервис GitHub.

 

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

Другие части статьи:

]]>
Thu, 07 Feb 2019 07:54:23 +0000 Konstantin Ostrovsky
🍕Slices🍕 https://web-panda.ru/post/slices 🍕Slices🍕 — это интересная головоломка, от которой будут в восторге ✌ люди всех возрастов! Ваша цель: собрать пиццы из шести кусков что бы получить 🍖 бонусные очки и перейти на новый уровень!

Скачать на Android: GooglePlay

Приятной игры! ;-) Соревнуйтесь со своими близкими и друзьями, зарабатывайте больше очков!

Особенности игры

  • Интересный и простой геймплей
  • Бесконечное количество уровней
  • Отличная графика
  • Приятное звуковое сопровождение
  • НИКАКОГО ДОНАТА
  • НИКАКОЙ РЕКЛАМЫ

Благодарности

НаименованиеГде?Ссылка
flaticonГрафика и дизаинflaticon.com
freesoundЗвук и эффектыfreesound.org
laggedИдея и механикаlagged.com
   

  

]]>
Sat, 12 Jan 2019 14:00:50 +0000 Пример Konstantin Ostrovsky
WallPepper 🌶️ https://web-panda.ru/post/wallpepper

Любите красивые, красочные и заставки или Вам больше по-душе мрачные обои? Как бы там ни было, новый сервис Wall Pepper позволит каждому найти идеальную заставку для любимого девайса! В базе более 10 000 000 обоев на любой вкус!

ПЕРЕЙТИ на https://wallpepper.web-panda.ru

 

🌶️🔥🥇  Wall Pepper - потрясающий сервис для поиска обоев для различных устройств. ⚠ Использует API нескольких CDN с изображениями, соответственно имеет огромнейшую базу с изображениями! 👌

]]>
Sat, 12 Jan 2019 13:37:11 +0000 Пример Konstantin Ostrovsky
Стабильный, бесплатный самообновляемый IPTV-плейлист https://web-panda.ru/post/iptv-playlist-free

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

Я пробовал множество IPTV-плейлистов, но стабильность их работы оставляла желать лучшего. Именно поэтому я решил самостоятельно написать скрипт, который ежедневно генерировал бы стабильный IPTV-плейлист. В моем плейлисте более 500 каналов, собранных из различных источников. Ежедневно в 21:00 по МСК производится автоматическое обновление каналов. Отбираются лучшие каналы у которых самый лучший отклик. Соответственно все каналы в плейлисте максимально быстро загружаются и обеспечивают лучшее качество.

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

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

Ссылка на плейлист: https://iptv.web-panda.ru/pl.m3u

Ссылка на проект: https://iptv.web-panda.ru/

]]>
Thu, 20 Dec 2018 10:41:48 +0000 Пример Konstantin Ostrovsky
Распознавание образов встроенное в Chrome https://web-panda.ru/post/detect-face-chrome

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

Мало кто знает, но в chrome с 2018-09-07 добавлена возможность распознавания лиц. Пока это лишь экспериментальная технология и для ее активации необходимо включить "экспериментальные возможности".
Начиная с Chrome 70 (бета-версия от 13 сентября 2018 года), API обнаружения формы уже доступен для Origin Trial. Это означает что пользователям Chrome старше 70 версии могут прямо сейчас начать пользоваться распознаванием образов, не включая никаких флагов.

 

Зачем?

В настоящее время очень популярными являются VR и AR технологии. Благодаря распознаванию образов, к примеру, сделаны маски и трансформации лиц в медиа-социальных сетях, таких как vk.com и instagram.com. До самого веба эта технология постепенно добирается. Уже есть множество frameworks для создания VR и AR приложений. Такие как A-frameWebVRPrimroseReact VR и Argon.js. Но стабильная нативная поддержка распознавания лиц в браузере это все равно круто и безусловно за этим будущее. 

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

Включаем экспериментальные возможности Chrome

Для включения экспериментальных возможностей перейдите по ссылке:  chrome://flags/#enable-experimental-web-platform-features

Включите экспериментальные возможности:

И перезапустите браузер. Проверить работоспособность можно вызвав в консоли класс FaceDetector. Если включены экспериментальные возможности, то класс будет доступен и Вы увидите следующее:

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

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

Источник изображения

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

  1. HTMLImageElement () - в этом случае будет использоваться статическое изображение. Если в ссылке будет находиться gif, то будет использоваться первый кадр анимации;
  2. HTMLVideoElement () - в качестве источника Вы можете использовать видео. В этом случае будет взят текущий кадр и с ним произведены операции. Соответственно если Вы хотите сделать realtime распознавание лиц в видео, то необходимо неоднократно находить и выделять лица для различных кадров;
  3. HTMLCanvasElement () - содержимое canvas в текущий момент будет использоваться для вычислительных операций.

 

Обнаружение лиц

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

const faceDetector = new FaceDetector ({ 
    maxDetectedFaces: 10, 
    fastMode: true 
});

FaceDetector принимает два необязательных аргумента:

  • maxDetectedFaces - максимальное количество лиц для поиска в источнике изображения;
  • fastMode - говорит браузеру попытаться установить приоритет скорости над точностью.

Затем метод FaceDetector экземпляра detect() можно использовать для обнаружения человеческих лиц из данного источника изображения.

const imageSource = document.querySelector ('img'); 
// так же Вы можете использовать 

faceDetector.detect() возвращает Promise, в который принимается массив из объектов типа DetectedFace. Структура этого объекта следующая:

  • boundingBox - объект, описывающий прямоугольник, который указывает положение и границы на изображении, где было обнаружено лицо. Эти координаты можно использовать для графического отображения найденных координат, к примеру отрисовать их при помощи canvas.
  • landmarks - массив Landmark объектов. Ориентир - это интересная особенность распознавания. В этом массиве могут быть найденные элементы лица: нос, рот, глаза и т.д. Или не быть, если системе не удалось их распознать, в таком случае значение будет null.

Специально для Вас я подготовил пример работы класса FaceDetector:

Распознавание текста

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

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

const textDetector = new TextDetector();

Просто! Не так ли? У объекта класса TextDetector есть метод detect(), который позволяет определить текст по изображению. В качестве аргументов так же как и в FaceDetector можно передавать , и . Возвращает функция detect() - Promise, аргументом в resolve передается объект типа DetectedText, который имеет следующие ключи:

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

Пример работы класса TextDetector:

Распознавание QR-кодов

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

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

const textDetector = new TextDetector();

У объекта класса BarcodeDetector есть метод detect(), который позволяет определить текст по BarCode. В качестве аргументов так же как и в FaceDetector можно передавать , и . Возвращает функция detect() - Promise, аргументом в resolve передается объект типа DetectedBarcode, который имеет следующие ключи:

  • boundingBox - объект, описывающий прямоугольник, который указывает положение и границы на изображении, где был обнаружен штрих-код.
  • rawValue - строковое значение, которое было декодировано из штрих-кода.
  • cornerPoints - массив точек, соответствующих координатам каждого угла обнаруженного штрих-кода. Он начинается с верхнего левого угла и идет по часовой стрелке. Точки не обязательно представляют правильный прямоугольник или квадрат из-за искажений перспективы.

Пример работы класса BarcodeDetector:

Заключение

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

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

]]>
Wed, 19 Dec 2018 14:16:32 +0000 JavaScript Konstantin Ostrovsky
Принципы построения нейронных сетей. Пишем простую нейросеть на JavaScript https://web-panda.ru/post/brainjs-simple Рассмотрим базовые принципы работы нейронных сетей, узнаем про Brain.js и попробуем подкрепить теорию на практике. Напишем свою первую нейронную сеть, которая будет уметь чуть больше чем ничего, но чуть меньше чем что-то. Статья не претендует на пособие по разработке нейронных сетей, я постараюсь дать Вам базовые знания и представления о работе нейросетей, которыми обладаю сам>

Введем понятие ИНС - искусственная нейронная сеть. т.e. сеть построенная при помощи компьютерной системы;

НС - нейронная сеть мозга человека.

Что такое ИНС?

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

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

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

Нейронная сеть (биологическая нейронная сеть) — совокупность нейронов головного и спинного мозга центральной нервной системы (ЦНС) и ганглия периферической нервной системы (ПНС), которые связаны или функционально объединены в нервной системе, выполняют специфические физиологические функции.

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

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

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

Разноцветные круги слева - нейроны. Линиями изображены синапсы. Как видно, каждый синапс обладает весом. Этот вес проставляется случайным образом в диапазоне от 0 до 1. На изображении справа изображена работа сумматора. Сумматор - это функция, которая рассчитывает вес входных сигналов и передает их дальше в функцию активации, об этом чуть позже. Давайте попробуем рассчитать вес входных сигналов, если результаты работы нейронов были следующие:

  • 1 - 0.35
  • 2 - 0.12
  • 3 - 0.6

Важно понимать что ИНС оперирует данными в диапазоне от 0 до 1. Вычисление веса в сумматоре производится пос следующей формуле:

(L1 * W1) +  (L2 * W2) + (L3 * W3) = W

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

(0.35 * 0.1) + (0.12 * 0.3) + (0.6 * 0.2) = 0.191

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

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

Функций активации достаточно много поэтому мы рассмотрим самые основные: Линейная, Сигмоид (Логистическая) и Гиперболический тангенс. Главные их отличия — это диапазон значений.

Линейная функция


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

Сигмоид


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

Гиперболический тангенс

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


Подведем итоги. Что мы узнали про ИНС?

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

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

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

Виды ИНС

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

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

На этом схожесть заканчивается и начинаются различия...

Однослойные нейронные сети

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

Выглядит однослойная нейронная сеть следующим образом:

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

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

Однослойная нейронная сеть (Single-layer neural network) — сеть, в которой сигналы от входного слоя сразу подаются на выходной слой, который и преобразует сигнал и сразу же выдает ответ.

Многослойные нейронные сети

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

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

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

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

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

Сети прямого распространения

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

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

Сети прямого распространения (Feedforward neural network) (feedforward сети) — искусственные нейронные сети, в которых сигнал распространяется строго от входного слоя к выходному. В обратном направлении сигнал не распространяется.

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

Однако никто не запрещает сигналу идти и в обратную сторону.

Сети с обратными связями

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

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

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

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

Классификация ИНС

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

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

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

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

Предсказание/прогноз. Пусть заданы n дискретных отсчетов {y (t1), y (t2)..., y (tn)} в последовательные моменты времени t1, t2,..., tn. Задача состоит в предсказании значения y (tn+1) в некоторый будущий момент времени tn+1. Предсказание/прогноз имеют значительное влияние на принятие решений в бизнесе, науке и технике. Предсказание цен на фондовой бирже и прогноз погоды являются типичными приложениями техники предсказания/прогноза.

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

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

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

Отлично! Но как научить сеть делать то, что я от нее хочу? Может нужно помочь ей? Или она сама себя обучит? 

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

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

Что мы можем менять в нейронной сети?

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

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

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

Остается только один вариант – менять веса связей.

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

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

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

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

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

Обучающая выборка (Training set) — конечный набор входных сигналов (иногда вместе с правильными выходными сигналами), по которым происходит обучение сети.

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

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

Тестовая выборка (Testing set) — конечный набор входных сигналов (иногда вместе с правильными выходными сигналами), по которым происходит оценка качества работы сети.

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

Обучение с учителем

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

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

Затем, с помощью специальных алгоритмов, вы меняете веса связей нейронной сети и снова даете ей входной сигнал. Сравниваете ее ответ с правильным и повторяете этот процесс до тех пор, пока сеть не начнет отвечать с приемлемой точностью (как я говорил в 1 главе, однозначно точных ответов сеть давать не может).

Обучение без учителя

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

Что же происходит при таком обучении сети? Оказывается, что при таком «обучении» сеть начинает выделять классы подаваемых на вход сигналов. Короче говоря – сеть начинает кластеризацию.

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

Обучение без учителя (Unsupervised learning) — вид обучения сети, при котором сеть самостоятельно классифицирует входные сигналы. Правильные (эталонные) выходные сигналы не демонстрируются.

Выводы

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

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

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

Вы уже знаете необходимую теорию.  Давайте попробуем подкрепить наши знания на практике.


Практика

Наиболее распространенным решением является использование Python для построения ИНС. Существует огромное множество готовых решений и библиотек для построения ИНС. Но так как мы лучше знакомы с веб языками программирования, то мы будем использовать JavaScript. При работе с ИНС Вам вряд ли придется их самостоятельно писать, но понимать принцип работы ИНС необходимо понимать при работе с ними.
Мы будем использовать популярную JavaScript библиотеку brain.js

В библиотеке уже реализованы все необходимые инструменты для работы с ИНС и нам лишь необходимо передать необходимые параметры для создания нужного нам экземпляра brain.js. Первый релиз библиотеки состоялся 1 января 2018г. Правильнее будет сказать, что первый релиз после упадка библиотеки состоялся 1 января 2018г. Библиотека brain.js является работой энтузиастов, которые не стали равнодушны к закрытию проекта brain и создали собственный форк, который по сей день очень активно развивается. Начать работать с brain.js очень просто, для этого Вам необходимо пройти несколько шагов:

  • Установить NodeJS и NPM, либо использовать версию для браузера (ее можно подключить прямо в документ с CDN);
  • Если Вы решили использовать NodeJS, то Вам необходимо установить пакет brain.js, выполнив команду npm install brain.js и подключить ее в файл командой const brain = require('brain.js');
  • Создать экземпляр объекта ИНС, передав необходимые параметры конструктору: const net = new brain.NeuralNetwork({...});
  • Тренировать сеть при помощи команды train и набора тренировочных данных;
  • Использовать ИНС при помощи команды run;

Библиотека имеет отличный пример работы в котором на первом этапе Вам необходимо создать тренировочные данные для ИНС выбирая цвет текста на разноцветных плитках, который лучше видно. На втором этапе после обучения, ИНС сама будет определять какой цвет текста будет лучше видно на разноцветных плитках. Пример находится по этому адресу. Так же существует отличный интерактивный урок по работе с brain.js на scrimba. Еще больше примеров и уроков можно найти в WIKI на GitHub.

Вот некоторая техническая информация которая может понадобиться Вам при работе с brain.js. Я не нашел русского перевода, поэтому перевел самостоятельно, поправьте если я где-то допустил ошибку.

Использование brain.js в браузере требует вычислительных затрат, поэтому вы должны попытаться обучить сеть в автономном режиме (или на рабочем месте) и использовать опции toFunction()или toJSON(), чтобы подключить предварительно обученную сеть к своему веб-сайту.

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

Тренировка с NeuralNetwork

Каждый тренировочный шаблон должен иметь an inputи an output, оба из которых могут быть либо массивом чисел от 0 до 1 , либо хешем чисел от 0 до 1. Для демонстрации цветового контраста это выглядит примерно так:

const net = new brain.NeuralNetwork();

net.train([{input: { r: 0.03, g: 0.7, b: 0.5 }, output: { black: 1 }},
           {input: { r: 0.16, g: 0.09, b: 0.2 }, output: { white: 1 }},
           {input: { r: 0.5, g: 0.5, b: 1.0 }, output: { white: 1 }}]);

const output = net.run({ r: 1, g: 0.4, b: 0 });  // { white: 0.99, black: 0.002 }

Для обучения с RNNTimeStep, LSTMTimeStepиGRUTimeStep
Каждый шаблон тренировки может:

- Быть массивом чисел
- Быть массивом массивов чисел

Пример использования массива чисел:

const net = new brain.recurrent.LSTMTimeStep();

net.train([
  [1, 2, 3]
]);

const output = net.run([1, 2]);  // 3

Пример использования массива чисел:

const net = new brain.recurrent.LSTMTimeStep({
  inputSize: 2,
  hiddenLayers: [10],
  outputSize: 2
});

net.train([
  [1, 3],
  [2, 2],
  [3, 1],
]);

const output = net.run([[1, 3], [2, 2]]);  // [3, 1]

Для обучения с RNN, LSTMиGRU
Каждый шаблон тренировки может:

- Быть массивом значений
 - Будь строкой
- Есть input и output
Любой из которых может массив значений или строка

Пример использования прямых строк:

const net = new brain.recurrent.LSTM();

net.train([
  'doe, a deer, a female deer',
  'ray, a drop of golden sun',
  'me, a name I call myself',
]);

const output = net.run('doe');  // ', a deer, a female deer'

Пример использования строк с входами и выходами:

const net = new brain.recurrent.LSTM();

net.train([
  { input: 'I feel great about the world!', output: 'happy' },
  { input: 'The world is a terrible place!', output: 'sad' },
]);

const output = net.run('I feel great about the world!');  // 'happy'

Варианты обучения

train() принимает хэш опций в качестве второго аргумента:

net.train(data, {
                            // Defaults values --> expected validation
      iterations: 20000,    // максимальное количество итераций обучающих данных -> число больше 0 
      errorThresh: 0.005,   // допустимый процент ошибок из обучающих данных - > число от 0 до 1 
      log: false,           // true для использования console.log, когда функция предоставляется, она используется -> либо true, либо функция 
      logPeriod: 10,        // итерации между выходом из системы -> число больше 0 
      learningRate: 0.3,    // масштабирование дельтой для повышения скорости тренировки -> число от 0 до 1 
      momentum: 0.1,        // масштабирование с значением изменения следующего слоя -> число между 0 и 1 
      callback: null,       // периодический обратный вызов, который может быть запущен во время обучения -> null или функция 
      callbackPeriod: 10,   // количество итераций данных обучения между вызовами обратного вызова -> число больше 0 
      timeout: Infinity     // максимальное количество миллисекунд, для которых нужно тренироваться -> число больше 0 
});

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

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

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

JSON
Сериализация или загрузка в состоянии обученной сети с помощью JSON:

const json = net.toJSON();
net.fromJSON(json);

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

const run = net.toFunction();
const output = run({ r: 1, g: 0.4, b: 0 });
console.log(run.toString()); // copy and paste! no need to import brain.js

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

sigmoid
- relu
- leaky-relu (с этой опцией доступен параметр «leakyReluAlpha», по умолчанию 0,01)
- tanh


Вот таблица (спасибо, Википедия!), Обобщающая множество функций активации - Функция активации

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

hiddenLayers: [3, 4]
По умолчанию brain.js используется один скрытый слой с размером, пропорциональным размеру входного массива.

Типы нейронных сетей

Теперь когда мы знаем что представляют из себя ИНС и обладаем технической информацией по работе с brain.js можно приступить к написанию своей первой ИНС. Я буду использовать repl.it для публикации кода и NodeJS для вычислительных процессов что бы не нагружать Ваши браузеры. 

В качестве первого примера предлагаю написать нейронную сеть по расчету XOR. XOR - это операция, которая принимает значение «истина» только если всего один из аргументов имеет значение «истина».

Более подробно изучить работу XOR Вы можете в отличной статье fealsoft на habr.com.

Пример 1

В реальной жизни эта ИНС конечно же является абсолютно бесполезной, но отлично подходит для простого промера. В качестве тренировочных данных на вход мы будем передавать два аргумента, а на выход результат XOR. К примеру [input: [0,0];output: 0,input:[0,1];output:1, ....]. Таким образом наша ИНС найдет закономерность и будет самостоятельно выявлять XOR. Важно понимать фактически она не будет высчитывать XOR, она будет делать предсказания каким может быть XOR для введенных аргументов. Весь код имеет комментарии и не вижу необходимости более детально углубляться в подробности реализации, Вы можете попробовать поменять значения передаваемые в функцию run и проверить корректность работы ИНС. Пример ИНС для расчета XOR:

Разрабатывать бесполезную ИНС для выполнения элементарных вычислений безумно "увлекательное " занятие, не так ли? Вы наверняка хотели бы создавать нейросети, которые будут уметь отвечать пользователю, проявлять признаки интеллекта или хотя бы будут как-то полезны обществу. Не вопрос!

Пример 2

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

Предположим что в учебном заведении есть закрытая социальная сеть, в которой учащиеся ежедневно оставляют более 500 000 сообщений. Эта информация строго конфиденциальная, но Вы имеете к ней доступ, так как подписали договор о не разглашении. Отлично! Теперь у нас есть несколько миллионов сообщений вместо 30 000 учеников! 

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

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

Входными данными является сообщение пользователя.

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

Пример работы:

Сообщение "Завтра будет просто ужасный день!"

Результат "плохое"

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

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

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


В заключение хочу сказать что JavaScript безусловно не является языком наиболее подходящим для построения ИНС. Вы наверно уже заметили как медленно проходит процесс обучения. Это вызвано тем что NodeJS, как и JavaScript является однопоточным и не раскрывает все вычислительные возможности процессора. Разработчики brain.js обещают улучшить производительность с выходом 2-й версии. Хотя и сейчас есть возможность использовать мощность видеопроцессора при помощи WebGL, но работу через GPU в brain.js поддерживают только neural networks. Для дальнейшего изучения рекомендую посмотреть в сторону Python.

 

Источники:

  1. https://neuralnet.info/chapter/основы-инс/
  2. https://habr.com/company/epam_systems/blog/317050/
  3. https://habr.com/post/312450/
  4. https://habr.com/post/40137/
  5. https://habr.com/post/398645/
  6. https://tproger.ru/translations/javascript-brain-neural-framework/
  7. https://itnan.ru/post.php?c=1&p=304414
  8. https://habr.com/post/183462/
  9. https://medium.com/openmindonline/emotion-detection-with-javascript-neural-networks-5a408f84eb75
]]>
Tue, 18 Dec 2018 09:18:43 +0000 JavaScript Konstantin Ostrovsky
Lodash - функции будущего в JS уже сегодня https://web-panda.ru/post/lodash-first-steps

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

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

Его можно разбить на несколько основных направлений:

  • Utilities - для упрощения общих задач программирования, таких как определение типа, а также упрощение математических операций.;
  • Function - упрощение связывания, декорирование, сдерживание, дросселирование, debouncing, currying и изменение указателя;
  • String - функции преобразования для выполнения основных операций с строками, такие как обрезка, преобразование в верхний регистр, случай верблюда и т.д.;
  • Array - создание, разбиение, объединение, изменение и сжатие;
  • Collection - итерация, сортировка, фильтрация, расщепление и строительство;
  • Object - доступ, расширение, слияние, дефолты и преобразование;
  • Seq  - caching, упаковка, фильтрация и тестирование.

 

Библиотека доступна для установки с CDN без использования сборщиков, доступна на npm, есть поддержка TypeScript. Начать пользоваться Lodash очень просто, поэтому мы не будем уделять внимание установке. Если у Вас возникнут сложности - можете обратиться к документации, здесь подробно рассмотрены все варианты подключения библиотеки.

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

  • forEach - используется для перебора массива;
  • filter - используется для фильтрации массива через callback функцию;
  • map -  используется для трансформации массива;
  • every/some - методы используются для проверки массива;
  • reduce/reduceRight - используется для последовательной обработки каждого элемента массива с сохранением промежуточного результата.

Более подробную информацию по этим функциям Вы можете найти здесь.

Так же появились такие нововведения как:

Но несмотря на это польза библиотеки все равно не вызывает ни капли сомнения, JavaScript еще не скоро "впитает" или повторит все возможности Lodash.

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

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

1) Пользователь открывает страницу - подгружаются все товары магазина и кладутся в переменную;

2) При взаимодействии с фильтрами и сортировками - JavaScript выполняет манипуляции с данными и выводит их пользователю;

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


var products = [
    {
        id: 0,
        name: "Товар 1",
        price: 1200,
        color: "Красный",
        размер: "XL"
    },
    ....
]

Lodash хранится в переменной _. С технической стороны: переменная _   - это объект Lodash, который содержит в себе множество методов (свойств).  Из этого следует что к переменной Lodash можно обращаться как к обычному объекту, используя "_.", таким образом для вызова функции "filter" нам потребуется написать следующее "_.filter(...)". Это важно для понимания и правильного восприятия структуры библиотек, во избежание эффекта "абракадабры" для разработчика (я написал вот так, а оно там как-то само все сделало). 

Для реализации задумки необходимо вывести два фильтра и одну сортировку:

  1. по цвету;
  2. по размеру;
  3. сортировка по цене.

Дабы сильно не заморачиваться, я сделал простые