Закладки — есть ли предел?

Всем привет!

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

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

Автор изображения Iñaki del Olmo

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

React Native: новая веха в мобильной разработке Shopify

Или почему Shopify переходит на React Native.

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

В конце каждого квартала мы видим одну и ту же картину: большинство наших клиентов делают покупки через мобильные устройства (в третьем квартале прошлого года их доля составила 71%). Чёрная пятница и Киберпонедельник — самое горячее время для наших продавцов, а активность покупателей в эти дни зашкаливает. В этом году в период скидок партнеры Shopify зафиксировали 3-процентный рост заказов с мобильных устройств, а средняя доля таких покупок составила 69% от общего числа транзакций.

Так почему же мы решили перейти на React Native? И почему именно сейчас? Что теперь будет с нашей нативной мобильной разработкой? Быстро и коротко ответить на эти вопросы не получится. Начнем с предыстории.

Мобильная разработка в Shopify — 2019

У нас в Shopify сформирована особая практика — делать ставку на сравнительно молодые технологии, находящиеся на раннем этапе развития, либо только набирающие популярность. Это помогает нам быстрее развиваться.

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

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

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

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

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

Ruby on Rails был на начальном этапе развития и еще не оформился как полноценный фреймворк, когда в 2004 году Тоби (наш генеральный директор) стал основным участником open source проекта. В течение многих лет Ruby on Rails считался несерьезным, неэффективным решением. Но выбор и изучение этой технологии на таком раннем этапе развития в результате дали Shopify конкурентное преимущество, хотя это был непопулярный выбор. Используя Ruby on Rails, команда смогла быстрее создавать продукты и привлекать ресурсы. Ведь это была современная технологию, с более высоким уровнем абстракции, чем у традиционных языков программирования и фреймворков, существовавших на тот момент. Аналогично, Пол Грэм в свое время рассказывал о том, как он решил использовать Lisp для создания Viaweb. 6 из 10 самых дорогих компаний Y Combinator сегодня используют Ruby on Rails (хотя, опять же, фреймворк все еще остается не очень популярным). С другой стороны, ни одна из 10 самых дорогих компаний Y Combinator не использует Java, который считается проверенным и достаточно надежным корпоративным решением.

Точно так же, 2 года назад Shopify решил перейти на Google Cloud. Опять же, это достаточно рискованное предприятие для второго по величине e-commerce сервиса в США (по состоянию на 2019 год) — провести облачную миграцию за пределы собственных дата-центров ради достаточно нового продукта, Google Kubernetes Engine. Мы увидели, что кривая создания дополнительной стоимости подтолкнула нас к тому, чтобы сосредоточиться на том, в чем мы действительно хороши (это помощь бизнесу), позволяя другим (в данном случае Google Cloud) взять на себя тяжелый труд, связанный с поддержанием оборудования в рабочем состоянии, с обеспечением мощностей, безопасности, с обновлением операционной системы и т. д.

React Native — что это?

В 2015 году Facebook анонсировал и выпустил релиз open source фреймворка React Native. Ранее его уже использовали внутри компании для разработки своих мобильных приложений. React Native — это фреймворк для кроссплатформенной разработки нативно отображаемых мобильных приложений с помощью js-библиотеки React. Таким образом, он даёт возможность использовать топовую js-библиотеку для создания пользовательского интерфейса нативных мобильных приложений.

В Shopify эта идея (тогда и в каком-то смысле, сейчас тоже) была воспринята скептически, но многие посчитали её перспективной. Таким образом очередное мероприятие Shopify Hackdays было целиком посвящено React Native. Хотя тогда команда оценила преимущества фреймворка, мы приняли решение, что в 2015 году мы не смогли бы реализовать React Native приложение, которым могли бы потом гордиться. Главным образом, это объяснялось проблемами с производительностью и отсутствием полноценной поддержки Android OS. Зато мы ясно осознали, что нам понравилась парадигма Reactive Programming (Реактивного программирования) и язык GraphQL. Кроме того, после знакомства с React Native мы разработали и выложили рендерер для iOS. В 2015 году мы внедрили эти технологии в наш стек, но не использовали React Native для массовой мобильной разработки. О наших первых экспериментах подробно написано здесь.

До сегодняшнего дня в Shopify стандартом была нативная мобильная разработка. Мы создали две команды, mobile tooling и foundations, которые были сфокусированы на iOS и Android, а также помогали нам ускорять процесс разработки. Несмотря на то, что они показали хорошие результаты, нам кажется, разработка станет более эффективной, если мы:

  • используем мощь JavaScript и других web-технологий в мобильной разработке;
  • внедрим парадигму реактивного программирования в разработку клиентских приложений;
  • объединим разработку под iOS и Android на React Native в один технологический стек.

Как работает React Native?

React Native позволяет создавать кроссплатформенные нативно отображаемые мобильные приложения с использованием JavaScript. React Native похож на React: мы также декларативно создаем пользовательский интерфейс на JS с деревом UI-элементов, или с виртуальным DOM (VDOM), если выражаться в терминах ReactJS. Если ReactJS отображает элементы интерфейса в браузере, то React Native преобразует объекты VDOM в нативные платформо-зависимые визуальные элементы для отображения на мобильных устройствах, используя биндинг: нативные компоненты обернуты в React. Нас интересуют только платформы Android и iOS, но есть энтузиасты, которые заинтересованы в развитии React Native для Windows, macOS и Apple tvOS.


ReactJS взаимодействует с браузером, а React Native — с мобильными API

Когда мы не используем React Native?

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

  • запуск приложения на старом “железе” (CPU < 1.5 GHz);
  • сложный процессинг;
  • сверхвысокая производительность;
  • много потоков, работающих в фоновом режиме.

Обратите внимание: низкоуровневые библиотеки, включая различные SDK с открытым кодом, остаются полностью нативными. Мы можем создавать собственные нативные модули, если нам хочется быть в более тесном контакте с “железом”.

Почему мы переходим на React Native именно сейчас?

У нас есть 3 главных причины:

  1. После приобретения маркетплейса Tictail (сервис разработан на React Native, по принципу mobile first) в 2018 году мы увидели, какое развитие получил React Native и в 2019 году мы вложились еще в три проекта.
  2. Shopify активно использует React в web-разработке, теперь настало время применить наши ноу-хау и в разработке мобильных приложений.
  3. Мы заметили, что кривая производительности поползла вверх (например, что мог раньше, и что теперь может Google Docs в сравнении с десктопным Microsoft Office) и сделали ставку на React Native в долгосрочной перспективе — так же, как в свое время мы поверили в Ruby on Rails, Kubernetes и Rich Media.

Мобильная разработка в Shopify в 2019

В Shopify продавцы и покупатели могут взаимодействовать несколькими способами: через web- и через мобильные приложения. Весь прошлый год три наших команды занимались экспериментами с React Native, и в результате разработали три мобильных приложения: Arrive, Point of Sale и Compass.

После наших экспериментов мы сделали следующие выводы:

  • переписывая Arrive app на React Native, команда обнаружила, что продуктивность работы выросла в два раза по сравнению с нативной разработкой, даже если писать только под одну платформу;
  • тестируя Android-версию Point of Sale app на малых мощностях, мы обнаружили, что приложение работает при более низкой частоте CPU: 1.5GHz (написано на React Native) против 2GHz (нативная разработка);
  • мы предварительно оценивали, что доля платформо-независимого кода составит ~80%; и мы были удивлены, когда в реальности она оказалась намного выше: 95% для Arrive и 99% для Compass.

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

Arrive

В конце 2018 года мы решили переписать на React Native одно из наших самых популярных клиентских приложений, Arrive. Это высокопроизводительное iOS-приложение с высоким рейтингом и миллионами скачиваний. Мы выбрали Arrive, потому что у нас не было его Android-версии. Таким образом мы пошли навстречу пользователям Android-устройств. Теперь и iOS-, и Android-версия написаны на React Native с долей общего кроссплатформенного кода в 95%.

В процессе переписывания мы добились следующих результатов:

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

Кроме того, команда смогла опробовать отличный метод быстрого выполнения pull-запросов “work-in-progress”. Просто сканируете QR-код из комментария Github с помощью телефона, и JS bundle вашего приложения обновляется. Таким образом вы каждый раз можете моментально обновлять приложение и использовать его актуальную версию. Наш СТО недавно описал этот процесс в Твиттере.

Point of Sale

В начале 2019 года мы провели 6-недельный эксперимент над нашим флагманским продуктом Point of Sale (POS) app, чтобы понять, является ли он хорошим кандидатом для переписывания на React Native. Мы много изучали этот вопрос, так как наши розничные продавцы рассчитывали, что нам удастся вдвое сократить время отклика нашего приложения: процесс обслуживания покупателей с помощью нашего приложения должен закрепиться в мышечной памяти продавцов, и они не должны отвлекаться на это.

Чтобы одновременно выполнить требования наших ритейлеров и глубже разобраться в разработке на React Native для POS-устройств, мы решили создать новое нативное мобильное приложение для iOS, а на React Native написать версию для Android OS.

Мы выделили на эти задачи две отдельные команды, и вот почему:

  1. У нас уже была команда с сильной экспертизой в iOS, включая разработчиков нативных POS-приложений.
  2. Мы хотели иметь возможность кроме непосредственной производительности приложения протестировать еще и нашу скорость разработки на React Native, сравнивая все это с нашим золотым стандартом, то есть с нативной разработкой под iOS.
  3. Чтобы выполнить высокие требования продавцов к производительности, мы решили произвести все обновления Facebook re-architecture updates to React Native (однако оказалось, что для производительности это не критично). Выделив отдельные команды для работы над двумя проектами, мы снизили риски, связанные со срывом плана релизов.

Мы анонсировали переписанный POS на конференции Unite 2019. Обе версии, iOS и Android на React Native, будут доступны в 2020 году.

Compass

В Spotify есть команда (Start team), которая помогает клиентам запускать собственный бизнес. Прежде чем, компания приняла принципиальное решение разрабатывать мобильные приложения на React Native, эта команда детально изучала Flutter and React Native. Выбор пал на React Native, и теперь у них есть бета-версии iOS — и Android-приложения Compass. Причем, ~99% кода у них общие.

Первые релизы выйдут в течение трех месяцев.

Мобильная разработка в Shopify 2020++

Мы много интересного приготовили на 2020 год.
Будем ли мы переписывать наши нативные мобильные приложения? Нет. Хотя это решение каждая команда принимает самостоятельно.
Будем ли мы нанимать нативных разработчиков? Да, много!
Мы хотим стать ведущими участниками сообщества React Native, создавать платформо-зависимые компоненты и продолжать разбираться в тонкостях каждой из платформ. А это требует сильной экспертизы. Звучит неплохо, правда?

Сотрудничество и Open Source

Мы верим, что разработка софта — это командная игра. Мы участвуем в разработке open web, open source и других открытых стандартов.

Мы вносим свой вклад в финансирование проектов компании Software Mansion и Кшиштофа Магеры (сооснователь React Native для Android), связанных с React Native.
Мы сотрудничаем с Уильямом Кэндильоном (ведет YouTube-канал Can It Be Done in React Native) по вопросам построения архитектуры и улучшения производительности.

У нас в планах тесное сотрудничество с командой React Native из Facebook по вопросам автоматизации, создания сторонних библиотек и курирования некоторых модулей в проекте Lean Core.

Вместе с компанией Discord мы активно работаем над тем, чтобы быстрее подготовить open source версию библиотеки FastList for React Native (позволяет рендерить только те элементы списка, которые находятся в видимой области) и оптимизировать её под Android OS.

Наши команды Tooling и Foundations для React Native

Когда вы делаете ставку на технологию и углубляетесь в неё, вы хотите получить от неё максимальный эффект. Для того, чтобы быстро ставить задачи и добиваться этой цели, мы создали два типа команд, которые помогают остальным сотрудникам Shopify быть продуктивными. Первый тип — это инструментальная группа (tooling team), которая помогает с конфигурированием, интеграцией и развертыванием. Второй тип — это команда разработчиков (foundation team), которая занимается SDK, повторным использованием кода и open source. В 2020 году обе команды начали развиваться в сторону React Native.

Наше популярное приложение Shopify Ping, которое позволяет общаться с сотнями тысяч клиентов, в настоящее время доступно только в iOS-версии. В 2020 году мы будем работать над версией для Android OS с использованием React Native в нашем филиале в Сан-Франциско, куда мы как раз нанимаем сотрудников.

В 2019 году Twitter выпустил десктопные и мобильные веб-приложения, используя технологию под названием React Native Web. Название может немного сбить вас с толку, но её главное отличие состоит в том, что эта технология позволяет использовать тот же стек React Native для разработки веб-приложений. В результате Facebook незамедлительно схантил Николаса Галлагера, ведущего разработчика проекта. В 2020 году мы в Shopify также проведем несколько экспериментов с React Native Web.


Подписывайтесь на нашего разработчика в Instagram

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

SQL HowTo: пишем while-цикл прямо в запросе, или «Элементарная трехходовка»

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

Наиболее «жизненный» пример — вывести 20 самых старых задач, числящихся на списке сотрудников (например, в рамках одного подразделения). Для различных управленческих «дашбордов» с краткими выжимками по участкам работы похожая тема требуется достаточно часто.

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

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

CREATE INDEX ON task(owner_id, task_date, id); -- а старый - удалим DROP INDEX task_owner_id_task_date_idx;

Как слышится, так и пишется

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

SELECT   * FROM   task WHERE   owner_id = ANY('{1,2,4,8,16,32,64,128,256,512}'::integer[]) ORDER BY   task_date, id LIMIT 20;


[посмотреть на explain.tensor.ru]

Немного грустно — мы заказывали всего 20 записей, а Index Scan вернул нам 960 строк, которые потом еще и сортировать пришлось… А давайте попробуем читать поменьше.

unnest + ARRAY

Первое соображение, которое нам поможет — если нам надо всего 20 отсортированных записей, то достаточно читать не более 20 отсортированных в том же порядке по каждому ключу. Благо, подходящий индекс (owner_id, task_date, id) у нас есть.

Воспользуемся тем же механизмом извлечения и «разворота в столбцы» целостной записи таблицы, что и в прошлой статье. А также применим свертку в массив с помощью функции ARRAY():

WITH T AS (   SELECT     unnest(ARRAY(       SELECT         t       FROM         task t       WHERE         owner_id = unnest       ORDER BY         task_date, id       LIMIT 20 -- ограничиваем тут...     )) r   FROM     unnest('{1,2,4,8,16,32,64,128,256,512}'::integer[]) ) SELECT   (r).* FROM   T ORDER BY   (r).task_date, (r).id LIMIT 20; -- ... и тут - тоже


[посмотреть на explain.tensor.ru]

О, уже намного лучше! На 40% быстрее, и в 4.5 раза меньше данных пришлось читать.

Материализация записей таблиц через CTE

Обращу внимание, что в некоторых случаях попытка сразу работать с полями записи после ее поиска в подзапросе, без «оборачивания» в CTE может приводить к «умножению» InitPlan пропорционально количеству этих самых полей:

SELECT   ((     SELECT       t     FROM       task t     WHERE       owner_id = 1     ORDER BY       task_date, id     LIMIT 1   ).*);

Result  (cost=4.77..4.78 rows=1 width=16) (actual time=0.063..0.063 rows=1 loops=1)   Buffers: shared hit=16   InitPlan 1 (returns $0)     ->  Limit  (cost=0.42..1.19 rows=1 width=48) (actual time=0.031..0.032 rows=1 loops=1)           Buffers: shared hit=4           ->  Index Scan using task_owner_id_task_date_id_idx on task t  (cost=0.42..387.57 rows=500 width=48) (actual time=0.030..0.030 rows=1 loops=1)                 Index Cond: (owner_id = 1)                 Buffers: shared hit=4   InitPlan 2 (returns $1)     ->  Limit  (cost=0.42..1.19 rows=1 width=48) (actual time=0.008..0.009 rows=1 loops=1)           Buffers: shared hit=4           ->  Index Scan using task_owner_id_task_date_id_idx on task t_1  (cost=0.42..387.57 rows=500 width=48) (actual time=0.008..0.008 rows=1 loops=1)                 Index Cond: (owner_id = 1)                 Buffers: shared hit=4   InitPlan 3 (returns $2)     ->  Limit  (cost=0.42..1.19 rows=1 width=48) (actual time=0.008..0.008 rows=1 loops=1)           Buffers: shared hit=4           ->  Index Scan using task_owner_id_task_date_id_idx on task t_2  (cost=0.42..387.57 rows=500 width=48) (actual time=0.008..0.008 rows=1 loops=1)                 Index Cond: (owner_id = 1)                 Buffers: shared hit=4"   InitPlan 4 (returns $3)     ->  Limit  (cost=0.42..1.19 rows=1 width=48) (actual time=0.009..0.009 rows=1 loops=1)           Buffers: shared hit=4           ->  Index Scan using task_owner_id_task_date_id_idx on task t_3  (cost=0.42..387.57 rows=500 width=48) (actual time=0.009..0.009 rows=1 loops=1)                 Index Cond: (owner_id = 1)                 Buffers: shared hit=4 

Одна и та же запись «поискалась» 4 раза… Вплоть до PostgreSQL 11 такое поведение встречается регулярно, и решением является «оборачивание» в CTE, что является безусловной границей для оптимизатора в этих версиях.

Рекурсивный аккумулятор

В предыдущем варианте суммарно мы прочитали 200 строк ради нужных 20. Уже не 960, но еще меньше — можно?

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

Шаг 1: стартовый список

Очевидно, что наш «целевой» список из 20 записей должен начинаться с «первых» записей по одному из наших owner_id-ключей. Поэтому сначала найдем такие «самые первые» по каждому из ключей и занесем в список, отсортировав его в порядке, который хотим — (task_date, id).

Шаг 2: находим «следующие» записи

Теперь, если мы возьмем из нашего списка первую запись и начнем «шагать» дальше по индексу с сохранением owner_id-ключа, то все найденные записи — как раз следующие в результирующей выборке. Конечно, только пока мы не пересечем прикладной ключ второй записи в списке.

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

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

Шаг 3: фильтруем и «разворачиваем» записи

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

Страшный итоговый запрос

WITH RECURSIVE T AS (   -- #1 : заносим в список "первые" записи по каждому из ключей набора   WITH wrap AS ( -- "материализуем" record'ы, чтобы обращение к полям не вызывало умножения InitPlan/SubPlan     WITH T AS (       SELECT         (           SELECT             r           FROM             task r           WHERE             owner_id = unnest           ORDER BY             task_date, id           LIMIT 1         ) r       FROM         unnest('{1,2,4,8,16,32,64,128,256,512}'::integer[])     )     SELECT       array_agg(r ORDER BY (r).task_date, (r).id) list -- сортируем список в нужном порядке     FROM       T   )   SELECT     list   , list[1] rv   , FALSE not_cross   , 0 size   FROM     wrap UNION ALL   -- #2 : вычитываем записи 1-го по порядку ключа, пока не перешагнем через запись 2-го   SELECT     CASE       -- если ничего не найдено для ключа 1-й записи       WHEN X._r IS NOT DISTINCT FROM NULL THEN         T.list[2:] -- убираем ее из списка       -- если мы НЕ пересекли прикладной ключ 2-й записи       WHEN X.not_cross THEN         T.list -- просто протягиваем тот же список без модификаций       -- если в списке уже нет 2-й записи       WHEN T.list[2] IS NULL THEN         -- просто возвращаем пустой список         '{}'       -- пересортировываем словарь, убирая 1-ю запись и добавляя последнюю из найденных       ELSE (         SELECT           coalesce(T.list[2] || array_agg(r ORDER BY (r).task_date, (r).id), '{}')         FROM           unnest(T.list[3:] || X._r) r       )     END   , X._r   , X.not_cross   , T.size + X.not_cross::integer   FROM     T   , LATERAL(       WITH wrap AS ( -- "материализуем" record         SELECT           CASE             -- если все-таки "перешагнули" через 2-ю запись             WHEN NOT T.not_cross               -- то нужная запись - первая из спписка               THEN T.list[1]             ELSE ( -- если не пересекли, то ключ остался как в предыдущей записи - отталкиваемся от нее               SELECT                 _r               FROM                 task _r               WHERE                 owner_id = (rv).owner_id AND                 (task_date, id) > ((rv).task_date, (rv).id)               ORDER BY                 task_date, id               LIMIT 1             )           END _r       )       SELECT         _r       , CASE           -- если 2-й записи уже нет в списке, но мы хоть что-то нашли           WHEN list[2] IS NULL AND _r IS DISTINCT FROM NULL THEN             TRUE           ELSE -- ничего не нашли или "перешагнули"             coalesce(((_r).task_date, (_r).id) < ((list[2]).task_date, (list[2]).id), FALSE)         END not_cross       FROM         wrap     ) X   WHERE     T.size < 20 AND -- ограничиваем тут количество     T.list IS DISTINCT FROM '{}' -- или пока список не кончился ) -- #3 : "разворачиваем" записи - порядок гарантирован по построению SELECT   (rv).* FROM   T WHERE   not_cross; -- берем только "непересекающие" записи


[посмотреть на explain.tensor.ru]

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

В любом случае, время выполнения получилось лучше, чем в «наивном» первом варианте. Но каким из этих 3 вариантов пользоваться — выбирать вам.

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

Чтобы получить свои личные данные, нужно выдать ещё больше личных данных

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


Компании просят пользователей предоставить свои личные данные перед тем, как выдать им доступ к своим данным – и всё это нужно, чтобы не дать доступа к данным не тем людям

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

Осенью я воспользовался правом на проверку этой системы, и отправил запросы на свои данные компаниям, занимающимся построением профилей потребителей и их оценкой. Одна из компаний, Sift, оценивающая кредитоспособность потребителей, отправила мне мой файл на 400 страниц, где содержались сообщения с Airbnb, заказы с Yelp и активность с Coinbase за долгие годы. Вскоре после публикации моей статьи Sift завалили требованиями – компания за короткое время получила больше 16 000 подобных запросов, и ей пришлось нанять подрядчика для их обработки.

Этот подрядчик, Berbix, помогал устанавливать личность людей, запрашивающих свои данные, требуя от них загружать фотографию их паспорта и делать селфи. Затем компания требовала от них сделать второе селфи со следующим условием: «Убедитесь, что на фото вы выглядите счастливым или радостным, и попробуйте снова».

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

«Это то кошмарное будущее, где я не могу запросить свои данные у какого-то стрёмного теневого кредитного бюро, не улыбнувшись для него предварительно – и это чистое безумие», — написал мне Джек Фелпс, программист из Нью-Йорка.

«Есть что-то неправильное в том, что нам приходиться делится ещё более личной информацией», — написала ещё одна читательница, Барбара Клэнси, профессор нейробиологии из Арканзаса на пенсии.

Такова неприятная реальность: чтобы получить свои личные данные, вам придётся расстаться с ещё большим количеством персональных данных. Сперва это кажется ужасным. Алистер Барр из Bloomberg назвал это «новый круг ада для приватности».

Однако тому есть серьёзные причины. Компании не хотят отдавать личные данные не тому человеку, а такое уже бывало в прошлом. В 2018 году Amazon отправила постороннему человеку 1700 аудиофайлов записей разговоров с помощником Alexa одного из своих клиентов.

Право на доступ к личным данным устанавливается новым калифорнийским законом о конфиденциальности потребителей. Закон частично повторяет европейский регламент, известный, как Общий регламент по защите данных (General Data Protection Regulation, GDPR). Вскоре после вступления регламента в силу, в мае 2018 один хакер получил доступ к учётной записи в сервисе Spotify директора технологической компании Джин Ян, и успешно провернул запрос на получение личных данных, узнав её домашний адрес, информацию по банковской карте и историю прослушанной музыки.

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

Один из исследователей, Джеймс Павюр, 24-летний аспирант из Оксфордского университета, отправил запросы на получение данных от имени своего партнёра по исследованиям и супруги, Кейси Кнерр, в 150 компаний, использовав её данные, которые легко можно было найти в интернете – почтовый адрес, электронный адрес и номер телефона. Для отправки запросов он специально завёл электронный почтовый ящик, похожий на один из вариантов написания её имени. И четверть из этих компаний отправили ему её личные данные.

«Я получил её номер социального страхования, список школьных оценок, большой срез информации о банковской карте, — сказал Павюр. – Компания, занимающаяся угрозами в сфере информационной безопасности, отправила мне все её пароли, утёкшие в сеть».

Мариано Ди Мартино и Питер Робинс, исследователи в области информатики из Хасселтского университета в Бельгии, достигли примерно такого же успеха в процентном соотношении, обратившись к 55 финансовым, развлекательным и новостным компаниям. Они запросили данные друг друга, правда, используя более продвинутые технологии, чем у Павюра – в частности, они подставляли на фото паспорт других людей в графическом редакторе. В одном случае Ди Мартино удалось получить данные совершенно незнакомого человека, чьё имя было похоже на имя Робинса.

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

«Компании в спешке принимают решения, ведущие их к небезопасным практикам», — сказал Робинс.

Для подтверждения личности у разных компаний есть разные технологии. Многие просто просят фотографию водительского удостоверения. Компания Retail Equation, принимающая решение, может ли потребитель вернуть товар в такие розничные магазины, как Best Buy и Victoria’s Secret, запрашивают только имя и номер водительского удостоверения.

У широкого спектра компаний, от которых теперь требуют обеспечение возврата пользователю данных, от Baskin Robbins до The New York Times, наблюдаются очень разные уровни познаний и опыта в области безопасности этих данных.

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

В случае, если пользователи не могут подтвердить свою личность, войдя в учётку, Ди Мартино и Робинс рекомендуют компаниям отправлять им емейл, звонить или запрашивать такую информацию, которую может знать только сам пользователь – типа номера недавнего чека.

«Регуляторам нужно глубже поразмыслить о непреднамеренных последствиях доступа пользователей к чтению и удалению своих данных, — сказал Стив Киркэм, работавший в команде безопасников Airbnb пять лет, перед тем, как в 2018-м основать Berbix. – Мы хотим предотвратить мошеннические запросы и удовлетворить легитимные».

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

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

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

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

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

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

Как левел-дизайнеры используют приёмы теории архитектуры для создания игровых уровней

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

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

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

Эмоционально-ориентированное планирование пространства

«Parti pris» или «parti», ― метод проектирования, который некоторые архитекторы используют на ранних стадиях планирования, чтобы определить пространственные параметры своего проекта. Являясь схематической интерпретацией, своеобразной отправной точкой всего проекта, parti может быть дополнен внешними идеями, которые зачастую выходят за пределы физической формы объекта. Таким образом, архитектурный объект может стать физическим воплощением некой философской концепции, если таковая закладывалась в его основу.


Рисунок 1. Пример parti: проект Горного центра для инженерного факультета Католического факультета (Сантьяго, Чили)

Римское понятие genius loci, или «духа места», тоже имеет к архитектуре непосредственное отношение: оно говорит о том, что каждое место обладает не только определёнными физическими параметрами, но и собственным характером. В случае левел-дизайна гении места могут создаваться через призму некого предполагаемого опыта, уже полученного игроком. Так, в главе «Дежавю на «Ишимуре» хоррора Dead Space 2 игрок снова оказывается в месте старта первой части игры и в своих флэшбеках проходит через самые запоминающиеся её моменты. Гений места здесь можно рассматривать как способ усиления драматического напряжения во всём пространственном объёме уровня.

Принцип «фигура-фон»

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

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

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

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

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

Иными словами, в архитектуре позитивное пространство равняется застроенному, негативное ― незастроенному.

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

Контраст между фигурой и фоном имеет множество способов достижения. Среди них ― цвет, объём и текстура.

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


Рисунок 2. N++ (2016), уровень Parkour Park Prototype

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

Некоторые уровни в N++ действительно страдают от этого: их физические массы и пустые пространства занимают визуально одинаковое количество места и тем самым нарушают различие между фигурами и фоном. Эта ситуация может усугубиться в том случае, если маccы уровня кажутся визуальными продолжениями игровой окантовки. Примером этого может послужить уровень Learning Process.

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


Рисунок 3. N++ (2016), уровень Learning Process

Ориентиры

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

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

image
Рисунок 4. Эйфелева башня. Архитектор: Гюстав Эйфель, 1889

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

В MMORPG «World of Warcraft: Битва за Азерот», прибывая в вымышленный город Дазар’алор, игроки видят монолитную конструкцию: она представляет собой позолоченную пирамиду, напоминающую аналогичные строения в Центральной Америке. В этой пирамиде располагаются высшие эшелоны местного общества и верхушка власти. Визуально пирамида контрастирует с небесным фоном точно так же, как это делают реально существующие достопримечательности вроде Эйфелевой башни.

image
Рисунок 5. World of Warcraft: Битва за Азерот (2018). Пирамида в Дазар’алоре

Расположение пирамиды Дазар’алора соответствует архитектурным правилам пространственного возвышения. Так, физическое возвышение фигуры над общим рельефом часто является культурно обоснованным решением, поскольку говорит о религиозной или социальной значимости объекта для области, над которой он виден. Пирамида является одним из самых высоких мест на всём континенте Зандалар, что указывает на её значимость для культурной самобытности города. Её местоположение посреди родины зандаларских троллей символизирует господство расы над прилежащей землёй. Эта идея находит продолжение также в смелой треугольной форме строения, имитирующей окружающие горы.

Тем же образом и Цитадель в Half-Life 2 доминирует над окружающим ландшафтом, но делает это так, что её теряющийся в облаках пик кажется подавляюще угнетающим. Футуристические приглушённые очертания и чудовищные размеры Цитадели придают ей противоречивый, но контрастный облик по сравнению со старыми кирпичными домами Сити 17. Она вызывает чувство страха и беспокойства, что, по словам Тоттена, вполне уместно, ведь таким образом игра сразу обозначает, что Цитадель является местом обитания главного антагониста игры.

image
Рисунок 6. Half-Life 2 (2004). Цитадель Сити 17

Использование ориентиров в качестве указателей пути

Помимо прочего, левел-дизайнеры могут использовать ориентиры в качестве физических целей или мест, которые игроку необходимо достичь. Эффект использования таких путевых точек может быть усилен архитектурной техникой, называемой «отказ и вознаграждение» (denial and reward). Цель её состоит в том, чтобы получить от прибытия к ориентиру или другому месту назначения наибольшее удовлетворение.

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

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

Позитивные пространства в городской среде

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

image
Рисунок 7. Фрагмент карты Нолли (1748)

Крупные города в World of Warcraft ― социальные среды, использующие те же свойства позитивного пространства. Как и во многих реальных городах, позитивные пространства в Штормграде формируются посредством рационального размещения архитектурных фигур. На карте Штормграда видно, что город имеет свои районы, отличающиеся друг от друга цветом крыши. Это основной и самый простой способ отразить визуальную идентичность этой ещё одной из пяти форм по Линчу. Кроме того, для более чёткого и наглядного разделения пространства на районы в Штормграде существуют водные каналы, благодаря которым переход из одного района в другой становится для игроков более очевидным.

image
Рисунок 8. World of Warcraft. Карта Штормграда

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


Рисунок 9. World of Warcraft. Диаграмма «фигура-фон» Штормграда

Негативные пространства в мультиплеерных шутерах

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

Аномальная популярность карты Facing Worlds из игры Unreal Tournament часто объясняется правильным использованием негативного пространства. В случае арена-шутеров негативные пространства позволяют игрокам различать других игроков ― как приятелей, так и противников ― с большего расстояния. Кроме того, негативное пространство помогает идентифицировать игровые цели и масштабные угрозы.

image
Рисунок 10. Unreal Tournament (1999), карта Facing Worlds

Левел-дизайнер Джим Браун противопоставляет рациональное использование негативного пространства в Facing Worlds его недостатку на карте Favela в Call of Duty: Modern Warfare 2. Здесь негативное пространство окружающего мира сложно отличить от игрового, что приводит к путанице, а оттого логичному недовольству игроков. Однако Браун настаивает на том, что дизайн среды на этой карте всего лишь соответствует её архитектурному источнику ― бразильским фавелам.

image
Рисунок 11. Call of Duty: Modern Warfare 2 (2009), карта Favela

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

В Modern Warfare 2 однопользовательская миссия Takedown тоже имеет место в бразильской фавеле: здесь используются те же элементы, что и в случае Favela, а потому характерно то же отсутствие визуальной ясности, как и в её мультиплеерном эквиваленте. Левел-дизайнер Дэн Тейлор использует этот уровень для того, чтобы доказать, что «путаница ― это круто», но признаёт, что такую идею нужно реализовывать очень аккуратно. Так что можно утверждать, что здесь отсутствие негативного пространства отвлекало бы от качественного прохождения уровня в той же степени, что и в Facing Worlds ― его наличие.

Пересмотр архитектурных условностей для нужд левел-дизайна

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

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

Впервые появившаяся в Call of Duty: Black Ops, карта Nuketown была тепло принята игровым сообществом и с тех пор появлялась и в более поздних частях франшизы. Популярность Nuketown, как и многих других известных многопользовательских карт, можно частично объяснить умелым использованием синергии между позитивными и негативными пространствами.

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


Рисунок 12. Call of Duty: Black Ops (2010). Карта Nuketown, составленная по принципу «фигура-фон»

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

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

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

image
Рисунок 13. Call of Duty: Black Ops, карта Nuketown

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

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

Заключение

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

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

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