Шаблоны (Темплейты)
Шаблоны — это динамические выражения, которые вычисляются на сервере до отправки страницы игрокам. В браузере во время игры отображается только результат вычисления для конкретной команды. Сам код шаблона игрокам не виден (его нет в исходном коде страницы).
Классические применения шаблонов:
- Индивидуальные задания для команды (разделение потоков).
Шаблоны можно прописывать в обычном режиме редактора или в режиме исходного кода (Source) в текст заданий, подсказок и бонусов. Шаблоны могут быть вложенными.
Google Таблица для генерации шаблонов
Для облегчения написания синтаксиса шаблонов вы можете скопировать себе и использовать специальную таблицу: Google Таблица генерации шаблонов QEng.
Различные виды шаблонов
Модификация задания для команды
По ID линейки (прохождения)
{% match line }:{
{%= 688 /*комментарий: название линейки*/}:{
Текст для линейки с ID 688
%}
{%= 643 }:{
Текст для линейки с ID 643
%}
{%= 653,655 }:{
Текст для линейки с ID 653 или 655
%}
{%= ?}:{
Текст для любой другой линейки
%}
%}
По ID команды
{% match team }:{
{%= 688 /*комментарий: название команды*/}:{
Текст для команды с ID 688
%}
{%= 643 }:{
Текст для команды с ID 643
%}
{%= 653,655 }:{
Текст для команды с ID 653 или 655
%}
{%= ?}:{
Текст для любой другой команды
%}
%}
Привязка события в задании к реальному времени
Полезно для выдачи виртуальных кодов/подсказок в строго определенное время. Для перевода даты в метку времени используйте Конвертер Unix Time.
{% unix_time 1639999296/*дата в unix time*/, Откроется, Осталось}:{
Этот текст будет показан только после наступления указанного времени.
%}
Шаблоны на основе вбитых ответов
Проверка последнего (текущего) ответа в первый код
*(Замените `code_1` на нужный номер кода, например, `code_5` для пятого кода)*
{% match code_1 }:{
{%= abc}:{
В первый код вбит ответ "abc".
%}
{%= bac, cba}:{
В первый код вбит ответ "bac" или "cba".
%}
{%= !no_answer!}:{
В первый код ещё не вводили правильный ответ.
%}
{%= ?}:{
Вбит какой-то другой синоним/ответ в первый код.
%}
%}
Проверка самого первого вбитого ответа во второй код
{% match code_first_2 }:{
{%= abc}:{
Первым в этот код был вбит ответ "abc".
%}
{%= !no_answer!}:{
Код ещё не вбит.
%}
{%= ?}:{
Был вбит другой ответ.
%}
%}
Особые варианты
Кроме конкретных ответов, в ветках можно писать:
!no_answer!— правильный ответ ещё не введён.!any_answer!— введён любой ответ. В отличие от?, не срабатывает, когда ответа ещё нет. Удобно, когда у кода есть синонимы и важен только факт того, что он вбит.?— любое значение, включая!no_answer!. Ставьте эту ветку последней: всё, что описано после неё, уже не проверяется.
{% match bonus_3 }:{
{%= !any_answer!}:{
Бонус закрыт — неважно, каким из синонимов.
%}
{%= !no_answer!}:{
Бонус ещё не закрыт.
%}
%}
Проверка бонусов и сквозных бонусов
Аналогично кодам, вы можете проверять ответы для бонусов:
bonus_1/bonus_first_1— последний или первый введенный ответ в первый бонус текущего уровня.gbonus_1/gbonus_first_1— последний или первый введенный ответ в первый сквозной (глобальный) бонус игры. Сквозные бонусы можно проверять даже на тех уровнях, где они не выведены на экран.
Проверка автора ввода (кто именно вбил код)
К параметрам проверки ответов можно добавить приставку who_, чтобы узнать, кто из игроков команды ввел код.
Возможные значения:
me— код введен текущим залогиненным пользователем.other— код введен другим участником команды.!no_answer!— ответ еще не введен.
*(Анонимные игроки без регистрации считаются одним пользователем).*
{% match who_code_1 }:{
{%= me}:{
Первый код ввел лично я.
%}
{%= other}:{
Первый код ввел мой напарник по команде.
%}
{%= !no_answer!}:{
Код еще никто не ввел.
%}
%}
Проверка команды, вбившей код (для межкомандных дуэлей)
Приставка who_team_ позволяет проверить, какая команда ввела код на общем/сквозном задании.
Возможные значения:
me— код ввела моя команда.other— код ввела команда соперников.!no_answer!— код еще не введен.
{% match who_team_code_1 }:{
{%= me}:{
Этот код первыми закрыли мы!
%}
{%= other}:{
Увы, соперники успели ввести этот код раньше нас.
%}
%}
Шаблоны, зависящие от языка интерфейса игрока
{% match lang }:{
{%= ru}:{
Выбран русский язык интерфейса.
%}
{%= uk }:{
Выбран украинский язык интерфейса (uk).
%}
{%= en }:{
Выбран английский язык интерфейса.
%}
{%= ?}:{
Какой-то другой язык.
%}
%}
Как сделать многоязычную игру
Есть способ проще - для перевода текста, ссылок и картинок. Многоязычную игру теперь делают переводами: Многоязычная игра (переводы). Задание остаётся одним текстом, переводы лежат рядом, а редактор показывает, что ещё не переведено. Шаблон ниже продолжает работать и ничего менять в готовых играх не надо, а для новых игр остаётся правильным выбором там, где языку нужна не другая версия того же текста (это как раз переводится), а другая структура: свой набор html-блоков, которого нет у других языков, своя логика в скрипте задания, а не просто другая строка в нём, или ветвление по языку, скомбинированное с другим шаблоном - по коду, по команде, по бонусу. Если же нужен именно перевод - см. переводы по ссылке выше.
Этим шаблоном одну игру можно выдавать сразу на нескольких языках: игрок увидит только свою ветку, остальные переводы не попадут даже в исходный код страницы.
Игрок выбирает язык в меню сайта; язык можно задать и параметром в адресе страницы — ?lang=de, ?lang=uk и так далее. Выбор запоминается в куках. Если игрок ничего не выбирал, язык определяется по настройкам его браузера.
lang возвращает двухбуквенный код языка. Актуальный список языков всегда виден в меню выбора языка на сайте; на момент написания статьи это de, en, es, et, fi, fr, it, lt, lv, nl, pl, ru, uk.
О чём стоит помнить:
- Всегда добавляйте ветку
?и ставьте её последней. Она сработает, если у языка игрока нет своей ветки, — иначе такой игрок увидит пустое задание. Обычно в неё кладут текст на основном языке игры. - Переводить на все языки не обязательно. Достаточно веток для языков вашей аудитории плюс запасная ветка.
- Одна ветка может покрывать несколько языков — коды перечисляются через запятую:
{%= ru, uk}:{ … %}. - Приём работает везде, где работают шаблоны: текст задания, подсказки, бонусы, тексты после решения.
- Коды-ответы лучше делать одинаковыми для всех языков — иначе придётся следить, чтобы ветки задания и ответы уровня не разъехались. Если ответ всё-таки языкозависимый (например, слово на локации), впишите в код все варианты через запятую.
- Шаблонами не переводятся название игры, её описание в списке игр и письма-приглашения — их пишут на языке, понятном всей аудитории, или дублируют через слэш.
Проверять перевод удобно, открывая игру с явным параметром языка — https://qeng.org/game/1234/?lang=lt. Загляните и в ветку ?: для этого достаточно выбрать язык, для которого ветки нет.
Если хочется дать игроку переключатель языка прямо в задании, добавьте в текст обычный select, а в Скрипт задания — его обработчик:
<select id="lang_select"> <option value="en">English (en)</option> <option value="uk">Українська (uk)</option> </select>
var select = document.getElementById('lang_select'); if (select) { // document.documentElement.lang - это язык КОНТЕНТА, он подменяется, если в // самой игре ещё и включены переводы (см. выше). Настоящий язык интерфейса, // выбранный игроком, надёжнее читать из куки lang. var match = document.cookie.match(/(?:^|; )lang=([^;]*)/); select.value = match ? decodeURIComponent(match[1]) : document.documentElement.lang; select.onchange = function () { var url = new URL(window.location.href); url.searchParams.set('lang', this.value); window.location.href = url.toString(); }; }
Проверка статуса оплаты товара (Пейволл)
Как завести товар, поставить кнопку оплаты и протестировать всё это без реальных денег, описано в разделе Платный контент (Paywall). Здесь — только шаблон, которым закрывается платное содержимое.
Если в вашей игре используются платные уровни или платные подсказки, вы можете проверить статус покупки:
product_KEY— где вместо KEY указывается ключ продукта из настроек.
Возможные значения:
yes— товар успешно куплен командой.pending— процесс оплаты начат, но транзакция еще обрабатывается.no— товар не оплачен.
{% match product_level_5 }:{
{%= yes}:{
Команда купила доступ к 5 уровню.
%}
{%= pending}:{
Оплата обрабатывается. Пожалуйста, подождите и обновите страницу.
%}
{%= no}:{
Доступ закрыт. Стоимость прохождения — $1. Нажмите для оплаты:
%pay_button level_5%
%}
%}
Шаблоны внутри javascript
Если шаблон стоит посреди javascript-кода, редактор кода ругается на синтаксис {% %} — для javascript это ошибка. Чтобы этого не происходило, служебные строки шаблона можно закомментировать двойным слэшем до вычисления шаблона, и код внутри шаблона станет рабочим.
. Движок уберёт эти
не обязателен, отступ перед убирается только тогда, когда сразу после него (не считая пробелов) идёт {% или %}. Пробел после , а короткий шаблон записать целиком в одну строку:
сохраняется.
<code JavaScript>
show_money();
{% match gbonus_141}:{
{%= some_code}:{
enter_silent('прошли игру целиком');
%}
{%= ?}:{
play_sound('limit');
%}
%}
</code>
Команда, вбившая в сквозной бонус 141 ответ some_code, получит:
<code JavaScript>
show_money();
enter_silent('прошли игру целиком');
</code>
Закрывающие скобки можно собрать в одну строку — %} %}
// {% match team}:{ {%= 172}:{ var boss = true; %} {%= ?}:{ var boss = false; %} %}
Обычные комментарии не затрагиваются: в строке смотри {% match team}:{ {%= 172}:{ сюда %} %} идёт текст, а не начало шаблона, поэтому после ).
останется на месте и строка так и будет комментарием ( смотри сюда