Как сохранять информацию о пользователе | Викторина | База данных
Потребность
Бот должен уметь сохранять информацию о пользователе: когда пользователь зайдет повторно в нашего бота, то сможет начать с того м еста, где остановился в предыдущий раз.
Решение
Для примера сделаем небольшую игру «Логические концовки». Вы можете поговорить с этим ботом в Telegram по адресу @Logic_check_bot. Посмотреть на сценарий вы можете здесь.
Как это работает
- Запрашиваем данные об игроке
В начале сценария нам нужно запросить данные об игроке. Для этого у нас должна быть создана какая-то база данных, в которой эти данные будут сохраняться и из которой их можно будет получить. Воспользуемся нашим сервисом для сохранения, удаления и чтения данных.
В сценарии создайте первый экран, добавьте на него блок HTTP-запрос:
- метод — GET * в поле URL вставьте данный адрес:
https://tools.aimylogic.com/api/data/${userId}
- На вкладке RESPONSE нажмите на + и в поле Имя переменной вставьте:
history
, а в поле Значение вставьте:$httpResponse
- Вкладки BODY и HEADERS заполнять не нужно.
- Нажмите Сохранить.
- Для удобства добавим на этот экран метку
ЕСТЬ ЛИ ИСТОРИЯ?
Если данные об игроке будут, то они сохранятся в переменную $history, запрос завершится успешно, и мы сможем оперировать этой переменной. Если же данных нет, то запрос завершится с ошибкой — это будет значить что пользователь к нам пришел первый раз.
- Если пользователь у нас впервые
-
От блока http-запрос Завершен с ошибкой сделаем новый экран с блоком Текст:
Привет! Это игра логические концовки. Вооружись логическим мышлением! В этой игре нужно правильно закончить фразы. Ну что, начнем?
-
Назовем этот экран
ЕСЛИ НЕТ ИСТОРИИ
- Добавим варианты ответов пользователя
- Добавим на экран «ЕСЛИ НЕТ ИСТОРИИ» блок Интенты.
- Добавим готовый интент Согласие.
- Сохраним блок
Вот что у нас получилось:
- Оформим таблицу, в которой будем хранить содержание игры
Пример таблицы вы можете посмотреть здесь. Можете просто скопировать эту таблицу.
После того, как пользователь согласился сыграть в игру, нужно дать ему первый вариант фразы, которую нужно продолжить. Фразы мы будем сохранять в Google Таблице.
Выглядеть таблица будет следующим образом:
- В таблице должно быть 4 столбца с названиями:
question
answer
level
score
- Заполните таблицу следующим содержанием, как видно на скриншоте выше:
question | answer | level | score |
---|---|---|---|
Если стол выше стула, то стул… | ниже стола | 1 | 10 |
Если два больше одного, то один… | меньше двух | 12 | 20 |
Если сестра старше брата, то брат… | младше сестры | 3 | 30 |
Если правая рука справа, то левая… | слева | 4 | 40 |
Если река глубже ручейка, то ручеек… | мельче реки | 5 | 50 |
- Колонки
Level
иScore
помогут нам возвращать пользователя к тому месту, где мы остановились, и также выводить счет, так что они должны содержать соответствующие числовые значения.
-
Обязательно опубликуйте вашу таблицу:
Файл → Опубликовать в интернете → Опубликовать → Ок → Закройте всплывающее окно.Путь из всплывающего окна копировать не нужно.
-
Откройте блокнот и скопируйте в него строку:
https://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 вашей Google Таблицы (можно копировать и вставлять).
Подробнее о сущностях вы можете почитать здесь.
- Нажмите Сохранить изменения.
- Сравниваем ответ пользователя с правильным ответом
- Вернитесь на вк ладку «Сценарий».
- От интента
$answer
создайте новый блок Условия
скопируйте и вставьте в этот блок Условия:
$answer === $items.current().answer
Если ввод пользователя попал в сущность $answer, бот перейдет к выполнению этого условия. И бот будет сравнивать содержание сущности $answer со строчкой из таблицы из столбца answer. Если введенное название сущности соответствует значению из таблицы, из колонки answer, то условие будет выполняться.
- Назовем этот экран
СРАВНИВАЕМ ОТВЕТ
- Объявим, что ответ правильный.
- От блока Условия создайте новый блок Текст:
Да, это правильный ответ!
- Назовем этот экран:
ПРАВИЛЬНЫЙ ОТВЕТ
- Добавьте экран «ПРАВИЛЬНЫЙ ОТВЕТ» блок Переход:
Теперь от экрана «ВЫВОДИМ ВОПРОС» от варианта Любая другая фраза создайте новый экран с блоком Текст, содержащим:
А вот и неправильно!
- Назовем этот экран:
НЕПРАВИЛЬНЫЙ ОТВЕТ
- На экран «НЕПРАВИЛЬНЫЙ ОТВЕТ» добавьте еще один блок текст:
Попробуй еще раз!
И блок Переход.
Свяжите блок «Переход» с экрана «Неправильный ответ» с экраном «Выводим вопрос»:
Соедините вариант else экрана «Сравниваем ответ» с экраном «Неправильный ответ»:
- Можем протестировать созданную часть сценария.
Нажмите Тестировать:
Скажите боту «да», затем введите правильный ответ — «ниже стола». Бот должен сказать, что ответ верный:
Перезапустите тестирование.
Скажите боту «да», затем введите неправильный ответ. Бот должен сказать, что ответ неверный:
Пока это все, что бот умеет делать. Продолжим работать над сценарием.
- Сохраним информацию об игроке
Когда пользователь ответил верно, нужно дать ему следующую фразу. Но перед тем, как выводить следующую фразу, от блока Переход с экрана «Правильный ответ» создадим блок HTTP-запрос
С помощью этого запроса отправим текущую информацию об игроке, его текущий уровень и счет.
Отправляем в ту же базу данных, откуда в начале сценария мы получали данные.
-
метод POST URL:
https://tools.aimylogic.com/api/data/${userId}
-
на вкладке BODY передаем нужные данные в таком формате (скопируйте и вставьте):
{ "level": "$items.current().level", "score": "$items.current().score"}
-
Вкладки RESPONSE и HEADERS запол нять не нужно.
-
Нажмите Сохранить.
-
Назовем этот экран:
СОХРАНИМ ПРОГРЕСС
- Выводим следующий вопрос.
Если запрос завершается успешно, будем выводить следующий вопрос.
От варианта Завершен успешно создайте блок Условия.
Делаем условие $items.next()
, которое возьмет вопрос из массива $items
- Назовем этот экран
ВЫВОДИМ СЛЕДУЮЩИЙ ВОПРОС
От экрана «ВЫВОДИМ СЛЕДУЮЩИЙ ВОПРОС» делаем связь на экран «ВЫВОДИМ ВОПРОС»:
- Добавляем действие на случай, если есть история о пользователе
Теперь нужно сделать так, чтобы на следующей сессии (например, при следующем запуске навыка в Алисе) мы узнавали пользователей и возвращали их на то место, где они остановились в последний раз.
- Вернемся в начало сценария. На экране «ЕСТЬ ЛИ ИСТОРИЯ?» от варианта Завершен успешно создайте новый блок Текст:
С возвращением! В прошлый раз мы дошли до уровня $history.level. Твой счет: $history.score. Продолжим?
- Назовем этот экран
ЕСЛИ ЕСТЬ ИСТОРИЯ
-
Добавим на экран «ЕСЛИ ЕСТЬ ИСТОРИЯ» блок Интенты. Добавим варианты реакций пользователя — готовые интенты Согласие и Отказ:
- Получаем неотвеченные вопросы
От интента Отказ экрана «ЕСЛИ ЕСТЬ ИСТОРИЯ» создадим блок http-запрос.
Здесь нам снова нужно получить данные из Google Таблицы, как обычно.
-
метод 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-запрос «Получаем вопрос», на котором обращаемся к Google Таблице.
-
С экрана «ПЕРВЫЙ ВОПРОС» свяжите вариант else с экраном «ИГРА ОКОНЧЕНА»
Игра готова!
Вот что у нас получилось. Скачайте изображение, чтобы увидеть крупнее.
Можете нажать кнопку Тестировать и проверить, как это работает:
Что дальше?
Мы составили набросок сценария. Можно сделать бота более работоспособным и «живым».
Дополните сценарий:
-
везде, где есть вариант «любая другая фраза» свяжите этот вариант либо с этим же экраном, либо с текстовым блоком, в котором дайте пользователям инструкцию на тот случай, если они вводят не то, что вы от них ожидаете. Если не связать вариант «Любая другая фраза» ни с чем, то бот будет отвечать «Извините, непонятно» на ввод, который не попадает в варианты Интентов.* дополните примеры интентов другими возможными словами, которые пользователи могут написать на соответствующем этапе сценария* добавьте кнопки* дополните речь бота другими репликами;
-
добавьте кнопку Новая игра на экран «С возвращением!»
-
В некоторых HTTP-запросах вариант «Завершен с ошибкой» на имеет связи с текстовыми блоками. Свяжите варианты «Завершен с ошибкой» с текстовым блоком, содержащим текст:
Ошибка $httpStatus
-
можете добавить обращение к пользователю по имени, как описано в этой статье.
-
В каждом текстовом блоке вы можете добавить другие варианты текста, нажав на «Добавить другую реплику». Тогда бот будет выдавать разные варианты фраз в случайном порядке и не будет повторяться.
-
Можете добавить в реплики бота смайлики, скопировав их отсюда.* Можете добавить экран, на котором бот будет прощаться с пользователем, если пользователь отказался играть, написал «хватит» или «пока».
-
Вы также можете добавить в начало сценария еще один блок условий, который будет проверять, не на последнем ли уровне остановился пользователь в прошлый раз.
$history.level == 5
else
свяжите с экраном «ЕСЛИ ЕСТЬ ИСТОРИЯ»
А само условие свяжите с экраном «ИГРА ОКОНЧЕНА»
Возникли сложности?
Вы можете обратиться в поддержку за помощью. При обращении предоставьте скриншот переписки с ботом (скриншот ошибки или скриншот, иллюстрирующий, в каком месте сценария находится сложность), скопируйте лог ошибки, если он есть. Сообщите email, прикрепленный к аккаунту и название сценария. С удовольствием вам поможем!
Также можете попросить совета в нашем сообществе в Telegram: https://t.me/aimylogic