-
Notifications
You must be signed in to change notification settings - Fork 1
LOG: Romutchio
- Постановка задачи / проблема на весь проект. (Может быть общая у всех из команды)
- Постановка своей собственной задачи (индивидуально).
- Описание архитектуры решения (может быть общая у всей команды).
- Подробное описание своего участка работы.
- Скриншоты или что-то подобное, что демонстрирует, как вся эта штуковина работает в сборе. (общая для всей команды).
- Литература - может быть общая, может быть нет.
Если у вас вдруг не было четкого разделения на области ответственности, то разделите постфактум, кто про что пишет. Общие части можете вместе написать. В отчете явно укажите, что делали проект вместе, а в п.2 и 4 явно укажите, что это > > ваша индивидуальная часть в команде.
- В обучении есть темы, которые нужно закреплять практикой. Каждому студенту требуется свое количество практики. Одна из таких тем - это оценка сложности алгоритмов.
- Студенты не всегда готовы выделить время за компьютером для дополнительной практики, но готовы тренироваться по несколько минут в день на телефоне, в моменты, когда есть свободное время без доступа к полноценному компьютеру. Сейчас они тратят это время на соц-сети, а могут тратить на обучение.
- Сделать бота для телеграмма, который позволит тренироваться в оценке сложности алгоритмов в свободное время прямо на своем телефоне. Для этого разработать механику, плавного увеличения сложности задач, с учетом успеваемости пользователя. Задания должны быть каждый раз уникальными и генерироваться на лету, чтобы исключить возможность запоминания уже увиденных вариантов.
- Обобщить бота так, чтобы его можно было использовать для других тем, отличных от оценки сложности алгоритмов.
- Обобщить код так, чтобы незначительными доработками можно было сделать его доступным через другие платформы для чат-ботов.
Грамотное создание диалогов -- весьма нетривиальная задача. Архитектурным решением данной задачи является конечный трансдьюсер.
Конечный трансдьюссер - шестерка (Q, Σ, ∆, δ, q0, F), где:
- Q — конечное множество состояний (в данном проекте - Сущность State),
- Σ —конечное множество входных символов (сообщения пользователя, колбеки кнопок),
- ∆ —конечное множество выходных символов (заготовленные ответы бота),
- δ ⊂ Q×Σ∗×∆∗×Q —конечное множество переходов (сущность Transition),
- q0 ∈ Q —начальное состояние,
- F ⊂ Q —множество заключительных состояний.
Ниже приведен автомат, визуализирующий данный трансдьюссер.
Общаться с серверами Telegram бот может двумя способами:
- getUpdates - pull: ваш бот постоянно дёргает сервер Telegram и проверяет есть ли новые сообщения;
- setWebhook - push: по мере поступления новых сообщений сервер Telegram отправляет их вашему боту.
Разницу можно изобразить следующим образом:
Очевидно, что второй способ setWebhook рациональнее для всех участников процесса.
Наш проект довольно объемный, уже на данный момент написана большая кодовая база. Моя основная задача в данном проекте - создание слоя визуальной части сервиса - Telegram бот.
- Все задания разбиты на уровни. Уровень определяет тему заданий. Чтобы пройти уровень, нужно заполнить прогрессбар уровня до конца. Level 1️⃣. Progress: 🔘🔘🔘🔘⚫️
- Внутри уровня много генераторов. Каждый генератор объявляет сколько ячеек прогресс бара он добавляет. Корректный ответ — +1, Ошибка — -1, но только если правильных ответов на задачи этого генератора больше, чем неправильных.
- Прохождение уровня может открывать возможность прохождения других уровней.
- В любой момент можно перейти на любой из открытых уровней и продолжить упражняться там.
- При неудачном ответе можно запросить объяснения.
- State - Состояние - тот же смысл, что и в Теории Автоматов
- Transition - Переход
- Command - Команда - действие, совершаемое при осуществлении перехода в следующее состояние.
Ниже представлен граф наследования, демонстрирующий существующие
Состояния, Переходы и Команды
:
public interface IStateMachine<TCommand>
{
(State state, TCommand command) GetNextState<TState, TTransition>(TState currentState, TTransition transition)
where TState : State where TTransition : Transition;
}
Данный метод принимает текущее состояние и переход, по которому мы в него попали. На основе этого, StateMachine выдает новое состояние в ДКА.
public (State state, ICommand command) GetNextState<TState, TTransition>(
TState currentState,
TTransition transition) where TState : State where TTransition : Transition
{
switch ((state: currentState, transition: transition))
{
case var t when t.transition is HelpTransition:
return (new TopicSelectionState(), new SelectTopicCommand());
case var t when t.transition is FeedbackTransition:
return (new TopicSelectionState(), new FeedBackCommand());
case var t when t.state is UnknownUserState:
return (new TopicSelectionState(), new SelectTopicCommand());
case var t when t.state is ReportState reportState:
return ProcessReportState(reportState, t.transition);
case var t when t.state is TopicSelectionState topicSelectionState:
return ProcessTopicSelectionState(topicSelectionState, t.transition);
case var t when t.state is LevelSelectionState levelSelectionState:
return ProcessLevelSelectionState(levelSelectionState, t.transition);
case var t when t.state is TaskState taskState:
return ProcessTaskState(taskState, t.transition);
}
return default;
}
[Route("api/[controller]")]
public class UpdateController : Controller
{
// POST api/update
[HttpPost]
public async Task<IActionResult> Post([FromBody] Update update)
{
Chat chat = null;
switch (update.Type)
{
case UpdateType.Message:
chat = update.Message.Chat;
break;
case UpdateType.CallbackQuery:
chat = update.CallbackQuery.Message.Chat;
await botService.Client.AnswerCallbackQueryAsync(update.CallbackQuery.Id);
break;
default:
return Ok();
}
var userCommand = updateService.ProcessMessage(update);
var serviceManager = new ServiceManager(quizService, userRepository, logger);
await userCommand.ExecuteAsync(chat, botService.Client, serviceManager);
return Ok();
}
}
Было принято решение писать бота на основе WebHook, поэтому по мере поступления новых сообщений сервер Telegram отправляет их нашему боту.
public interface IUpdateService
{
ICommand ProcessMessage(Update update);
}
public ICommand ProcessMessage(Update update)
{
var userEntity = userRepository.FindByTelegramId(userId) ??
userRepository.Insert(new UserEntity(new UnknownUserState(), userId, Guid.NewGuid(), 0));
var state = userEntity.CurrentState;
var transition = parser.Parse(state, update, quizService, logger);
var (currentState, currentCommand) = stateMachine.GetNextState(state, transition);
userRepository.Update(new UserEntity(currentState, userId, userEntity.Id, userEntity.MessageId));
return currentCommand;
}
Поскольку пользователей телеграм необходимо где-то хранить, была выбрана база данных MongoDB. Для удобного использования, был написан репозиторий, реализующий работу с ней:
using System;
using MongoDB.Driver;
namespace QuizBotCore.Database
{
public class MongoUserRepository : IUserRepository
{
public const string CollectionName = "telegramUsers";
private readonly IMongoCollection<UserEntity> userCollection;
public MongoUserRepository(IMongoDatabase database)
{
userCollection = database.GetCollection<UserEntity>(CollectionName);
}
public UserEntity Insert(UserEntity user)
{
userCollection.InsertOne(user);
return user;
}
public UserEntity FindById(Guid id)
{
return userCollection.Find(u => u.Id == id).SingleOrDefault();
}
public UserEntity FindByTelegramId(long telegramId)
{
return userCollection.Find(u => u.TelegramId == telegramId).SingleOrDefault();
}
public void Update(UserEntity user)
{
userCollection.ReplaceOne(u => u.Id == user.Id, user);
}
public void Delete(Guid id)
{
userCollection.DeleteOne(u => u.Id == id);
}
public UserEntity UpdateOrInsert(UserEntity user)
{
userCollection.ReplaceOne(u => u.Id == user.Id, user, new UpdateOptions {IsUpsert = true});
return user;
}
}
}
- Приветственное сообщение
- Обратная связь (вызов посредством команды /feedback)
- Выбор уровня
- Отображение задачи
- Сообщение после прохождение уровня
- Пользователь нажал на кнопку "Пожаловаться на задачу" и сообщил об ошибке:
- После репорта, сообщение прилетает в специальный чат в таком виде:
http://kadm.imkn.urfu.ru/files/shurzam.pdf
https://telegrambots.github.io/book/