> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bedolagam.ru/llms.txt
> Use this file to discover all available pages before exploring further.

# Конкурсы и игры

> Ежедневные мини-игры с призами и реферальные конкурсы

## Обзор

Система конкурсов состоит из двух подсистем:

* **Ежедневные игры** — мини-игры с мгновенными призами (дни подписки, баланс)
* **Реферальные конкурсы** — соревнования по привлечению рефералов с рейтингами

Обе подсистемы управляются общим флагом `CONTESTS_ENABLED`, но работают на разных моделях данных.

```env theme={null}
CONTESTS_ENABLED=true
CONTESTS_BUTTON_VISIBLE=true
```

> [!NOTE]
>
> Участие в конкурсах доступно только пользователям с **активной подпиской** (платной или триальной).

## Ежедневные игры

### Архитектура

```
ContestTemplate → ContestRound → ContestAttempt
    (шаблон)       (раунд)       (попытка)
```

* **Шаблон** — определяет тип игры, расписание, призы
* **Раунд** — конкретный экземпляр игры с временным окном
* **Попытка** — одна попытка пользователя (уникальна: один раунд — одна попытка)

### 7 типов игр

| Игра | Механика | Ввод | Описание |
| - | - | - | - |
| **Quest Buttons** | Сетка 3x3 | Кнопка | Найти скрытую ноду в сетке |
| **Lock Hack** | 20 замков | Кнопка | Найти единственный открытый замок |
| **Server Lottery** | 10 флагов стран | Кнопка | Угадать правильный сервер |
| **Blitz Reaction** | Одна кнопка | Кнопка | Кто первый нажмёт — тот победил |
| **Letter Cipher** | Числовой шифр | Текст | Расшифровать слово (A=1, B=2...) |
| **Emoji Guess** | Перемешанные эмодзи | Текст | Угадать название сервиса по подсказкам |
| **Anagram** | Перемешанные буквы | Текст | Составить слово из букв |

### Расписание и ротация

Каждый шаблон имеет:

* `schedule_times` — список времён запуска (формат `HH:MM`, через запятую)
* `cooldown_hours` — длительность раунда (по умолчанию 24ч)
* `is_enabled` — вкл/выкл для конкретной игры

Фоновый сервис `ContestRotationService` проверяет расписание каждые 60 секунд. При наступлении времени создаёт новый раунд и:

1. Анонсирует в канале подписки (`CHANNEL_SUB_ID`)
2. Рассылает всем пользователям с активной подпиской

### Призы

| Тип приза | Описание |
| - | - |
| `days` | Продление подписки на N дней |
| `balance` | Начисление на баланс (в копейках) |
| `custom` | Произвольный текст (ручное выполнение) |

### Определение победителя

Используется атомарная проверка с блокировкой строки (`SELECT FOR UPDATE`):

1. Пользователь отправляет ответ
2. Стратегия игры проверяет правильность
3. Если верно — блокируется строка раунда, проверяется `winners_count < max_winners`
4. При победе приз выдаётся автоматически

### Настройки шаблонов по умолчанию

| Игра | Расписание | Макс. победителей | Приз |
| - | - | - | - |
| Quest Buttons | 10:00, 18:00 | 3 | 1 день |
| Lock Hack | 09:00, 19:00 | 1 | 5 дней |
| Letter Cipher | 12:00, 20:00 | 1 | 1 день |
| Server Lottery | 15:00 | 1 | 7 дней |
| Blitz Reaction | 11:00, 21:00 | 1 | 1 день |
| Emoji Guess | 13:00 | 1 | 1 день |
| Anagram | 17:00 | 1 | 1 день |

> [!NOTE]
>
> Все 7 шаблонов создаются автоматически при первом запуске, но **отключены по умолчанию**. Включайте их по мере необходимости.

## Реферальные конкурсы

### Как работают

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

### Типы конкурсов

| Тип | Что считается очком |
| - | - |
| `referral_paid` | Реферал зарегистрировался **и** купил подписку |
| `referral_registered` | Реферал просто зарегистрировался |

### Создание конкурса (FSM)

1. Выбор режима: `referral_paid` или `referral_registered`
2. Название конкурса
3. Описание (опционально, `-` для пропуска)
4. Текст призов (опционально)
5. Дата начала (`дд.мм.гггг ЧЧ:ММ`)
6. Дата окончания
7. Время ежедневной сводки (`ЧЧ:ММ` или несколько через запятую)

### Ежедневные сводки

* Отправляются в канал подписки и чат администраторов
* Поддержка нескольких времён в день (`daily_summary_times`)
* По завершении конкурса — финальная сводка (отправляется один раз)
* Содержание: название, топ-5, общее количество рефералов, призы, оставшееся время

### Виртуальные участники

Администраторы могут добавлять "призраков" для создания видимости конкуренции:

* **Индивидуально** — имя + количество рефералов
* **Массово ("Массовка")** — 1-50 призраков с одинаковым количеством рефералов и случайными именами
* В админке отмечены иконкой призрака
* В публичном канале выглядят как обычные участники

### Лидерборд

Лидерборд объединяет реальных участников (из `referral_contest_events`) и виртуальных. Доступен из админки (топ-10) и в ежедневных сводках (топ-5).

## Управление (админ-панель)

### Ежедневные игры

| Действие | Описание |
| - | - |
| Список шаблонов | Все 7 игр с состоянием вкл/выкл |
| Вкл/Выкл | Переключение конкретной игры |
| Запуск раунда | Немедленный запуск (ручной или с автовключением) |
| Редактирование | Тип приза, значение, макс. победителей, расписание, cooldown |
| Сброс попыток | Сбросить попытки активного раунда |
| Закрытие раунда | Принудительно завершить текущий раунд |
| **Массовые операции** | Закрыть все раунды, сбросить все попытки, запустить все |

### Реферальные конкурсы

| Действие | Описание |
| - | - |
| Список конкурсов | С пагинацией (5 на страницу) |
| Детали | Статус, период, призы, топ-5, всего событий |
| Вкл/Выкл | Переключение активности |
| Статистика | Участники, рефералы, платные/бесплатные, суммы |
| Синхронизация | Синхронизация событий с реальными платежами |
| Очистка | Удаление невалидных событий |
| Виртуальные участники | Добавление, редактирование, удаление, массовое создание |

## Видимость

Конкурсы имеют многоуровневую систему видимости:

1. **`CONTESTS_ENABLED`** — глобальный переключатель (фоновые сервисы, обработчики)
2. **`CONTESTS_BUTTON_VISIBLE`** — видимость кнопки "Конкурсы" в главном меню
3. **Вкл/выкл шаблона** — каждая ежедневная игра переключается отдельно
4. **Активность конкурса** — каждый реферальный конкурс переключается отдельно
5. **Требование подписки** — только пользователи с активной/триальной подпиской

## Настройка

| Переменная | По умолчанию | Описание |
| - | - | - |
| `CONTESTS_ENABLED` | `false` | Глобальный переключатель системы конкурсов |
| `CONTESTS_BUTTON_VISIBLE` | `false` | Показывать кнопку "Конкурсы" в меню |
| `TIMEZONE` | `UTC` | Часовой пояс для расписания |
| `CHANNEL_SUB_ID` | — | ID канала для анонсов |

## Cabinet и Web API

### Cabinet (для пользователей)

* `GET /contests/count` — количество доступных (неотыгранных) игр
* `GET /contests` — список доступных игр со статусом
* `GET /contests/{round_id}` — данные игры
* `POST /contests/{round_id}/answer` — отправка ответа

### Web API (для администраторов)

Полный CRUD для шаблонов, раундов, попыток (ежедневные игры) и реферальных конкурсов с аутентификацией по API-токену.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.