...

суббота, 13 августа 2016 г.

Новый пользователь Вашего продукта — как ему помочь?

Так ли понятен пользователю интерфейс Вашего продукта, как Вам кажется?

Сможет ли пользователь быстро оценить его достоинства и остаться с Вами надолго?

В статье ниже я рассмотрю концепцию “обучения во взаимодействии” на примере абстрактной web-системы. Данный подход хорошо можно объяснить примером из современного игрового мира. Сначала вы проходите tutorial. Вам на плечи не вешают сразу килотонны обучающего материала. Вас ведут по ранней стадии игры, в нужное время выдавая подсказки. Например, при первом взаимодействии с новым объектом игры. Накапливается положительный опыт. Вы обучаетесь взаимодействовать. Рискну предположить, что скорее всего Вы считаете себя продвинутым пользователем, когда речь касается приложений. Как и большинство из них вы мгновенно жмёте на кнопку “Пропустить” / “Приступить к работе” …

На самом деле, я тоже почти всегда сразу жму на кнопку “Пропустить”. Это нормально, потому как в данный момент я не готов много запоминать. А после нажатия я иногда жалею о содяном)) И точно таким же взглядом, как девушка выше начинаю “недоумевать в экран”. Поэтому режим обучения “обо-всём-сразу” перед стартом работы с системой — слабоэффективен. К счастью, не все системы требуют обучения. Есть достаточно очевидные (airbnb), а есть и такие, с которыми сперва придётся повозиться (bitrix). Это не значит, что такая система плоха. Это значит, что она решает настолько сложные задачи, что это привело к непростому интерфейсу. Вам просто нужно потратить опередённое время, чтобы освоиться. Возможно Вы позднее поймёте, что это и “правда удобно”…

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

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

Пользователь видит информацию только о фильтрах. Т.к. они играют основную роль в данном разделе. Мы будем считать, что он всё прочитал, после того, как сделал первый клик по любому элементу в фильтре. Если он сделал onfocus по первой форме, значит он готов начинать работу. Считаем, что невозможно читать текст и одновременно кликнуть по элементам фильтра :) Всё-таки наконец он сделал свой первый клик. Готов! Теперь самое время показать ему первую выдачу результатов.

Альтернативный вариант описания работы с фильтрами: показать, что фоном есть контент. Вынудить к прочтению подсказки, чтобы unlock-нуть контент, взаимодействуя с фильтрами. Это можно считать наградой за действия. Достаточно агрессивный режим подсказки, требующий в 100% случаев подтверждения от пользователя (клик на “Поехали!”).

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

“ — Хорошо, если мне нужно это знать прямо сейчас, тогда спасибо, что сообщили и подчеркнули это!” — как бы мысленно произношу я. А что если второй инструмент тоже потенциально может вызвать вопросы? Тогда, попытаемся оказаться в балансе подачи подсказок и покажем вторую чуть ниже. Мы начинаем скроллить ниже и натыкаемся на вторую.

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

Видите? Мы получили подсказку ни раньше ни позже нужного нам момента. У нас есть очередное знание — в этой системе поиск как у Google :) А еще можно применить трюк “внезапного усложнения”. Нас сначала заманивают простой поисковой формой, но при вводе первых символов уже “запугивают” требованием конкретики. Возможно тут еще и выигрыш в освобождении шапки от дополнительных контролов.

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

Давайте теперь уйдём в другой раздел. Например в “Карта мира”. Вообще UX почти всех карт в наши дни идентичен. Но если в Вашей карте есть что-то особенное о чем должен знать Ваш пользователь, то самое время сейчас об этом сказать.

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

Подсказка также может иметь тайминг, после которого она автоматически исчезнет с экрана. Это средний случай, который подойдет для ситуаций, когда нужно что-то сообщить пользователю, но нет необходимости прерывать его сценарий. Пускай он сделает клик на карте. Тайминговая подсказка появляется сверху. Если таких подсказок много в системе, то через несколько итераций выработается опыт о том, что тайминговые выпадают вверху. И если требующие реакции — всегда снизу, то это тоже может запомниться. Привычку “закрывать на автомате” никто не отменял.

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

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

Попап пораждается контекстуально. Показывается связка с событием — клик. Но возможность работать с картой не пропадает. Судя по всему закрыть такой попап можно как кликом в “ОК” так и кликом в любую часть карты.

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

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


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


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


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


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

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

PS: Да и не забывайте “вешать” всплывающие тултипы про онховере на требующие этого элементы. Кто хотя бы об этом помнит, тот делает наш Мир лучше!

PPS: Я готов к сотрудничеству! Если Вы хотите улучшить свою систему, сделать её интерфейс более понятным и дружественным для пользователя — пишите в скайп creativiter, или на почту kamushken@gmail.com

Комментарии (0)

    Let's block ads! (Why?)

    Security Week 32: проект Саурон, уязвимость в iOS, червь в PLC

    Между тем уютным секьюрити дайджестам исполнился годик. Как быстро летит время! В выпуске за 32-ю неделю прошлого года я писал о дыре в Android, уязвимости в автомобилях концерна Fiat Chrysler и концепции Do Not Track 2.0. Что изменилось? Недостатка в новостях о безопасности я по-прежнему не испытываю, даже наоборот. Изменения к лучшему есть, но не везде, что как раз можно увидеть на примере этих трех давних сообщений.

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

    Автобезопасность остается сложной темой. С одной стороны откровений уровня прошлогодней новости о беспроводном взломе авто не появилось, с другой — отсутствие громких разоблачений не говорит о безопасности. Скорее причина в закрытости автоиндустрии по отношению к независимым исследователям. Хорошая история по теме произошла на этой неделе: исследователи из университета Бирмингема раскрыли детали уязвимости штатной противоугонной системы, которая устанавливается на автомобили концерна Volkswagen аж с 1995 года. Перехватывать сигналы с беспроводного брелка такой системы оказалось весьма просто. Важно, что все данные были на руках у исследователей уже в 2013 году, но VW притормозил публикацию отчета судебным иском. Их тоже можно понять, но судя по косвенным данным, об уязвимости сигнализации не знала только общественность, а вот преступники пользуются ей уже давно. В таком раскладе владельцу авто лучше все-таки знать о потенциальной небезопасности штатной системы.

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

    Проект «Саурон» — новая таргетированная кампания учитывает ошибки предшественников
    Новость. Исследование «Лаборатории». Исследование Symantec.

    В начале этой неделе эксперты «Лаборатории» и исследователи из Symantec независимо друг от друга публикуют отчет новой атаки класса APT. Мы ее называем ProjectSauron, наши коллеги — Strider. «Саурон» использует достаточно продвинутые методы атаки, сбора и эксфильтрации данных, хотя и не настолько крутые, как, например в The Equation. Пожалуй, главными особенностями атаки является максимальная заточенность под жертву и максимальная же сложность обнаружения. Вредоносные компоненты хранятся только в оперативной памяти, под каждую жертву создается собственный комплект из малвари, доменов и серверов для вывода данных. А для эксфильтрации используется целый арсенал средств: от стандартных, но с применением сильного шифрования, до эксплуатации внутренних почтовых серверов и вывода данных из air-gapped систем с помощью хитро размеченных флешек. Позитивным моментом является наличие приемов борьбы с ломами и такой классификации: вредоносная активность была задетектирована с помощью нашего решения для защиты от таргетированных атак. Больше технических деталей в подробном отчете «Лаборатории» в PDF.


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

    В iOS 9.3.4 закрыта критическая RCE уязвимость
    Новость. Advisory на сайте Apple.

    Победитель в номинации «Самая короткая новость недели». В очередном обновлении мобильной операционной системы iOS компания Apple закрыла опасную уязвимость, позволявшую приложению выполнить код с привилегиями ядра. Все! Apple может себе такое позволить: код системы закрыт, отношения с внешними исследователями также ведутся непублично. Даже запущенная недавно программа Bug Bounty компанией Apple ведется приватно: как сообщают с мест, в программу приглашены всего две дюжины исследователей, и нет, нам даже не расскажут, кто именно. Кстати, за информацию об уязвимости Apple благодарит китайскую команду Team Pangu, группу хакеров, специализирующуся на джейлбрейках.

    Исследователи показали proof of concept червя, живущего в программируемых логических контроллерах
    Новость. Исследование в PDF.

    А вот и обещанный на прошлой неделе компот — еще одно интересное исследование с конференции Blackhat. Исследователь Маик Брюггеманн из компании OpenSource Security довольно много времени провел анализируя взаимодействие программируемых логических контроллеров (PLC) Siemens с управляющей консолью TIA Portal.

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

    К счастью, это все еще proof of concept, а не реальный червь. Производитель железа, компания Siemens, и вовсе утверждает, что демонстрация была очень теоретического свойства. В частности, для реализации своей идеи исследователь поотключал системы безопасности, которые в нормальных условиях должны быть включены всегда. Тем не менее, картина получается красивая и пугающая: на современном производстве потенциально уязвимых компьютеров и так десятки, а тут получается что сотни. Брюггеманн делает вывод: производителям надо менять подход к безопасности. Хорошо, но неконкретно: в данном случае можно начать с контроля целостности кода для PLC, и желательно не только вендором.

    Что еще произошло:
    Серьезная уязвимость в реализации протокола TCP в Linux, позволяющая перехватывать трафик.

    К атаке на POS-систему Oracle возможно причастны авторы Carbanak.

    У Microsoft кажется большие проблемы с системой SecureBoot (а у джейлбрейкеров праздник).

    Древности:
    «V-492»

    Резидентный очень опасный вирус. Заражает COM-файлы при их запуске на выполнение. Длину файлов не проверяет. Копирует себя в конец файла и изменяет его первые 6 байт (JMP xx xx zz zz zz).

    При активизации ищет файл C:\COMMAND.COM и инфицирует его. Затем остается резидентным в памяти. Для этого вирус копирует себя в таблицу векторов прерываний по адресу 0000:0200. Периодически стирает несколько секторов со случайными номерами. Изменяет int 1Ch и int 21h. Содержит команду 'PUSH 100h', поэтому не распространяется на компьютерах с процессором 8086/88.

    Цитата по книге «Компьютерные вирусы в MS-DOS» Евгения Касперского. 1992 год. Страницa 87.

    Disclaimer: Данная колонка отражает лишь частное мнение ее автора. Оно может совпадать с позицией компании «Лаборатория Касперского», а может и не совпадать. Тут уж как повезет.

    Комментарии (0)

      Let's block ads! (Why?)

      [Перевод] Процедурная генерация уровней для игр-головоломок

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

      Здорово было бы найти способ заставить компьютер сэкономить вам время и решить проблемы, о которых я сказал выше… И именно тут на помощь приходит процедурная генерация!

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

      Fruit Dating — правила и особенности


      Не так давно мы выпустили игру Fruit Dating для устройств iOS (также она доступна для Android и даже для невыпущенного (на момент релиза игры) Tizen). Это игра-головоломка с простыми правилами. Её цель — соединять пары фруктов одного цвета, проводя пальцем по экрану. Перемещение пальца соответствует наклону игрового поля в нужном направлении. Когда игрок пытается выполнить свою задачу, на его пути встают различные препятствия, такие как камни, машины и другие фрукты. Все подвижные объекты перемещаются в одном направлении. На картинках ниже показан первый уровень, в котором для соединения фруктов требуется 3 хода.

      Со временем добавляются новые особенности:

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

      Вы наверно уже заметили, что уровень состоит из плиток; это упрощает работу, потому что каждый уровень может быть представлен как маленькая сетка. Её максимальный размер 8x8 плиток, но всегда есть неподвижная граница, так что «полезная» область не больше 6x6 плиток. Этого может показаться мало, но доказано, что для такого поля можно создать достаточно сложные задачи.

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

      Раз и два.

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

      Инструмент для решения головоломок


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

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

      Как видите, это простой брутфорс-подход. Итак, количество возможных положений на поле было: 4, 4*4 = 42, 4*4*4 = 43,… 4n. На 10 ходу получалось более миллиона комбинаций поля, а на 25 ходу — 1125899906842624 комбинаций. Ну хорошо, тогда мы можем ограничить максимальное количество ходов, скажем до 10, и нас не будут интересовать более сложные уровни, но здесь скрывается другая опасность. Некоторые из головоломок могут быть созданы или сгенерироваться таким образом, что игрок, сделавший в начале несколько плохих ходов, не сможет завершить уровень. Или же в некоторых уровнях может возникнуть зацикленность состояний на поле. Если алгоритм разветвляется в таком направлении слишком рано, уровень может быть помечен как нерешаемый, даже если есть более короткие ветви с более простым решением. Также если алгоритм нашёл решение, нет никаких гарантий, что оно самое короткое — нужно завершить все ветви, чтобы найти кратчайшее решение. Кроме того, на поле часто возникают такие состояния, что один ход в определённом направлении ничего не изменяет. Посмотрите на третью картинку в части «Fruit Dating — правила и особенности» — ничего не изменится, если мы сдвинемся влево.

      Поэтому правила изменились:

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

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


      Из исходного положения ходы разветвляются на четыре возможных направления. Пометим их как 1-1, 1-2, 1-3, 1-4. Алгоритм всегда стремится переместиться в следующем порядке: вправо, вверх, влево, вниз. Поскольку для дальнейшего изучения сохраняемых состояний нужно применить стек, первое продолжающее состояние передаётся в стек последним (в нашем случае 1-4). Снова первым ходом является сдвиг вправо (2-1) и поскольку это новое состояние, оно записывается в стек. Следующим становится сдвиг вверх, который приводит к состоянию 2-2. Мы уже были в этом состоянии в первой итерации. Поэтому мы применяем правило г) и обрываем эту ветвь — в стек ничего не записывается. Далее идёт попытка хода влево. Он приводит к новому состоянию (2-3) и оно помещается в стек. Последний ход — сдвиг вниз, но в нём нет различия между 1-4 и 2-4, поэтому мы ничего не помещаем в стек (правило б)… нет нового состояния = ничего не делаем). Теперь верхнее состояние стека — это 2-3. Из него мы перемещаемся вправо и попадаем в состояние 3-1, которое равно состоянию 2-1. Но в 2-1 мы были на второй итерации, так что обрываем эту ветвь. Затем мы двигаемся вверх, фрукты оказываются на соседних плитках, и поскольку это была единственная пара, игра завершается.

      Алгоритм работает, хотя он может и не найти кратчайший путь. Он просто берёт первое найденное решение. Чтобы исправить это, я сначала ограничил максимальное количество ходов равным 30. Если решение не находится, я считаю уровень непроходимым. Если решение находится, допустим на 15 ходу, я снова запускаю «решатель» с максимальной глубиной решения 14 (15 — 1). Если решение не находится, то 15 — это кратчайший путь. Если решение найдено например на 13 ходу, я запускаю инструмент с максимальной глубиной 12 (13 — 1). Я продолжаю процесс, пока возвращается какое-нибудь решение. Последнее возвращённое решение является кратчайшим решением.

      Генератор


      Мы создали «решатель», теперь можно переходить к генератору и проверять с его помощью каждую сгенерированную головоломку.

      Фаза генерирования состоит из двух частей:

      • генерирование стен
      • генерирование объектов на поле

      Генерирование стен всегда начинается с рисования неподвижной границы поля:

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

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

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

      Поскольку все стены начинаются от границы поля, то каждая отдельная плитка была соединена с границей. Для меня это выглядело скучно, поэтому я добавил ещё один этап, на котором генерируются внутренние стены. Внутренние стены не соединены ни с одной имеющейся плиткой. Этап начинается с выбора случайной плитки и проверки того, свободна ли она и плитки в пределах 3x3 от неё. Если это так, то стена БУДЕТ помещена в сетку, и следующая плитка выбирается согласно случайному направлению (это направление случайно выбирается перед тестированием первой плитки). Цикл прерывается, когда условие свободных на 3x3 плиток не выполняется. Обратите внимание на выделенное выше слово «будет». Если вы поместите стену в сетку сразу же и перейдёте к обработке следующей плитки, область в пределах 3x3 никогда не будет свободной, потому что вы только что поместили туда стену. Поэтому я сохраняю все плитки стен во временный массив и одновременно помещаю их в сетку после прекращения цикла.

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

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

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


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

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

      Для концов коридоров, окружённых плитками с трёх сторон, я выбрал вес 6 + Random (3). Для плиток в горизонтальных или вертикальных коридорах я выбрал вес 2. Для углов я выбрал вес 3 + Random (3), а для свободных областей — 1.

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

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

      Кстати, с помощью весов можно делать и другие хитрости. Позже я добавил спящего ёжика и муравьеда (их описания приведены в начале статьи). Не имеет смысла помещать их в середине коридора, поэтому для коридоров их вес = 0.

      В этой анимации показано расположение на уровне фруктов и препятствий:


      Окончательный сгенерированный уровень показан на статичной картинке ниже. Для решения требуется 6 ходов (вправо, вверх, влево, вниз, вправо, вверх). Отлично, через 1-2 минуту после нажатия на кнопку Generate у нас получился интересно выглядящий уровень, прохождение которого возможно через 6 ходов (никто не будет играть в уровни, для прохождения которых нужно 30 ходов!); к тому же, для его поиска нам не пришлось ни капли мучиться. Но… всегда можно сделать чуть-чуть лучше. И с этой точки в нашей статье мы будем пытаться сделать уровни красивее.

      Редактор


      Генерирование уровней завершилось в предыдущей части. Наш редактор поддерживает drag&drop, так что можно легко перетаскивать объекты, чтобы получить более высокий уровень симметрии. Например, вот так:

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

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

      Окончательный результат


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

      Об авторе: Томас Рыхновски (Tomas Rychnovsky) — инди-разработчик небольших мобильных игр для Android, iOS и Tizen.

      Комментарии (0)

        Let's block ads! (Why?)

        пятница, 12 августа 2016 г.

        Сопроцессы: -что, -как, -зачем?

        Многие пользователи Bash знают о существании со-процессов, появившихся в 4-й версии Bash'a. Несколько меньшее количество знает о том, что сопроцессы в Bash не какая-то новая фича, а древний функционал KornShell'a появившийся ещё в реализации ksh88 в 1988 году. Ещё меньшее количество пользователей shell'ов умеющих сопроцессить знают синтаксис и помнят как это делать.
        Вероятно, я отношусь к четвёртой группе — знающих о сопроцессах, периодически умеющих ими пользоваться но так и не понимающих «зачем?». Я говорю «периодически», так как иногда я освежаю в голове их синтаксис, но к тому моменту, когда мне кажется что «вот тот случай когда можно применить co-proc» я уже напрочь забываю о том как это делать.
        Этой заметкой я хочу свести воедино синтаксисы для разных шеллов чтобы на случай, если таки придумаю зачем они мне нужны, я если и не вспомню как это делать, то по крайней мере, буду знать где это записано.
        В заголовке статьи у нас 3 вопроса. Пойдём по порядку.

        Что?
        Что же такое co-process?
        Со-процессинг — это одновременное выполнение двух процедур, одна из которых считывает вывод другой. Для его реализации необходимо предварительно запустить фоновый процесс выполняющий функционал канала. При запуске фонового процесса его stdin и stdout присваиваются каналам связанными с пользовательскими процессами. Соответственно, один канал для записи, второй для чтения.
        Пояснять это проще на примерах, поэтому сразу перейдём ко второму вопросу.

        Как?
        Реализации со-процессов в шеллах разнятся. Я остановлюсь на 3-х известных мне реализациях в ksh, zsh и bash. Рассмотрим их в хронологическом порядке.
        Хоть это и не имеет прямого отношения к вопросам статьи, отмечу, что все нижеприведённые примеры сделаны на

        $ uname -opr
        FreeBSD 10.1-STABLE amd64
        
        

        Ksh
        $ `echo $0` --version
          version         sh (AT&T Research) 93u+ 2012-08-01
        
        

        Синтаксис
        cmd |&
        
        

        кажется мне наиболее логичным. Здесь для выполнения команды cmd в фоновом режиме мы используем специальную операцию |&, выражающую соответвенно:
        — "&" — фоновый процесс;
        — "|" — каналы.

        Запускаем фоновый процесс:

        $ tr -u a b |&
        [2]     6053
        
        

        Убедимся, что он жив:
        $  ps afx | grep [6]053
         6053  4  IN        0:00.00 tr -u a b
        
        

        Теперь мы можем общаться с нашим фоновым процессом.
        Пишем:
        $ print -p abrakadabra1
        $ print -p abrakadabra2
        $ print -p abrakadabra3
        
        

        и читаем:
        $ read -p var; echo $var
        bbrbkbdbbrb1
        $ read -p var; echo $var
        bbrbkbdbbrb2
        $ read -p var; echo $var
        bbrbkbdbbrb3
        
        

        или так:
        $ print abrakadabra1 >&p
        $ print abrakadabra2 >&p
        $ print abrakadabra3 >&p
        $ while read -p var; do echo $var; done
        bbrbkbdbbrb1
        bbrbkbdbbrb2
        bbrbkbdbbrb3
        
        

        Закрываем «конец» трубы для записи:
        $ exec 3>&p 3>&-
        
        

        и для чтения:
        $ exec 3<&p 3<&-

        Zsh
        $ `echo $0` --version
        zsh 5.2 (amd64-portbld-freebsd10.1)
        
        

        Синтаксис со-процессов в zsh не слишком отличается от ksh, что не удивительно, т.к. в его man'е сказано «zsh most closely resembles ksh».
        Основным отличием является использование ключевого слова coproc вместо оператора |&. В остальном всё очень похоже:
        $ coproc tr -u a b
        [1] 22810
        $ print -p abrakadabra1
        $ print abrakadabra2 >&p
        $ print -p abrakadabra3
        $ read -ep
        bbrbkbdbbrb1
        $ while read -p var; do echo $var; done
        bbrbkbdbbrb2
        bbrbkbdbbrb3
        
        

        Для закрытия каналов чтения/записи можно воспользоваться идиомой exit:
        $ coproc exit
        [1] 23240
        $
        [2]  - done       tr -u a b
        $
        [1]  + done       exit
        
        

        При этом запустился новый фоновый процесс, который тут же завершился.
        Это ещё одно отличие от ksh — мы можем не закрывать существующий сопроцесс, а сразу инициировать новый:
        $ coproc tr -u a b
        [1] 24981
        $ print -p aaaaa
        $ read -ep
        bbbbb
        $ coproc tr -u a d
        [2] 24982
        $
        [1]  - done       tr -u a b
        $ print -p aaaaa
        $ read -ep
        ddddd
        $
        
        

        в ksh мы бы просто получили:
        $ tr -u a b |&
        [1]     25072
        $ tr -u a d |&
        ksh93: process already exists
        
        

        Несмотря на эту возможность рекомендуется, всегда явно убивать фоновый процесс, особенно, при использовании «setopt NO_HUP».
        Здесь же стоит упомянуть, что иногда мы можем получить неожиданные результаты связанные с буферизацией вывода, именно поэтому в приведённых выше примерах мы используем tr с опцией -u.
        $ man tr | col | grep "\-u"
             -u      Guarantee that any output is unbuffered.
        
        

        Хоть это и не имеет оношения исключительно к со-процессам продемонстрирую это поведение примером:
        $ coproc tr a b
        [1] 26257
        $ print -p a
        $ read -ep
        ^C
        $
        [1]  + broken pipe  tr a b
        
        

        Буфер не полон и мы ничего не получаем из нашей трубы. Заполним его «доверху»:
        $ coproc tr a b
        [1] 26140
        $ for ((a=1; a <= 4096 ; a++)) do print -p 'a'; done
        $ read -ep
        b
        
        

        Разумеется, если данное поведение нас не устраивает, его можно изменить, например используя stdbuf
        $ coproc stdbuf -oL -i0 tr a b
        [1] 30001
        $ print -p a
        $ read -ep
        b
        
        

        Bash
        $ `echo $0` --version
        GNU bash, version 4.3.42(1)-release (amd64-portbld-freebsd10.1)

        Для запуска со-процесса в bash также как и в zsh используется зарезервированное слово coproc, но в отличии от рассмотренных выше shell'ов доступ к сопроцессу осуществляется не с помощью >&p и <&p, а посредством массива $COPROC:
        ${COPROC[0]} для записи;
        ${COPROC[1]} для чтения.
        Соответственно, процедура записи/чтения будет выглядеть примерно так:
        $  coproc tr -u a b
        [1] 30131
        $ echo abrakadabra1 >&${COPROC[1]}
        $ echo abrakadabra2 >&${COPROC[1]}
        $ echo abrakadabra3 >&${COPROC[1]}
        $ while read -u ${COPROC[0]}; do printf "%s\n" "$REPLY"; done
        bbrbkbdbbrb1
        bbrbkbdbbrb2
        bbrbkbdbbrb3
        
        

        , а закрытие дескрипторов:
        $ exec {COPROC[1]}>&-
        $ cat <&"${COPROC[0]}"
        [1]+  Done                    coproc COPROC tr -u a b
        
        

        Если имя COPROC по каким-то причинам не устраивает можно указать свое:
        $ coproc MYNAME (tr -u a b)
        [1] 30528
        $ echo abrakadabra1 >&${MYNAME[1]}
        $ read -u ${MYNAME[0]} ; echo $REPLY
        bbrbkbdbbrb1
        $  exec {MYNAME[1]}>&- ; cat <&"${MYNAME[0]}"
        [1]+  Done                    coproc MYNAME ( tr -u a b )
        
        

        Зачем?
        Прежде чем попытаться ответить зачем нужны сопроцессы подумаем можно ли реализовать их функционал в shell'ах которые не имеют coproc «из коробки». Например в таком:
        $ man sh | col -b | grep -A 4 DESCRIPTION
        DESCRIPTION
             The sh utility is the standard command interpreter for the system.  The
             current version of sh is close to the IEEE Std 1003.1 (``POSIX.1'') spec-
             ification for the shell.  It only supports features designated by POSIX,
             plus a few Berkeley extensions.
        $ man sh | col -b | grep -A 1 -B 3 AUTHORS
             This version of sh was rewritten in 1989 under the BSD license after the
             Bourne shell from AT&T System V Release 4 UNIX.
        
        AUTHORS
             This version of sh was originally written by Kenneth Almquist.
        
        

        Именованные каналы никто не отменял:
        $ mkfifo in out
        $ tr -u a b <in >out &
        $ exec 3> in 4< out
        $ echo abrakadabra1 >&3
        $ echo abrakadabra2 >&3
        $ echo abrakadabra3 >&3
        $ read var <&4 ; echo $var
        bbrbkbdbbrb1
        $ read var <&4 ; echo $var
        bbrbkbdbbrb2
        $ read var <&4 ; echo $var
        bbrbkbdbbrb3
        
        

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

        Ну и зачем же нужны сопроцессы? Я процитирую выдержку из перевода статьи Mitch Frazier:

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

        И в действительности я лишь один раз смог с относительной пользой применить со-процессы в своих скриптах. Задумка была реализовать некий «persistent connect» для доступа к MySQL.
        Выглядело это примерно так:
        $ coproc stdbuf -oL -i0 mysql -pPASS
        [1] 19743
        $ printf '%s;\n' 'select NOW()' >&${COPROC[1]}
        $ while read -u ${COPROC[0]}; do printf "%s\n" "$REPLY"; done
        NOW()
        2016-04-06 13:29:57
        
        

        В остальном все мои попытки использовать coproc действительно были надуманными.
        Спасибо
        Хочется поблагодарить Bart Schaefer, Stéphane Chazelas, Mitch Frazier чьи комментарии, письма и заметки помогли в написании статьи.

        Комментарии (0)

          Let's block ads! (Why?)

          Как сбой в дата-центре может привести к отмене тысяч рейсов крупнейших авиакомпаний

          В прошлый понедельник многие интернет-СМИ писали о том, что тысячи авиарейсов второй по размеру и значимости авиакомпании мира были отменены. Речь идет о Delta Air Lines. Тысячи и тысячи пассажиров Delta Air Lines не смогли никуда улететь, поскольку рейсы, на которые они купили билет, просто перестали существовать. Как оказалось, проблема — в сбое компьютерной системы компании. Причем не в региональной, а в основной — проблема случилась в главном дата-центре Delta Air Lines, расположенном в Атланте, США.


          Служащий Delta Airlines помогает пассажиру, чей рейс отменили, разобраться в ситуации

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

          Как оказалось, штатное переключение с основной энергосистемы на вспомогательный генератор привело к выходу из строя последнего. Случился пожар, который быстро был потушен. Но вся инфраструктура дата-центра Delta Air оказалась обесточенной. Только через несколько часов удалось ввести в строй 400 из 500 серверов, и спустя еще некоторое время восстановилась работа остальных 100 серверов. Все это время почти весь флот из 800 самолетов оставался на земле. А отмена всего одного авиарейса обошлась компании в $17 000, плюс пришлось компенсировать пассажирам транспорт, питание, дополнительные расходы и т.п.

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

          А что с Southwest Airlines?


          Это еще одна крупная авиакомпания, потерявшая миллионы долларов США из-за сбоя в дата-центре, случившегося еще 20 июля. А причина сбоя — частичный отказ в работе одного-единственного маршрутизатора, коих в дата-центре компании сотни. Служба поддержки ДЦ не заметила проблемы, и буквально через несколько минут вся система рассыпалась, как карточный домик. Руководитель компании сравнил происшествие с наводнением, которое случается раз в 1000 лет.

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

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

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

          И это еще не все


          Southwest Airlines и Delta Airlines не единственные авиакомпании, которые потеряли деньги из-за сбоев оборудования дата-центров. В мае компания JetBlue просила своих пассажиров регистрироваться в аэропорту «вручную», а не автоматически. Причина — все тот же сбой компьютерной системы. Плюс United Airlines отменила сотни авиарейсов из-за сбоев в собственном дата-центре в прошлом году.

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

          Согласно недавнему исследованию, проведенного институтом Понемона, сбой в дата-центре обходится его владельцам в среднем в $74000 (в 2015 году). Наиболее дорогим оказалась одна из прошлогодних аварий, с общей суммой убытков для владельца дата-центра в $2.4 млн.

          Другие наши публикации:

          Комментарии (0)

            Let's block ads! (Why?)

            Создание бесконечного раннера на JavaScript, механика движения фона

            HelloHome Case Study

            image

            HelloHome Case Study


            HelloHome – приложение для поиска соседей созданное по модели Tinder.


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


            Основные проблемы в этой сфере были и остаются следующие:


            1. Ниша узкая, на рынке не много предложений.


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

            В приложении HelloHome мы постарались решить эти основные проблемы.


            image

            HelloHome — Light VS Dark


            1. Проблема которую решает приложение


            Существует достаточное количество приложений, сервисов и сайтов, но у них всех много похожих проблем:


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

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


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

            image

            Скриншот с экранов совпадения


            2. Структура приложения


            Приложение состоит из двух видов пользователей, людей которые ищут квартиру и владельцев квартир, которые ищут себе соседа. Соответственно в HelloHome нужно было сделать два типа анкет, в отличии от Tinder в котором реализован только один тип анкет для всех пользователей. Эти факторы нужно было учитывать при проектировании приложения. В процессе проектирования мы постарались учесть все детали, вы можете увидеть это в прототипе на invisionapp.


            image

            Скриншот карточки апартаментов и пользователя


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


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


            Особенности приложения

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

            image

            Скриншот с шагами в wireframes с воронкой регистрации


            1. Несколько раз на этапе проектирования и дизайна была переделана и реализована страница анкеты квартиры

            image

            Скриншот с несколькими вариантами анкет


            4. Дизайн


            Было принято решение сделать уникальный дизайн который бы запоминался и ассоциировался именно с этим приложением. Нужно было сделать что-то свое и чтобы дизайн не выглядел 1 в 1 как Tinder. Это решение аргументировалось тем, что стиль приложения должен отложиться в голове у пользователя, а если пользователь будет делиться приложением с друзьями, то в двух словах это должно было звучать примерно так «Это как Tinder только для поиска соседей». Также мы решили немного отойти от гайдлайнов.


            Long Shadow


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


            image

            Скриншот с Long Shadow


            Воронка регистрации


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


            image

            Скриншот с воронкой регистрации


            Tour Screens & Sucsess Screens


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


            image

            Tour screens for HelloHome


            Которые бы дали начальную цель, а также парочку Succsess Screens для поднятия настроения.


            image

            Скриншот с Succsess screens


            Сейчас насколько эффективно это решение сказать к сожалению не можем, но тесты покажут и мы поправим этот момент уже во второй версии.


            Amenities


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


            image

            Скриншот с Amenities


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


            Изначально предполагалось сделать 8 экранов, в последствии приложение разрослось до 53.


            Собственно что получилось можете увидеть в нашем проекте на invisionapp и dribble.


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


            Будем рады услышать от вас фидбек.

            Комментарии (0)

              Let's block ads! (Why?)