Что будет, если посмотреть на CS2 и Dota 2 как айтишник

от автора

Чтобы лучше играть, нужно больше играть. Или нет? 

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

Маленькая предыстория

Я был плохим студентом-айтишником: прогуливал пары, потому что всю ночь перед ними катал в CS в компьютерном клубе с друзьями. Тогда мы были уверены: чтобы играть лучше, надо просто больше играть.

Шли годы. Мы пересели с геймерских кресел на офисные стулья. Но у меня случилась ирония судьбы: последние пару лет я работаю продактом в проекте, который продает скины для CS2, так что киберспорт стал одновременно и хобби, и работой.

И вот в какой-то момент я поймал себя на мысли. На работе я привык принимать решения на основе метрик, логов и данных. А в игре с 2007 года полагаюсь на интуицию и божий промысел.

Но что, если посмотреть на CS2 как на продукт, а на собственную игру — как на пользовательское поведение, которое можно разобрать и улучшить? Так и сделал: изучил, как это делают профессиональные команды, и выстроил пайплайн под себя.

Как профи используют кодинг в разборе матчей

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

По сути, киберспортивная аналитика — это чистый дата-сайенс. Есть сырые данные. Надо собрать их, привести в порядок, разметить и только потом уже делать выводы. Реплеи парсят, фильтруют и прогоняют через скрипты. Если ты аналитик в Team Spirit или NAVI, то мало сказать, что «вражеский керри много фармит». Здесь надо вытащить из данных конкретный паттерн и отработать его с игроками.

Как это выглядит на практике

Иногда так

Иногда так

Сначала идет парсинг и нормализация. Демка или реплей — это поток событий, которые игра записывала в реальном времени: «Игрок X нажал кнопку Y», «Объект Z переместился в точку A».

Первым делом мы прогоняем его через парсер, чтобы получить вменяемый JSON или CSV. На этом же этапе данные очищаются от мусора: отсекаются паузы, дисконнекты и технические артефакты.

Затем наступает этап обогащения и агрегации. Одиночные события сами по себе мало что значат. Их нужно объединить в контекстные сущности: раунды, тимфайты или фазы фарма. Здесь мы накладываем на данные бизнес-логику игры. Например, скрипт должен понять, что смерть саппорта на 5-й минуте при попытке заблочить кемп — это ок, а смерть керри без байбэка на 40-й — это критическая ошибка, которая сильно снижает вероятность победы.

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

Нашел любопытные кейсы, как это выглядит в разных играх.

Кейс № 1

Авторы взяли открытые сырые данные по Valorant Champions Tour, матча Paper Rex против Evil Geniuses. 

Так как в них все свалено в кучу — от убийств и ассистов до каждого использованного скила, — то сначала декомпозировали общий массив по уровням: серия (series), отдельные игры (games), сегменты внутри игры, команды, игроки. 

Этап декомпозиции

Этап декомпозиции

И только после этого перешли к расчету K/D и KDA. Без предварительной структуры попытка посчитать общую статистику игрока превращается в гадание, так как контекст (карта, сторона, конкретный матч) теряется.

Кейс № 2

Здесь автор пошел дальше и собрал полноценный сервис OpponentIQ

Задача: автоматизировать составление отчета скаута с пулом героев соперника, любимых стратегий и т. д.

Стек: Python + FastAPI. 

Пайплайн: двухэтапный сбор данных через Grid API. Сначала сервис дергает метаданные, чтобы понять, какие матчи вообще были у команды, а затем глубоко анализирует каждый из них. В итоге обработка десяти с лишним матчей занимает меньше пяти секунд. На выходе пользователь получает структурированный PDF-отчет, который можно сразу рассылать всей команде перед матчем.

Сейчас проект умеет анализировать Valorant и League of Legends, но планирует масштабироваться на CS2 и Dota 2.

# Упрощенный пример двухэтапного подходаdef fetch_team_matches(team_name, num_matches):    # Этап 1: получаем ID серий из Central Data    series_ids = central_data_query(team_name, num_matches)    # Этап 2: получаем детальную статистику из Series State    matches_data = []    for series_id in series_ids:        match_data = series_state_query(series_id)        matches_data.append(match_data)    return matches_data

Кейс № 3

Нашел проект на Reddit: автор решил автоматизировать самую нудную часть тренировок — просмотр собственных реплеев игры. Вместо того чтобы часами перематывать видео, он написал программу, которая анализирует видео сама. 

Главный плюс: система группирует данные в тактические паттерны. Например, скрипт может подсветить, что команда пять раз за матч выходила на точку А с одинаковой раскидкой под один и тот же тайминг и в большинстве случаев это заканчивалось сливом раунда.

Вот пример, как выглядит сухой разбор матча CS2 между Team Spirit и G2. Тут все разложено по слоям: отдельно смотрят экономику, ключевые и переломные раунды, импакт игроков по ролям, контроль карты, трейды, клатчи и повторяющиеся тактические ходы. 

Вставлять сухой текст не стал, визуализировал.

Урон по игрокам

Урон по игрокам
Контроль карты

Контроль карты

Что из этого может взять себе непрофессиональный игрок

Поднимать всю эту цепочку самому, на коленке — занятие веселое, но трудозатратное.

Стек на каждый этап

Этап

CS2

Dota 2

Получить данные

awpy — парсер файлов .dem 

OpenDota API — бесплатный REST API

Обработать

pandas

Хранить

CSV / SQLite

Визуализировать

matplotlib, seaborn

Среда

Jupyter (локально или в облаке)

Готовые сервисы

HLTV, Leetify

STRATZ, Dotabuff

Пайплайн (без усложнений)

Шаг 1. Выберите один вопрос

Не надо анализировать всю игру. Берите что-то одно. 

Куда смотрим

Что ищем

На какой вопрос отвечаем

Перемещения и позиции

Повторяющиеся маршруты, входы на объект

Не стал ли я слишком читаемым на этой карте?

Тайминги

Когда кидают дымовые гранаты, идут на пуш, закупаются

Не опаздываю ли я на ключевые позиции?

Экономика

Распределение ресурсов, форс-бай после поражений

После каких раундов я сам загоняю себя в плохой закуп?

Боевые эпизоды

Кто первым входит в контакт, где чаще умирает

В каких ситуациях я стабильно умираю первым?

Типовые сценарии

Клатчи, ретейки, пистолетки, драки за Рошана

Есть ли у меня паттерн, который соперник уже считывает?

Контекст действия

Вижен, кулдауны, расположение союзников до события

Принимаю ли я решения вслепую?

Шаг 2. Соберите данные 

Для CS2 проще всего начать с Leetify: он сам собирает ваши матчи и делает экспорт. Для Dota 2 — с OpenDota API. Достаточно знать Steam ID игрока — и за пару запросов получаете историю матчей в JSON. Если хочется работать с сырыми демками CS2, берете awpy, указываете путь к файлу .dem и получаете на выходе удобную таблицу.

Шаг 3. Сложите все в простую таблицу 

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

Вот маленький кусочек — пример моей таблички:

Карта

Герой

Роль

Длительность матча

Результат

K/D/A

Урон

Экономика

Комментарий

de_anubis

SH1RO

AWP

50:57

Победа

24/12/5

3 200

7 800 $

Ключевые клатчи

de_anubis

NiKo

Entry

50:57

Поражение

18/19/3

2 500

6 400 $

Слабый трейд

de_anubis

m0NESY

AWP

50:57

Поражение

20/17/4

2 800

7 000 $

Нестабильная игра

Хранить эту базу можно в хранилище S3. 

Создаем бакет: 

Уже в бакете храним файлик со статистикой в папке, у меня она называется data:

Шаг 4. Отрежьте все лишнее

Главная ошибка — смотреть на все матчи сразу. Так вы получите кашу. Нужна маленькая выборка под один сценарий: только одна карта, один герой или игры с одной и той же проблемой.

Шаг 5. Ищите повторяемости

Сначала просто смотрим, что совпадает: тайминг, позиция, маршрут, тип решения или поведение после конкретного события.

Например, можно внезапно увидеть, что на Dust 2 вы раз за разом слишком поздно занимаете одну и ту же позицию. Или что дело не в патче вообще, а в том, что после него вы продолжаете играть старым темпом.

Под эту задачу можно реализовать агента. Покажу, как это сделал я в AI Factory.

Выбираем пункт AI Agents

Выбираем пункт AI Agents

Задаю параметры агента: в «Общих параметрах» выбираю простого агента, даю название под сценарий. А в разделе «Модель и конфигурация» выбираю Foundation Models и Qwen3-235B-A22B-Instruct-2507.

Следующим шагом подключаю MCP-сервер. 

Добавить MCP-сервер → Источник → Каталог → Excel MCP

Добавить MCP-сервер → Источник → Каталог → Excel MCP

А дальше прописываю системный промпт.

# Role & ExpertiseТы эксперт по анализу киберспортивных данных, специализирующийся на работе с таблицами Excel, хранящимися в S3-бакетах. Твоя задача — извлекать, обрабатывать, визуализировать и интерпретировать данные о матчах, игроках, статистике и результатах киберспортивных соревнований.# Available MCP Tools (excel-mcp)— create_workbook: создать пустую книгу Excel с указанным именем первого листа.— get_workbook_info: получить метаданные книги — имена листов, размеры, активный лист.— list_worksheets: получить список всех листов в книге с размерами и статусом активности.— create_worksheet: добавить новый лист в существующую книгу.— delete_worksheet: удалить указанный лист из книги.— read_cell: прочитать значение, формулу и формат одной ячейки.— write_cell: записать значение, число, логическое значение или формулу в ячейку.— read_range: прочитать прямоугольный диапазон ячеек, опционально с заголовками.— read_worksheet: прочитать весь лист как массив объектов (первая строка — заголовки).— write_dataframe: записать табличные данные (список словарей) на лист с возможностью заголовков.— append_data: добавить новые строки в конец листа, автоматически определяя заголовки.— export_to_csv: экспортировать лист в CSV-файл в S3.— get_worksheet_summary: получить сводку по листу — размеры, имена столбцов, примеры данных, статистику по числовым полям.— add_image: вставить изображение (например, логотип команды) в указанную ячейку листа.— add_chart: добавить диаграмму (bar, column, line, pie, area, scatter, radar) на лист с настройкой размеров и заголовка.# Main TaskТы получаешь запросы, связанные с анализом киберспортивных данных в excel-файлах, хранящихся в S3. Твоя задача — использовать доступные инструменты excel-mcp для выполнения операций: чтения, обработки, визуализации, сохранения и вывода результатов.# Step-by-Step Process1. Проанализируй запрос пользователя: что именно нужно извлечь, изменить или визуализировать?2. Определи, какой excel-файл и лист содержат нужные данные (используй get_workbook_info или list_worksheets).3. Прочитай данные с помощью read_worksheet или read_range.4. Если требуется обработка, используй write_cell, write_dataframe или append_data.5. Если требуется визуализация, создай диаграмму через add_chart или вставь изображение через add_image.6. Сохрани результат в новый файл или поверх существующего (используй output_key).7. Сформулируй ответ: кратко, по делу, с ключевыми выводами и ссылками на использованные данные.8. Проверь согласованность: все ли шаги выполнены, нет ли противоречий в данных, все ли поля корректны?# Style Requirements— Отвечай профессионально, но понятно. Избегай излишнего жаргона.— Всегда указывай, какой файл и лист использовались.— Если данные неполные или ошибочные, сообщи об этом и предложи альтернативу.— При визуализации уточняй тип диаграммы и почему он выбран.# Self-Consistency CheckПеред финальным ответом:— Убедись, что все использованные ключи файлов (key, output_key) корректны.— Проверь, совпадают ли названия листов с теми, что существуют.— Убедись, что числовые данные не содержат NaN или неожиданных строк.— Подтверди, что диаграммы и изображения привязаны к корректным ячейкам.# Error Handling— Если файл не найден, сообщи: «Файл с ключом [key] не найден в бакете. Проверьте имя или предоставьте корректный ключ». — Если лист отсутствует, сообщи: «Листа „[sheet_name]“ не существует в книге. Доступные листы: [список]».— Если данные в диапазоне не соответствуют ожидаемому формату, укажи: «Обнаружены некорректные значения в столбце [имя]. Ожидалось: [ожидаемый тип]».— Если инструмент не поддерживает параметр, сообщи: «Инструмент [tool_name] не поддерживает параметр [param]. Используйте допустимые: [список]»."key": "data/esports_stats_example_clean.xlsx""bucket": "bucket-crts-op-3-nextcloud"

В разделе «Генерация ответа» увеличиваю значение «Максимум токенов в ответе» до 50 000 и «Бюджет токенов на размышления» до 2 048:

Получился вот такой агент:

Наконец-то могу задать ему вопросы по статистике. Пример: «Какие роли чаще побеждают при конкретном стиле (AWP vs Entry vs Support)?»

Шаг 6. Сформулируйте гипотезу 

Например:

  • проблема не в стрельбе, а в позднем выходе;

  • проблема не в герое, а в маршруте;

  • проблема не в карте, а в одном конкретном сценарии на ней.

Шаг 7. Вернитесь в игру и проверьте

Сыграйте несколько матчей с поправкой на эту гипотезу. Потом сравните. Если стало лучше — отлично. Если нет — тоже нормально: значит, выбираем новую гипотезу.


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

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

Он ждет ваших инсайтов

Жду ваших инсайтов

ссылка на оригинал статьи https://habr.com/ru/articles/1034994/