Установка и настройка терминального сервера на Windows Server + Оптимизация настроек для 1С ч.2

Предисловие

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

Конфигурирование хранения персональных данных пользователей

Для активации дисков профилей пользователя необходимо перейти в Службы удаленных рабочих столов > в разделе Свойства открываем меню Задачи > изменить свойства > Диски профилей пользователя

Ставим флаг напротив «Включить диски профилей пользователей»

Указываем путь до каталога на файловом сервере, где будут храниться VXDX диски профилей, и указываем размер 1 гб (Больше места нам не нужно, так как в диске будет храниться совсем мало данных но и меньше 1 гб сделать нельзя) и нажимаем применить

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

Устраняем проблему с хромом

При использовании дисков профилей в Google Chrome возникает ошибка Error COULD NOT GET TEMP DIRECTORY, это связанно с тем что хром не может получить доступ к общей папке TEMP, потому переместим ее в другое место и дадим на нее права

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

Для каждого пользователя, который входит в систему, создает личную папку в папке C: TEMP Изменить переменные среды TEMP и TMP Есть две настройки, которые можно применить на уровне пользователя.

1 — Создание личной папки в папке TEMP:

2 — Модификация переменных окружения:

Далее нам необходимо настроить миграцию профилей

Открываем «Управление групповой политикой «

Создаем объект Групповой политики и связываем его с Подразделением в котором расположены пользователи терминального сервера

Далее переходим Конфигурация пользователя > политики > Конфигурация Windows > Перенаправление папки

По каждому из представленных каталогов ПКМ > Свойства

В окне выбираем пункты

  • Перенаправлять папки для всех пользователей в одно расположение.

  • Создать папку для каждого пользователя на корневом пути

  • Указываем корневой путь (!Важно: данный путь должен быть доступен пользователям на запись)

На вкладке параметры снимаем все галочки и выбираем «После удаления политики оставить папку в новом расположении»

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

Настройка политики ограниченного использования программ

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

Спрячем логические диски от пользователей

Конфигурация пользователя > политики > Административные шаблоны > Компоненты windows > Проводник > выбираем политику Скрыть выбранные диски из окна мой компьютер > ставим включено и выбираем Ограничить доступ ко всем дискам

Убираем все лишнее с рабочих столов пользователей

Для этого создадим следующие групповые политики

  • Ограничение функционала проводника

  • Очищаем меню пуск

Ограничение функционала проводника

Идем Конфигурация пользователя > Политики > Административные шаблоны > Компоненты Windows > Проводник и включаем следующие политики

  • Запрашивать подтверждение при удалении файлов

  • Отключить возможности библиотеки Windows, использующие данные индексированных файлов

  • Запретить изменение видеоэффектов для меню

  • Скрыть значок «Вся сеть» в папке «Сеть»

  • Удалить меню «Файл» из проводника Удалить вкладку «Оборудование»

  • Скрыть команду «Управление» из контекстного меню проводника

  • Удалить «Общие документы» из окна «Мой компьютер»

  • Удалить команды «Подключить сетевой диск» и «Отключить сетевой диск»

  • Удалить ссылку «Повторить поиск» при поиске в Интернете

  • Удалить вкладку «Безопасность» Удалить кнопку «Поиск» из проводника

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

Очищаем меню пуск

Идем Конфигурация пользователя > Политики > Административные шаблоны > Меню «Пуск» и панель задач

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

Запрет запуска программ

Для решения данной задачи есть 2 способа

1 способ

При помощи политики «Выполнять только указанные приложения Windows» Указать список всех exe приложений которые будут доступны»

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

У данного метода есть несколько недостатков

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

  • назовем их «Энтузиасты » , которые пытаются запускать приложения переименовав их исполнительный файл в один из разрешенных

  • Проблема с обновлением приложений (Зачем же разработчикам ПО оставлять старые названия своих exe, и правда Зачем? )

  • Отсутствие какого либо журнала заблокированных политикой приложений

Настраивается следующим образом

Создаем объект Групповой политики и связываем его с Подразделением в котором расположены пользователи терминального сервера

Идем Конфигурация пользователя > Административные шаблоны > Система > Находим политику «Выполнять только указанные приложения Windows»

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

Далее нам Желательно на рабочем столе разместить ярлыки запуска приложения

Идем Конфигурация пользователя > Настройка > Конфигурация Windows > Ярлыки > Создать > Ярлык

После чего задаем параметры. !ВАЖНО на вкладке «Общие параметры поставить «Выполнять в контексте….»

Ура политика создана

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

после чего ВАЖНО не забыть на вкладке Делегирование добавить группе «Прошедшие проверку» право на чтение политики (Иначе работать не будет)

2 й способ

Используем функцию AppLocker

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

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

идем Конфигурация компьютера > Конфигурация Windows > Параметры безопасности > Политики управления приложениями >applocker > Исполняемые правила > Создать правила по умолчанию

после чего идем Конфигурация компьютера > Конфигурация Windows > Параметры безопасности > Политики управления приложениями >applocker и тыкаем «Настроить применение правил»

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

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

Журналы приложений и служб > Microsoft > Windows > AppLocker > EXE и DLL будут появляется события содержащие сведения о запускаемых приложениях, которые мы будем использовать для дальнейшей настройки политики

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

ПКМ > Новое правило

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

Выберем условие Путь

Скопируем путь из отчета о событии

в исключения мы добавлять ничего не будем так что далее > Создать

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

После чего в свойствах applocker следует переключить «Только аудит» на «Принудительное применение правил»

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

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

ссылка на оригинал статьи https://habr.com/ru/post/535826/

ИИ итоги уходящего 2020-го года в мире машинного обучения

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

Если тебе интересно машинное обучение, то приглашаю в «Мишин Лернинг» — мой субъективный телеграм-канал об искусстве глубокого обучения, нейронных сетях и новостях из мира искусственного интеллекта.

GPT-3

Ресерчеры из OpenAI представили GPT-3 — сеть Generative Pre-trained Transformer 3, одну из лучших языковых моделей на сегодняшний день. Архитектура GPT-3 подобна GPT-2, параметров стало 175 миллиардов, и модель учили на 570 гигабайтах текста.

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

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

NVIDIA MAXINE 

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

MuZero

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

Иллюстрация поиска по дереву Монте-Карло, используя MuZero
Иллюстрация поиска по дереву Монте-Карло, используя MuZero

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

Алгоритм уже умеет играть в привычные нам для этой сферы игры: го, шахматы и кучу игр для приставки Atari.

AlphaFold

И опять DeepMind с их нейросетевым алгоритмом впредсказания трехмерной структуры белка по последовательности аминокислот — AlphaFold 2. Точность такого алгоритма составляет 92,4 балла из 100, что является рекордом на сегодняшний день! 

При считывании информации с матричной РНК (трансляция) молекула белка формируется как цепочка аминокислот. Потом, в зависимости от физических и химических свойств, цепочка начинает сворачиваться. Таким образом формируется третичная структура белка. Именно от этой структуры и зависят свойства конкретного белка.

Задача определения первичной аминокислотной структуры белка (самой последовательности) является элементарной. Это легко читается напрямую из ДНК. Кодон — тройка нуклеотидных остатков (триплет) образуют 64 варианта, а именно 4 (аденин, гуанин, цитозин, тимин) в третей степени. Из них 61 комбинация кодирует определённые аминокислоты в будущем белке, а 3 оставшихся кодона сигнализируют об остановке трансляции и называются стоп-кодонами. При этом 61 комбинация кодирует всего 20 различный аминокислот белка. Знакомые с теорий информации и избыточностью уже улыбаются, ну, а биологи называют кодоны, кодирующие одинаковые аминокислоты, изоакцепторными кодонами.

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

Процесс предсказания третичной структуры белка
Процесс предсказания третичной структуры белка

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

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

Новая специализация TensorFlow: Advanced Techniques от deeplearning ai, основанной самим Andrew Ng

YouTube-Лекция: Нейронные сети: как их создают и где применяют? Два часа о “самом главном”

Поздравляю всех с Новым годом! Больше ресерча в наступающем году!

ссылка на оригинал статьи https://habr.com/ru/post/535832/

Как сделать ёлку, если ты математик

Поздравляю Хабр и Хаброжителей с Новым 2021 годом и дарю всем нам вот такую незатейливую и приятную Функциональную Ёлку (fЁлка). В этой статье я рассказываю как сделать ёлочку на мониторе за 10 минут. Свою вторую статью я посвящу тому, как «слепить» снеговика, положить подарки под ёлку и всё это припорошить сверху снегом.

Базовая идея

Весь рисунок — это набор математических функций от двух аргументов, x и y. Все они так или иначе базируются на SDF. Для рисования графиков использовался desmos.com.

Базовые функции

Ограничение нуля

x+\left|x\right|

Эллипс

\frac{\left(x-2\right)^{2}}{3}+\frac{\left(y-3\right)^{2}}{1}=1

Ёлка

Опишем основу ёлки

-\left(y-13\right)-2\left|x\right|=0

Добавим ветви

-0.2\cos\left(6.8y\right)\left(y-13\right)-2\left|x\right|=0

Пригнём кончики ветвей к земле

-0.2\cos\left(6.8y+0.7\left|x\right|\right)\left(y-13\right)-2\left|x\right|=0

Ограничим ель сверху

-0.2\cos\left(6.8y+0.7\left|x\right|\right)\left(y-13\right)-2\left|x\right|-0.51\left(y+\left|y\right|\right)=0

Ель съехала вниз, это исправится позднее

Параллельный ход: ограничение снизу

Ограничитель

2x=5\left(y-\left|y-2\right|\right)

Итог данного этапа

-0.2\cos\left(6.8y+0.7\left|x\right|\right)-2\left|x\right|+5\left(y-\left|y-2\right|\right)=0

Комбинируем

-0.2\cos\left(6.8y+0.7\left|x\right|\right)\left(y-13\right)-2\left|x\right|-0.51\left(y+\left|y\right|\right)+5\left(y-\left|y-2\right|\right)=0

Финальный штрих

2-0.2\cos\left(6.8y+0.7\left|x\right|\right)\left(y-13\right)-2\left|x\right|-0.51\left(y+\left|y\right|\right)+5\left(y-\left|y-2\right|\right)=0

Займёмся стволом

Эллипс с более острыми углами

\ 0.1x^{10}+30\left(y-1\right)^{10}-1=0

Объединение объектов

Объединение, пересечение и вырезание базируются на простейшей операции min(a, b). В зависимости от знаков перед a и b получаются различные булевы операции.

Листва — a(xy), ствол — b(xy)

-a\le0, b\le0

Финал

\min\left(-a,b\right)\le0

Все формулы для вставки в desmos.com

a=2-0.2\cos\left(6.8y+0.7\left|x\right|\right)\left(y-13\right)-2\left|x\right|-0.51\left(y+\left|y\right|\right)+5\left(y-\left|y-2\right|\right)

b\ =\ 0.1x^{10}+30\left(y-1\right)^{10}-1

\min\left(-a,\ b\right)\le0

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

ссылка на оригинал статьи https://habr.com/ru/post/535834/

Как мы устроили допрос на детекторе лжи с помощью Котлина, книг по режиссуре и OBS: изнанка спецпроекта

image

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

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

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

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

Идея игры: режиссура, подбор актрис и вопросов

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

Это был крайне ненадежный сценарий, и я объясню почему.

Есть известный принцип 1%: в каждом интернет-коммьюнити есть 90% потребителей контента, 9% контрибьюторов и всего 1% тех, кто сам создает контент. Это не научное знание, но я в него верю: в моей практике оно часто подтверждалось.

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

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

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

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

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

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

Дальше надо было каким-то образом срежиссировать истории, которые девушки будут рассказывать. За 60 минут каждая девушка должна была стать «родной» зрителю, как персонажи сериалов, которым симпатизируешь.

Как срежиссировать историю, сюжет которой не знаешь

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

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

Так как же структурировать историю, которой ты не знаешь?

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

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

image

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

  • Дать немного узнать человека: к какому базовому характеру он принадлежит
  • Рассказать о нем что-то хорошее, что вызовет симпатию, Воглер называет это «дать, за что полюбить»
  • Поставить героя в непреодолимую ситуацию, которая вызывает у него стресс. Тут зритель начинает сочувствовать, если все сделано правильно
  • Дать ему решить ситуацию, изменив себя к лучшему, и закончить историю

Так мы и поступили. Написали порядка 200 вопросов, сразу вычистили скучные и оставили 100 «горячих». Затем разделили их на категории и сделали предположение, какой, скорее всего, будет на него история: например, если спросить про самый стыдный эпизод жизни – это один эмоциональный окрас и уровень напряжения. Если спросить про страхи — другой. Если про первую любовь — третий.

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

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

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

Техническая часть проекта: Kotlin, война за синхронизацию и реверс-инжиниринг полиграфа

Из каких частей состоял проект

Всего в игре было 5 частей:

  • Интерфейс игрока — основной сайт игры, где велась трансляция и можно было сыграть
  • Интерфейс полиграфолога — веб-страничка, на которой полиграфолог отмечал свой вердикт. Именно с ним и соотносились ответы игроков
  • Интерфейс девопса — специальный образ в маркетплейсе c Ubuntu. Подключившись к нему по SSH можно было задать вопрос девушке
  • Интерфейс модератора — страничка, где модератор пропускали или отклонял вопросы от зрителей. Вопрос можно было отредактировать (например, поправить грамматику и орфографию
  • Сервер, принимающий вопросы от девопсов и передающий их в интерфейс полиграфолога

Трансляция велась отдельно через Open Broadcaster Software (OBS) и YouTube.

Как все это было связано

Вся наша система состояла из сервера и кучи клиентов. Одна группа была многочисленной — много клиентов девопсов, один клиент — веб страничка модератора, веб-страничка полиграфолога и много веб-страничек игроков.

Был еще один отдельный клиент системы — программа написанная на Котлине и работающая на компьютере полиграфолога. Всей игрой управлял именно он, обычный стационарный компьютер на Windows. ОС была принципиальной — программа Sheriff 7, в которой работал наш полиграфолог Миша есть только под Windows.

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

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

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

Брокером в нашей системе выступил Mosquitto. Возможно многим читателям знакомы более популярные в энтерпрайз сфере другие MQ-протоколы — AMQP, RabbitMQ, ActiveMQ.

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

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

Синхронизация событий в игре: как мы сразились со временем и выиграли

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

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

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

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

  • В интерфейсе полиграфолога это системное время ПК через Date.now()
  • В клиенте, читающем графики — System.currentTimeMillis()
  • В интерфейсе игроков — YoutubeIFrameAPI.getDuration(), которое согласно своей документации, возвращает длительность в секундах воспроизводимого видео. Если видео, как в нашем случае, является прямой трансляций, то функция вернет время прошедшее с момента начала стрима

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

Как она работает:

Видеозапись от стартового пистолета до фотофиниша, на которой Усейн Болт ставит мировой рекорд на 100 м длится точно 9.58 секунд. Ожидается, что и функция getDuration() для прямой трансляции будет возвращать приемлемо точное время с начала трансляции. Она монотонна, непрерывна и даже линейна. Последнее математически не требуется, но без учета всяких СТО Эйнштейна является и свойством обычного времени тоже.

Как мы использовали эту функцию у игрока?

На страничке игрока есть iframe c плеером YouTube внутри — там отвечает на вопросы девушка. У плеера есть API, один из методов которого — упомянутый ранее getDuration(). Полученное событие нужно воспроизвести через

event.relativeTime - iframeAPI.getDuration()

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

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

Тут очень приятно (нет) было пользоваться типом boolean. В игре есть ответ девушки — true/false, есть ответ игрока true/false, есть ответ полиграфолога true/false и угадал игрок ответ или нет — true/false. Не так уж сложно писать условия, но вот устно объяснять этот момент было непросто.

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

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

Расшифровка и отрисовывание графиков

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

Как Федор вынул графики из полиграфа

image

Полиграф КРИС, с точки зрения компьютера — абстрактное COM-USB устройство. Что в этом было хорошего, так это то, что для работы он подключается компьютеру.

А вот то, что работать с ним умеет только допотопная программа Шериф 7, документация к которой только пользовательская и официально поставляется она вместе с бинарником в вот таком виде:

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

Федор думал о двух вариантах:

  • Перехватить коммуникацию через COM-порт и посмотреть, что же там передаётся
  • Попробовать декомпилировать Шериф, который сделан на ископаемых, но простых технологиях и использовать его код для получения чисел.

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

И оба решения нам не подошли, потому что:

  • нет безлимитного доступа к устройству на время разработки — полиграфологи не расстаются со своими устройствами, прямо как парикмахеры никому не дают в руки свои ножницы
  • у Федора не было навыков работы с ним
  • сложно оценить время, которое потребуется на реверс-инжиниринг. Через COM можно передавать данные в каком угодно виде (сам прибор вообще явно аналоговый), насколько легко будет идти реверс-инжениринг самого Шерифа тоже неясно

Тем более, работает Шериф на Windows, а Федор привык к Linux или, на крайний случай, MacOS.

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

Федор находился в Питере (а вся остальная команда проекта в Москве, включая полиграфолога Мишу), так что он нашел полиграфолога на Авито, прихватил с собой жертву, посадил ее на ровный такой же полиграф и записал скринкаст допроса. В сыром виде без сжатия и цветовых манипуляций, последовательность bmp-файлов получилось только в 30 fps. Если кому интересно, 2.5 минуты 1920х156 заняли 1Гб, который очень приятно сжимался до 30 Мб с помощью 7z.

Алгоритм расшифровки графиков

Он достаточно примитивен:

Делаем скриншот, проходим getPixel-ем один столбец в правом краю полотна и получаем 6 чисел — 6 точек на графике. Проходим другой столбец — по меткам в правом краю полотна и получаем вторые 6 чисел — центры шкал каждой из 6 величин.

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

Федор выбрал Kotlin/JVM и занимался разработкой распознавателя графиков под линуксом. Метод java.aw.Robot.createScreenshot показал впечатляющую производительность: больше 1000 fps на частичных скриншотах (ему не весь экран был нужен, а только краешек), пришлось еще отсеять повторяющиеся скрины.

В качестве отладочного вывода Федор рисовал в файлик 1920х1080 участок кривых соответствующей длины так, как они прочитались. Получилось так

Учитывая, что Федор работал со скринкастом в 30 fps, на живом Шерифе точно должно получиться хорошо, но… Не получилось.

График во фронтенде оказался нечитаемо ломаным, даже хуже чем в отладочной картинке.

Выяснилось, что Windows заботливо ограничивает частоту работы native методов позади Robot.createScreenshot 30-ю снимками в секунду. Стало ясно, почему скринкаст не получилось сделать больше 30…

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

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

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

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

Как мы передавали данные для графиков игроку

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

События с величинами складывались в чанки по несколько штук в mqtt-сообщение — столько, сколько снялось за секунду, около 50 штук. Они складывались в очередь на отрисовку в соответствующие TimeChart-ы. Библиотека отрисовки сама двигает плоскость графика и ставит точки на нужном расстоянии друг от друга по оси времени (гарантий строгой периодичности, к сожалению, не было).

Как и чем отрисовывали графики

Одна из технических сложностей — рисовать 6 графиков величин от реального времени (едущих слева-направо), в масштабе ~20 секунд и с высокой плотностью точек.

Удобный и красивый ApexCharts.js и близко не подошел по производительности — fps порядка единиц и огромная загрузка ЦП. Альтернативы тоже не радовали: по запросу “high performance realtime charts” ничего интересного не находилось.

Спас чат Саматика @ctodaily, куда Федор написал и посоветовался насчет библиотек. Так стало понятно, что почти все либы рисуют графики svg, стало быть, нам надо было искать “webGL charts”.

Из быстро нашедшихся webgl-plot, lightningcharts и TimeChart, Федор выбрал последний. С производительностью же у всех было хорошо, в результате получилось обновлять графики с частотой около 50 fps, как раз с такой частотой полиграф и отдавал значения.

Войны за синхронизацию

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

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

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

Перед отображением у игрока первый кадр видео проходит долгий путь:

  • кодирование,
  • доставка ютьюбу
  • и обработка ютьюбом записи у себя

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

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

  • Менял величину коррекции, и она сразу передавалась всем игрокам.
  • Нажимал кнопку проверки — тогда страница синхронизации посылала специальное указание “пыхнуть” (то есть, менял фон на черный и обратно за 100мс) интерфейсу полиграфолога.
  • Тот, получив сигнал, пыхал и сразу же отправлял обратно странице синхронизации просьбу пыхнуть в ответ, но на этот раз в виде события, что принципиально.

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

Как мы проводили первоначальную синхронизацию перед игрой:

  • Ставили монитор полиграфолога в кадр
  • Слали ему сигнал пыхнуть
  • Засекали примерное время между пыхами
  • Устанавливали его в качестве коррекции
  • Продолжали пыхать и подправлять коррекцию до тех пор, пока пыхи в трансляции и в интерфейсе игрока-синхронизатора не станут одновременными

Принципиально важный момент: нужно было мерить не лаг трансляции с youtube между отправкой команды и пыхом, а время между пыхом полиграфолога и ответным пыхом на него в относительно времени. То есть мы измеряли величину отставания относительного getDuration-времени от относительного времени, которое нам хотелось бы иметь — с нулем точно в начале трансляции, а не на 2-8 секунд раньше.

Таким образом, один цикл ручной синхронизации занимал 1-12 секунд лага youtube для игрока, плюс 2-8 секунд лага между OBS и сервером youtube.

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

Но через 20 минут на съемочной площадке просело подключение к Интернету — до 1.5 МБ/с, пинга 100 и какого-то сумасшедшего трёхзначного джиттера и тогда синхронизация сбилась.

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

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

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

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

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

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

Чтобы протестировать синхронизатор, мы сделали стресс-тест: запустили трансляцию через 3G, раздаваемый c телефона на компьютер с OBS.

За 6 часов непрерывной трансляции удалось поймать два скачка времени, которые хорошо обработались. Через какое-то время вылез еще один рассинхрон и из логов стало ясно, что время не просто нелинейно, оно НЕ МОНОТОННО.

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

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

Happy end

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

До новых спецпроектов в Новом Году! И спасибо, что дочитали лонгрид.

ссылка на оригинал статьи https://habr.com/ru/company/ruvds/blog/535398/

Hackboard 2: одноплатник для разработчиков с x86-процессором за $99

У большинства одноплатных компьютеров самых разных производителей, включая Raspberry Pi, есть одна общая черта. Это ARM-процессор. Но далеко не всем разработчикам и любителям DIY-электроники такие платы подходят.

На днях в продажу поступил одноплатный ПК Hackboard 2, который решает эту проблему. Его создатели оснастили устройство x86-процессором. Чипы ARM позволяют уменьшать платы, делать их недорогими и экономными в плане энергопотребления. Но x86 увеличивает степень совместимости одноплатника с другими системами. Что собой представляет Hackboard 2?

Этот одноплатник разработан в качестве недорогой альтернативы подобным ПК на основе чипов Intel, например, ODYSSEY — X86J4105800, который стоит $218.

Стоимость же Hackboard 2 составляет $99. Размеры платы — 120*80 мм, ее основа — 64-х битный Intel Celeron N4020. Частота работы — 2,8 ГГц, кэш — 4 МБ. Кроме того, плата оснащена 4 ГБ ОЗУ DDR4, eMMC объемом в 64 ГБ и двумя слотами NVMe M.2, которые дают возможность установить SSD объемом до 4 ТБ.

Что касается аудио и видео, то плата оснащена Intel UHD Graphics 600 с выводом 4K HDMI 2.1 output. Плюс есть стандартный аудиоразъем для наушников. Беспроводные модули тоже есть: плата оснащена Wi-Fi модулем Intel dual-band AC95060, Bluetooth 5.1, гигабитным Ethernet и опциональными модулями 4G и 5G связи.

image

Также у платы есть три USB 3.0 порта, USB 2.0 и 40-пиновой интерфейс для подключения дополнительных модулей.

Разработчики создали для платы несколько дополнительных устройств. Например, в Hackboard 2 Starter Kit входит Hackboard 2 с Windows 10 Pro, блок питания, теплоотвод, веб-камера, беспроводная клавиатура со встроенным тачпадом. В Hackboard 2 Complete Kit входит еще и дисплей 13.3" IPS 1080p HD со встроенными динамиками.

Что еще? Плата поддерживает как Windows, так и Linux. Что касается Windows, то плата идет с предустановленным Python. Есть и вариант платы с Ubuntu Linux. У платы есть традиционное BIOS-меню, позволяющее без проблем сконфигурировать загрузку и настроить некоторые другие параметры.

Пока что плата доступна только на Crowd Supply. За $99 можно приобрести начальный комплект с Linux, за $140 — то же самое с Windows 10. Понятно, что можно приобрести самую недорогую версию и установить на нее Windows в случае необходимости. Ну и еще дороже обойдутся разные варианты наборов платы и дополнительных модулей к ней.

ссылка на оригинал статьи https://habr.com/ru/company/selectel/blog/535782/