Этот пост об API сайта рейтинга, почему и отчего он плохой и как его можно улучшить. В посте предлагается более явно разделить функции сайта рейтинга и с этой целью все действия выполнять через новый API базы турниров. Ссылка на описание в конце поста. Приглашаю обсудить этот API и подобную организацию.
Вероятно, многим известно, что у сайта рейтинга есть API. Я пытался работать с ним. Мне этот процесс не понравился; на мой взгляд, API плохой. Чуть дальше я приведу свои аргументы, а пока немного порассуждаю о причинах такого плохого дизайна. В одной дискуссии о рейтинге была мысль о том, что следует разделить функции базы турниров и подсчёта рейтинга. Эта мысль мне нравится, более того, её можно продолжить.
Какие функции и насколько хорошо выполняет сайт рейтинга?
1. Организация турниров, распространение вопросов и т.д. С этой функцией я больше знаком как ведущий и представитель; со стороны оргкомитета моя работа с ней была крайне ограниченной. Практически всё мне кажется нормальным, кроме неудачного UI скачивания пакетов. И я помню некоторые жалобы на выставление дат отыгрыша, ввода спорных и т.п.
2. Ввод составов команд и результатов. Эта функция мне хорошо знакома и за несколько лет она стала намного лучше. Впрочем, я слышал жалобы на неудобный формат загрузки результатов.
3. Подсчёт рейтинга. Это крайне болезненный вопрос для сообщества, мне не хотелось бы обсуждать здесь саму формулу рейтинга. Как-то подсчёт рейтинга работает, и это неплохо, мне кажется.
4. База турниров. Здесь есть большие, на мой взгляд, недостатки. Если посмотреть глазами на сайт ещё можно, то с использованием API для машинного анализа возникают огромные проблемы. В общем, в текущем виде использовать API невозможно, требуется парсить сам сайт. Это глупо, ведь внутри данные, очевидно, хранятся в структурированном виде.
Недостатки API сайта рейтинга
Приведу примеры имеющихся недостатков API.
- какая версия API реализована -- нигде в API не указывается, только в документации;
- практически все данные, которые являются числами, возвращаются как строки;
- можно получить информацию о турнире, но непонятно, в каком он состоянии -- ещё не проводился, идёт ввод результатов, принимаются апелляции, учтён в релизе и т.п. -- эти данные есть на страницах турниров, но не в API. В результате, если я хочу, например, скачать все данные, мне нужно вытягивать все данные всех турниров, я не могу пройтись только по обновлённым данным;
- нигде не указаны лимиты на количество запросов и т.п. -- надеюсь, я не сломаю сайт, если буду выкачивать всё (см. предыдущий пункт) раз в день, скажем;
- нет простого способа загрузить составы всех команд (неясно, отчего -- базовых составов у одной команды не так уж и много, можно было бы отдавать сразу, без необходимости запроса к каждой команде);
- нет метаинформации (которая есть на странице турнира): дат приёма заявок, ввода составов и результатов; состава оргкомитета, ИЖ и АЖ и т.п.; кто, когда и как дисквалифицировал, переименовал команду и т.п.; какие были спорные и апелляции, кому они были зачтены;
- нет способа выгрузить всю информацию, ни в виде какого-то дампа, ни через API;
- даже имеющийся API плохо документирован.
Как нам организовать рейтинг? (tm)
Мне кажется, что все эти недостатки API возникают из-за того, что самому сайту рейтинга он не нужен. Все процессы ввода, организации, подсчёта рейтинга и отображения турниров, скорее всего, используют базу данных напрямую. Поэтому усилия на разработку API выделяются по остаточному принципу.
Но что, если в прекрасном сайте рейтинга будущего (tm) все эти функции будут разделены? Как будет выглядеть экосистема, если системы ввода данных, подсчёта рейтинга и базы турниров не будут писать напрямую в базу, а будут общаться только через разработанный API?
Во-первых, сам API неизбежно станет лучше -- это необходимое условие такого разделения функций. Без этого ничего не заработает.
Во-вторых, упростится анализ -- все данные будет проще получить. Поиск аномалий, обсуждение формул рейтинга -- всё это можно будет делать с данными на руках. Сейчас, прежде чем начать собственно работать, нужно потратить довольно много времени на парсинг сайта рейтинга и это отпугивает (меня, например). Если будет нормальный документированный API -- клиенты этого API можно будет генерировать из описания для большого числа языков. Получение данных упростится на порядок, оставив больше времени на анализ.
В-третьих, будет легче что-то менять и предлагать новое. Новый интерфейс ввода, новая формула рейтинга, новое отображение турниров -- пыщь-пыщь и в продакшен. Не нужно выкладывать исходный код всего сайта рейтинга, раз на это есть причины. Можно открыть лишь часть (а можно и вовсе не открывать, главное, чтобы API был открыт и задокументирован).
Недостатки, разумеется, тоже есть -- это работа по разделению сайта на подсистемы и организацию их работы через API. Но этот процесс может быть поэтапным и постепенным. Конечно, после внедрения уже не получится взять и быстренько поставить костылей где-то в середине сайта -- впрочем, не уверен, что это минус.
Предлагаемый API базы турниров
Здесь я предлагаю обсудить первый шаг -- разработку API базы турниров. Как, на мой взгляд, он должен быть устроен?
В качестве основы я взял имеющийся API, убрал оттуда данные о рейтинге команд, оставив только относящееся к турнирам: игроков, команды и собственно, турниры. Постарался везде расставить правильные типы (целые для идентификаторов и т.п.). Вся документация об API - в формате swagger.
Запросы об игроках и командах, по сути, те же, что и в имеющемся API (пара незначительных изменений).
Для получения данных о турнирах я бы предложил следующие запросы.
Во-первых, каждый турнир -- по сути двумерная таблица с плюсами и минусами (строки соответствуют командам, столбцы -- вопросам). Соответственно, хорошо бы иметь возможность её получить.
Во-вторых, может быть полезным иметь запросы для получения расплюсовки отдельной команды или по отдельному вопросу.
Однако таблица турнира может меняться -- могут добавляться какие-то данные, могут сниматься вопросы, засчитываться спорные и апелляции и т.п. Кроме того из-за этих изменений сложно сделать правильное разбиение по страницам, чтобы сохранялась консистентность данных (подробнее проблема описана здесь). Поэтому предлагается ввести ещё один запрос, который возвращает список изменений в хронологическом порядке (а таблица турнира собирается из них при помощи некоторой свёртки). Здесь уже несложно сделать разбиение по страницам.
Ссылки
- Сгенерированная документация в формате html: https://chgk.restlet.io
- Тестовый сайт, автосгенерированный и запиленный за пару часов: http://rating.gltronred.info/api/v0.1 - работают только GET-запросы, но не все и не везде заполнены все поля, потому что мне лениво полностью парсить сайт рейтинга. Полное описание ограничений есть в описании API. Исходный код выложу чуть позже, когда дошлифую то, что было сгенерировано автоматически. Работает медленно, поскольку код не оптимизировал.
PS. Пожалуйста, предлагайте ваши соображения, замечания и дополнения в комментариях, буду рад обсудить.