# Система типов игр

## Обзор

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

| Тип | Значение | Описание |
|-----|----------|----------|
| **Челленджи** | `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                       │
    │  • Загрузка пруфа                               │
    │  • Начисление очков                             │
    │  • Увеличение серии                             │
    └─────────────────────────────────────────────────┘
```
