Не секрет, что среди айтишников много тех, кто любит физическую активность. Возможно, это вызвано сидячим характером работы и желанием позаботиться о своем здоровье. Или, может быть, это просто мода на велосипеды, бег и плавание. В любом случае, некоторые из тех, кто любит физическую активность, занимаются любительским спортом или регулярно тренируются.
Другая вещь, которую любят айтишники, это разнообразная статистика и цифры. Обычные спортивные сервисы не позволяют как-то играться со статистикой, предоставляя лишь стандартные виды отчетов, вроде счетчиков пробега или времени по неделям и дням недели и видам активности. Так уж получилось, что автор этих строк одновременно и тренируется, и участвует в разработке DevExpress Dashboard. И конечно же мне захотелось самому сделать дэшборд (и показать всем, как это легко) по данным из своего дневника тренировок.
Дневник я веду просто в виде таблицы Google doc. Вести дневник просто: для каждой тренировки надо записать по типу занятия, получившееся время, дистанцию, средней/максимальной скорости, данные по пульсу. Обычно я переношу в дневник данные из стравы или из movescount.com (так как тренировки я записываю при помощи часов suunto ambit 3). Самое сложное при этом — не забыть с утра измерить свой пульс в покое, что является показателем общей усталости и перетренированности, если она вдруг возникнет. Выглядит дневник так:
Наши дэшборды начиная с версии 15.2 позволяют импортировать данные из экселя, поэтому для использования их достаточно просто сохранить в файл в формате xls.
Конечно, для построения дэшборда данные пришлось немного «причесать». Я проставил правильные форматы (числовой или временной) для ячеек, удалил некорректные значения, а также добавил колонку «Тип активности», чтобы по ней можно было агрегировать. Она может принимать одно из следующих значений -«Road bike», «MTB», «Велотренажер», «Бассейн», «Бег» и «Тренажерный зал», которые я проставил руками для каждой тренировки.
Что бы мне хотелось увидеть на моем дэшборде:
— стандартную статистику по пробегам по типу активности — общие цифры пробега, времени и набора высот по типам активностей, а также их графики по времени,
— историю тренировок по дням недели, примерно как это выглядит в страве,
— какие-либо данные по пульсу, например корреляцию между средним пульсом на тренировке и средней скоростью,
— ну и конечно же, дэшборд должен быть живым, то есть не быть просто статической картинкой. В нем должен быть максимум интерактивности, чтобы можно было выбирать какой-то конкретный срез данных и посмотреть на них «более внимательно».
Теперь можно запустить дизайнер (а чтобы сделать дизайнер, достаточно создать новое WinForms приложение, добавить на форму DashboardDesigner и сгенерировать для него риббон), создать новый дэшборд (или аналитическую панель, как написано в русской локализации). Начнем с добавления в него источника данных из Excel:
Далее, добавим на дэшборд карточки, поместим поле «тип активности» в ряды данных (Series), и сделаем несколько карточек (по времени и по пробегу). Однако, тут есть несколько проблем:
Во-первых, длительность тренировки приходит из экселя в виде DateTime колонки, в которой составляющая даты равна 01.01.0001. Суммировать даты невозможно, и поэтому длительность необходимо перевести в число с плавающей точкой, что можно сделать с помощью вычисляемого поля (calculated field), задав ему выражение GetHour([TM]) + GetMinute([TM]) / 60.0. Тренировок длиннее суток у меня не предвидится, поэтому ограничимся часами и минутами.
Во-вторых, «голые» карточки смотрятся не очень хорошо, поэтому хорошо было бы добавить туда спарклайн. Но, для того, чтобы график красиво смотрелся, нужно сгруппировать данные по неделям. К сожалению, встроенного интервала группировки (Group interval) по неделям и годам у нас нет, а группировать только по номеру недели в году будет неправильно, придется сделать еще одно вычисляемое поле с датой начала недели, чтобы его можно было использовать как значение для группировки. Выражение будет выглядеть так AddDays([Дата], — GetDayOfWeek([Дата]) + 1). Еще чуть-чуть настроек (формат чисел и названия) и получаем следующее:
Да, дэшборды это не только числа и функциональность, но и красивая картинка. При разработке конкретного дэшборда приходится учитывать и его визуальную составляющую — все должно хорошо выглядеть.
После общих цифр мне хотелось бы показать на дэшборде более детальную информацию. Добавим графики объемов тренировок по пробегу, времени, набору высот в разрезе разного типа активностей и дат. Для этого создадим в дэшборде новый элемент — диаграмму (Chart). Чтобы получить группировку по неделям и годам, сначала добавим в аргументы поле «Дата» с группировкой по году, а потом еще раз его же с группировкой «Номер недели в году». Далее добавим несколько панелей (Рane) и добавим на них поля по продолжительности тренировки, времени и набору высоты. Далее, добавим в ряды (Series) тип тренировки, и включим по ним раскраску. Переключим типы графиков на всех панелях в «Stacked bar» (по-русски это звучит как «гистограмма с накоплением») и получим следующую картину:
Теперь хочется проверить — а правильные ли данные показывает дэшборд? А также удовлетворить любопытство и узнать, что же скрывается под конкретным столбиком на диаграмме. Например, узнать, а что за тренировки были в ту неделю, когда набор высоты перевалил за 3 тыс м? Для этого нужно дать дэшборду его важную способность — интерактивность. Для начала, добавим в дэшборд таблицу (Grid Dashboard Item). Я бы хотел увидеть там детальную информацию по тренировкам — то есть практически все поля из исходных данных. Придется потратить немного времени, добавляя их в таблицу и настраивая опции их отображения. После этого, включим у ранее добавленного графика режим множественного мастер-фильтра и посмотрим, что получилось:
Таким образом, кликая по графику, можно отфильтровать записи в таблице снизу. А чтобы фильтр не влиял на карточки вверху — им надо выставить режим игнорирования мастер фильтра. Заодно, можно сделать чтобы фильтр срабатывал и при клике по карточке. Только теперь, чтобы он не влиял на графики, им тоже придется запретить реагировать на мастер фильтр.
Итак, теперь дэшборд позволяет выбрать какой-то один или несколько конкретных типов активностей и увидеть список тренировок по ним в таблице внизу. После этого можно выбрать одну или несколько дат на графиках активности и отфильтровать данные в таблице еще более детально:
Теперь у нас есть статистика по объемам и датам тренировок, но в исходных данных есть еще данные о пульсе. По идее, средний пульс должен отражать интенсивность тренировки и хотелось бы посмотреть на корреляцию между средним пульсом и средней скоростью, что должно примерно отражать прогресс в тренировках. Конечно, простая зависимость пульс/средняя скорость не будет учитывать то, что по беговой дорожке бежать проще, чем по пересеченной местности, а для велосипеда скорость зависит еще и от качества дороги, ветра и прочих внешних факторов. Но все равно, было бы интересно на неё посмотреть.
Для этого воспользуемся точечной диаграммой. Поместим средний пульс на ось X, среднюю скорость на ось Y. В аргументы поместим дату поездки, чтобы точки не сливались в одну, и тип активности, чтобы раскрасить разные типы разным цветом (но тем же самым, которым раскрашены элементы диаграммы — спасибо поддержке дэшбордами глобальных палитр). В поле «вес» поместим «набор высот», чтобы отличать поездки по ровному рельефу от поездок с большим набором (но при этом мы теряем тренировки на велостанке, так как, к сожалению, для них нет данных о наборе высот и на диаграмме они показаны не будут).
Также будет удобно свести к одной шкале темп бега, который задается в минутах/км, и скорость при езде на велосипеде, которая задается в км/ч. Для этого сделаем еще одно вычисляемое поле «Средняя скорость/темп бега» со следующим выражением: Iif([AVS темп] < 1, [AVS темп] * 24, [AVS темп])
Вообще говоря, есть еще и плавание, где темп часто записывают в мин/100м, но точных данных по скорости в бассейне у меня набралось мало, да и набор высот в бассейне не имеет смысла. Поэтому скорость в бассейне я учитывать в этом выражении не стал. В лыжах скорость также часто записывают в виде темпа, как и при беге — но автор этих строк не очень любит беговые лыжи.
Включим для получившейся диаграммы режим фильтрации, чтобы по конкретному значению можно было узнать, какие тренировки в него попали. Итоговый дэшборд будет иметь следующий вид:
Что в результате получилось?
Дэшборд можно использовать для подробного «копания» в данных. Например, можно выбрать только беговые тренировки за определенную неделю и посмотреть для них распределение скорости/пульса. Или выбрать неделю с максимальным объемом тренировок и посмотреть, что это были за тренировки. Диаграмме пульса при этом покажет корреляцию между интенсивностью тренировки и средним пульсом, а также значения, «выпадающие» из общей тенденции. При этом можно будет легко посмотреть, почему они такие получились. В моем случае это либо большой набор высот, из-за которого при том же среднем пульсе средняя скорость получилась 15 км/ч вместо обычных для такого пульса 22 км/ч, либо специфический тип активности, как например, для мтб, где выделяются последние кросс-кантри гонки прошлого сезона. В которых, несмотря на достаточно экстремальные для меня значения пульса, средняя скорость получилась всего 10 км/ч, что, впрочем, для них нормально.
Исходный код примера, а также данные и xml файл дэшборда можно скачать с GitHub. Можно как попробовать поменять дэшборд, так и подставить свои данные в xls файл(или добавить свой источник данных).
Буду рад ответить на все вопросы, как по тренировочному процессу, так и по дэшбордам.
Автор: DevExpress