# Документация по проектной практике

## Реализация телеграм-бота "МосПолиХелпер"

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

## Исследование предметной области

### Анализ проблемы навигации в кампусе

Перед началом разработки был проведен анализ существующей проблемы ориентирования в кампусах Московского Политехнического Университета. Основные выявленные сложности:

1. **Разнородность кампусов**:
   - Пять различных кампусов с уникальной планировкой
   - Отсутствие унифицированной системы навигации между корпусами

2. **Сложность обозначения кабинетов**:
   - Разные форматы нумерации в зависимости от корпуса
   - Неинтуитивные префиксы в обозначениях (например, "ав" для Автозаводской)

3. **Потребности пользователей**:
   - Новые студенты и сотрудники часто теряются в кампусе
   - Гости университета испытывают сложности при поиске аудиторий
   - Необходимость быстрого ориентирования при плотном расписании

### Обзор существующих решений

В рамках исследования были рассмотрены различные подходы к решению проблемы навигации:

1. **Статические карты и указатели**:
   - Недостаточно интерактивны
   - Не обеспечивают персонализированные маршруты

2. **Мобильные приложения с GPS-навигацией**:
   - Требуют специальной инфраструктуры для точного позиционирования внутри зданий
   - Высокая стоимость разработки и поддержки

3. **Текстовые инструкции**:
   - Сложны для восприятия без визуального сопровождения
   - Трудности с описанием сложных маршрутов

После анализа было принято решение разработать решение на базе Telegram, объединяющее доступность мессенджера и наглядность видеоинструкций.

## Архитектурное проектирование

### Определение требований

На основе проведенного анализа были сформулированы следующие функциональные и нефункциональные требования:

**Функциональные требования**:
1. Предоставление интерфейса для выбора корпуса университета
2. Возможность указать конкретный кабинет в соответствии с принятыми обозначениями
3. Формирование видеомаршрута от территории кампуса или от входа в корпус
4. Создание комбинированных маршрутов из отдельных видеофрагментов
5. Кеширование сгенерированных маршрутов для оптимизации

**Нефункциональные требования**:
1. Время отклика не более 5 секунд на запрос маршрута (при наличии в кеше)
2. Максимальное время генерации нового маршрута не более 30 секунд
3. Поддержка обработки до 100 одновременных пользователей
4. Оптимизация видеоинструкций для минимизации объема данных
5. Модульная архитектура для упрощения дальнейшего расширения

### Выбор технологического стека

Для реализации проекта были выбраны следующие технологии и инструменты:

1. **Python 3.10+**:
   - Высокоуровневый язык программирования с богатой экосистемой библиотек
   - Простота интеграции с различными API и сервисами
   - Наличие специализированных библиотек для обработки мультимедиа

2. **Aiogram 3.x**:
   - Асинхронный фреймворк для работы с Telegram Bot API
   - Поддержка современных паттернов разработки (FSM, роутеры)
   - Встроенная поддержка обработки интерактивных элементов интерфейса

3. **MoviePy**:
   - Библиотека для обработки видео на Python
   - Возможности для конкатенации, ускорения и модификации видеопотоков
   - Простой и понятный API для манипуляции видеофайлами

4. **JSON для хранения данных**:
   - Легковесный формат для хранения структурированной информации
   - Нативная поддержка в Python без дополнительных зависимостей
   - Достаточная производительность для данных объемов данных

### Проектирование модульной структуры

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

```
src/code/
├── bot.py            # Точка входа в приложение
├── config.py         # Конфигурационные параметры
├── database.py       # Модуль работы с данными пользователя
├── handlers.py       # Обработчики команд и сообщений
├── init.py           # Инициализация компонентов бота
└── scripts.py        # Модуль обработки видео
```

**Взаимодействие модулей**:

1. `bot.py` инициализирует приложение и подключает роутеры из `handlers.py`
2. `init.py` настраивает экземпляр бота, используя конфигурацию из `config.py`
3. `handlers.py` содержит логику обработки сообщений и вызывает функции из `scripts.py`
4. `scripts.py` отвечает за обработку видео и использует путь из `database.py`
5. `database.py` обеспечивает хранение и получение данных о пользовательских сессиях

## Реализация программных компонентов

### Модуль инициализации (init.py)

Модуль отвечает за настройку экземпляра бота, инициализацию диспетчера сообщений и подготовку команд меню:

```python
from aiogram import Bot, Dispatcher
from aiogram.enums.parse_mode import ParseMode
from aiogram.fsm.storage.memory import MemoryStorage
from aiogram.client.bot import DefaultBotProperties
from aiogram.types import BotCommand, BotCommandScopeDefault
from aiogram.methods import SetMyCommands

import config

# Структурированное определение команд для меню
async def setup_bot_commands():
    commands = [
        BotCommand(command="help", description="Получить помощь"),
        BotCommand(command="route", description="Построить маршрут")
    ]

    await bot(SetMyCommands(
        commands=commands,
        scope=BotCommandScopeDefault()
    ))

bot = Bot(token=config.BOT_TOKEN, default=DefaultBotProperties(parse_mode=ParseMode.HTML))
dp = Dispatcher(storage=MemoryStorage())
```

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

### Модуль обработки маршрутов (scripts.py)

Ключевой модуль, отвечающий за формирование и обработку видеомаршрутов:

```python
def get_routes(id_building: str, id_cab: str, other=False):
    """
    Формирует список путей к видеофрагментам для маршрута.
    
    Args:
        id_building: Идентификатор корпуса
        id_cab: Идентификатор кабинета
        other: Флаг для специальных случаев
        
    Returns:
        list: Список путей к видеофрагментам
    """
    # Логика определения путей к видеофрагментам
    # в зависимости от выбранного корпуса и кабинета
    
def make_full_clip(paths):
    """
    Создает полный видеоклип из фрагментов маршрута.
    
    Args:
        paths: Список путей к видеофрагментам
        
    Returns:
        str: Путь к готовому видеоклипу или None в случае ошибки
    """
    # Проверка наличия файлов
    if not all(os.path.exists(path) for path in paths):
        print("Некоторые файлы не найдены")
        return None

    # Создание клипов из файлов
    clips = [VideoFileClip(path) for path in paths]

    # Объединение клипов
    full_clip = concatenate_videoclips(clips)
    
    # Оптимизация видео
    full_clip = full_clip.without_audio()  # Удаление звука
    full_clip = full_clip.time_transform(lambda t: t * 1.5).with_duration(full_clip.duration / 1.5)  # Ускорение в 1.5 раза
    full_clip = full_clip.resized(height=512)  # Оптимизация размера
    
    # Генерация имени выходного файла
    full_clip_name = f"{paths[-1][21:].replace('.mp4', '')}-{'all' if len(paths) == 3 else 'small'}.mp4"
    
    # Рендеринг видео с оптимизированными параметрами
    full_clip.write_videofile(
        f"../data/cache/{full_clip_name}",
        fps=30,
        codec="libx264",
        bitrate="1500k",
        preset="fast",
        ffmpeg_params=["-crf", "23"]
    )
    
    return f"../data/cache/{full_clip_name}"
```

Функция `make_full_clip` выполняет следующие оптимизации:
- Удаление аудиодорожки для уменьшения размера файла
- Ускорение видео в 1.5 раза для сокращения продолжительности
- Уменьшение разрешения для оптимизации передачи через Telegram
- Применение эффективных параметров кодирования H.264

### Модуль обработчиков команд (handlers.py)

Модуль содержит обработчики команд и событий пользовательского интерфейса:

```python
@router.message(CommandStart())
async def start_handler(msg: Message) -> None:
    """Обработчик команды /start"""
    await msg.answer("Здравствуйте! Этот бот поможет вам добраться до кабинета в структуре корпусов Московского "
                     "Политехнического Университета. Для начала работы просто пропишите команду <b>/route</b>")

@router.message(Command("route"))
async def route_handler(msg: Message) -> None:
    """Обработчик команды /route"""
    buttons = [[InlineKeyboardButton(text=f"На Большой Семёновской", callback_data="edu:bs")],
               [InlineKeyboardButton(text=f"На Павла Корчагина", callback_data="edu:pk")],
               [InlineKeyboardButton(text=f"На Прянишкова", callback_data="edu:pr"),
                InlineKeyboardButton(text=f"На Михалковской", callback_data="edu:mi")],
               [InlineKeyboardButton(text=f"На Автозаводской", callback_data="edu:av")]]
    keyboard = InlineKeyboardMarkup(inline_keyboard=buttons)

    await msg.answer(text="Выберите корпус на котором вы хотите проложить маршрут:", reply_markup=keyboard)

@router.callback_query(F.data.startswith("route:"))
async def var_button(call: CallbackQuery) -> None:
    """Обработчик выбора типа маршрута"""
    action = call.data.split(":")[1]
    
    # Получение данных о сессии пользователя
    jsn = JsonTools(call.from_user.id)
    user_dict = jsn.read_json()
    edu_keys = list(user_dict.keys())
    lst_routes = user_dict[edu_keys[0]]
    
    # Уведомление о начале обработки
    msg = await call.message.answer("1. Получение видео...")
    path = ""
    
    # Логика выбора или генерации маршрута
    if action == "build":  # От входа на территорию
        # Проверка наличия в кеше
        if os.path.exists(f"../data/cache/{lst_routes[-1][21:].replace('.mp4', '-all.mp4')}"):
            path = f"../data/cache/{lst_routes[-1][21:].replace('.mp4', '-all.mp4')}"
        else:
            # Генерация нового маршрута
            path = make_full_clip(lst_routes)
            if not path:
                await msg.edit_text("Данного маршрута в нашей базе пока нет, извините за неудобство...")
                return 0
    elif action == "floor":  # От входа в корпус
        # Аналогичная логика для маршрута от входа в корпус
        # ...
    
    # Отправка результата
    msg_finally = await msg.edit_text("2. Видео готово!")
    await msg.answer_video_note(video_note=FSInputFile(path))
    await msg_finally.delete()
```

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

### Модуль работы с данными (database.py)

Модуль реализует хранение и получение данных о пользовательских сессиях:

```python
class JsonTools:
    """
    Класс для работы с JSON-данными пользователей.
    
    Attributes:
        f_name (str): Путь к файлу пользовательской сессии
    """
    
    def __init__(self, user_id):
        """
        Инициализация инструмента работы с данными.
        
        Args:
            user_id: Идентификатор пользователя Telegram
        """
        self.f_name = f"../data/users/{user_id}.json"

    def save_json(self, data):
        """
        Сохранение данных в JSON-файл.
        
        Args:
            data: Данные для сохранения
            
        Returns:
            dict: Результат операции сохранения
        """
        with open(self.f_name, "w", encoding="utf8") as f:
            return json.dump(data, f)

    def read_json(self):
        """
        Чтение данных из JSON-файла.
        
        Returns:
            dict: Прочитанные данные
        """
        with open(self.f_name, "r", encoding="utf8") as f:
            return json.load(f)

    def get_buildings(self):
        """
        Получение списка корпусов из данных пользователя.
        
        Returns:
            list: Список идентификаторов корпусов
        """
        return self.read_json().keys()
```

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

### Основной модуль приложения (bot.py)

Модуль является точкой входа в приложение и отвечает за запуск и общую координацию работы бота:

```python
import asyncio, logging

from init import *
from handlers import router

async def main() -> None:
    """
    Основная функция запуска бота.
    Настраивает роутеры, веб-хук и команды.
    """
    dp.include_router(router)
    await bot.delete_webhook(drop_pending_updates=True)

    await setup_bot_commands()
    await dp.start_polling(bot, allowed_updates=dp.resolve_used_update_types())

if __name__ == "__main__":
    logging.basicConfig(level=logging.INFO)

    try: 
        asyncio.run(main())
    except KeyboardInterrupt: 
        pass
```

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

## Тестирование и валидация

### Разработка тестовых сценариев

Для проверки работоспособности бота были разработаны следующие тестовые сценарии:

1. **Базовая функциональность**:
   - Тестирование команды `/start` и получение приветственного сообщения
   - Проверка команды `/help` и полноты предоставляемой информации
   - Тестирование команды `/route` и корректности отображения интерфейса выбора корпуса

2. **Выбор корпуса и кабинета**:
   - Проверка обработки выбора каждого из корпусов через интерактивные кнопки
   - Тестирование ввода корректных номеров кабинетов для каждого корпуса
   - Проверка реакции на некорректный формат номера кабинета

3. **Формирование видеомаршрутов**:
   - Тестирование генерации маршрутов "от входа на территорию"
   - Проверка формирования маршрутов "от входа в корпус"
   - Тестирование системы кеширования и повторного использования маршрутов

4. **Обработка ошибок**:
   - Проверка поведения при отсутствии необходимых видеофрагментов
   - Тестирование обработки сетевых ошибок и сбоев при рендеринге видео
   - Проверка корректного информирования пользователя о проблемах

### Результаты тестирования

В ходе тестирования были выявлены и устранены следующие проблемы:

1. **Производительность**:
   - Оптимизированы параметры рендеринга видео для ускорения процесса
   - Реализовано кеширование для минимизации повторной обработки маршрутов
   - Улучшена асинхронная обработка запросов для повышения отзывчивости

2. **Обработка ошибок**:
   - Добавлена проверка наличия файлов перед объединением видеофрагментов
   - Реализованы информативные сообщения при невозможности построения маршрута
   - Добавлена корректная обработка прерываний и исключений

3. **Улучшение пользовательского опыта**:
   - Добавлено отображение прогресса обработки видео
   - Оптимизированы размер и продолжительность видеомаршрутов
   - Улучшены подсказки и инструкции для пользователей

## Развертывание и сопровождение

### Подготовка среды выполнения

Для эффективной работы бота требуется следующая инфраструктура:

1. **Серверные требования**:
   - Операционная система: Linux (Ubuntu 20.04 или новее)
   - Python 3.10 или выше
   - Не менее 2 ГБ оперативной памяти
   - Не менее 10 ГБ дискового пространства для хранения видеофрагментов и кеша

2. **Необходимые зависимости**:
   - aiogram==3.0.0
   - moviepy==1.0.3
   - ffmpeg (системный пакет)

3. **Структура каталогов**:
   ```
   /
   ├── src/
   │   └── code/            # Исходный код бота
   ├── data/
   │   ├── cache/           # Сгенерированные видеомаршруты
   │   ├── users/           # Пользовательские данные
   │   └── videos/          # Исходные видеофрагменты маршрутов
   └── logs/                # Журналы работы бота
   ```

### Мониторинг и обслуживание

Для обеспечения стабильной работы бота рекомендуется:

1. **Регулярное обслуживание**:
   - Мониторинг использования дискового пространства
   - Периодическая очистка устаревших кешированных маршрутов
   - Обновление исходных видеофрагментов при изменениях в кампусе

2. **Резервное копирование**:
   - Создание резервных копий видеофрагментов маршрутов
   - Периодическое копирование пользовательских данных
   - Хранение копий конфигурационных файлов

3. **Обновление и расширение**:
   - Добавление новых маршрутов по запросам пользователей
   - Актуализация существующих маршрутов при изменениях в кампусе
   - Расширение функциональности по результатам обратной связи

## Выводы и перспективы развития

### Результаты проекта

В результате выполнения вариативной части проектной практики:

1. Разработан и внедрен телеграм-бот "МосПолиХелпер", предоставляющий интерактивные видеомаршруты по кампусам Московского Политехнического Университета.

2. Реализована модульная архитектура с четким разделением ответственности, обеспечивающая масштабируемость и поддерживаемость кода.

3. Создана эффективная система обработки видеофрагментов с оптимизацией для использования в мессенджере Telegram.

4. Реализовано кеширование маршрутов для повышения производительности и оптимизации пользовательского опыта.

5. Проведено комплексное тестирование и оптимизация производительности бота.

### Перспективы развития

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

1. **Расширение функциональности**:
   - Добавление текстовых инструкций к видеомаршрутам
   - Интеграция с расписанием занятий для автоматического определения нужного кабинета
   - Добавление статических карт и схем кампуса

2. **Технологические улучшения**:
   - Переход на базу данных (SQLite или PostgreSQL) для более эффективного хранения данных
   - Внедрение системы аналитики для отслеживания популярных маршрутов
   - Оптимизация алгоритмов обработки видео для дальнейшего повышения производительности

3. **Расширение охвата**:
   - Добавление маршрутов между корпусами университета
   - Включение маршрутов до близлежащих объектов инфраструктуры (общежития, столовые и т.д.)
   - Интеграция с общественным транспортом для полной навигации до университета

## Заключение

Телеграм-бот "МосПолиХелпер" является практическим решением реальной проблемы ориентирования в кампусах Московского Политехнического Университета. Проект демонстрирует применение современных технологий разработки и обработки мультимедиа для создания полезного интерактивного инструмента.

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

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