Все кейсы
FullstackТехлид, fullstack-разработка

Scout — протокол матчей ESports Turbo

Автоматический протокол матчей для киберспортивного оператора ESports Turbo: события Dota 2 попадают из игры в живую таблицу рядом с трансляцией, судья видит счёт и таймер в реальном времени и выгружает готовый протокол в Excel.

Проект под NDA — детали архитектуры и код готов разобрать голосом.

Scout — протокол матчей ESports Turbo

Результат

2
турнирных формата: Dota 2 5×5 Turbo и 1×1 Solo
2
независимых источника данных: GSI и кастомный режим
16
типов событий матча в протоколе

Задача бизнеса

Оператор проводил ежедневные турниры по Dota 2 в двух форматах — 5×5 Turbo и 1×1 Solo — и вёл протокол матча руками: судья смотрел эфир и переносил в таблицу первую кровь, гонки на 5, 10 и 15 убийств, снесённые башни и бараки, Рошана, терзателя, мегакрипов и руны. Данные расходились с картинкой, а по итогам дня протокол нужно было отдавать организаторам файлом. От продукта требовалось забирать события из самой игры, показывать их рядом с плеером трансляции и не мешать турнирам: эфиры шли с 07:00 до 16:00 семь дней в неделю, окно для релиза открывалось только после последнего матча.

Моя роль

Техлид по вебу: отвечал за архитектуру и разработку протокола целиком — бэкенд на NestJS, панель судьи на Next.js, схему данных и деплой. Согласовывал контракт событий с разработчиком кастомного режима Dota 2 на Lua и вёл подрядчика по разбору GSI: описывал модель данных, ревьюил код, принимал задачи. Планировал релизы вокруг расписания эфиров и держал два стенда, чтобы правки проверялись на тесте, пока прод обслуживает турнир.

Решение

Данные приходят из двух независимых источников. Первый — Game State Integration: клиент наблюдателя шлёт состояние карты на серверный роут, бэкенд разбирает его сам, без сторонних обёрток. Второй — кастомный режим на Lua: он ловит события внутри игры и шлёт их точечно, отдельными запросами на события, счёт и таймер. Оба источника пишут в общую сущность лога с идентификатором матча, поэтому один матч собирается из двух потоков без дублей, а если один источник отваливается, протокол продолжает жить на втором. Бэкенд на NestJS с TypeORM и PostgreSQL распознаёт начало и конец матча по состояниям игры, принудительно закрывает предыдущий матч при старте нового и чистит логи через минуту после победы. Панель судьи на Next.js держит на одной странице таблицу событий на русском, карточки счёта, таймер и плеер трансляции; обновления приходят по вебсокету, выгрузка в Excel формируется на клиенте. Доступ закрыт авторизацией, стенды разведены на stage и прод. Турниры, матчи и команды переехали из старой админки в Strapi поверх MongoDB, а расхождение эфира и протокола закрыл локальный ресендер: он придерживает пакеты GSI на нужное число секунд, чтобы таблица не опережала картинку.

Стек

  • Next.js
  • TypeScript
  • NestJS
  • TypeORM
  • PostgreSQL
  • WebSocket
  • Dota 2 GSI
  • Strapi
  • MongoDB
  • Docker