Небольшой проект для визуализации статистики игроков в Dota 2

Небольшой проект для визуализации статистики игроков в Dota 2

Всем привет! Хочу поделиться своей небольшой историей, про создание pet-проекта.

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

Однако, всегда есть интерес посмотреть на "цифры". Чтобы понять, на каком герое игрок чаще всего играет или на каком герое получается лучше.

В самой игре есть небольшой раздел со статистикой, но она недостаточно информативная. Есть несколько популярных онлайн-сервисов, которые предоставляют невероятно подробную игровую статистику, однако я обнаружил некоторые недостатки (по моему мнению) в их функционале. Например, при подсчете самых популярных героев у конкретного игрока, учитываются только рейтинговые игры, т.е. если вы не играете в таком режиме, то такая статистика вам не будет интересна. Аналогичная ситуация с игровыми рекордами, например "самый долгий по длительности" матч, учитываются только рейтинговые игры. Так же мне хотелось выдергивать интервальные данные, то есть видеть статистику за последние 100 или 500 игровых матчей.

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

Мне нравится использовать node/js/ts, поэтому сомнений в выборе ЯП не было. Так же мне не хотелось делать обычный скрипт или клиент-серверное приложение. Я никогда не работал над CLI приложениями, и подумал, что это был бы интересный опыт. Плюс я думаю, что в таком формате этим могли бы пользоваться мои друзья и знакомые, у которых нет какого либо опыта в разработке приложений.

Первоначальный план выглядел примерно так:

  1. Реализовать веб-парсер для сбора данных необходимого количества последних матчей конкретного игрока.
  2. Отсортировать данные, добавить нужные расчеты и получить что-то вроде топ-рейтинга популярных героев.
  3. Каким-то образом отобразить уже готовые данные пользователю.

У выбранного мной онлайн-сервиса нет общедоступного API, поэтому я решил получать необходимые HTML страницы с помощью обычных GET-запросов. А затем, используя библиотеку JSDOM, я начал выдергивать данные с помощью самых обычных querySelector().

Далее необходимо было отсортировать массив объектов по их популярности, таким образом я выявил героев, которыми игрок играл чаще всего:

export function sortByPopularityObjects(array: IAllArray[]): IAllArray[] { const countHeroMatches = Object.create(null); for (let i: number = 0; i < array.length; ++i) { countHeroMatches[array[i].name] = ~~countHeroMatches[array[i].name] + 1; } return array.sort(function (x: IAllArray, y: IAllArray) { return ( countHeroMatches[y.name] - countHeroMatches[x.name] || x.name.localeCompare(y.name) ); }); }

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

Пример таблицы с данными в CLI приложении. <a href="https://api.dtf.ru/v2.8/redirect?to=https%3A%2F%2Fstackoverflow.com%2Fquestions%2F67015361%2Fhow-to-display-a-table-in-terminal-stored-in-sql-file-using-mysql-xaamp&postId=2408342" rel="nofollow noreferrer noopener" target="_blank">Источник</a>.
Пример таблицы с данными в CLI приложении. Источник.

Однако лучшей идеей оказалось реализация HTML-странички. Здесь можно было пользоваться и удобной версткой и красивыми стилями.
В зависимости проекта я подтянул fastify и fastify/static, чтобы доставить необходимые файлы до пользователя. Завершающим этапом этого пункта, стало использование библиотечки open, для открытия этой самой HTML-странички в браузере пользователя.

В первых версиях проекта, результат визуализации данных выглядел как-то так:

Первые версии недостаточно презентабельны.
Первые версии недостаточно презентабельны.

Далее я столкнулся с некоторыми распространенными проблемами веб-парсеров, которые не используют прокси для отправки запросов. После нескольких тестовых запусков, я был благополучно заблокирован, а в ответ мне прислали 429 ошибку.

Я мог бы использовать playwright или puppeteer, чтобы пройти через анти-бот систему. Это позволило бы мне получить некоторые необходимые куки из контекста браузера, что значительно увеличило бы количество успешных запросов к сайту. Но такое решение превратилось бы в достаточно громоздкие зависимости, для небольшого CLI приложения. В этот момент я придумал немного иное решение.

В качестве альтернативы я подключил к своему приложению еще одного поставщика данных, другой онлайн-сервис, у которого был публичный API. Благодаря этому, появилась возможность получать любое количество матчей одним GET-запросом. Это замечательно!

Теперь я предоставил пользователю выбор из нескольких поставщиков данных, в этом мне пригодилась библиотека inquirer:

const providers = [ { name: "openDota", value: openDotaApi, }, { name: "dotaBuff", value: parserDotaBuff, }, ]; const { service } = await inquirer.prompt([ { type: "list", name: "service", message: "Select a data provider:", choices: providers, }, ]);

В документации к приложению я оставил некую подсказку для пользователя, в которой сказано, что для быстрого анализа небольшого количества матчей - лучшим решением будет использовать поставщика, реализация которого выполнена с помощью парсинга HTML страницы. В случае, если необходимо подсчитать большое количество матчей или всю историю игр, то лучше использовать поставщика данных у которого имеется публичный API.

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

Актуальная визуализация данных.
Актуальная визуализация данных.

Небольшой pet-проект, который я планировал реализовать за несколько часов, превратился в проект, над которым я работаю уже несколько недель, а количество коммитов перевалило за сотню. В текущем виде приложением достаточно удобно пользоваться мне, а так же моим друзьям. Самое главное - я получил массу удовольствия и опыта, при разработке своего приложения.

Безусловно, работы впереди еще много. Есть много идей для интеграции в приложение. Например сохранение историй расчетов статистики, для получения к ней доступа в любой момент. Некоторые спорные моменты ждут исправлений в следующих обновлениях.

Спасибо за то, что прочитали мой пост! Возможно, найдутся еще любители доты, которые не играют в рейтинговых режимах, но хотят узнать свою игровую статистику. Возможно, кому-то данный пост добавит мотивации при разработке собственного проекта. Возможно, кто-то захочет внести свой вклад в разработку следующих обновлений. Я буду рад вашим комментариям и отзывам!

Исходный код доступен в моем GitHub.
Загрузить приложение для использования можно с помощью NPM.

Дайте знать, если кому-то потребуется подробная инструкция по использованию приложения на Windows платформах.

88
6 комментариев

Красава, в своё время писал аналитический сервис на основе пиков и разных стат из матча!

Работать с сырым протобафом было впадлу поэтому делал на основе данных с opendota, как и ты) Однако у них в то время доки расходились с реальностью и нужные мне данные они не отдавали, потом ещё и дизайн стало делать в падлу да и дота начала куда то не туда развиваться так что забил.

Красава что сделал, было бы прикольно потыкать в виде tg/дискорд бота

2
Ответить

Привет! Спасибо большое!

Была такая идея, но не хотелось поднимать и держать где-то сервак для хостинга приложения. CLI формат как раз дал возможность, чтобы каждый пользователь запускался и считал на своем железе.

А насчет потыкать и протестировать, приложение устанавливается на любую ОС в одну команду из NPM (конечно при условии уже установленного npm и node). Так что я буду рад, если тебе пригодится!

1
Ответить

круто, молодец. Только вот.. ответь на вопрос, зачем? Для чего. Для себя?
просто подобных хреново тучу, реально.
молодец что делаешь, работаешь над продуктом

Ответить

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

1
Ответить

Однако, всегда есть интерес посмотреть на "цифры". Чтобы понять, на каком герое игрок чаще всего играет или на каком герое получается лучше.

А разве в Дота+ нет этой информации?

Ответить

Привет! К сожалению я сейчас не могу ответить точно на этот вопрос, так как я не использую платную подписку от разработчиков игры. Думаю что там история такая же, в детальную статистику идут только рейтинговые матчи.

Ответить