# Система типов игр ## Обзор В системе существует два типа игр, определяющих логику выдачи заданий: | Тип | Значение | Описание | |-----|----------|----------| | **Челленджи** | `challenges` | При спине выдаётся один случайный челлендж из списка | | **Прохождение** | `playthrough` | Нужно пройти игру целиком, челленджи становятся бонусными | --- ## Модели данных ### Game ``` game_type: str # "challenges" | "playthrough" playthrough_points: int? # Очки за прохождение (только для playthrough) playthrough_description: str? # Описание задания playthrough_proof_type: str? # Тип пруфа: screenshot/video/steam playthrough_proof_hint: str? # Подсказка для пруфа ``` ### Assignment ``` challenge_id: int? # ID челленджа (для challenges) game_id: int? # ID игры (для playthrough) is_playthrough: bool # True если это прохождение ``` ### BonusAssignment ``` main_assignment_id: int # Ссылка на основное задание (playthrough) challenge_id: int # ID бонусного челленджа status: str # "pending" | "completed" proof_path: str? # Путь к файлу пруфа proof_url: str? # URL пруфа proof_comment: str? # Комментарий со ссылкой points_earned: int # Заработанные очки ``` --- ## Логика спина ### Тип "Челленджи" (challenges) ``` 1. Выбрать случайную игру из доступных 2. Отфильтровать уже выполненные челленджи этой игры 3. Выбрать случайный невыполненный челлендж 4. Создать Assignment с challenge_id ``` **Игра исключается из спина**, если все её челленджи выполнены. ### Тип "Прохождение" (playthrough) ``` 1. Выбрать случайную игру из доступных 2. Создать Assignment с game_id и is_playthrough=True 3. Создать BonusAssignment для каждого челленджа игры 4. События (Jackpot, Golden Hour и т.д.) ИГНОРИРУЮТСЯ ``` **Игра исключается из спина**, если есть Assignment со статусом COMPLETED или DROPPED. --- ## Завершение заданий ### Челлендж (challenges) ``` POST /marathons/{id}/complete-assignment ``` 1. Загрузить пруф (файл или комментарий) 2. Начисляются очки челленджа × модификатор события 3. Увеличивается серия участника 4. Статус → COMPLETED ### Прохождение (playthrough) ``` POST /marathons/{id}/complete-assignment ``` 1. Загрузить пруф прохождения 2. Начисляются очки за прохождение (`playthrough_points`) 3. Бонусные очки добавляются из completed BonusAssignments 4. Увеличивается серия участника 5. Все pending BonusAssignments удаляются (больше нельзя выполнить) 6. Статус → COMPLETED ### Бонусный челлендж ``` POST /marathons/{id}/assignments/{assignment_id}/bonus/{challenge_id}/complete ``` 1. Доступно только пока основное задание ACTIVE 2. Загрузить пруф бонусного челленджа 3. BonusAssignment.status → COMPLETED 4. Очки накапливаются в BonusAssignment.points_earned 5. **Очки НЕ добавляются сразу** — добавятся при завершении основного задания **Исключение:** Если main assignment уже COMPLETED (перепрохождение после диспута), очки добавляются сразу. --- ## Фильтрация игр для спина ### Функция `get_available_games_for_participant` ```python for game in approved_games: if game.game_type == "playthrough": # Исключить если есть COMPLETED или DROPPED assignment if has_finished_playthrough(participant, game): continue else: # challenges # Исключить если ВСЕ челленджи выполнены if all_challenges_completed(participant, game): continue available.append(game) ``` --- ## Система очков ### Челлендж ``` base_points = challenge.points modifier = event_modifier (если есть активное событие) total = base_points × modifier ``` ### Прохождение ``` base_points = game.playthrough_points bonus_points = sum(bonus.points_earned for bonus in completed_bonuses) total = base_points + bonus_points ``` **События НЕ влияют на очки за прохождение.** --- ## Дроп задания ### Челлендж - Штраф в очках (зависит от настроек марафона) - Серия обнуляется - Игра остаётся доступной (можно получить другой челлендж) ### Прохождение - Штраф в очках - Серия обнуляется - **Игра исключается из спина навсегда** - Все BonusAssignments удаляются --- ## Диспуты ### Оспаривание прохождения Если диспут признан недействительным: 1. Assignment → RETURNED 2. Вычитаются все очки (прохождение + бонусы) 3. Серия обнуляется 4. Все BonusAssignments сбрасываются в PENDING ### Оспаривание бонуса Если диспут признан недействительным: 1. BonusAssignment → PENDING 2. Вычитаются очки бонуса 3. Proof данные очищаются 4. Можно попробовать выполнить заново --- ## API эндпоинты | Метод | Путь | Описание | |-------|------|----------| | POST | `/marathons/{id}/spin` | Крутить колесо | | POST | `/marathons/{id}/complete-assignment` | Завершить основное задание | | POST | `/marathons/{id}/assignments/{id}/bonus/{challenge_id}/complete` | Завершить бонус | | GET | `/marathons/{id}/available-games` | Список доступных игр | | GET | `/marathons/{id}/available-games-count` | Количество доступных игр | --- ## Схема работы ``` ┌─────────────────────────────────────────────────────────────────┐ │ СПИН │ └─────────────────────────────────────────────────────────────────┘ │ ┌───────────────┴───────────────┐ ▼ ▼ ┌─────────────────┐ ┌─────────────────┐ │ PLAYTHROUGH │ │ CHALLENGES │ └─────────────────┘ └─────────────────┘ │ │ ▼ ▼ ┌─────────────────┐ ┌─────────────────┐ │ Assignment │ │ Assignment │ │ game_id = X │ │ challenge_id │ │ is_playthrough │ │ = X │ └─────────────────┘ └─────────────────┘ │ │ ▼ │ ┌─────────────────┐ │ │ BonusAssignment │ │ │ × N (по числу │ │ │ челленджей) │ │ └─────────────────┘ │ │ │ ├───────────────────────────────┤ ▼ ▼ ┌─────────────────────────────────────────────────┐ │ COMPLETE │ │ • Загрузка пруфа │ │ • Начисление очков │ │ • Увеличение серии │ └─────────────────────────────────────────────────┘ ```