Оглавление

Предисловие

Описание

Scipio - это telegram-bot, который позволяет пользователям решать задачи по математике, логике, создавать свои собственные карточки, ставить запуск тренировки в определенное время - в общем, обучаться.

Откуда идея?

Летом 2020 года возникла идея, что нужно создать некую программу, которая помогала бы людям тренироваться решать примеры в уме (Например: перемножить числа 28 и 73 или возвести во вторую степень число 34) - это нужно, чтобы при решении математических и не только математических задач не отвлекаться на базовые примеры и решать их быстро и без проблем.

Почему я вообще решил, что нужна программа, разве обычной теории и простой тренировки не хватит?

Ответ на это - нет, не хватит. Чтобы получить любой навык и достичь в нём совершенства, нужна ежедневная, упорная практика.

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

Почему Telegram бот?

Создание отдельный программы для телефона и для компьютера заняла бы слишком много времени. После размышления о различных вариантах появилась идея о создании telegram-бота.

Почему это было отличным решением? Потому что:

  • Сам алгоритм бота будет общим для любого пользователя и работать как на компьютере, так и на любых телефонах

  • Через ботов очень удобно взаимодействовать с пользователями. Если пользователю нужно получить какую-то информацию, ему нужно просто отправить боту сообщение

  • Telegram в данный момент является одним из самых популярных, самых быстроразвивающихся и самых технологически хороших мессенджеров. + из-за последних событий популярность telegram устремилась вверх с огромными темпами

  • 99% ботов в telegram написаны на языке python. Я не только активно применял данный язык в работе, но и хотел просто усовершенствовать свои навыки.

Почему именно ScipIO?

Название ScipIO не просто так. Cоздатель увлекается историей древнего Рима, а в ней Scipio (Сципион) был великим полководцем, который победил самого Ганнибала, а также в программировании (и в особенности в телеграмме) есть одно из основных понятий IO (input-output), которое значит ввод-вывод. Это способ взаимодействия программы с другими ее частями, или со внешним миром, а конкретнее с сервером.

План

Почему без плана нельзя?

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

  • Уйдёт слишком много времени на создание проекта

  • Вы сделали не то, что хотели или не сделали вовсе

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

Сам план

Первоначальный план бота состоял в том, чтобы сделать следующий функционал:

  1. Mentally math (тренировка подсчета в уме)

  2. category_math, category_logic (задачи по математике и логике)

  3. Timer (Запуск тренировки в определенное время по желанию пользователя)

После выполнения данных пунктов, возникли идеи уже для следующих алгоритмов:

  1. flashcards - тренировка по карточкам. С одной стороны написано слово и вы должны назвать слово с обратной стороны

  2. statistics (для пользователей) - статистика решенных задач пользователя

  3. admin панель:

    • Отправка сообщения всем пользователям

    • Статистика количества пользователей

Инструмент для плана

Чтобы не путаться в плане и задачах, я создал доску trello. Это отличный инструмент, т.к. он позволяет чётко и подробно составлять задачи, ставить цели и позволяет всей команде очень удобно просматривать задачи.

Если интересно, то таблица по-итогу выглядит так:

Подготовка

Сесть за проект нельзя было так сразу и так просто, поэтому перед написанием была проведена подготовка:

  • Python - тут проблем особенно не возникло, т.к. он уже был знаком мне. Тем не менее, для повторения (и укрепления) знаний была перечитана книжка Марка Лутца "Изучаем python".

Также выдам ссылку на просмотр файла, в который я сохранял полезные ссылки и вырезки по python, пока повторял всё нужное (все ссылки находятся в Полезной литературе).

  • Асинхронность, а также многопроцессорность и многопоточность - чтобы правильно работать с aiogram, нужно обязательно уметь взаимодействовать с асинхронностью (Не буду описывать что это значит и т.д., всё подробнее есть в полезных ссылках). Также я думал, что может пригодится уметь взаимодействовать с многопроцессорностью и многопоточностью, но пока в первых релизах бота оно не потребовалось

  • Aiogram - это асинхронный python фреймворк для создания telegram-ботов. В качестве подготовки было написано несколько маленьких ботов, которые выполняли ту или иную функцию.

И кстати, я всем советую так подготавливаться, поскольку при прочтении теории может сложиться впечатление, что вы всё знаете и понимаете, но сразу при создании основного бота будете сильно путаться и тупить. Избежать этого как раз и поможет создание маленьких ботов.

  • Sql, beatifulsoap, matplotlib, pillow - все эти вещи были изучены или повторены уже при процессе написания бота. Это не те инструменты, для базового осознания которых требуется отдельно выделять время для изучения, и вы вполне можете их освоить уже в процессе.

Основная часть

Далее рассказывается о самой работе наших алгоритмов и т.д. Тут не будет подробного технического объяснения функционала, т.к. всё более подробное содержится в ReadMe нашего проекта или в комментариях кода.

База данных

Сначала БД нужна была нам, чтобы сохранять задачки по математике (category_math) и логике. В дальнейшем база данных стала расширяться, т.к. появились потребности сохранять telegram_id пользователей, карточки пользователей и т.д.

Sqlite

Sqlite был выбран, потому что это отличная СУБД для начала. Поддерживаются простые sql запросы (если хотите, можно также воспользоваться инструментом SQLAlchemy) и очень удобная программа на компьютере, позволяющая просматривать данные и взаимодействовать с БД.

Но мы крайне не рекомендуем использовать Sqlite, когда вы уже запускаете проект для большого количества пользователей, т.к. Sqlite может быть и простой, но это локальная база данных и мерджить БД в git приходится вслепую.
По возможности постарайтесь сразу изучить PostgreSQL, т.к. он технически более развит и намного функциональнее.

Таблица

Описание

actions

Таблица действий пользователя. Например, при выполнении flc, выполняется функция action_add(message.from_user.id, 'flc'), которая добавляет данные в таблицу

category

Категории заданий

flashcards

Карточки пользователей

task_logic

Задачи по категории логика

task_math

Задачи по категории математика

time

Таймеры пользователей

users

Все пользователи, пользующиеся ботом

Более подробное описание БД находиться в README

Mentally math

Как и говорилось, проект был изначально создан для алгоритма тренировки математических примеров, поэтому первой функцией Scipio стал /mentally_math.

Функция работает так: у пользователя спрашивается готов ли он, а потом (если пользователь нажал “Да”) пользователю генерируется и присылается пример. Пользователь решает некоторое количество задач, и когда он нажимает на кнопку “Закончить примеры в уме”, бот присылает статистику (в неё входят id задач, правильные ответы на них, кол-во попыток понадобившихся на решение примера). Если пользователь хочет изучить или повторить теорию для решения примеров счета в уме, он должен прописать в бота /mell_theory.

Кратное техническое описание алгоритма Mentally math

Основной алгоритм очень схож с (flashcards_training), но у него есть некоторое отличие, а именно алгоритм требует постоянно проверять ввод пользователя (ответ).

/mentally_math - это тренировка счёта в уме. В зависимости от того, генерируется степень или умножение, диапазон чисел варьируется, но точнее он такой:
- Для умножения берётся 2 рандомных числа в диапазоне 11 - 99
- Для степени берётся 1 рандомное число от 11 - 99 и возводится в степень 2

Task category

Задачи по категориям - это функционал, с помощью которого пользователи могут сами решать задачи из выбранных категорий бота. Например, если пользователь зайдёт в “категории по математике” и выберет основную категорию “Алгебра”, а после выберет подкатегорию "Последовательности", то ему пришлёт задание из категории “Последовательности”, которое пользователь сам прорешивает, а потом сверяется с “Ответом”, а если непонятно, то смотрит на “Решение 1” или “Подсказка”.

Нам нужно было каким-то образом получить большое количество задач. И мы нашли решение - парсинг.

Парсинг всех заданий производился с помощью ряда библиотек:

  1. BeautifulSoup - основная библиотека, с помощью которой происходил парсинг

  2. generate_user_agent - библиотека каждый раз генерировала разный user_agent, который помогал обходить блокировку со стороны сайта. После того, как задача была спарсена, мы добавляли её в json-файл.

После того, как задача была спарсена, мы добавляли её в json-файл. Делалось это для того, чтобы:

  1. Если бы что-то случилось с БД, мы могли легко перенести всё обратно

  2. При желании все эти json файлы можно было бы продать.

Когда json-файлы были созданы, всё было перенесено в БД

  • Первая версия задач имела 631 математическую задачу

  • Вторая версия задач имеет около 6000 мат. задач и около 1000 различных логических заданий

Кратное техническое описание алгоритма task category

Функция работает так: бот проходится по таблице с математическими задачами и выводит все имеющиеся категории в виде inline кнопок. Когда пользователь выбирает категорию, программа берет из данной категории рандомную задачу и показывает её пользователю. При нажатии “Следующая задача” алгоритм срабатывает циклически, выводя другую задачу из той же категории.

Flashcards

Как объяснить концепцию карточек? Всё просто - вы когда-нибудь видели такие карточки, где на одной стороне например написано cat, а на другой стороне показан перевод слова? Вот такая же идея у этого функционала.

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

Тренировка работает так. Если пользователь отметил “Правильно”, то при дальнейшей тренировке эта карточка показываться больше не будет , а если “Неправильно”, то наоборот будет показываться. Тренировка не закончится, пока пользователь или не закончит сам тренировку, или все карточки не будут отмечены “Правильно”.

Отличия 1 версии и 2 версии:

В первой версии карточки присылались в виде обычного текста.

Во второй версии карточки приходят в виде фото.

Кратное техническое описание алгоритма flashcards

Основная идея данного алгоритма в том, что из-за того что всё происходит в основной функции, то при нажатии "Правильно" и "Неправильно" следующее что делает функция flc_game, это создаёт новую flashcard и вызывает саму себя. Из-за этого алгоритм после "Правильно"/"Неправильно" сразу создаёт новую flashcard и показывает её, не требуя ввести сообщение от пользователя.

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

Timer

Сама идея таймера очень проста. Пользователю в назначенное им время должно приходить уведомление о том, что необходимо пройти “Ежедневное задание” по 1 из 4 выбранной им категорий заданий (категории логика, категории математика, карточки, примеры в уме).

Технически таймер выглядит так:
При запуске бота запускается таймер, который каждые 60 секунд проверяет по БД, есть ли какой-то таймер пользователя в данное время, и если есть, то отправляет сообщение с ежедневным заданием пользователю, который этот таймер и создал.

1 версия таймера

1 версия таймера была разработка вручную и основывалась на функции asyncio.sleep(60), которая асинхронно ждала и запускала блок проверки времени now со таймерами пользователей.

Но у неё была основная проблема, которая заключалась в том, что таймер запускался только тогда, когда администратор пропишет специальную команду, а не одновременно с запуском команды.

Почему нельзя было засовать эту функцию одновременно с запуском бота, то есть в if __name__ == "__main__":

Потому что, если запустить функцию таймера до asyncio.run(main()), то она блокирует работу всего бота (т.к выполняется бесконечно), а если после, то таймер просто не запускается, т.к выполняется работа бота

2 версия таймера

2 версия таймера была намного лучше, т.к основывается на библиотеке apscheduler, которая удобно и гибко позволяет проводить настройки асинхронного таймера и решает проблему с одновременным запуском бота и таймера.

Статистика

Этот функционал создан, чтобы подробнее показывать статистику решёных задач пользователю. А именно:

  • Пользователь запускает /statistics, которое показывает:

    • Количество показов flc, cat_math, cat_logic, ment_math пользователя за всё время

    • Составляет круглую диаграмму по данным выше

    • Составляет диаграмму bar действий разных типов actions пользователя за неделю

Работа данного алгоритма основана на библиотеке matplotlib, которая позволяет строить подробные и функциональные графики.

*более подробное техническое описание находится в коде проекта, а именно в файле handlers/statistics/charts.py *

admin

Админ панель.

В нее входит две функции:

  1. Отправка сообщения всем - для информирования пользователей telegram бота. Данная функция перебирает всех пользователей из базы данных и отправляет каждому сообщение, набранное админом

  2. Статистика пользователей - показывает количество пользователей, сколько новых пользователей за день, за прошедшие 7 дней и за прошедшие 30 дней.

Сервер

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

В качестве первого (тестирующего) сервера - был Raspberry Pi. Его плюсы заключались в том, что:

  • Raspberry Pi - предназначен для начинающих, а соответственно вся настройка в нём происходила интуитивно понятно

  • Это хоть и маленький, но достаточно мощный компьютер. Конкретно у меня raspberry Pi имеет 4 гб оперативной памяти, что очень хорошо

  • То что оно было под рукой, уже тоже плюс

Но Raspberry нельзя было использовать в качестве постоянно сервера, потому что:

  1. Зависело от электричество дома, в котором я живу

  2. Могло перегреться или просто не выдержать нагрузки и полететь

  3. Для серьёзного сервера и для дальнейшей работы не подходило

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

Таким сервисом оказался Google Cloud. Почему именно он? Потому что:

  1. Это серьезный инструмент, навык владения которым поможет в дальнейшей работе.

  2. Сервера удаленные, и поэтому если ляжет мой сервер из-за электричества, то ляжет пол мира.

  3. Есть гибкая настройка сервера, поэтому если не будет хватать мощностей, то можно будет просто обновить сервер

  4. Google Cloud - оказался бесплатным на 3 месяца, что стало ещё одним отличным плюсом для нас.

В данный момент сам сервер выглядит вот так:


А это нагрузка сервера:

Заключение

Что удалось сделать

На данный момент, наш бот имеет:

  • более 4000 различных задач (категории логики и математики), которые можно решать пользователю

  • функционал flashcard, который позволяет пользователям самим создавать все карточки и проходить тренировку по ним

  • функционал mentally_math, который позволяет тренировать подсчёт в уме.

  • функционал timer, напоминающий о "Ежедневных тренировках"

  • функционал statistics, показывающий статистику о прорешёных задачах пользователя

  • Функционал admin, отправляющий сообщения всем пользователям, а также позволяющий просматривать администраторам статистику о новых и о всех имеющихся пользователях

  • Понятный код и ReadMe файл, который позволяет разработчикам удобно повзаимодействовать с кодом

Будущее

В будущем наш проект будет развиваться и мы хотим сделать для него:

  • Удобную Базу Данных. А именно полностью перейти на Postgresql

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

  • Удобную панель управления для администраторов и модераторов задач.

  • Сделать различные наборы карточек(flashcards).

  • И много чего другого

Благодарности и пару красивых слов

Отдельно хочется выразить благодарность MasterGroosha и сообществу aiogram, без них этого проекта не было бы.

Пользуйтесь нашим ботом: t.me/scipio_edu_bot
Переходите в GitHub, чтобы попробовать пошаманить с ботом или помочь нам
Переходите в наш telegram-канал (он будет развиваться, зуб даю): https://t.me/scipio_edu_channel

Команда разработчиков:

  • Андрей Тощаков - создатель проекта, основной разработчик (ник в telegram: @Endrey_k)

  • Ахмед Шагбанов - основной разработчик (ник в telegram: @ShagbanovAhmed)

  • Татьяна Самохвалова - многочисленная помощь в редактировании, коррекции данных и т.д

  • Жанна Клыпо - за создание "оформления" бота (логотип, бэкграунды и т.п)

Просьба о помощи

Поскольку наш бот развивается и много чего там работает плохо или не работает вообще, то мы крайне ждём от вас помощи, советов и т.д. Для связи пишите в личку Андрея, Ахмеда или переходите на наш GitHub

Полезная литература

Есть список полезных ссылок от официального aiogram сообщества и от MasterGroosha

Aiogram:

Чаты

Комментарии (3)


  1. AndryPetrov
    30.03.2022 10:52

    Спасибо за статью, очень интересный проект.)


    1. Endrey_cot Автор
      30.03.2022 19:06
      +1

      Спасибо большое за отзыв!


  1. makar_crypt
    30.03.2022 16:34

    Добрый день. Во время ваших расследований вы не натыкались на такой вопрос?

    Как можно выдернуть урл на медиа ресурсы, например на видео? Мы долго рыскали по API , но не нашли такого функционала. При этом знаем что существуют боты которые формируют эти линки если переслать им сообщение с видео.