New Flame Steel Engine logo:

Soft & Games
Представляю вашему вниманию чистый декларативный язык программирования – Zakaz. Основная идея нового языка – приложение содержит команды на выполнение, написанные в произвольной форме, которые должны быть выполнены “исполнителями”. Если ни один “исполнитель” не может выполнить команду, то выполнение программы останавливается. Приложения называются техзаданиями (tez) и должны иметь расширение .tez. Синтаксис Zakaz обязывает соблюдать два правила:
Пример Hello World.tez:
Show "Hello World" text on screenShow "Zakaz 'tez' example" text on screen
Пример тз которое выводит описание принципа работы и открывающего сайт http://demensdeum.com в браузере Firefox
Show "Show website demo" text on screenShow "You need Firefox installed on your system to run this 'tez', and it should be callable through \"system\" C function" text on screenShow "Also there should be \"FirefoxPerformer\" assigned to Zakaz Runtime, please check manual for more information" text on screenShow website with address "http://demensdeum.com" in Firefox
Запускать пример выше необходимо вместе с “исполнителем” FirefoxPerformer, который способен обработать последнюю команду по выводу сайта через Firefox
./ZakazRuntime openDemensdeumSite.tez FirefoxPerformer
Для имплементации своего исполнителя необходимо реализовать его в виде динамической библиотеки, используя абстрактный класс ZakazRuntime::Performer, и вернуть его вместе с умным указателем из метода глобальной функции createPerformer(). В качестве примера можно использовать реализацию FirefoxPerformer.
https://gitlab.com/demensdeum/zakaz
В этой заметке я опишу пример добавления функционала в C++ приложение с помощью плагинов. Описана практическая часть реализации для Linux, с теорией можно будет ознакомиться по ссылкам в конце статьи.
Для начала напишем плагин – функцию которую будем вызывать:
#include "iostream" using namespace std; extern "C" void extensionEntryPoint() { cout << "Extension entry point called" << endl; };
Далее соберем плагин как динамическую библиотеку “extension.so”, которую и будем подключать в дальнейшем:
clang++ -shared -fPIC extension.cpp -o extension.so
Напишем основое приложение, которое будет загружать файл “extension.so”, искать там указатель на функцию “extensionEntryPoint”, и вызывать его, печатая ошибки при необходимости:
#include "iostream" #include "dlfcn.h" using namespace std; typedef void (*VoidFunctionPointer)(); int main (int argc, char *argv[]) { cout << "C++ Plugins Example" << endl; auto extensionHandle = dlopen("./extension.so", RTLD_LAZY); if (!extensionHandle) { string errorString = dlerror(); throw runtime_error(errorString); } auto functionPointer = VoidFunctionPointer(); functionPointer = (VoidFunctionPointer) dlsym(extensionHandle, "extensionEntryPoint"); auto dlsymError = dlerror(); if (dlsymError) { string errorString = dlerror(); throw runtime_error(errorString); } functionPointer(); exit(0); }
Функция dlopen возвращает хэндлер для работы с динамической библиотекой; функция dlsym возвращает указатель на необходимую функцию по строке; dlerror содержит указатель на строку с текстом ошибки, если таковая имеется.
Далее собираем основное приложение, копируем файл динамической библиотеки в папку с ним и запускаем. На выходе должен быть вывод “Extension entry point called”
К сложным моментам можно отнести отсутствие единого стандарта работы с динамическими библиотеками, из-за этого есть необходимость экспорта функции в относительно глобальную область видимости с extern C; разница в работе с разными операционными системами, связанные с этим тонкости работы; отсутствие C++ интерфейса для реализации ООП подхода к работе с динамическими библиотеками, однако существуют open-source врапперы, например m-renaud/libdlibxx
https://gitlab.com/demensdeum/cpppluginsexample
http://man7.org/linux/man-pages/man3/dlopen.3.htm
https://gist.github.com/tailriver/30bf0c943325330b7b6a
https://stackoverflow.com/questions/840501/how-do-function-pointers-in-c-work
[Feel the power of Artificial Intelligence]
В данной заметке я расскажу как предсказывать будущее.

В статистике существует класс задач – анализ временных рядов. Имея дату и значение некой переменной, можно прогнозировать значение этой переменной в будущем.
Поначалу я хотел реализовать решение данной задачи на TensorFlow, однако нашел библиотеку Prophet от Facebook.
Prophet позволяет делать прогноз на основе данных (csv), содержащих колонки даты (ds) и значения переменной (y). О том как с ней работать, можно узнать в документации на официальном сайте в разделе Quick Start
В качестве датасета я использовал выгрузку в csv с сайта https://www.investing.com, при реализации я использовал язык R и Prophet API для него. R мне очень понравился, так как его синтаксис упрощает работу с большими массивами данных, позволяет писать проще, допускать меньше ошибок, чем при работе с обычными языками (Python), так как пришлось бы работать с лямбда выражениями, а в R уже все лямбда выражения.
Для того чтобы не подготавливать данные к обработке, я использовал пакет anytime, который умеет переводить строки в дату, без предварительной обработки. Конвертация строк валюты в number осуществляется с помощью пакета readr.
В результате я получил прогноз по которому биткоин будет стоить 8400$ к концу 2019 года, а курс доллара будет 61 руб. Стоит ли верить данным прогнозам? Лично я считаю что не стоит, т.к. нельзя использовать математические методы, не понимая их сущности.
https://facebook.github.io/prophet
https://habr.com/company/ods/blog/323730/
https://www.r-project.org/
https://gitlab.com/demensdeum/MachineLearning/tree/master/4prophet
В этой заметке я опишу процесс создания генератора цитат.
Для обучения и генерации текста – использовать библиотеку textgenrnn, для фильтрации фраз нужно использовать проверку орфографии с помощью утилиты hunspell и ее библиотеки для C/python. После обучения в Colaboratory, можно приступать к генерации текста. Примерно 90% текста будет абсолютно не читаемым, однако оставшиеся 10% будут содержать толику смысла, а при ручной доработке фразы будут выглядеть вполне неплохо.
Проще всего запустить готовую нейросеть в Colaboratory:
https://colab.research.google.com/drive/1-wbZMmxvsm3SoclJv11villo9VbUesbc(opens in a new tab)”>https://colab.research.google.com/drive/1-wbZMmxvsm3SoclJv11villo9VbUesbc
https://gitlab.com/demensdeum/MachineLearning/tree/master/3quotesGenerator
https://karpathy.github.io/2015/05/21/rnn-effectiveness/https://medium.com/deep-learning-turkey/google-colab-free-gpu-tutorial-e113627b9f5dhttps://minimaxir.com/2018/05/text-neural-networks/
https://github.com/wooorm/dictionaries (opens in a new tab)” href=”https://minimaxir.com/2018/05/text-neural-networks/” target=”_blank”>https://minimaxir.com/2018/05/text-neural-networks/
https://karpathy.github.io/2015/05/21/rnn-effectiveness/
https://medium.com/deep-learning-turkey/google-colab-free-gpu-tutorial-e113627b9f5d
https://karpathy.github.io/2015/05/21/rnn-effectiveness/ (opens in a new tab)” href=”https://karpathy.github.io/2015/05/21/rnn-effectiveness/” target=”_blank”>https://karpathy.github.io/2015/05/21/rnn-effectiveness/
https://medium.com/deep-learning-turkey/google-colab-free-gpu-tutorial-e113627b9f5d
https://karpathy.github.io/2015/05/21/rnn-effectiveness/https://medium.com/deep-learning-turkey/google-colab-free-gpu-tutorial-e113627b9f5dhttps://github.com/wooorm/dictionaries
” rel=”noopener” target=”_blank”>https://github.com/wooorm/dictionaries (opens in a new tab)”>https://github.com/wooorm/dictionaries
На Hacker News нашел очень интересную статью в которой автор предлагает использовать метод Петерсена-Линкольна, который используется биологами для подсчета популяции птичек, обезьянок и прочих животных, для *барабанная дробь* подсчета багов в приложении.

Баг в естественной среде обитания – Bigfoot Sighting by Derek Hatfield
Метод очень прост, берем двух орнитологов, они находят птичек какого-то определенного вида, их задача – определить размер популяции этих птичек. Найденные птички помечаются обоими орнитологами, далее подсчитывается количество общих, подставляется в формулу индекса Линкольна и мы получаем примерный размер популяции.
Теперь для приложений – метод также очень прост, берем двух QA и они находят баги в приложении. Допустим один тестировщик нашел 10 багов (E1), а второй 20 багов (E2), теперь берем число общих багов – 3 (S), далее по формуле получаем индекс Линкольна:

Это и есть прогноз числа багов во всем приложении, в приведенном примере ~66 багов.
Я реализовал тестовый стенд для проверки метода, посмотреть можно здесь:
https://paiza.io/projects/AY_9T3oaN9a-xICAx_H4qw?language=swift
Параметры которые можно менять:
let aliceErrorFindProbability = 20 – процент нахождения багов у QA Alice (20%)
let bobErrorFindProbability = 60 – процент нахождения багов у QA Bob (60%)
let actualBugsCount = 200 – сколько багов в приложении на самом деле
В последнем запуске я получил следующие данные:
Estimation bugs count: 213
Actual bugs count: 200
Тоесть в приложении есть 200 багов, индекс Линкольна дает прогноз – 213:
“Alice found 36 bugs”
“Bob found 89 bugs”
“Common bugs count: 15”
—
Estimation bugs count: 213
Actual bugs count: 200
Использовать данный метод можно для оценки количества ошибок в приложении, на всех этапах разработки, в идеале количество багов должно уменьшаться. К слабым сторонам метода я могу отнести человеческий фактор, так как количество найденных багов от двух тестировщиков должно быть разным и найдены разные баги, однако должны быть найдены и общие, иначе метод работать не будет (ноль общих багов – деление на ноль)
Также такое понятие как общие баги требует обязательное наличие эксперта для понимания их общности.
How many errors are left to find? – John D. Cook, PhD, President
The thrill of the chase – Brian Hayes
https://paiza.io/projects/AY_9T3oaN9a-xICAx_H4qw?language=swift
https://gitlab.com/demensdeum/statistics/tree/master/1_BugsCountEstimation/src
Ах муза, как сложно тебя поймать порой.
Разработка Death-Mask, и связанных фреймворков (Flame Steel Core, Game Toolkit и др.) приостанавливается на несколько месяцев, для того чтобы определиться с художественной частью игры, музыкальным, звуковым сопровождением, продумыванием геймплея.
В планах – создать редактор для Flame Steel Game Toolkit, написать интерпретатор игровых скриптов (на основе синтаксиса Rise), реализовать игру Death-Mask для максимально большого количества платформ.
Сложнейший этап пройден – на практике доказана возможность написания своего собственного кроссплатформенного игрового движка, своего IDE, набора библиотек.
Перехожу к этапу создания действительно продуманного, интересного проекта, следите за новостями.
Новостной краулер iOS – приложение ищет текст и выводит результат во время загрузки.
Заложена поддержка больших файлов из коробки (> 200мб), результаты сохраняются в result.log файл.
Простой, продуманный дизайн.
Поддержка регулярок с помощью библиотеки Regex.

Исходный код:
https://gitlab.com/demensdeum/news-crawler
Notes Keep – OS X веб клиент для Google Keep.

Релиз:
NotesKeep 1.0
Исходный код:
https://gitlab.com/demensdeum/notes-keep
Исходный код игры Demon’s Cave iOS перенесен на Swift 4, выгружен в GitLab:
https://gitlab.com/demensdeum/demons-cave-ios
Минимальная версия для запуска – iOS 8
С сегодняшнего дня игра Death-Mask уходит в открытый доступ – можете следить за прогрессом реализации игры по ссылке: (Вау!)
[Death-Mask Wild]
На данный момент версия – 0.1 содержит базовое управление на стрелках, wsad, генерация карт, предметов (в том числе и маску смерти!), рендеринг.
Предстоит еще куча работы, и мне очень интересен ваш фидбэк – поэтому можете писать комментарии на странице с wild версией игры.
В финальной версии игра заканчивается после того как игрок найдет предмет – Маску Смерти (Death-Mask)
Приятного теста : )
—
Авторы ресурсов

Hangar18 – утилита для индексации исходного кода C++, написанная на Rust. Данная утилита будет реализовывать функционал “перейти к определению” в Saber-Plus IDE.
На вход утилите подается абсолютный путь к директории исходного кода, строка декларации которую необходимо найти. На выходе grep-подобный вывод.
Исходный код:
https://gitlab.com/demensdeum/hangar18

Представляю вашему вниманию Taytay – утилиту для контроля статуса репозиторев git для языка Swift. На текущий момент Свифт можно установить на всех мейнстримовых десктопных операционных системах. Для Ubuntu я рекомендую использовать Swiftenv. Завязан Тайтай на утилиту git-cola, но можешь отредактировать исходник и поменять на любую другую программу.
Исходный код:
https://gitlab.com/demensdeum/taytay
К любому разработчику на OpenGL периодически приходит Малевич. Происходит это неожиданно и дерзко, ты просто запускаешь проект и видишь черный квадрат вместо чудесного рендера:

Сегодня я опишу по какой причине меня посетил черный квадрат, найденные проблемы из-за которых OpenGL ничего не рисует на экране, а иногда и вообще делает окно прозрачным.
Для отладки OpenGL мне помогли два инструмента: renderdoc и apitrace. Renderdoc – инструмент для отладки процесса рендеринга OpenGL, просматривать можно все – вертексы, шейдеры, текстуры, отладочные сообщения от драйвера. Apitrace – инструмент для трейсинга вызовов графического API, делает дамп вызовов и показывает аргументы. Также есть великолепная возможность сравнивать два дампа через wdiff (или без него, но не так удобно)
У меня есть операционная система Ubuntu 16.10 со старыми зависимостями SDL2, GLM, assimp, GLEW. В последней версии Ubuntu 18.04 я получаю сборку игры Death-Mask которая ничего не показывает на экране (только черный квадрат). При использовании chroot и сборке в 16.10 я получаю рабочую сборку игры с графикой.

Похоже что-то сломалось в Ubuntu 18.04
LDD показал линковку к идентичным библиотекам SDL2, GL. Прогоняя нерабочий билд в renderdoc, я увидел мусор на входе в вертексный шейдер, но мне нужно было более солидное подтверждение. Для того чтобы разобраться в разнице между бинариками я прогнал их оба через apitrace. Сравнение дампов показало мне что сборка на свежей убунте ломает передачу матриц перспективы в OpenGL, фактически отправляя туда мусор:

Матрицы собираются в библиотеке GLM. После копирования GLM из 16.04 – я снова получил рабочий билд игры. Проблема оказалась в разнице инициализации единичной матрицы в GLM 9.9.0, в ней необходивно явно указывать аргумент mat4(1.0f) в конструкторе. Поменяв инициализацию и отписав автору библиотеки, я принялся делать тесты для FSGL. в процессе написания которых я обнаружил недоработки в FSGL, их опишу далее.
Для корректной работы с OpenGL нужно в добровольно принудительном порядке запросить контекст определенной версии. Так это выглядит для SDL2 (проставлять версию нужно строго до инициализации контекста):
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 2); SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE );
Например Renderdoc не работает с контекстами ниже 3.2. Хочется отметить что после переключения контекста высока вероятность увидеть тот самый черный экран. Почему?
Потому что контекст OpenGL 3.2 обязательно требует наличие VAO буфера, без которого не работают 99% графических драйверов. Добавить его легко:
glGenVertexArrays(1, &vao); glBindVertexArray(vao);
Также я встретился с интересной проблемой на Kubuntu, вместо черного квадрата у меня выводился прозрачный, а иногда все рендерилось корректно. Решение этой проблемы я нашел на Stack Overflow:
https://stackoverflow.com/questions/38411515/sdl2-opengl-window-appears-semi-transparent-sometimes
В коде тестового рендера FSGL тоже присутствовал sleep(2s); Так вот на Xubuntu и Ubuntu я получал корректный рендер и отправлял приложение спать, однако на Kubuntu я получил прозрачный экран в 80% случаев запуска из Dolphin и 30% запусков и терминала. Для решения данной проблемы я добавил рендеринг в каждом кадре, после опроса SDLEvent, как это рекомендуется делать в документации.
Код теста:
https://gitlab.com/demensdeum/FSGLtests/blob/master/renderModelTest/
OpenGL поддерживает канал связи между приложением и драйвером, для его активации нужно включить флаги GL_DEBUG_OUTPUT, GL_DEBUG_OUTPUT_SYNCHRONOUS, проставить оповещение glDebugMessageControl и привязать каллбек через glDebugMessageCallback.
Пример инициализации можно взять здесь:
https://github.com/rock-core/gui-vizkit3d/blob/master/src/EnableGLDebugOperation.cpp

Saber-Plus – быстрый и простой редактор для C++.
Релиз пакета deb для Ubuntu and Debian:
saberplus1.0_amd64.zip
В данной заметке я расскажу о своих злоключениях с умными указателями shared_ptr. После реализации генерации следующего уровня в своей игре Death-Mask, я заметил утечку памяти. Каждый новый уровень давал прирост + 1 мегабайт к потребляемой оперативной памяти. Очевидно что какие-то объекты оставались в памяти и не освобождали ее. Для исправления данного факта необходимо было реализовать корректную реализацию ресурсов при перегрузке уровня, чего видимо сделано не было. Так как я использовал умные указатели, то вариантов решения данной задачи было несколько, первый заключался в ручном отсмотре кода (долго и скучно), второй же предполагал исследование возможностей дебагера lldb, исходного кода libstdc++ на предмет возможности автоматического отслеживания изменений счетчика.
В интернете все советы сводились к тому чтобы вручную отсматривать код, исправить и бить себя плетями после нахождения проблемной строчки кода. Также предлагалось реализовать свою собственную систему работы с памятью, как это делают все крупные проекты разрабатываемые еще с 90-х и нулевых, до прихода умных указателей в стандарт C++11. Мною была предпринята попытка использовать брейкпоинты на конструкторе копии всех shared_ptr, после нескольких дней ничего дельного не получилось. Была идея добавить логирование в библиотеку libstdc++, однако трудозатраты (о)казались чудовищными.

Cowboy Bebop (1998)
Решение пришло мне в голову внезапно в виде отслеживания изменений приватной переменной shared_ptr – use_count. Сделать это можно с помощью встроенных в lldb ватчпоинтов (watchpoint) После создания shared_ptr через make_shared, изменения счетчика в lldb можно отслеживать с помощью строки:
watch set var camera._M_refcount._M_pi->_M_use_count
Где “camera” это shared_ptr объект состояние счетчика которого необходимо отследить. Конечно внутренности shared_ptr будут различаться в зависимости от версии libstdc++, но общий принцип понять можно. После установки ватчпоинта запускаем приложения и читаем стектрейс каждого изменения счетчика, потом отсматриваем код (sic!) находим проблему и исправляем. В моем случае объекты не освобождались из таблиц-кешэй и таблиц игровой логики. Надеюсь данный метод поможет вам разобраться с утечками при работе с shared_ptr, и полюбить этот инструмент работы с памятью еще больше. Удачного дебага.
Третий выпуск непостоянной рубрики об играх Games Vision.

Observer (ПК и консоли, Bloober Team) – киберпанк-хоррор от доблестных поляков. Короткий и очень атмосферный ужастик с Рутгером Хауэром в главной роли. Мне, как фанату киберпанка, в игре понравилось абсолютно все. Не очень сложные загадки, очаровательные глюки главного героя, геймплей со спокойными моментами в перемешку с экшеном, возможность в буквальном смысле копаться в воспоминаниях мертвых, сюжет в стиле Призрака в Доспехах + множество отсылок к Sci-Fi попкультуре. Из минусов – перебор с гличами, иногда кажется что из-за их обилия невозможно играть, также некоторых игроков выводили из себя специфические хоррор элементы, пугающие настолько что они не могли продолжать играть.
Оценка: 8/10

Paradigm (Windows/OS X, Jacob Janerka) – квест который умудряется пародировать и смеяться над всем и сразу. Здесь есть высмеивание СССР, Америки, жанра квестов, глэм-рока, старых приставок, людей, памятников, айтишников, конусов, компьютеров, женщин, детей, родителей, художников, любви, ученых, игровой индустрии, самых игроков – вообщем всего не перечислить. Абсолютно непредсказуемый сюжет, абсурдная атмосфера и арт, не особо сложные загадки. В игре есть редкие баги и вылеты, некоторые моменты и шутки слегка предсказуемы и не оригинальны.
Оценка: 9/10

Late Shift (ПК и консоли, CtrlMovie Ltd) – интерактивный фильм. Мне действительно жаль что в принципе хорошая задумка получила столь плохую реализацию. Плохо все – сюжет, отсутствие звездных актеров, актерская игра, постоянные зависания в версии для ПК, практически нулевая вариативность (иллюзорная). Совершенно непонятно как можно было выпустить игру с таким количеством проблем в 2010-х, ведь по сути это обычный видеоплеер, всю игру можно было разместить в интернете например на youtube, но вместо этого использовали Unity и умудрились сломать даже столь мощный игровой движок. Официальный форум в Steam посвящен фиксам, хотфиксам, воркараундам и т.д. Налицо техническая катастрофа, отсутствие службы поддержки пользователей, все тестирование происходит прямо на игроках. Купленные восторженные обзоры и отзывы.
Оценка: 3/10
Обновлен Saber-Plus C++ IDE, добавлен вывод содержимого умных указателей (shared_ptr)
Демо можно посмотреть ниже:
Исходный код Saber-Plus:
https://gitlab.com/demensdeum/saberplus/
Представляю вашему вниманию мой собственный язык программирования под названием – Rise. На данный момент доступен транспайлер из Rise в JavaScript.
Его можно увидеть и попользоваться по ссылке ниже – Rise в JavaScript (диалект ECMAScript 5):
https://gitlab.com/demensdeum/Rise
Также представляю вашему вниманию демо приложение полностью написанное на Rise:
Исходный код Rise Demo Application:
https://gitlab.com/demensdeum/RiseDemoApplication
Можете написать мне если у вас есть идеи, предложения, комментарии по новому языку.
Было тяжело дышать, на дисплее шлема выводился запас кислорода ровно на полчаса. За это время Ревил планировал добраться до городского центра и заполучить Маску Смерти. Вокруг стоял едкий зеленый туман, воздуха здесь небыло, по улицам бродили полуживые люди, существа захваченные влиянием Маски.
Звук шагов распространялся по пустым комнатам заброшенного здания, Ревил двигался осторожно, не зная чего ожидать в самом опасном месте Технолаба.

Город давно был захвачен коррупцией, однако не земной, которая порабощает умы политиков и властолюбивых. Коррупция Маски Смерти захватывает умы живых существ, они теряют контроль над собой и начинают жить ради выполнения ее желаний. Все попавшие под влияние, начинали верить что получат вечную жизнь в результате своего служения. Для поддержания контроля, Маске требуется постоянный приток новых рабов, захват новых территорий с чистыми существами.
На северо-западе Ревил увидел синее свечение о котором говорила ему Алиса, в центре его находится огромное здание, созданное строителями Технолаба. Странное, гротескное нагромождение торчащих каркасов и механических частей будто созданное безумцем, наводило ужас своим видом.
Ревил спустился из окна здания на улицу, для того чтобы продолжить путь, как вдруг он услышал громкий удар металлических конечностей об асфальт. Обернувшись он увидел перед собой Демона – биомеханическое существо с тремя человеческими головами, похожее на паука, медленно двигалось к нему. В небе появился круг странного зеркально-черного цвета, с трудом можно было оторвать взгляд. Раздался оглушительный рев городской сирены, призывающий существ-рабов на помощь Демону. Дело было чертовски плохо, однако на этот случай у Ревила был заготовлен сюрприз…
Начал разработку собственного IDE для С++ – Saber-Plus. Основные идеи нового IDE – быть простым, быстрым и *помогающим* в разработке. На данный момент исходный код доступен по лицензии MIT на GitHub, для работы с UI используется Qt. В дальнейшем планирую перенести всю разработку связанную с C++ на Saber-Plus – точно будет проведена миграция игры Death-Mask. Подробнее по пунктам:

Для сборки редактора для вашей операционной системы, нужно установить Qt 5 SDK, загрузить код IDE из репозитория, открыть файл Saber-Plus.pro в Qt Creator и запустить сборку:
https://github.com/demensdeum/saberplus
Представляю вашему вниманию простейший пример работы с фреймворком для работы с Deep Learning – TensorFlow. В этом примере мы научим нейросеть определять положительние, отрицательные числа и ноль. Установку TensorFlow и CUDA я поручаю вам, эта задачка действительно не из легких)
Для решения задач классификации используются классификаторы. TensorFlow имеет несколько готовых высокоуровневых классификаторов, которые требуют минимальной конфигурации для работы. Сначала мы потренируем DNNClassifier с помощью датасета с положительными, отрицательными числами и нулем – с корректными “лейблами”. На человеческом уровне датасет представляет из себя набор чисел с результатом классификации (лейблами):
10 – положительное
-22 – отрицательное
0 – ноль
42 – положительное
… другие числа с классификацией
Далее запускается обучение, после окончания которого можно подавать на вход числа которые даже не входили в датасет – нейросеть должна корректно их определять.
Ниже приведен полный код классификатора с генератором датасета для обучения и входных данных:
import tensorflowimport itertoolsimport randomfrom time import timeclass ClassifiedNumber:__number = 0__classifiedAs = 3def __init__(self, number):self.__number = numberif number == 0:self.__classifiedAs = 0 # zeroelif number > 0:self.__classifiedAs = 1 # positiveelif number < 0:self.__classifiedAs = 2 # negativedef number(self):return self.__numberdef classifiedAs(self):return self.__classifiedAsdef classifiedAsString(classifiedAs):if classifiedAs == 0:return "Zero"elif classifiedAs == 1:return "Positive"elif classifiedAs == 2:return "Negative"def trainDatasetFunction():trainNumbers = []trainNumberLabels = []for i in range(-1000, 1001):number = ClassifiedNumber(i)trainNumbers.append(number.number())trainNumberLabels.append(number.classifiedAs())return ( {"number" : trainNumbers } , trainNumberLabels )def inputDatasetFunction():global randomSeedrandom.seed(randomSeed) # to get same resultnumbers = []for i in range(0, 4):numbers.append(random.randint(-9999999, 9999999))return {"number" : numbers }def main():print("TensorFlow Positive-Negative-Zero numbers classifier test by demensdeum 2017 (demensdeum@gmail.com)")maximalClassesCount = len(set(trainDatasetFunction()[1])) + 1numberFeature = tensorflow.feature_column.numeric_column("number")classifier = tensorflow.estimator.DNNClassifier(feature_columns = [numberFeature], hidden_units = [10, 20, 10], n_classes = maximalClassesCount)generator = classifier.train(input_fn = trainDatasetFunction, steps = 1000).predict(input_fn = inputDatasetFunction)inputDataset = inputDatasetFunction()results = list(itertools.islice(generator, len(inputDatasetFunction()["number"])))i = 0for result in results:print("number: %d classified as %s" % (inputDataset["number"][i], classifiedAsString(result["class_ids"][0])))i += 1randomSeed = time()main()
Все начинается в методе main(), мы задаем числовую колонку с которой будет работать классификатор – tensorflow.feature_column.numeric_column(“number”) далее задаются параметры классификатора. Описывать текущие аргументы инициализации бесполезно, так как API меняется каждый день, и обязательно нужно смотреть документацию именно установленной версии TensorFlow, не полагаться на устаревшие мануалы.
Далее запускается обучение с указанием на функцию которая возвращает датасет из чисел от -1000 до 1000 (trainDatasetFunction), с правильной классификацией этих чисел по признаку положительного, отрицательного либо нуля. Следом подаем на вход числа которых не было в обучающем датасете – случайные от -9999999 до 9999999 (inputDatasetFunction) для их классификации.
В финале запускаем итерации по количеству входных данных (itertools.islice) печатаем результат, запускаем и удивляемся:
number: 4063470 classified as Positivenumber: 6006715 classified as Positivenumber: -5367127 classified as Negativenumber: -7834276 classified as Negative
Честно говоря я до сих пор немного удивлен что классификатор *понимает* даже те числа которым я его не обучал. Надеюсь в дальнейшем я разберусь более подробно с темой машинного обучения и будут еще туториалы.
GitLab:
https://gitlab.com/demensdeum/MachineLearning
Ссылки:
https://developers.googleblog.com/2017/09/introducing-tensorflow-datasets.html
https://www.tensorflow.org/versions/master/api_docs/python/tf/estimator/DNNClassifier
Данная заметка не является призывом к действию, здесь я опишу слабые и потенциально опасные стороны биткоина и технологии блокчейн.
Принцип работы биткоина и блокчейна заключается в хранении, изменении общей базы данных, полная копия которой хранится у каждого участника сети. Система выглядит децентрализованной, т.к. нет единой организации/сервера на котором хранится база данных. Также децентрализованность выдается за главный плюс блокчейна, дает гарантию что ничего не случится с вашими биткоинами без вашего ведома.
Принцип блок-чума от Елкина
Для того чтобы блокчейн работал, нужно сделать так чтобы каждый пользователь скачивал последнюю копию базы данных блокчейна, и работал с ней по определенным правилам. К таким правилам относится реализация принципа майнинга биткоина, получение процента от каждой транзакции при подтверждении (transaction fee) передачи средств с одного кошелька на другой. Пользователь не может нарисовать себе 1000000 биткоинов и купить на них что-то, т.к. у других пользователей количество денег на его счету будет неизменным. Также исключен вариант со снятием средств с чужого кошелька только внутри своей базы данных т.к. это изменение не будет отражено у других пользователей биткоина, и будет проигнорировано.
Уязвимость текущей реализации заключается в том что биткоин кошелек находится на сервере github что полностью перекрывает рекламные лозунги о децентрализации. Без загрузки кошелька из единого центра – сайта разработчика, невозможно работать с биткоином, тоесть в любой момент разработчики имеют полный контроль над сетью. Таким образом, сама технология блокчейн является децентрализованной, но клиент для работы с сетью загружается из единого центра.
Сценарий атаки – допустим в кошелек добавлен код для снятия всех средств и обналичивания на счет третьих лиц, после этого любой пользователь последней версии кошелька потеряет все биткоины автоматически (без возможности восстановления). Сомневаюсь что многие владельцы кошелька проверяют и собирают его из исходного кода, поэтому последствия такой атаки затронут большинство пользователей.
Блокчейн является децентрализованной p2p сетью, подтверждением всех операций занимаются сами пользователи в автоматическом режиме. Сценарий атаки – необходимо получить 51% сети для того чтобы игнорировать подтверждения оставшихся 49%, после этого атакующий получает полный контроль над биткоином/блокчейном. Этого можно добиться подключив вычислительные мощности перекрывающие остальных. Этот сценарий атаки известен как 51% attack.
При первом запуске кошелька, компьютер генерирует пару – приватный и публичный ключ для обеспечения своей корректной работы. Уникальность данных ключей крайне высока, однако есть вариант сгенерировать ключи с помощью кодового слова – так называемый “brain wallet“. Человек хранит ключи у себя в голове, ему не нужно делать бекап файла wallet.dat, т.к. в любой момент ключи можно будет перегенерить с помощью данного кодового слова. Сценарий атаки – злоумышленник подбирает или узнает кодовое слово, генерирует пару приватный-публичный ключ и получает контроль над кошельком.
Пара приватный-публичный ключ содержится в файле wallet.dat. Любое программное обеспечение имеющее доступ к данному файлу – имеет доступ к кошельку биткоин. Защитой от такого нападения служит добавление кодового слова, которое должен будет помнить и вводить пользователь, для всех операций с кошельком. После добавления кодового слова, злоумышленнику нужно будет иметь wallet.dat и кодовое слово для получения полного контроля.
Также стоит добавить что при вводе кодового слова оно попадает в память компьютера, таким образом любые уязвимости аппаратные и/или программые позволяющие читать *чужую* память позволят прочитать и это кодовое слово вирусному программному обеспечению.
Взлом алгоритмов шифрования биткоина моментально приведет к его смерти. Допустим в реализации алгоритмов допущена ошибка, злоумышленник нашедший ее получает либо полный, либо частичный контроль над блокчейном. Также алгоритмы шифрования используемые в биткоине не защищены от взлома с помощью будущих квантовых компьютеров, их появление и реализация квантовых алгоритмов – поставит крест на текущей реализации биткоина. Однако это может быть решено с помощью перехода на постквантовые алгоритмы шифрования.
Видео:
Версия для Windows:
http://demensdeum.com/games/deathMask/prototype/DeathMaskPrototype.exe
Пользователи Linux и OS X могут собрать игру из исходников:
https://github.com/demensdeum/Death-Mask
Дальше я буду добавлять геймплейные элементы, освещение, анимацию.
Я собрал свою альтернативу MSYS, данный набор включает в себя утилиты coretools + git + cmake + make + добавляет msvs msbuild в переменную окружения PATH. Данный набор приложений необходим тем разработчикам, которые привыкли к разработке на платформе Linux, и им необходимо собирать приложение под Windows из командной строки с использованием Microsoft Visual Studio. Скачать:
https://www.mediafire.com/file/s5yf75blfslkbym/nixenv.exe
https://www.4shared.com/file/QyjJXBaJca/nixenv.html
Установите, измените пути в файле nixenv.bat и запускайте его.

Черновик концепт документа игры Death Mask на английском:
https://docs.google.com/document/d/1KWkbs89-okkNOgbuIYcFdZRPVJtpukPLUWSS3UHiqJI/edit?usp=sharing