Русский
Русский
English
Статистика
Реклама

Game design

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

04.08.2020 10:19:03 | Автор: admin
Чувствуете ли вы азарт, когда обнаруживаете в игре сбой? Когда, наконец, попадаете в скрытую область на карте, не предназначенную для игроков? Которая была заблокирована кажущимися непроходимыми горами и невидимыми стенами? Если ваш ответ да, поздравляем, вы исследователь.

Как исследователя, меня всегда восхищало то, что скрыто от глаз в играх, в которые я играю. До сих пор хорошо помню, как в первый раз попала под Штормград в World of Warcraft. Добраться туда нетрудно, и я, конечно, не была первой. Но когда я спустилась вниз под шумный город, мой восторг было не передать. Прямо надо мной стояли сотни людей: все куда-то спешили, продавали вещи на аукционе или болтали с друзьями, и я была как бы не с ними, но все еще там. С тех пор я всегда искала в играх что-то подобное. Мне все время хочется заглянуть за дым и зеркала и увидеть игру такой, какая она на самом деле. Это привело меня к размышлению о том, как разработчики создают игры для таких людей, как я, исследователей.

image


Кто же такие исследователи?


Если вы опросите тысячу поклонников The Elder Scrolls, что им больше всего нравится в игре, вы получите множество разных ответов. Однако это не будет тысячей разных ответов. Возможно, нам хотелось бы верить, что наши мотивы уникальны, но в действительности они часто следуют определенным схемам и могут быть определены по категориям. Так, в своем исследовании 1996 года Ричард Бартл поделил игроков на четыре психотипа: исследователей, карьеристов, коммуникаторов и киллеров.

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

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

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

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

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




Как игры наказывают исследователей


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

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


Скрытые области


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

Существует три ситуации, когда это действительно должно быть наказуемо:

  • Игрок получает доступ к разрушающим качественный игровой опыт предметам и использует их. Мы могли это наблюдать в 2019 году, когда Bethesda заблокировала аккаунты игроков, получивших доступ в комнату разработчиков Fallout 76, где хранятся абсолютно все игровые предметы, включая броню и оружие.
  • Игрок получил доступ к чему-либо вразрез Пользовательскому соглашению (Terms of Service (ToS)). Обычно это значит, что игрок использовал некий чит-код например, удаляющий невидимые стены, ускоряющий героя или позволяющий ему летать там, где он хочет.
  • Доступ к скрытой области дает игроку явное преимущество над остальными. Такое часто встречается в шутерах от первого лица, где игроки могут попытаться проникнуть в скрытую область карты, откуда удобно убивать ничего не подозревающих противников.

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


Та самая комната разработчиков


Необычное использование игровых механик


Создатель YouTube-канала Archvaldors Warcraft Hacks недавно опубликовал видео под названием Как меня забанили за БОТОВ при отсутствии ботов. В этом видео он объясняет, как его забанили в World of Warcraft по запрету Activision-Blizzard. Этот запрет должен был решить проблему ботов, которая всегда преследовала игру. Единственная проблема заключалась в том, что Арчвальдор не использовал никаких ботов.

Как он думает, кто-то пожаловался на него, как на бота, потому что он пытался получить доступ к области, заблокированной воротами. Чтобы добиться своей цели, он бежал к воротам и пытался применить на них ряд различных способностей, чтобы посмотреть, сработает ли что-то из этого. Гейм-мастер (сотрудник Blizzard, которому поручено решать внутриигровые проблемы) уделил проблеме буквально несколько секунд, а затем исчез. Впоследствии он игнорировал все попытки Арчвальдора выйти на диалог, а спустя три недели тот оказался забанен на полгода без права обжалования после попытки подняться по местности в другой области игры.

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

Это не первый раз, когда Activision подвергается критике за чрезмерный бан. Они также получали негативную реакцию за то, что банили игроков на 10 лет в Call of Duty Mobile буквально ни за что. Похоже, что в попытке сделать игры честными для игроков античит-программы предпочитают избавляться от исследователей наряду с ботами. И если для того, чтобы избавиться от ботов, нужно перебанить и всех исследователей что ж, пусть будет так.


Что исследователи привносят в игры


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

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


Как создавать игры для исследователей


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


The Legend of Zelda: Breath of the Wild всегда поощряла игроков исследовать свой мир


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


Во-первых, разработчики игр должны расширить понятие того, как следует играть в их игры. В последние годы некоторые MMORPG обвинялись в том, что они стали MMO в духе тематических парков. Это означает, что все игроки движутся по одному и тому же игровому сценарию. Свобода игрока уже не столь важна на первый план выходит сюжетно-ориентированная составляющая игрового процесса. Так устроено большинство однопользовательских линейных игр, и этот подход показывает себя очень эффективно. Игроки The Last of Us не жалуются, что не могут исследовать открытый мир. Зачем им это? Они купили игру ради захватывающей истории и развития характеров героев. Но MMO совсем другой жанр, где исследование открытого мира и свобода игроков являются ключевыми понятиями.

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


Сложность


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


Пасхальные яйца


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

Вот пара примеров таких пасхалок:

  • В Doom 2 есть секретная концовка, открывающаяся в случае, если игрок выстрелит боссу в лицо и затем пройдет по нему. В этом случае вы увидите голову геймдизайнера игры Джона Ромеро, насаженную на кол.
  • Если в Saints Row 2 вы отправитесь на скрытый прибрежный остров и побродите по его побережью, но увидите огромного фиолетового кролика, поднимающегося из глубин океана.




Удаляйте контент только в случае необходимости


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

Менеджмент будущего. Без начальников, переработок и KPI

05.01.2021 18:18:32 | Автор: admin

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

Кто такие Valve?

Valve Corporation американская компания-разработчик компьютерных игр. Автор хитов Conter-Strike, Left for Dead, Dota 2, создатель магазина игр Steam и очков виртуальной реальности Steam Index. Основана в 1996 году бывшими сотрудниками Microsoft Гэйбом Ньюэллом и Майком Харрингтоном.

В 2017 Forbes подсчитал, что основатель Valve Гэйб Ньюэлл с состоянием в $4,1 млрд. обогнал самого Дональда Трампа с его $3,7 млрд. При этом основной доход Ньюэлла составляет прибыль от магазина игр Steam, в том числе от покупок геймеров в Dota 2 и Counter Strike: Global Offensive.

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

все иллюстрации взяты из руководства для новых сотрудников, опубликованного на сайте Valveвсе иллюстрации взяты из руководства для новых сотрудников, опубликованного на сайте Valve

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

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

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

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

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

Принцип 2. Выбери проект по душе или придумай свой

В компаниях типа Google сотрудникам дают право посвящать до 10% времени личным проектам. В компании Valve этот процент равен 100.

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

  • В каком из проектов я буду наиболее полезен?

  • Какой проект больше влияет на потребителей?

  • От работы над какими задачами я получу удовольствие?

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

Принцип 3. У столов должны быть колесики

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

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

Принцип 4. Право на ошибку

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

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

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

Принцип 5. Обратная связь всему голова

Как устроен карьерный рост в Valve? Как повышать кому-то зарплату в компании, где все равны?

В Valve существует два официальных способа оценки друг друга: рецензирование и ранжирование.

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

Ранжирование и оплата труда

Прибыль компании в пересчете на сотрудника превышает аналогичные показатели Google, Amazon и Microsoft. В связи с этим Valve считает справедливым платить своим людям выше рынка.

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

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

1. Профессиональный уровень/технические навыки

2. Продуктивность/результативность работы

3. Роль в команде

4. Вклад в разработку продукта

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

Принцип 6. Баланс работы и отдыха

В Valve не поощряют переработки. Здесь это считается признаком неправильно организованного процесса и поводом к его пересмотру. Кроме этого, компания оплачивает путешествия своим сотрудникам и по максимуму обеспечивает комфорт в офисе:

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

Принцип 7. Поиск сотрудников важнее, чем воздух

Мы ищем людей, которые лучше нас.

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

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

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

  • Хотел бы я, чтобы этот человек был моим начальником?

  • Многому ли он меня научит?

  • Что будет, если этот человек начнет работать у наших конкурентов?

Принцип 8. Ищите Т-образных людей

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

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

Принцип 9. Самофинансирование

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

Все права на интеллектуальную собственность также принадлежат Valve.

Valve это самофинансируемая компания. Ничто не мешает нам принимать собственные решения в отношении наших продуктов.

Слабые стороны Valve

Несмотря на впечатляющие результаты и революционный подход к менеджменту, Valve признает, что некоторые вопросы им пока даются тяжело:

  • Помощь новичкам в работе и наставничество

  • Распространение информации в компании

  • Поиск и прием на работу специалистов в совершенно новых сферах

  • Прогнозирование на период более 3-4 месяцев

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

Вопросы за кадром

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

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

На сайте по поиску работу Indeed всего три отзыва о Valve, и все они неплохие, средний бал 4,3:


Источники:

1. Официальный сайт Valve

2. Руководство для новых сотрудников на русском и на английском

3. Статья в Нью-Йорк Таймс

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

5. Страничка Indeed с отзывами на Valve


Для тех, кто предпочитает короткий жанр, автор ведет телеграм-канал@annakopyrneva, где пишет о софтскиллах, продукте и своей работе в ИТ.

Подробнее..

Игровая статика, или как я перестал бояться и полюбил Google Apps Script

07.08.2020 14:13:35 | Автор: admin


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

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

Давайте посмотрим, как для таких целей может подходить Google Spreadsheets и встроенный в него Google Apps Script и можно ли на этом сэкономить время.

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

Итак, для редактирования тех же мечей вам потребуется выполнить три операции:
  1. извлечь текущие показатели урона (если у вас нет готовых расчетных таблиц);
  2. рассчитать обновленные значения в старом добром экселе;
  3. перенести новые значения в игровые JSON-ы.

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

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

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

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

Плюсы Минусы
  • Совместное редактирование
  • Удобно переносить расчеты из других спредшитов
  • Макросы (Google Apps Script)
  • Есть история редактирования (вплоть до ячейки)
  • Родная интеграция с Google Drive и прочими сервисами

  • Лагает при большом количестве формул
  • Нельзя создавать отдельные ветки изменений
  • Лимит времени отработки скриптов (6 минут)
  • Сложность в отображении nested JSON-ов


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

Что получилось в итоге?


В Google Spreadsheets сделан отдельный документ, в котором есть лист Main, где мы управляем выгрузкой, и остальные листы, по одному на каждый игровой объект.
При этом, чтобы привычный nested JSON уложить в плоскую таблицу, пришлось немного переизобрести велосипед. Допустим, мы имели следующий JSON:

{  "test_craft_01": {    "id": "test_craft_01",    "tags": [ "base" ],"price": [ {"ident": "wood", "count":100}, {"ident": "iron", "count":30} ],"result": {"type": "item","id": "sword","rarity_wgt": { "common": 100, "uncommon": 300 }}  },  "test_craft_02": {    "id": "test_craft_02","price": [ {"ident": "sword", "rarity": "uncommon", "count":1} ],"result": {"type": "item","id": "shield","rarity_wgt": { "common": 100 }}  }}


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

  • text это поле или объект
  • / разделитель иерархии
  • text[] массив
  • #number индекс элемента в массиве


Таким образом, в таблицу JSON будет записан следующим образом:


Соответственно, добавление нового объекта такого типа это еще один столбец в таблице и, если у объекта были какие-то особые поля, то расширение списка строк с ключами в keypath.

Разделение на root и остальные уровни это дополнительное удобство в целях использования фильтров в таблице. В остальном работает простое правило: если значение в объекте не пустое, то мы его добавим в JSON и выгрузим.
На случай, если же в JSON будут добавляться новые поля и кто-то ошибется в пути он проверяется следующей регуляркой на уровне условного форматирования:
=if( LEN( REGEXREPLACE(your_cell_name, "^[a-zA_Z0-9_]+(\[\])*(\/[a-zA_Z0-9_]+(\[\])*|\/\#*[0-9]+(\[\])*)*", ""))>0, true, false)

А теперь о том, как происходит выгрузка. Для этого необходимо перейти на лист Main, выбрать желаемые объекты для выгрузки в столбце #ACTION и
нажать на Палпатина ( )


В результате будет запущен скрипт, который возьмет данные с листов, указанных в поле #OBJECT, и выгрузит их в JSON. Путь для выгрузки указан в поле #PATH, а место, куда будет выгружен файл, это ваш личный Google Drive, привязанный к учетной записи Google, под которой вы просматриваете документ.

Поле #METHOD позволяет настроить, как именно требуется выгрузить JSON:
  • Если single выгружается один файл с названием, равным названию объекта (без эмодзи, конечно же, они тут только для читаемости)
  • Если separate каждый объект с листа будет выгружен в отдельный JSON.

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

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

Исходники


Соответственно, как выглядит сбор JSON-a на уровне кода:
  1. Берем поле #OBJECT и ищем все данные листа с таким именем
    var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(name)
    
  2. Ищем координаты основных якорей, по которым будем фильтровать данные листа (идем по рэнжу как по двумерному массиву, пока не найдем ячейку со значением == тексту якоря)
    function GetAnchorCoordsByName(anchor, data){  var coords = { x: 0, y: 0 }    for(var row=0; row<data.length; row++){    for(var column=0; column<data[row].length; column++){      if(data[row][column] == anchor){        coords.x = column;        coords.y = row;        }    }  }  return coords;}
    
  3. Отрезаем столбцы объектов, которые выгружать не потребуется (для них в строке с якорем ###enable### можно изначально выставить true|false)
    function FilterActiveData(data, enabled){    for(var column=enabled.x+1; column<data[enabled.y].length; column++){    if(!data[enabled.y][column]){      for(var row=0; row<data.length; row++){        data[row].splice(column, 1);      }      column--;    }  }  return data}
    
  4. Отрезаем строки за пределами якорей ###data### и ###end_data###
    function FilterDataByAnchors(data, start, end){  data.splice(end.y)  data.splice(0, start.y+1);    for(var row=0; row<data.length; row++){    data[row].splice(0,start.x);  }  return data;}
    
  5. Забираем данные первого столбца в качестве ключей наших атрибутов
    function GetJsonKeys(data){  var keys = [];    for(var i=1; i<data.length; i++){    keys.push(data[i][0])  }  return keys;}
    
  6. Пробегаемся по каждому столбцу и создаем на каждый из них по объекту
    //На вход получаем отфильтрованные значения. //В случае, если экспорт идет как single-file, - сюда приходят все столбцы с листа. //Иначе - метод вызывается столько раз, сколько будет создано separate JSON-овfunction PrepareJsonData(filteredData){  var keys = GetJsonKeys(filteredData)    var jsonData = [];  for(var i=1; i<filteredData[0].length; i++){    var objValues = GetObjectValues(filteredData, i);       var jsonObject = {      "objName": filteredData[0][i],      "jsonBody": ParseToJson(keys, objValues)    }    jsonData.push(jsonObject)  }    return jsonData;}//Упаковываем в JSON конкретный столбец (пары ключ-значение)function ParseToJson(fields, values){  var outputJson = {};  for(var field in fields){    if( IsEmpty(fields[field]) || IsEmpty(values[field]) ){       continue;     }    var key = fields[field];    var value = values[field];        var jsonObject = AddJsonValueByPath(outputJson, key, value);  }  return outputJson;}//Добавляем конкретный атрибут в JSON по его полному путиfunction AddJsonValueByPath(jsonObject, path, value){  if(IsEmpty(value)) return jsonObject;    var nodes = PathToArray(path);  AddJsonValueRecursive(jsonObject, nodes, value);    return jsonObject;}//Разбиваем string с адресом поля на сегментыfunction PathToArray(path){  if(IsEmpty(path)) return [];  return path.split("/");}//Рекурсивно проверяем, существует ли нода адреса, и если нет - добавляемfunction AddJsonValueRecursive(jsonObject, nodes, value){  var node = nodes[0];    if(nodes.length > 1){    AddJsonNode(jsonObject, node);    var cleanNode = GetCleanNodeName(node);    nodes.shift();    AddJsonValueRecursive(jsonObject[cleanNode], nodes, value)  }  else {    var cleanNode = GetCleanNodeName(node);    AddJsonValue(jsonObject, node, value);  }  return jsonObject;}//Добавляем ранее не существовавшую ноду в JSON. Индексы массивов обрабатываются отдельно.function AddJsonNode(jsonObject, node){  if(jsonObject[node] != undefined) return jsonObject;  var type = GetNodeType(node);  var cleanNode = GetCleanNodeName(node);    switch (type){    case "array":      if(jsonObject[cleanNode] == undefined) {        jsonObject[cleanNode] = []      }      break;    case "nameless":       AddToArrayByIndex(jsonObject, cleanNode);      break;    default:        jsonObject[cleanNode] = {}  }  return jsonObject;}//Добавляем новый объект в массив по указанному индексуfunction AddToArrayByIndex(array, index){  if(array[index] != undefined) return array;    for(var i=array.length; i<=index; i++){    array.push({});  }  return array;}//Заполняем конечный атрибут значением (после того, как проверен полный путь до атрибута)function AddJsonValue(jsonObject, node, value){  var type = GetNodeType(node);  var cleanNode = GetCleanNodeName(node);  switch (type){    case "array":      if(jsonObject[cleanNode] == undefined){        jsonObject[cleanNode] = [];      }      jsonObject[cleanNode].push(value);      break;    default:      jsonObject[cleanNode] = value;  }  return jsonObject}//Узнаем тип ноды.//Если object - будем добавлять вложенные ключи по дефолту//Если array - проверяем его наличие и создаем, если его нет//Если nameless - проверяем в массиве выше наличие объекта с соответствующим индексом, и если такого нет - создаемfunction GetNodeType(key){  var reArray       = /\[\]/  var reNameless    = /#/;    if(key.match(reArray) != null) return "array";  if(key.match(reNameless) != null) return "nameless";    return "object";}//Вычищаем из имени ноды псевдоразметку для указания конечного значения уже в JSONfunction GetCleanNodeName(node){  var reArray       = /\[\]/;  var reNameless    = /#/;    node = node.replace(reArray,"");    if(node.match(reNameless) != null){    node = node.replace(reNameless, "");    node = GetNodeValueIndex(node);  }  return node}//Извлекаем индекс объекта массива из nameless-объектаfunction GetNodeValueIndex(node){  var re = /[^0-9]/  if(node.match(re) != undefined){    throw new Error("Nameless value key must be: '#[0-9]+'")  }  return parseInt(node-1)}
    
  7. Полученный JSON передаем для создания соответствующего файла в Google Drive
    //Основной метод, в который необходимо передать: путь, имя файла (с расширением) и string с данными.function CreateFile(path, filename, data){  var folder = GetFolderByPath(path)     var isDuplicateClear = DeleteDuplicates(folder, filename)  folder.createFile(filename, data, "application/json")  return true;}//Ищем конкретную папку в GoogleDrive по полному путиfunction GetFolderByPath(path){  var parsedPath = ParsePath(path);  var rootFolder = DriveApp.getRootFolder()  return RecursiveSearchAndAddFolder(parsedPath, rootFolder);}//Разбиваем полный путь к папке на сегментыfunction ParsePath(path){  while ( CheckPath(path) ){    var pathArray = path.match(/\w+/g);    return pathArray;  }  return undefined;}//Проверяем валидность переданного на вход путиfunction CheckPath(path){  var re = /\/\/(\w+\/)+/;  if(path.match(re)==null){    throw new Error("File path "+path+" is invalid, it must be: '//.../'");  }  return true;}//Если вдруг в папке уже есть файл с таким именем, с которым мы хотим создать файл, - маркируем старый на удаление. //Иначе - получим дублирование файлов, т.к. старый сам не удалитсяfunction DeleteDuplicates(folder, filename){  var duplicates = folder.getFilesByName(filename);    while ( duplicates.hasNext() ){    duplicates.next().setTrashed(true);  }}//Штатной возможности поиска по пути нет, поэтому мы идем от корневого раздела вниз до конечного, ища каждый сегмент пути по имениfunction RecursiveSearchAndAddFolder(parsedPath, parentFolder){  if(parsedPath.length == 0) return parentFolder;     var pathSegment = parsedPath.splice(0,1).toString();  var folder = SearchOrCreateChildByName(parentFolder, pathSegment);    return RecursiveSearchAndAddFolder(parsedPath, folder);}//Ищем в parent папку name, и если нет - создаемfunction SearchOrCreateChildByName(parent, name){  var childFolder = SearchFolderChildByName(parent, name);     if(childFolder==undefined){    childFolder = parent.createFolder(name);  }  return childFolder}//Перебираем итератор файлов в parent на предмет соответствия name на входеfunction SearchFolderChildByName(parent, name){  var folderIterator = parent.getFolders();    while (folderIterator.hasNext()){    var child = folderIterator.next();    if(child.getName() == name){       return child;    }  }  return undefined;}
    


Готово! Теперь идем в Google Drive и забираем там свой файлик.

Для чего была нужна возня с файлами в Google Drive, и почему не постить сразу в гит? В основном только для того, чтобы можно было проверять файлы до того, как они улетели на сервер и совершили непоправимое. В будущем быстрее будет пушить файлы напрямую.
Чего нормально решить не удалось: при проведении различных A/B-тестов всегда возникает необходимость создавать отдельные ветки статики, в которых меняется часть данных. Но так как по сути это еще одна копия дикта, мы можем для A/B-теста копировать сам спредшит, поменять данные в нем и уже оттуда выгружать данные для теста.

Заключение.


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

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

Основным бутылочным горлышком производительности становится API Google Drive: поиск и удаление/создание файлов занимает максимальное время, здесь помогает только выгрузка не всех файлов сразу или выгрузка листа не отдельными файлами, а единым JSON-ом.

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

Ссылки:


Пример спредшита-экспортера
Ссылка на проект в Google Apps Script
Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru