Sync your own workout data from your "Strong" app
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge pull request #8 from tolik518/examples

authored by

Anatolij Vasilev and committed by
GitHub
cd9597f0 4209d081

+302
.github/heatmap.png

This is a binary file and will not be displayed.

+12
README.MD
··· 6 6 The URL to the API backend is not provided here, for now, because it's not entirely public and because of possible legal implications. 7 7 8 8 If using docker-compose, the service will run 18:00, 18:30, 19:00, 19:30, 20:00 and 20:30, but you can change this in the `Dockerfile`. 9 + 10 + ## Why? 11 + 12 + So you can do fun stuff with your workout data, like doing silly grafana dashboards. 13 + For example, you can use the [Grafana Clickhouse plugin](https://grafana.com/grafana/plugins/grafana-clickhouse-datasource/) to visualize your workout data. 14 + 15 + You can make heatmaps, like the one you have on github, or you can make a dashboard that shows your progress over time, or you can make a dashboard that shows your workout history. 16 + 17 + ![heatmap](./.github/heatmap.png) 18 + You can find the Grafana JSON for the [heatmap](./examples/heatmap.json) and for the [excercises per week](./examples/excercises_per_week.json) in the [examples](./examples) folder. 19 + 20 + 9 21 ## How to use 10 22 11 23 0. Have your Clckhouse database ready and running
+152
examples/grafana/excercises-per-week.json
··· 1 + { 2 + "id": 11, 3 + "type": "barchart", 4 + "title": "Excercises per week", 5 + "gridPos": { 6 + "x": 0, 7 + "y": 1, 8 + "h": 8, 9 + "w": 24 10 + }, 11 + "fieldConfig": { 12 + "defaults": { 13 + "custom": { 14 + "lineWidth": 1, 15 + "fillOpacity": 73, 16 + "gradientMode": "none", 17 + "axisPlacement": "right", 18 + "axisLabel": "", 19 + "axisColorMode": "series", 20 + "axisBorderShow": false, 21 + "scaleDistribution": { 22 + "type": "linear" 23 + }, 24 + "axisCenteredZero": false, 25 + "hideFrom": { 26 + "tooltip": false, 27 + "viz": false, 28 + "legend": false 29 + }, 30 + "thresholdsStyle": { 31 + "mode": "off" 32 + }, 33 + "axisGridShow": true 34 + }, 35 + "color": { 36 + "mode": "thresholds" 37 + }, 38 + "mappings": [], 39 + "thresholds": { 40 + "mode": "absolute", 41 + "steps": [ 42 + { 43 + "color": "transparent", 44 + "value": null 45 + }, 46 + { 47 + "color": "light-green", 48 + "value": 1 49 + }, 50 + { 51 + "value": 2, 52 + "color": "green" 53 + }, 54 + { 55 + "value": 3, 56 + "color": "semi-dark-green" 57 + }, 58 + { 59 + "value": 4, 60 + "color": "dark-green" 61 + } 62 + ] 63 + }, 64 + "fieldMinMax": false, 65 + "max": 7, 66 + "min": 0 67 + }, 68 + "overrides": [ 69 + { 70 + "matcher": { 71 + "id": "byValue", 72 + "options": { 73 + "reducer": "count", 74 + "op": "neq", 75 + "value": 0 76 + } 77 + }, 78 + "properties": [ 79 + { 80 + "id": "mappings", 81 + "value": [ 82 + { 83 + "type": "value", 84 + "options": { 85 + "0": { 86 + "index": 0, 87 + "text": "​" 88 + } 89 + } 90 + } 91 + ] 92 + } 93 + ] 94 + } 95 + ] 96 + }, 97 + "pluginVersion": "11.6.1", 98 + "targets": [ 99 + { 100 + "datasource": { 101 + "type": "grafana-clickhouse-datasource", 102 + "uid": "cegmu4gilxn28d" 103 + }, 104 + "editorType": "sql", 105 + "format": 0, 106 + "meta": { 107 + "builderOptions": { 108 + "columns": [], 109 + "database": "", 110 + "limit": 1000, 111 + "mode": "list", 112 + "queryType": "table", 113 + "table": "" 114 + } 115 + }, 116 + "pluginVersion": "4.8.2", 117 + "queryType": "timeseries", 118 + "rawSql": "WITH\n 'Europe/Berlin' AS tz,\n -- Time frame of the and get the week start\n toStartOfWeek(toDate(toTimeZone(toDateTime(intDiv(${__from},1000)), tz)), 1) AS w_from,\n toStartOfWeek(toDate(toTimeZone(toDateTime(intDiv(${__to}, 1000)), tz)), 1) AS w_to,\n\n -- All Weeks in Range\n weeks AS (\n SELECT addWeeks(w_from, number) AS week_start\n FROM numbers(dateDiff('week', w_from, w_to) + 1)\n ),\n\n -- Real Sessions per Week\n per_week AS (\n SELECT\n toStartOfWeek(toTimeZone(start_date, tz), 1) AS week_start,\n countDistinct(workout_id) AS sessions\n FROM workouts.workout_sets\n WHERE $__timeFilter(start_date)\n GROUP BY week_start\n )\n\n-- Ergebnis: every week exactly once, missing zeroes added => 0, Label = Weeknumber\nSELECT\n concat(leftPad(toString(toISOWeek(week_start)),2,'0')) AS week_label,\n ifNull(p.sessions, 0) AS sessions\nFROM weeks w\nLEFT JOIN per_week p USING (week_start)\nORDER BY week_start;\n", 119 + "refId": "A" 120 + } 121 + ], 122 + "datasource": { 123 + "type": "grafana-clickhouse-datasource", 124 + "uid": "cegmu4gilxn28d" 125 + }, 126 + "options": { 127 + "orientation": "vertical", 128 + "xTickLabelRotation": 0, 129 + "xTickLabelSpacing": -100, 130 + "showValue": "always", 131 + "stacking": "none", 132 + "groupWidth": 0.7, 133 + "barWidth": 0.9, 134 + "barRadius": 0.25, 135 + "fullHighlight": false, 136 + "tooltip": { 137 + "mode": "single", 138 + "sort": "none", 139 + "hideZeros": false 140 + }, 141 + "legend": { 142 + "showLegend": false, 143 + "displayMode": "list", 144 + "placement": "right", 145 + "calcs": [] 146 + }, 147 + "text": {}, 148 + "xField": "week_label", 149 + "colorByField": "sessions" 150 + }, 151 + "timeFrom": "365d" 152 + }
+138
examples/grafana/heatmap.json
··· 1 + { 2 + "id": 7, 3 + "type": "status-history", 4 + "title": "Heatmap", 5 + "gridPos": { 6 + "x": 0, 7 + "y": 9, 8 + "h": 8, 9 + "w": 21 10 + }, 11 + "fieldConfig": { 12 + "defaults": { 13 + "custom": { 14 + "lineWidth": 0, 15 + "fillOpacity": 80, 16 + "hideFrom": { 17 + "tooltip": false, 18 + "viz": false, 19 + "legend": false 20 + }, 21 + "axisPlacement": "auto" 22 + }, 23 + "color": { 24 + "mode": "thresholds" 25 + }, 26 + "mappings": [], 27 + "thresholds": { 28 + "mode": "absolute", 29 + "steps": [ 30 + { 31 + "color": "#2f2f2fed", 32 + "value": null 33 + }, 34 + { 35 + "color": "semi-dark-green", 36 + "value": 1 37 + }, 38 + { 39 + "color": "dark-green", 40 + "value": 2 41 + } 42 + ] 43 + }, 44 + "fieldMinMax": false, 45 + "min": 0, 46 + "decimals": 0, 47 + "noValue": "0" 48 + }, 49 + "overrides": [] 50 + }, 51 + "transformations": [ 52 + { 53 + "id": "renameByRegex", 54 + "options": { 55 + "regex": "value \\d(.*)", 56 + "renamePattern": "$1" 57 + } 58 + } 59 + ], 60 + "pluginVersion": "11.6.1", 61 + "targets": [ 62 + { 63 + "builderOptions": { 64 + "aggregates": [], 65 + "columns": [ 66 + { 67 + "alias": "*", 68 + "custom": false, 69 + "name": "*", 70 + "type": "String" 71 + } 72 + ], 73 + "database": "workouts", 74 + "filters": [], 75 + "groupBy": [], 76 + "limit": 1000, 77 + "meta": {}, 78 + "mode": "list", 79 + "orderBy": [], 80 + "queryType": "table", 81 + "table": "workout_sets" 82 + }, 83 + "datasource": { 84 + "type": "grafana-clickhouse-datasource", 85 + "uid": "cegmu4gilxn28d" 86 + }, 87 + "editorType": "sql", 88 + "format": 0, 89 + "meta": { 90 + "builderOptions": { 91 + "aggregates": [], 92 + "columns": [ 93 + { 94 + "alias": "*", 95 + "custom": false, 96 + "name": "*", 97 + "type": "String" 98 + } 99 + ], 100 + "database": "workouts", 101 + "filters": [], 102 + "groupBy": [], 103 + "limit": 1000, 104 + "meta": {}, 105 + "mode": "list", 106 + "orderBy": [], 107 + "queryType": "table", 108 + "table": "workout_sets" 109 + } 110 + }, 111 + "pluginVersion": "4.8.2", 112 + "queryType": "timeseries", 113 + "rawSql": "WITH\n 'Europe/Berlin' AS tz,\n toStartOfWeek(toDate(toTimeZone(toDateTime(intDiv(${__from},1000)), tz)), 1) AS w_from,\n toStartOfWeek(toDate(toTimeZone(toDateTime(intDiv(${__to}, 1000)), tz)), 1) AS w_to,\n\n weeks AS (\n SELECT addWeeks(w_from, number) AS week_start\n FROM numbers(dateDiff('week', w_from, w_to) + 1)\n ),\n\n per_day AS (\n SELECT\n toDate(toTimeZone(start_date, tz)) AS day,\n countDistinct(workout_id) AS sessions\n FROM workouts.workout_sets\n WHERE $__timeFilter(start_date)\n GROUP BY day\n ),\n\n grid AS (\n /* 7 \"Slots\" per week (Mo..So) */\n SELECT\n w.week_start,\n n.number AS dow0, -- 0..6\n addDays(w.week_start, n.number) AS day\n FROM weeks w\n CROSS JOIN numbers(7) AS n\n )\n\nSELECT\n week_start AS time, -- X-Axis = Beginning of the week (Monday)\n concat(toString(dow0+1), ' ', formatDateTime(day, '%a')) AS metric, -- Name of the row\n ifNull(per_day.sessions, 0) AS value\nFROM grid\nLEFT JOIN per_day USING (day)\nORDER BY time, metric;\n", 114 + "refId": "A" 115 + } 116 + ], 117 + "datasource": { 118 + "type": "grafana-clickhouse-datasource", 119 + "uid": "cegmu4gilxn28d" 120 + }, 121 + "options": { 122 + "showValue": "never", 123 + "rowHeight": 0.85, 124 + "colWidth": 0.8, 125 + "legend": { 126 + "showLegend": false, 127 + "displayMode": "table", 128 + "placement": "right" 129 + }, 130 + "tooltip": { 131 + "mode": "multi", 132 + "sort": "none", 133 + "hideZeros": false 134 + }, 135 + "perPage": 0 136 + }, 137 + "timeFrom": "365d" 138 + }