Потребность

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

Решение

Для примера сделаем небольшую игру «Логические концовки». Вы можете поговорить с этим ботом в телеграме по адресу @Logic_check_bot. Посмотреть на сценарий вы можете здесь.

Как это работает

Запрашиваем данные об игроке

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

В сценарии создайте первый экран, добавьте на него блок HTTP-запрос:

метод - GET
в поле URL вставьте данный адрес:
https://tools.aimylogic.com/api/data/${userId}
На вкладке RESPONSE нажмите на + и в поле Имя переменной вставьте:
history
а в поле Значение вставьте:
$httpResponse

Вкладки BODY и HEADERS заполнять не нужно.

Нажмите Сохранить.



Для удобства добавим на этот экран метку:

ЕСТЬ ЛИ ИСТОРИЯ?



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

Если пользователь у нас впервые

От блока http-запрос Завершен с ошибкой сделаем новый экран с блоком Текст:
Привет! Это игра логические концовки. Вооружись логическим мышлением! В этой игре нужно правильно закончить фразы. Ну что, начнём?

Назовём этот экран:

ЕСЛИ НЕТ ИСТОРИИ



Добавим варианты ответов пользователя

Добавим на экран "ЕСЛИ НЕТ ИСТОРИИ" блок Интенты.




Добавим готовый интент Согласие.







Сохраним блок


Узнать больше о блоке Интенты вы можете здесь, а о готовых интентах - здесь.

Вот что у нас получилось:



Оформим таблицу, в которой будем хранить содержание игры

Пример таблицы вы можете посмотреть здесь. Можете просто скопировать эту таблицу.

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

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



В таблице должно быть 4 столбца с названиями:

question

answer

level

score

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

Заполните таблицу следующим содержанием, как видно на скриншоте выше:

Если стол выше стула, то стул... ниже стола 1 10
Если два больше одного, то один... меньше двух 12 20
Если сестра старше брата, то брат... младше сестры 3 30
Если правая рука справа, то левая... слева 4 40
Если река глубже ручейка, то ручеек... мельче реки 5 50



Колонки Level и Score помогут нам возвращать пользователя к тому месту, где мы остановились, и также выводить счёт, так что они должны содержать соответствующие числовые значения.

Обязательно опубликуйте вашу таблицу:

Файл -> Опубликовать в интернете -> Опубликовать -> Ок -> Закройте всплывающее окно.
Путь из всплывающего окна копировать не нужно.





Откройте блокнот и скопируйте в него строку:

http://tools.aimylogic.com/api/googlesheet2json?sheet=1&id=



Затем найдите в пути вашей таблицы данный элемент:



Этот элемент находится между /d/ и /edit. Это идентификатор страницы.

Скопируйте его:



И вставьте в блокнот сразу после строки, которую вы скопировали раньше:



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

Получаем данные из таблицы

Кликните на интент Согласие и от него создайте новый HTTP-запрос.





Метод - GET.

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



На вкладке RESPONSE нажмите на + и в поле Имя переменной вставьте:
items
а в поле Значение вставьте:
$httpResponse
Вкладки BODY и HEADERS заполнять не нужно.

В итоге получится такой запрос:



Нажмите Сохранить.

Назовём этот экран:

ПОЛУЧАЕМ ВОПРОС



Вот что у нас получилось:



Получаем первый вопрос

Ранее мы добавили в HTTP-запрос переменную $items:



В переменной $items находится весь массив с фразами. Далее нам нужно взять из этого массива только первую фразу. Для этого будем использовать встроенные функции Aimylogic.

От варианта блока http-запрос Завершен успешно создаем новый блок Условия, в который пишем:

$items.first()


Назовём этот экран:

ПЕРВЫЙ ВОПРОС



Вот что у нас получилось:



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

Выводим первый вопрос

Чтобы вывести текст первого вопроса, соедините условие $items.first() с новым блоком Текст. В блоке Текст напишите:

Дополни такую фразу:



Назовём этот экран:

ВЫВОДИМ ВОПРОС



На этот же экран "ВЫВОДИМ ВОПРОС" добавьте ещё один блок Текст




и напишите в нём:
$items.current().question





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



Если вопрос не выводится, вернитесь к шагу 5 и убедитесь, что вы опубликовали страницу.

Если появляется ошибка или бот выводит не то, что в таблице, то убедитесь, что вы нигде не допустили опечатку.

Принимаем варианты ответов

Остановите тестирование.

Добавим на экран "ВЫВОДИМ ВОПРОС" блок Интенты. Создадим интент:

$answer



Этот интент будет принимать ответы, которые мы пропишем в справочнике сущностей.

Создадим справочник

Сохраните сценарий.


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



Кликните "Создать справочник":


Назовите справочник:
answer



Это название соответствует названию, которое мы ранее указали в интентах, это очень важно:



Нажмите Продолжить.



Перенесите в колонку "Сущность" содержание столбца answer вашей гугл-таблицы (можно копировать и вставлять).





Если названия в колонке Сущности будут не совпадать с текстом у вас в таблице, вы получите ошибку.

Подробнее о сущностях вы можете почитать здесь.

Нажмите Сохранить изменения.


Сравниваем ответ пользователя с правильным ответом

Вернитесь на вкладку "Сценарий".



От интента $answer создайте новый блок Условия




скопируйте и вставьте в этот блок Условия:

$answer === $items.current().answer


Eсли ввод пользователя попал в сущность $answer, ,бот перейдет к выполнению этого условия. И бот будет сравнивать содержание сущности $answer со строчкой из таблицы из столбца answer. Если введенное название сущности соответствует значению из таблицы, из колонки answer, то условие будет выполняться.

Назовём этот экран

СРАВНИВАЕМ ОТВЕТ



Объявим, что ответ правильный.

От блока Условия создайте новый блок Текст:

Да, это правильный ответ!



Назовём этот экран:

ПРАВИЛЬНЫЙ ОТВЕТ



Добавьте экран "ПРАВИЛЬНЫЙ ОТВЕТ" блок Переход:



Теперь от экрана "ВЫВОДИМ ВОПРОС" от варианта Любая другая фраза создайте новый экран с блоком Текст, содержащим:

А вот и неправильно!


Назовём этот экран:

НЕПРАВИЛЬНЫЙ ОТВЕТ



На экран "НЕПРАВИЛЬНЫЙ ОТВЕТ" добавьте еще один блок текст:

Попробуй ещё раз!


И блок Переход.



Cвяжите блок "Переход" с экрана "Неправильный ответ" с экраном "Выводим вопрос":



Соедините вариант else экрана "Сравниваем ответ" с экраном "Неправильный ответ":



Можем протестировать созданную часть сценария.

Нажмите Тестировать:

Скажите боту "да", затем введите правильный ответ - "ниже стола". Бот должен сказать, что ответ верный:


Перезапустите тестирование.

Скажите боту "да", затем введите неправильный ответ. Бот должен сказать, что ответ неверный:



Пока это всё, что бот умеет делать. Продолжим работать над сценарием.

Сохраним информацию об игроке

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



С помощью этого запроса отправим текущую информацию об игроке, его текущий уровень и счет.

Отправляем в ту же базу данных, откуда в начале сценария мы получали данные.
метод POST
url:
https://tools.aimylogic.com/api/data/${userId}
на вкладке BODY передаем нужные данные в таком формате (скопируйте и вставьте):

{
"level": "$items.current().level",
"score": "$items.current().score"
}



Вкладки RESPONSE и HEADERS заполнять не нужно.

Нажмите Сохранить.

Назовём этот экран:

СОХРАНИМ ПРОГРЕСС



Выводим следующий вопрос.

Если запрос завершается успешно, будем выводить следующий вопрос.

От варианта Завершен успешно создайте блок Условия.

Делаем условие, которое возьмет из массива $items следующий вопрос:

$items.next()



Назовём этот экран:

ВЫВОДИМ СЛЕДУЮЩИЙ ВОПРОС


От экрана "ВЫВОДИМ СЛЕДУЮЩИЙ ВОПРОС" делаем связь на экран "ВЫВОДИМ ВОПРОС":



Добавляем действие на случай, если есть история о пользователе

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

Вернемся в начало сценария. На экране "ЕСТЬ ЛИ ИСТОРИЯ?" от варианта Завершен успешно создайте новый блок Текст:

С возвращением! В прошлый раз мы дошли до уровня $history.level. Твой счет: $history.score. Продолжим?



Назовём этот экран:

ЕСЛИ ЕСТЬ ИСТОРИЯ



Добавим на экран "ЕСЛИ ЕСТЬ ИСТОРИЯ" блок Интенты. Добавим варианты реакций пользователя - готовые интенты Согласие и Отказ:




Получаем неотвеченные вопросы

От интента Отказ экрана "ЕСЛИ ЕСТЬ ИСТОРИЯ" создадим блок http-запрос.

Здесь нам снова нужно получить данные из гугл-таблицы, как обычно.

метод GET

url может быть таким же, как в блоке HTTP-запрос "Получаем вопрос"




на вкладке RESPONSE нажмите на + и в поле Имя переменной вставьте:
items
а в поле Значение вставьте:
$httpResponse.slice(parseInt($history.level))



Давайте разберемся, что значит это выражение в блоке Значение:

slice - возвращает новый массив, содержащий копию части исходного массива, parseInt - преобразует строку в число.

$history.level - уровень, на котором остановился пользователь. Получится, что мы откинем часть массива, а значит, выведем пользователю только те фразы, на которые он еще не давал ответ.

Нажмите Сохранить.


Назовём этот экран:

НЕОТВЕЧЕННЫЕ ВОПРОСЫ



Связываем вариант Завершен успешно экрана "НЕОТВЕЧЕННЫЕ ВОПРОСЫ" с экраном "Первый вопрос".



Добавим распознавание желания начать новую игру

Осталось дать возможность пользователю начать новую игру.

Добавим блок Интенты в любое место сценария:





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



Добавим интент:

* нов* игр* *



Этот интент будет ловить такой ввод, как "новая игра", "новую игру", "начать новую игру", "хочу новую игру", "новую игру давай" и т.д. Подробнее читайте в статье о синтаксисе шаблонов.

Назовём экран:
ГЛОБАЛЬНЫЙ ИНТЕНТ



От интента * нов* игр* * создадим новый блок http-запрос, с помощью которого будем удалять данные о пользователе:

выберите метод DELETE и
в поле URL скопируйте данную ссылку:
https://tools.aimylogic.com/api/data/${userId}


нажмите Сохранить.

Назовём этот экран:

УДАЛЯЕМ


Так мы очистим все данные об этом игроке.

От варианта Завершен успешно экрана "УДАЛЯЕМ" делаем связь с экраном "ЕСЛИ НЕТ ИСТОРИИ"



Добавим сообщение об успешном завершении игры

Найдите экран "ВЫВОДИМ СЛЕДУЮЩИЙ ВОПРОС". От варианта else создайте блок Текст:

Поздравляю, игра пройдена! Хочешь сыграть ещё?


Это сообщение будет выводиться, если вопросов больше не осталось.

Назовём этот экран:

ИГРА ОКОНЧЕНА



На экран "ИГРА ОКОНЧЕНА" добавьте блок Интенты и добавьте возможные варианты ответа, например, готовые интенты "Согласие" и "Отказ":



Свяжите интент "Согласие" с блоком HTTP-запрос "Получаем вопрос", на котором обращаемся к гугл-таблице.




С экрана "ПЕРВЫЙ ВОПРОС" свяжите вариант else с экраном "ИГРА ОКОНЧЕНА"





Игра готова!

Вот что у нас получилось. Скачайте изображение, чтобы увидеть крупнее.





Можете нажать кнопку Тестировать и проверить, как это работает:

Что дальше?

Мы составили набросок сценария. Можно сделать бота более работоспособным и "живым".

Дополните сценарий:

везде, где есть вариант "любая другая фраза" свяжите этот вариант либо с этим же экраном, либо с текстовым блоком, в котором дайте пользователям инструкцию на тот случай, если они вводят не то, что вы от них ожидаете. Если не связать вариант "Любая другая фраза" ни с чем, то бот будет отвечать "Извините, непонятно" на ввод, который не попадает в варианты Интентов.
дополните примеры интентов другими возможными словами, которые пользователи могут написать на соответствующем этапе сценария
добавьте кнопки
дополните речь бота другими репликами;
добавьте кнопку Новая игра на экран "С возвращением!"
В некоторых HTTP-запросах вариант "Завершен с ошибкой" на имеет связи с текстовыми блоками. Свяжите варианты "Завершен с ошибкой" с текстовым блоком, содержащим текст:

Ошибка $httpStatus

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

$history.level == 5


else свяжите с экраном "ЕСЛИ ЕСТЬ ИСТОРИЯ"



А само условие свяжите с экраном "ИГРА ОКОНЧЕНА"





Подключите один из каналов, например, Telegram или вк.





Возникли сложности?

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

Также можете попросить совета в нашем сообществе в телеграме: https://t.me/aimylogic
Была ли эта статья полезна?
отменить
Спасибо!