---
name: dataset-collector
description: Собирает данные о матчах Dota 2 из Kaggle и OpenDota API, извлекает признаки, доступные на момент первой крови, унифицирует схему, делает EDA.
license: MIT
compatibility: opencode
metadata:
    category: data-engineering
    version: 1.0.0
---

# Dataset Collector — Dota 2

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

## ВАЖНО: Рабочая директория

Все файлы создаются в ТЕКУЩЕЙ рабочей директории (CWD).

**Выход:**

- `data/raw/kaggle_matches.parquet` — матчи из Kaggle
- `data/raw/opendota_matches.parquet` — матчи из OpenDota API
- `data/raw/hero_winrates.json` — вратейты героев по текущему патчу
- `data/raw/combined.parquet` — объединённый унифицированный датасет
- `data/eda/REPORT.md` — EDA отчёт

---

## Унифицированная схема (ОБЯЗАТЕЛЬНАЯ)

Все источники приводятся к этим колонкам:

| Колонка               | Тип   | Описание                                   |
| --------------------- | ----- | ------------------------------------------ |
| `match_id`            | int   | Уникальный ID матча                        |
| `radiant_win`         | bool  | Победила ли команда Radiant                |
| `first_blood_time`    | int   | Время первой крови (секунды)               |
| `first_blood_team`    | str   | `'radiant'` или `'dire'`                   |
| `radiant_heroes`      | str   | JSON-список из 5 hero_id                   |
| `dire_heroes`         | str   | JSON-список из 5 hero_id                   |
| `radiant_avg_winrate` | float | Средний вратейт героев Radiant в патче     |
| `dire_avg_winrate`    | float | Средний вратейт героев Dire в патче        |
| `winrate_delta`       | float | `radiant_avg_winrate - dire_avg_winrate`   |
| `fb_advantage`        | str   | `'radiant'`, `'dire'` или `'none'`         |
| `avg_rank_tier`       | float | Средний ранг игроков (1–80), если доступен |
| `source`              | str   | `'kaggle'` или `'opendota_api'`            |
| `collected_at`        | str   | ISO timestamp                              |

---

## Workflow

### Шаг 0: Setup окружения

```bash
python3 -m venv .venv
.venv/bin/pip install pandas kaggle requests pyarrow matplotlib seaborn python-dotenv tqdm
mkdir -p data/raw data/eda
```

Проверить наличие `.env` в рабочей директории:

```
OPENDOTA_API_KEY=     # опционально, без ключа лимит 60 req/min
STRATZ_TOKEN=         # опционально
```

И `kaggle.json` в `~/.kaggle/kaggle.json` (нужен для Kaggle API).

---

### Шаг 1: Выяснить параметры

Спросить пользователя:

1. Сколько матчей из OpenDota API собирать? (По умолчанию 2000)
2. Минимальный ранг игроков? (По умолчанию 0 — все ранги)
3. Использовать ли Kaggle датасет? (По умолчанию да)

---

### Шаг 2: Загрузка вратейтов героев

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

```bash
.venv/bin/python -c "
import requests, json
resp = requests.get('https://api.opendota.com/api/heroStats')
heroes = resp.json()
winrates = {
    str(h['id']): {
        'name': h['localized_name'],
        'winrate': round(h.get('7_pick', 1) and h['7_win'] / h['7_pick'], 4)
        if h.get('7_pick', 0) > 0 else 0.5
    }
    for h in heroes
}
with open('data/raw/hero_winrates.json', 'w') as f:
    json.dump(winrates, f)
print(f'Loaded winrates for {len(winrates)} heroes')
"
```

> Эндпоинт `/heroStats` возвращает статистику по текущему патчу (поле `7_pick`, `7_win` — последние 7 дней).

---

### Шаг 3: Источник 1 — Kaggle Dataset

```bash
.venv/bin/python ~/.claude/skills/dataset-collector/scripts/fetch_kaggle.py \
    --dataset devinanzelmo/dota-2-matches \
    --output data/raw/kaggle_matches.parquet \
    --winrates data/raw/hero_winrates.json
```

Скрипт:

- Скачивает датасет через `kaggle datasets download`
- Читает `match.csv` (основная таблица матчей)
- Читает `players.csv` (данные игроков) и `hero_names.csv`
- Извлекает: `match_id`, `radiant_win`, `first_blood_time`, `first_blood_team`
- Объединяет пики героев из `players.csv` (slot 0–4 = radiant, 5–9 = dire)
- Считает `radiant_avg_winrate`, `dire_avg_winrate`, `winrate_delta`
- Добавляет `fb_advantage`, `source='kaggle'`, `collected_at`

---

### Шаг 4: Источник 2 — OpenDota API

```bash
.venv/bin/python ~/.claude/skills/dataset-collector/scripts/fetch_opendota.py \
    --output data/raw/opendota_matches.parquet \
    --winrates data/raw/hero_winrates.json \
    --limit 2000
```

Скрипт использует эндпоинт `/publicMatches`:

```
GET https://api.opendota.com/api/publicMatches?mmr_ascending=0
```

Возвращает матчи с полями: `match_id`, `radiant_win`, `radiant_team` (hero_ids), `dire_team` (hero_ids), `avg_mmr`, `duration`.

> **Важно:** First blood time из `/publicMatches` недоступен напрямую.
> Для каждого матча делать запрос `/matches/{match_id}` для получения `first_blood_time`.
> Rate limit: 1 запрос/сек без ключа. Использовать `time.sleep(1.1)`.

---

### Шаг 5: Таблица источников для пользователя

```
## Найденные источники

| # | Источник | Тип | Размер | Примечание |
|---|----------|-----|--------|------------|
| 1 | Kaggle: devinanzelmo/dota-2-matches | Готовый датасет | ~50K матчей | Патч 6.x, исторические данные |
| 2 | OpenDota API /publicMatches | REST API | до 2000 матчей | Актуальные матчи, текущий патч |

Продолжаем со всеми источниками? [да/изменить]:
```

---

### Шаг 6: Унификация и объединение

```bash
.venv/bin/python ~/.claude/skills/dataset-collector/scripts/unify_schema.py \
    --inputs data/raw/kaggle_matches.parquet data/raw/opendota_matches.parquet \
    --output data/raw/combined.parquet
```

Скрипт проверяет наличие всех обязательных колонок и типы данных.

---

### Шаг 7: EDA

```bash
.venv/bin/python ~/.claude/skills/dataset-collector/scripts/eda_analysis.py \
    --input data/raw/combined.parquet \
    --winrates data/raw/hero_winrates.json \
    --output data/eda
```

Создаёт:

- `class_balance.png` — соотношение побед Radiant/Dire
- `first_blood_time_dist.png` — распределение времени первой крови
- `winrate_delta_dist.png` — распределение разницы вратейтов
- `fb_advantage_vs_win.png` — влияние первой крови на победу
- `eda_results.json`

```bash
.venv/bin/python ~/.claude/skills/dataset-collector/scripts/generate_report.py \
    --input data/eda/eda_results.json \
    --output data/eda/REPORT.md
```

---

## Правила

1. **Все файлы в ТЕКУЩЕЙ рабочей директории**
2. **Rate limiting для API** — `time.sleep(1.1)` между запросами к OpenDota
3. **НЕ использовать `source activate`** — только `.venv/bin/python`
4. **Обязательно загружать вратейты** перед обработкой любого источника
5. **Показывать прогресс** при скачивании через API (tqdm)
6. **Обрабатывать матчи без first_blood_time** — пропускать или ставить `-1`
