Содержание

Шаблоны (Темплейты)

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

Классические применения шаблонов:

Шаблоны можно прописывать в обычном режиме редактора или в режиме исходного кода (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!}:{
Код ещё не вбит.
  %}
  {%= ?}:{
Был вбит другой ответ.
  %}
%}

Особые варианты

Кроме конкретных ответов, в ветках можно писать:

{% match bonus_3 }:{
  {%= !any_answer!}:{
Бонус закрыт — неважно, каким из синонимов.
  %}
  {%= !no_answer!}:{
Бонус ещё не закрыт.
  %}
%}

Проверка бонусов и сквозных бонусов

Аналогично кодам, вы можете проверять ответы для бонусов:

Пример в игре

Проверка автора ввода (кто именно вбил код)

К параметрам проверки ответов можно добавить приставку who_, чтобы узнать, кто из игроков команды ввел код. Возможные значения:

*(Анонимные игроки без регистрации считаются одним пользователем).*

{% match who_code_1 }:{ 
  {%= me}:{
Первый код ввел лично я.
  %}
  {%= other}:{
Первый код ввел мой напарник по команде.
  %}
  {%= !no_answer!}:{
Код еще никто не ввел.
  %}
%}

Проверка команды, вбившей код (для межкомандных дуэлей)

Приставка who_team_ позволяет проверить, какая команда ввела код на общем/сквозном задании. Возможные значения:

{% 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.

О чём стоит помнить:

Проверять перевод удобно, открывая игру с явным параметром языка — 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). Здесь — только шаблон, которым закрывается платное содержимое.

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

Возможные значения:

{% 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}:{ сюда %} %} после идёт текст, а не начало шаблона, поэтому останется на месте и строка так и будет комментарием ( смотри сюда).