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

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



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

Архитектура


Библиотека состоит из пяти независимых модулей:

  • configure извлекает data- атрибуты из HTML и готовит конфигурацию для остальных модулей
  • extract добывает данные из файла или API
  • transform преобразует данные в стандартный формат
  • calculate считает победы, поражения, голы и другие штуки, а также добавляет метаинформацию
  • visualize рисует интерактивную таблицу и возвращает объект с методами вроде play() и drillDown(item)

Но модулей мало не бывает, поэтому extract, transform и visualize сами состоят из подмодулей.



Каждый модуль знает, что к нему придёт на вход и что ему нужно отдать на выходе.

Такая архитектура позволяет добавлять функции быстро и безболезненно. Так, для поддержки JSON-файлов в extract, достаточно было добавить 13 строк кода.

Визуализаторы


Но это ещё не самое крутое. В какой-то момент стало понятно, что пытаться идеально адаптировать одну и ту же таблицу к разными видам спорта через data- атрибуты — это путь в никуда. Поэтому в visualize появились визуализаторы. Визуализатор определяет, как строить таблицу, как перемещаться между раундами и как углубляться в результаты команды.

Благодаря визуализаторам из одних и тех же данных можно получить две очень разные таблицы:



Теперь, если вы захотите поэкспериментировать с визуализацией, например, сезона Формулы-1, вам не придётся готовить данные и программировать анимацию таблицы — всё это библиотека сделает за вас. Просто напишите свой визуализатор.

Или поступите, как Виталик. Виталик сделал красивый прототип, а мы его оживили и добавили в библиотеку:



Результат


Поиграйте с живыми таблицами:


Библиотека умеет работать с csv и json файлами, управляется со списком матчей и таблицей очков и предлагает два визуализатора: классическую таблицу и таблицу со спарклайнами.

Использование


Как и прежде, исходный код лежит на Гитхабе, а рядом с ним — документация.

Предполагается два варианта использования: подключить скрипты в head и наслаждаться тем, как дивы превращаются в интерактивные таблицы, или установить библиотеку через npm и запрограммировать чудеса.

Милосердная лицензия позволяет пользоваться библиотекой без ограничений на любых сайтах.

Мы будем рады замечаниям, предложениям и пулл-реквестам.
Поделиться с друзьями
-->

Комментарии (20)


  1. BOOTor
    22.05.2017 21:47
    +1

    Отличная работа!
    Только поправьте в примерах ссылочку данных футбола на json вместо csv.


  1. Horoshiy78
    23.05.2017 11:39

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


    1. antoniokov
      23.05.2017 11:47

      Да, есть такие планы. Сейчас параметр orderBy принимает список вычислений, например, «points, wins, draws' и сортирует по порядку: сначала по очкам, потом по победам, потом по ничьям. Для большинства чемпионатов этого достаточно: в той же премьер-лиге дополнительные показатели — разница забитых и пропущенных и количество забитых мячей.

      В будущем есть два пути: принимать что-то вроде 'matchesBetween, matchesBetween.goalsDifference' или давать возможность переопределять саму функцию сравнения.


    1. Crusader_12
      23.05.2017 20:00

      Если смотреть на примере АПЛ то там как раз не личные встречи считают а кто забил больше и у кого лучше разница голов.


  1. BigTenis
    23.05.2017 11:39

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


    1. antoniokov
      23.05.2017 11:49

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

      Рынок ставок мне неинтересен, поэтому двигаться в этом направлении желания нет.


  1. KreetKreet
    23.05.2017 11:39

    Добрый день!
    Идея неплохая, но есть серьезное замечание:
    Согласно Вашего примера в АПЛ после первого тура было такое положение:
    1. Халл 2-1
    2. Свонси 1-0

    5. МЮ 3-1
    6 Ливерпуль 4-3
    Это неверно. В АПЛ при равенстве очков считают сначала разницу забитых, пропущенных, а затем количество забитых.

    Так что визуализация это здорово, но порядок быть должон!


    1. antoniokov
      23.05.2017 11:50

      Справедливо, спасибо! Достаточно добавить в orderBy=«points,goalsDifference,goalsFor» — поправлю :)


    1. antoniokov
      23.05.2017 12:00

      Решил не откладывать в долгий ящик:


      1. KreetKreet
        23.05.2017 12:22

        Да, теперь порядок верный.
        Еще рекомендация, у Вас пишнтся изменение количества очков +3 +1 0. Мне кажется + тут лишнее, по-моему нет спортивных соревнований, где количество очков уменьшается :)


        1. antoniokov
          23.05.2017 12:26

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


          1. KreetKreet
            23.05.2017 12:34

            Возможно имеет смысл рассмотреть варианты представления, например, в большом теннисе точно количество очков за матч может меняться (для общего рейтинга), а вот футбол / хоккей может имеет смысл рассмотреть типовые «в», «н», «п» (выигрыш, ничья, поражение), а может и вовсе обойтись без этой метки. Так как, большинство болельщиков и так знают сколько очков дается в их виде спорта (футбол/хоккей) за результат — возможно достаточно будет уже существующей у Вас раскраски результата матча.


          1. feik_brutus
            23.05.2017 18:57

            Есть случаи когда Федерация лишает очков команду за нарушения (тот же Милан и Ювентус в 2006). Этот случай как отобразится?


            1. antoniokov
              24.05.2017 00:14

              Ух ты, вот это интересно. Об этом мы не думали, спасибо.

              Лучшим решением выглядит параметр fines в модуле calculate, в который будет приходить массив вида «команда-тур-количество штрафных очков», а визуализаторы уже будут сами решать, как лучше показывать штрафы.

              В спарклайнах я бы добавлял чёрные кирпичики в начало или конец сезона.

              Случай хоть и интересный, но достаточно редкий, поэтому мы пока займём выжидательную позицию до очередного коррупционного скандала :)


  1. Another09
    23.05.2017 12:00

    Есть общий вопрос. Откуда еще можно автоматом брать статистику? Маловато чемпионатов на football-data.org
    Видел еще football-data.co.uk, но там тоже только основные страны.


    1. antoniokov
      23.05.2017 12:05

      К сожалению, у меня нет ответа. Для прошлого года я брал csv с football-data.co.uk, в этом году — выгружал json из API football-data.org, потому что там здорово проставлены matchdays.

      Могу разве что посоветовать список спортивных баз и API. Но большинство ресурсов там уступают по удобству и полноте двум сайтам выше.

      Есть ещё платные API вроде Opta, но я их не пробовал.

      Будет здорово, если кто-то подскажет удобный API — можно будет сделать real-time таблицы.


  1. KreetKreet
    23.05.2017 12:38

    Отдельным вопросом. А как быть с отложенными матчами? Например, когда переносят 3 матча 4 тура. Остальные команды играют по расписанию, а вот отложенные играются позже.

    Как вариант могу предложить рассмотреть возможность двигаться не по турам, а по датам (чтобы отложенный матч влиял на таблицу в правильный момент времени), тогда конечно нужно сразу отображать текущее количество матчей, проведенных командой


    1. antoniokov
      23.05.2017 12:53

      В этом случае будет дырка в спарклайне, и она будет хорошо заметна. Как-то так:


      В классической таблице для незаконченных сезонов мы советуем выводить колонку с количеством сыгранных матчей — она называется «rounds».

      Если строить по датам, то получается уж очень большое число раундов. У нас есть ещё одно решение: подавать на вход список матчей с датами и ставить collapseToRounds="true": таблица сама посчитает 1-й, 2-й, 3-й и n-й матч для каждой команды и схлопнет 180 дат в 38 раундов.


      1. maxzuber
        23.05.2017 17:04

        Если тур разбивается на несколько игровых дней, группировка более чем желательна. Отложенный же матч вырывается из своего тура, и возвращать его на родное место некорректно. Лучше сделать дырку и сохранить игровую последовательность. Возможно, в один условный тур потребуется сгруппировать отложенные матчи из разных туров, в чемпионатах предусмотрены резервные даты. Например, в Испании недавно был отложенный матч Сельта — Реал. Зато все срезы будут соответствовать ходу чемпионата.

        Пропуск игры в любом случае лучше предусмотреть, ведь в группе с нечётным количеством участников в каждом туре есть отдыхающий.


        1. antoniokov
          24.05.2017 00:08

          Визуализация и сейчас умеет работать со случаем, когда команда сыграла 1-й и 3-й тур, но пропустила 2-й: на месте второго будет пустой «спарк».

          Дело исключительно в подготовке данных: как вы устроите matchweeks/matchdays, так результаты и отобразятся.