geo-activity-playground 0.45.0__py3-none-any.whl → 1.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. geo_activity_playground/alembic/versions/dc8073871da7_add_plotspec_group_by.py +28 -0
  2. geo_activity_playground/core/config.py +1 -0
  3. geo_activity_playground/core/datamodel.py +12 -0
  4. geo_activity_playground/core/export.py +129 -0
  5. geo_activity_playground/core/meta_search.py +1 -1
  6. geo_activity_playground/core/parametric_plot.py +101 -47
  7. geo_activity_playground/webui/app.py +10 -1
  8. geo_activity_playground/webui/authenticator.py +4 -2
  9. geo_activity_playground/webui/blueprints/activity_blueprint.py +11 -10
  10. geo_activity_playground/webui/blueprints/auth_blueprint.py +6 -2
  11. geo_activity_playground/webui/blueprints/bubble_chart_blueprint.py +2 -1
  12. geo_activity_playground/webui/blueprints/calendar_blueprint.py +3 -2
  13. geo_activity_playground/webui/blueprints/eddington_blueprints.py +3 -2
  14. geo_activity_playground/webui/blueprints/entry_views.py +11 -11
  15. geo_activity_playground/webui/blueprints/equipment_blueprint.py +2 -1
  16. geo_activity_playground/webui/blueprints/explorer_blueprint.py +343 -197
  17. geo_activity_playground/webui/blueprints/export_blueprint.py +31 -0
  18. geo_activity_playground/webui/blueprints/hall_of_fame_blueprint.py +79 -0
  19. geo_activity_playground/webui/blueprints/plot_builder_blueprint.py +38 -19
  20. geo_activity_playground/webui/blueprints/summary_blueprint.py +114 -240
  21. geo_activity_playground/webui/blueprints/upload_blueprint.py +9 -0
  22. geo_activity_playground/webui/columns.py +40 -7
  23. geo_activity_playground/webui/static/{browserconfig.xml → favicons/browserconfig.xml} +1 -1
  24. geo_activity_playground/webui/static/{site.webmanifest → favicons/site.webmanifest} +2 -2
  25. geo_activity_playground/webui/static/server-side-explorer.js +60 -0
  26. geo_activity_playground/webui/templates/activity/name.html.j2 +4 -4
  27. geo_activity_playground/webui/templates/activity/show.html.j2 +8 -8
  28. geo_activity_playground/webui/templates/auth/index.html.j2 +1 -0
  29. geo_activity_playground/webui/templates/eddington/distance.html.j2 +3 -3
  30. geo_activity_playground/webui/templates/eddington/elevation_gain.html.j2 +3 -3
  31. geo_activity_playground/webui/templates/elevation_eddington/index.html.j2 +3 -3
  32. geo_activity_playground/webui/templates/equipment/index.html.j2 +1 -1
  33. geo_activity_playground/webui/templates/explorer/server-side.html.j2 +42 -36
  34. geo_activity_playground/webui/templates/export/index.html.j2 +39 -0
  35. geo_activity_playground/webui/templates/hall_of_fame/index.html.j2 +58 -0
  36. geo_activity_playground/webui/templates/home.html.j2 +1 -4
  37. geo_activity_playground/webui/templates/page.html.j2 +26 -43
  38. geo_activity_playground/webui/templates/plot-macros.html.j2 +72 -0
  39. geo_activity_playground/webui/templates/plot_builder/edit.html.j2 +12 -7
  40. geo_activity_playground/webui/templates/plot_builder/import-spec.html.j2 +24 -0
  41. geo_activity_playground/webui/templates/plot_builder/index.html.j2 +5 -0
  42. geo_activity_playground/webui/templates/summary/index.html.j2 +23 -230
  43. geo_activity_playground/webui/templates/summary/vega-chart.html.j2 +3 -0
  44. {geo_activity_playground-0.45.0.dist-info → geo_activity_playground-1.1.0.dist-info}/METADATA +2 -1
  45. {geo_activity_playground-0.45.0.dist-info → geo_activity_playground-1.1.0.dist-info}/RECORD +74 -65
  46. geo_activity_playground/webui/templates/explorer/index.html.j2 +0 -148
  47. /geo_activity_playground/webui/static/{bootstrap-dark-mode.js → bootstrap/bootstrap-dark-mode.js} +0 -0
  48. /geo_activity_playground/webui/static/{bootstrap.bundle.min.js → bootstrap/bootstrap.bundle.min.js} +0 -0
  49. /geo_activity_playground/webui/static/{bootstrap.min.css → bootstrap/bootstrap.min.css} +0 -0
  50. /geo_activity_playground/webui/static/{android-chrome-192x192.png → favicons/android-chrome-192x192.png} +0 -0
  51. /geo_activity_playground/webui/static/{android-chrome-512x512.png → favicons/android-chrome-512x512.png} +0 -0
  52. /geo_activity_playground/webui/static/{apple-touch-icon.png → favicons/apple-touch-icon.png} +0 -0
  53. /geo_activity_playground/webui/static/{favicon-16x16.png → favicons/favicon-16x16.png} +0 -0
  54. /geo_activity_playground/webui/static/{favicon-32x32.png → favicons/favicon-32x32.png} +0 -0
  55. /geo_activity_playground/webui/static/{favicon-48x48.png → favicons/favicon-48x48.png} +0 -0
  56. /geo_activity_playground/webui/static/{favicon.ico → favicons/favicon.ico} +0 -0
  57. /geo_activity_playground/webui/static/{favicon.svg → favicons/favicon.svg} +0 -0
  58. /geo_activity_playground/webui/static/{mstile-150x150.png → favicons/mstile-150x150.png} +0 -0
  59. /geo_activity_playground/webui/static/{web-app-manifest-192x192.png → favicons/web-app-manifest-192x192.png} +0 -0
  60. /geo_activity_playground/webui/static/{web-app-manifest-512x512.png → favicons/web-app-manifest-512x512.png} +0 -0
  61. /geo_activity_playground/webui/static/{Leaflet.fullscreen.min.js → leaflet/Leaflet.fullscreen.min.js} +0 -0
  62. /geo_activity_playground/webui/static/{MarkerCluster.Default.css → leaflet/MarkerCluster.Default.css} +0 -0
  63. /geo_activity_playground/webui/static/{MarkerCluster.css → leaflet/MarkerCluster.css} +0 -0
  64. /geo_activity_playground/webui/static/{fullscreen.png → leaflet/fullscreen.png} +0 -0
  65. /geo_activity_playground/webui/static/{fullscreen@2x.png → leaflet/fullscreen@2x.png} +0 -0
  66. /geo_activity_playground/webui/static/{leaflet.css → leaflet/leaflet.css} +0 -0
  67. /geo_activity_playground/webui/static/{leaflet.fullscreen.css → leaflet/leaflet.fullscreen.css} +0 -0
  68. /geo_activity_playground/webui/static/{leaflet.js → leaflet/leaflet.js} +0 -0
  69. /geo_activity_playground/webui/static/{leaflet.markercluster.js → leaflet/leaflet.markercluster.js} +0 -0
  70. /geo_activity_playground/webui/static/{vega-embed@6 → vega/vega-embed@6.js} +0 -0
  71. /geo_activity_playground/webui/static/{vega-lite@4 → vega/vega-lite@4.js} +0 -0
  72. /geo_activity_playground/webui/static/{vega@5 → vega/vega@5.js} +0 -0
  73. {geo_activity_playground-0.45.0.dist-info → geo_activity_playground-1.1.0.dist-info}/LICENSE +0 -0
  74. {geo_activity_playground-0.45.0.dist-info → geo_activity_playground-1.1.0.dist-info}/WHEEL +0 -0
  75. {geo_activity_playground-0.45.0.dist-info → geo_activity_playground-1.1.0.dist-info}/entry_points.txt +0 -0
@@ -1,6 +1,8 @@
1
1
  <!DOCTYPE html>
2
2
  <html lang="en">
3
3
 
4
+ {% from "plot-macros.html.j2" import vega, vega_direct, activity_tag, tabbed_vega %}
5
+
4
6
  <head>
5
7
  <meta charset="utf-8">
6
8
  <meta name="viewport" content="width=device-width, initial-scale=1">
@@ -8,37 +10,37 @@
8
10
  <title>Geo Activity Playground</title>
9
11
 
10
12
  <!-- Bootstrap CSS. -->
11
- <link href="/static/bootstrap.min.css" rel="stylesheet">
13
+ <link href="/static/bootstrap/bootstrap.min.css" rel="stylesheet">
12
14
 
13
15
  <!-- Leaflet for interactive maps. -->
14
- <link rel="stylesheet" href="/static/leaflet.css" />
15
- <script src="/static/leaflet.js"></script>
16
+ <link rel="stylesheet" href="/static/leaflet/leaflet.css" />
17
+ <script src="/static/leaflet/leaflet.js"></script>
16
18
 
17
19
  <!-- Fullscreen button for Leaflet. -->
18
- <link href='/static/leaflet.fullscreen.css' rel='stylesheet' />
19
- <script src='/static/Leaflet.fullscreen.min.js'></script>
20
+ <link href='/static/leaflet/leaflet.fullscreen.css' rel='stylesheet' />
21
+ <script src='/static/leaflet/Leaflet.fullscreen.min.js'></script>
20
22
 
21
- <link rel="stylesheet" href="/static/MarkerCluster.css" />
22
- <link rel="stylesheet" href="/static/MarkerCluster.Default.css" />
23
- <script src="/static/leaflet.markercluster.js"></script>
23
+ <link rel="stylesheet" href="/static/leaflet/MarkerCluster.css" />
24
+ <link rel="stylesheet" href="/static/leaflet/MarkerCluster.Default.css" />
25
+ <script src="/static/leaflet/leaflet.markercluster.js"></script>
24
26
 
25
27
  <!-- Vega for plots.-->
26
- <script src="/static/vega@5"></script>
27
- <script src="/static/vega-lite@4"></script>
28
- <script src="/static/vega-embed@6"></script>
28
+ <script src="/static/vega/vega@5.js"></script>
29
+ <script src="/static/vega/vega-lite@4.js"></script>
30
+ <script src="/static/vega/vega-embed@6.js"></script>
29
31
 
30
- <script src="/static/bootstrap-dark-mode.js"></script>
32
+ <script src="/static/bootstrap/bootstrap-dark-mode.js"></script>
31
33
 
32
34
  <script src="/static/table-sort.min.js"></script>
33
35
 
34
36
  <!-- Favicon. -->
35
- <link rel="apple-touch-icon" sizes="180x180" href="/static/apple-touch-icon.png">
36
- <link rel="icon" type="image/png" sizes="32x32" href="/static/favicon-32x32.png">
37
- <link rel="icon" type="image/png" sizes="16x16" href="/static/favicon-16x16.png">
38
- <link rel="manifest" href="/static/site.webmanifest">
39
- <link rel="shortcut icon" href="/static/favicon.ico">
37
+ <link rel="apple-touch-icon" sizes="180x180" href="/static/favicons/apple-touch-icon.png">
38
+ <link rel="icon" type="image/png" sizes="32x32" href="/static/favicons/favicon-32x32.png">
39
+ <link rel="icon" type="image/png" sizes="16x16" href="/static/favicons/favicon-16x16.png">
40
+ <link rel="manifest" href="/static/favicons/site.webmanifest">
41
+ <link rel="shortcut icon" href="/static/favicons/favicon.ico">
40
42
  <meta name="msapplication-TileColor" content="#da532c">
41
- <meta name="msapplication-config" content="/static/browserconfig.xml">
43
+ <meta name="msapplication-config" content="/static/favicons/browserconfig.xml">
42
44
  <meta name="theme-color" content="#ffffff">
43
45
  </head>
44
46
 
@@ -78,6 +80,8 @@
78
80
  <li><a class="dropdown-item" href="{{ url_for('summary.index') }}">Summary
79
81
  Statistics</a>
80
82
  </li>
83
+ <li><a class="dropdown-item" href="{{ url_for('hall_of_fame.index') }}">Hall of Fame</a>
84
+ </li>
81
85
  <li><a class="dropdown-item" href="{{ url_for('eddington.distance') }}">Eddington
82
86
  Number</a>
83
87
  </li>
@@ -94,14 +98,10 @@
94
98
  Explorer
95
99
  </a>
96
100
  <ul class="dropdown-menu">
97
- <li><a class="dropdown-item" href="{{ url_for('explorer.map', zoom=14) }}">Explorer
98
- Tiles (Zoom 14)</a></li>
99
- <li><a class="dropdown-item" href="{{ url_for('explorer.map', zoom=17) }}">Squadratinhos
100
- (Zoom 17)</a></li>
101
- <li><a class="dropdown-item" href="{{ url_for('explorer.server_side', zoom=14) }}">Fast
101
+ <li><a class="dropdown-item" href="{{ url_for('explorer.server_side', zoom=14) }}">
102
102
  Explorer
103
103
  Tiles (Zoom 14)</a></li>
104
- <li><a class="dropdown-item" href="{{ url_for('explorer.server_side', zoom=17) }}">Fast
104
+ <li><a class="dropdown-item" href="{{ url_for('explorer.server_side', zoom=17) }}">
105
105
  Squadratinhos
106
106
  (Zoom 17)</a></li>
107
107
 
@@ -150,6 +150,7 @@
150
150
  <li><a class="dropdown-item" href="{{ url_for('plot_builder.index') }}">Plot Builder</a>
151
151
  </li>
152
152
  <li><a class="dropdown-item" href="{{ url_for('settings.index') }}">Settings</a></li>
153
+ <li><a class="dropdown-item" href="{{ url_for('export.index') }}">Data Export</a></li>
153
154
  </ul>
154
155
  </li>
155
156
 
@@ -186,24 +187,6 @@
186
187
  </div>
187
188
  </nav>
188
189
 
189
- {% macro vega(id, path) %}
190
- <div id="{{ id }}"></div>
191
- <script type="text/javascript">
192
- vegaEmbed('#{{ id }}', "{{ path }}").then(function (result) { }).catch(console.error);
193
- </script>
194
- {% endmacro %}
195
-
196
- {% macro vega_direct(id, spec) %}
197
- <div id="{{ id }}"></div>
198
- <script type="text/javascript">
199
- vegaEmbed('#{{ id }}', {{ spec| safe }}).then(function (result) { }).catch(console.error);
200
- </script>
201
- {% endmacro %}
202
-
203
- {% macro activity_tag(tag) %}
204
- <span class="badge" style="background-color: {{ tag.color or '#0d6efd' }}">{{ tag.tag }}</span>
205
- {% endmacro %}
206
-
207
190
  {% with messages = get_flashed_messages(with_categories=true) %}
208
191
  {% if messages %}
209
192
  {% for category, message in messages %}
@@ -238,7 +221,7 @@
238
221
  </div>
239
222
  </div>
240
223
 
241
- <script src="/static/bootstrap.bundle.min.js"></script>
224
+ <script src="/static/bootstrap/bootstrap.bundle.min.js"></script>
242
225
  </body>
243
226
 
244
227
  </html>
@@ -0,0 +1,72 @@
1
+ {% macro vega(path) %}
2
+ {% set id = unique_id() %}
3
+ <div id="{{ id }}"></div>
4
+ <script type="text/javascript">
5
+ vegaEmbed('#{{ id }}', "{{ path }}").then(function (result) { }).catch(console.error);
6
+ </script>
7
+ {% endmacro %}
8
+
9
+ {% macro vega_direct(spec) %}
10
+ {% set id = unique_id() %}
11
+ <div id="{{ id }}"></div>
12
+ <script type="text/javascript">
13
+ vegaEmbed('#{{ id }}', {{ spec| safe }}).then(function (result) { }).catch(console.error);
14
+ </script>
15
+ {% endmacro %}
16
+
17
+ {% macro activity_tag(tag) %}
18
+ <span class="badge" style="background-color: {{ tag.color or '#0d6efd' }}">{{ tag.tag }}</span>
19
+ {% endmacro %}
20
+
21
+ {% macro tabbed_vega(tab_dict, last=False) %}
22
+ {% set id = unique_id() %}
23
+ <ul class="nav nav-pills mb-3" role="tablist">
24
+ {% for key in tab_dict.keys() %}
25
+ {% set plot_id = id ~ "-" ~ loop.index %}
26
+ <li class="nav-item" role="presentation">
27
+ <button class="nav-link {% if (last and loop.last) or (not last and loop.first) %} active {% endif %}"
28
+ id="{{ plot_id }}-tab" data-bs-toggle="tab" data-bs-target="#{{ plot_id }}-pane" type="button" role="tab"
29
+ aria-controls="{{ plot_id }}-pane" aria-selected="{{ loop.last }}">{{ key }}</button>
30
+ </li>
31
+ {% endfor %}
32
+ </ul>
33
+ <div class="tab-content mb-3">
34
+ {% for plot in tab_dict.values() %}
35
+ {% set plot_id = id ~ "-" ~ loop.index %}
36
+ <div class="tab-pane fade {% if (last and loop.last) or (not last and loop.first) %} show active {% endif %}"
37
+ id="{{ plot_id }}-pane" role="tabpanel" aria-labelledby="{{ plot_id }}-tab" tabindex="0">
38
+ {{ vega_direct(plot) }}
39
+ </div>
40
+ {% endfor %}
41
+ </div>
42
+ {% endmacro %}
43
+
44
+ {% macro parametric_plot(spec, plot_groups, outer_loop_index) %}
45
+ {% if spec.group_by %}
46
+ <ul class="nav nav-pills mb-3" id="myTab_{{ outer_loop_index }}" role="tablist">
47
+ {% for key, plot in plot_groups.items() %}
48
+ {% set plot_id = "custom_plot_" ~ outer_loop_index ~ "_" ~ loop.index %}
49
+ <li class="nav-item" role="presentation">
50
+ <button class="nav-link {% if loop.last %} active {% endif %}" id="{{ plot_id }}-tab" data-bs-toggle="tab"
51
+ data-bs-target="#{{ plot_id }}-pane" type="button" role="tab" aria-controls="{{ plot_id }}-pane"
52
+ aria-selected="{{ loop.last }}">{{ key }}</button>
53
+ </li>
54
+ {% endfor %}
55
+ </ul>
56
+ <div class="tab-content mb-3" id="myTabContent_{{ outer_loop_index }}">
57
+ {% for key, plot in plot_groups.items() %}
58
+ {% set plot_id = "custom_plot_" ~ outer_loop_index ~ "_" ~ loop.index %}
59
+ <div class="tab-pane fade {% if loop.last %} show active {% endif %}" id="{{ plot_id }}-pane" role="tabpanel"
60
+ aria-labelledby="{{ plot_id }}-tab" tabindex="0">
61
+ {{ vega_direct(plot) }}
62
+ </div>
63
+ {% endfor %}
64
+ </div>
65
+ {% else %}
66
+ <div class="row mb-3">
67
+ <div class="col">
68
+ {{ vega_direct(plot_groups[""]) }}
69
+ </div>
70
+ </div>
71
+ {% endif %}
72
+ {% endmacro %}
@@ -1,11 +1,17 @@
1
1
  {% extends "page.html.j2" %}
2
2
 
3
- {% block container %}
3
+ {% from "plot-macros.html.j2" import parametric_plot %}
4
4
 
5
- <h1 class="row mb-3">Plot Builder</h1>
5
+ {% block container %}
6
6
 
7
- <div class="mb-3"><a class="btn btn-primary" href="{{ url_for('.index') }}">Back to overview</a></div>
7
+ <nav aria-label="breadcrumb">
8
+ <ol class="breadcrumb">
9
+ <li class="breadcrumb-item"><a href="{{ url_for('.index') }}">Plot Builder</a></li>
10
+ <li class="breadcrumb-item active" aria-current="page">Edit</li>
11
+ </ol>
12
+ </nav>
8
13
 
14
+ <h1 class="row mb-3">Plot Builder</h1>
9
15
 
10
16
  <div class="row mb-3">
11
17
  <div class="col-md-4">
@@ -22,12 +28,13 @@
22
28
  </div>
23
29
  {% endmacro %}
24
30
 
25
- <form>
31
+ <form method="post">
26
32
  <div class="mb-3">
27
33
  <label for="name">Name</label>
28
34
  <input type="text" name="name" id="name" class="form-control" value="{{ spec.name }}">
29
35
  </div>
30
36
 
37
+ {{ select_field("Group by", "group_by", group_by, spec.group_by)}}
31
38
  {{ select_field("Mark", "mark", marks, spec.mark)}}
32
39
 
33
40
  {{ select_field("X", "x", continuous, spec.x)}}
@@ -45,7 +52,7 @@
45
52
  </div>
46
53
  <div class="col-md-8">
47
54
  {% if plot %}
48
- {{ vega_direct("plot", plot) }}
55
+ {{ parametric_plot(spec, plot, 0) }}
49
56
  {% endif %}
50
57
  </div>
51
58
  </div>
@@ -58,6 +65,4 @@
58
65
 
59
66
  <code><pre>{{ spec.to_json() }}</pre></code>
60
67
 
61
-
62
-
63
68
  {% endblock %}
@@ -0,0 +1,24 @@
1
+ {% extends "page.html.j2" %}
2
+
3
+ {% block container %}
4
+
5
+ <nav aria-label="breadcrumb">
6
+ <ol class="breadcrumb">
7
+ <li class="breadcrumb-item"><a href="{{ url_for('.index') }}">Plot Builder</a></li>
8
+ <li class="breadcrumb-item active" aria-current="page">Import</li>
9
+ </ol>
10
+ </nav>
11
+
12
+ <h1 class="mb-3">Import Custom Plot</h1>
13
+
14
+ <form method="post">
15
+ <div class="mb-3">
16
+ <label for="spec_json" class="form-label">Plot specification JSON</label>
17
+ <textarea class="form-control" id="spec_json" rows="3" name="spec_json"></textarea>
18
+ </div>
19
+
20
+ <button type="submit" class="btn btn-primary">Import & Preview</button>
21
+ </form>
22
+
23
+
24
+ {% endblock %}
@@ -2,8 +2,11 @@
2
2
 
3
3
  {% block container %}
4
4
 
5
+
5
6
  <h1 class="row mb-3">Plot Builder</h1>
6
7
 
8
+ <p>Build custom plots here. For inspiration, check out <a href="https://martin-ueding.github.io/geo-activity-playground/build-custom-plots/" target="_blank">the documentation</a>.</p>
9
+
7
10
  {% if specs %}
8
11
  <table class="table mb-3">
9
12
  <thead>
@@ -29,4 +32,6 @@
29
32
 
30
33
  <a class="btn btn-primary" href="{{ url_for('.new') }}">New</a>
31
34
 
35
+ <a class="btn btn-primary" href="{{ url_for('.import_spec') }}">Import</a>
36
+
32
37
  {% endblock %}
@@ -1,5 +1,7 @@
1
1
  {% extends "page.html.j2" %}
2
2
 
3
+ {% from "plot-macros.html.j2" import parametric_plot %}
4
+
3
5
  {% block container %}
4
6
 
5
7
  <h1>Summary Statistics</h1>
@@ -9,249 +11,40 @@
9
11
  </div>
10
12
 
11
13
  {% if custom_plots %}
12
- <h2>Your custom plots</h2>
13
- {% for spec, plot in custom_plots %}
14
- <h3>{{ spec.name }}</h3>
15
- <div class="row mb-3">
16
- <div class="col">
17
- {{ vega_direct("custom_plot_" ~ loop.index, plot) }}
18
- </div>
19
- </div>
14
+ <h2>Custom plots</h2>
15
+ {% for spec, plot_groups in custom_plots %}
16
+ <h3 class="mb-3">{{ spec.name }}</h3>
17
+ {{ parametric_plot(spec, plot_groups, loop.index) }}
18
+ <p><a class="btn btn-sm btn-secondary" href="{{ url_for('plot_builder.edit', id=spec.id) }}">Edit this plot</a></p>
20
19
  {% endfor %}
21
20
  {% endif %}
22
21
 
23
- <h2>Distances</h2>
22
+ <h2>Per year and kind</h2>
24
23
 
25
- <p>This is your weekly distance for the past rolling year, split by activity kind.</p>
24
+ <p>How much distance (or else) did you cover within each year? The following plots show the quantity summed up for a
25
+ year, differentiated by activity kind.</p>
26
26
 
27
- <div class="row mb-3">
28
- <div class="col">
29
- {{ vega_direct("plot_weekly_distance", plot_weekly_distance) }}
30
- </div>
31
- </div>
27
+ {{ tabbed_vega(plot_per_year_per_kind) }}
32
28
 
33
- <p>Similarly, you find the same data but aggregated by whole months for the past two years. Also split by activity kind.
34
- </p>
35
-
36
- <div class="row mb-3">
37
- <div class="col">
38
- {{ vega_direct("plot_monthly_distance", plot_monthly_distance) }}
39
- </div>
40
- </div>
29
+ <h2>Per week</h2>
41
30
 
42
- <p>How much distance have you covered in each year up to that time of the year? The first plot gives you each year as
43
- one line. The second plot shows you how distance you have covered in each year and with which activity kinds.</p>
31
+ <p>What's the distance (or else) per week? See it for all weeks in all years. The larger the circle is, the more you did
32
+ in that week.</p>
44
33
 
45
- <div class="row mb-3">
46
- <div class="col-md-6">
47
- {{ vega_direct("plot_year_cumulative", plot_year_cumulative) }}
48
- </div>
49
- <div class="col-md-6">
50
- {{ vega_direct("plot_yearly_distance", plot_yearly_distance) }}
51
- </div>
52
- </div>
53
-
54
- <div class="row mb-3">
55
- <div class="col-md-4">
56
- <p>What's the average distance per activity? This naturally differs per activity and perhaps also varies with
57
- the years. This table gives you all the mean values.</p>
58
- </div>
59
-
60
- <div class="col-md-8">
61
- <table class="table table-sort table-arrows">
62
- <thead>
63
- <tr>
64
- <th style="text-align: right;">Year</th>
65
- {% for col in tabulate_year_kind_mean['columns'][1:] %}
66
- <th style="text-align: right;">{{ col }}</th>
67
- {% endfor %}
68
- </tr>
69
- </thead>
70
- <tbody>
71
- {% for row in tabulate_year_kind_mean['data'] %}
72
- <tr>
73
- {% for value in row %}
74
- <td align="right">
75
- {% if value == value %}
76
- {{ value | round(2) }}
77
- {% if not loop.first %}
78
- km
79
- {% endif %}
80
- {% endif %}
81
- </td>
82
- {% endfor %}
83
- </tr>
84
- {% endfor %}
85
- </tbody>
86
- </table>
87
- </div>
88
- </div>
34
+ {{ tabbed_vega(plot_per_iso_week) }}
89
35
 
90
- <p>Next we take one row per month, each column is a day-of-month. The brighter a box, the more distance you have covered
91
- on that day. This makes it easy to spot those days where you really covered a lot of distance!</p>
36
+ <h2>Per day</h2>
92
37
 
38
+ <p>And also more fine-grained per day for the past rolling year. This is grouped by day of the week such that you can
39
+ easily spot patterns in your daily routine.</p>
93
40
 
94
- <ul class="nav nav-pills mb-3" id="myTab" role="tablist">
95
- {% for year, plot in plot_distance_heatmaps.items() %}
96
- <li class="nav-item" role="presentation">
97
- <button class="nav-link {% if loop.last %} active {% endif %}" id="heatmap-{{ year }}" data-bs-toggle="tab"
98
- data-bs-target="#heatmap-{{ year }}-pane" type="button" role="tab" aria-controls="heatmap-{{ year }}-pane"
99
- aria-selected="{{ loop.last }}">{{ year }}</button>
100
- </li>
101
- {% endfor %}
102
- </ul>
41
+ {{ tabbed_vega(heatmap_per_day) }}
103
42
 
104
- <div class="tab-content mb-3" id="myTabContent">
105
- {% for year, plot in plot_distance_heatmaps.items() %}
106
- {% if year %}
107
- <div class="tab-pane fade {% if loop.last %} show active {% endif %}" id="heatmap-{{ year }}-pane" role="tabpanel"
108
- aria-labelledby="heatmap-{{ year }}" tabindex="0">
109
- {{ vega_direct("plot_distance_heatmap_%d"|format(year), plot) }}
110
- </div>
111
- {% endif %}
112
- {% endfor %}
113
- </div>
114
-
115
- <h2>Elevation Gain</h2>
116
-
117
- <p>This is your weekly elevation gain for the past rolling year, split by activity kind.</p>
118
-
119
- <div class="row mb-3">
120
- <div class="col">
121
- {{ vega_direct("plot_weekly_elevation_gain", plot_weekly_elevation_gain) }}
122
- </div>
123
- </div>
124
-
125
- <p>Similarly, you find the same data but aggregated by whole months for the past two years. Also split by activity kind.
126
- </p>
127
-
128
- <div class="row mb-3">
129
- <div class="col">
130
- {{ vega_direct("plot_monthly_elevation_gain", plot_monthly_elevation_gain) }}
131
- </div>
132
- </div>
43
+ <h2>Cumulative per year</h2>
133
44
 
134
- <p>How much elevation have you gained in each year up to that time of the year? The first plot gives you each year as
135
- one line. The second plot shows you how much elevation you have gained in each year and with which activity kinds.
136
- </p>
137
-
138
- <div class="row mb-3">
139
- <div class="col-md-6">
140
- {{ vega_direct("plot_year_elevation_gain_cumulative", plot_year_elevation_gain_cumulative) }}
141
- </div>
142
- <div class="col-md-6">
143
- {{ vega_direct("plot_yearly_elevation_gain", plot_yearly_elevation_gain) }}
144
- </div>
145
- </div>
146
-
147
- <div class="row mb-3">
148
- <div class="col-md-4">
149
- <p>What's the average elevation gain per activity? This naturally differs per activity and perhaps also varies
150
- with
151
- the years. This table gives you all the mean values.</p>
152
- </div>
153
-
154
- <div class="col-md-8">
155
- <table class="table table-sort table-arrows">
156
- <thead>
157
- <tr>
158
- <th style="text-align: right;">Year</th>
159
- {% for col in tabulate_year_kind_mean_elevation_gain['columns'][1:] %}
160
- <th style="text-align: right;">{{ col }}</th>
161
- {% endfor %}
162
- </tr>
163
- </thead>
164
- <tbody>
165
- {% for row in tabulate_year_kind_mean_elevation_gain['data'] %}
166
- <tr>
167
- {% for value in row %}
168
- <td align="right">
169
- {% if value == value %}
170
- {{ value | round(1) }}
171
- {% if not loop.first %}
172
- m
173
- {% endif %}
174
- {% endif %}
175
- </td>
176
- {% endfor %}
177
- </tr>
178
- {% endfor %}
179
- </tbody>
180
- </table>
181
- </div>
182
- </div>
183
-
184
- <p>Next we take one row per month, each column is a day-of-month. The brighter a box, the more elevation gain you have
185
- covered
186
- on that day. This makes it easy to spot those days where you really covered a lot of elevation gain!</p>
187
-
188
-
189
- <ul class="nav nav-pills mb-3" id="myTab" role="tablist">
190
- {% for year, plot in plot_elevation_gain_heatmaps.items() %}
191
- <li class="nav-item" role="presentation">
192
- <button class="nav-link {% if loop.last %} active {% endif %}" id="heatmap-elevation-gain-{{ year }}"
193
- data-bs-toggle="tab" data-bs-target="#heatmap-elevation-gain-{{ year }}-pane" type="button" role="tab"
194
- aria-controls="heatmap-elevation-gain-{{ year }}-pane" aria-selected="{{ loop.last }}">{{ year }}</button>
195
- </li>
196
- {% endfor %}
197
- </ul>
198
-
199
- <div class="tab-content mb-3" id="myTabContent">
200
- {% for year, plot in plot_elevation_gain_heatmaps.items() %}
201
- <div class="tab-pane fade {% if loop.last %} show active {% endif %}" id="heatmap-elevation-gain-{{ year }}-pane"
202
- role="tabpanel" aria-labelledby="heatmap-elevation-gain-{{ year }}" tabindex="0">
203
- {{ vega_direct("plot_elevation_gain_heatmap_%d"|format(year), plot) }}
204
- </div>
205
- {% endfor %}
206
- </div>
207
-
208
- <h2>Hall of Fame</h2>
209
-
210
- <script>
211
- function add_map(id, geojson) {
212
- let map = L.map(`map-${id}`, {
213
- fullscreenControl: true
214
- })
215
- L.tileLayer('/tile/color/{z}/{x}/{y}.png', {
216
- maxZoom: 19,
217
- attribution: '{{ map_tile_attribution|safe }}'
218
- }).addTo(map)
219
-
220
- let geojson_layer = L.geoJSON(geojson).addTo(map)
221
- map.fitBounds(geojson_layer.getBounds())
222
- return map
223
- }
224
- </script>
225
-
226
- {% for activity_batch in nominations|batch(3) %}
227
- <div class="row row-cols-1 row-cols-md-3 g-4 mb-3">
228
- {% for activity, reasons, line_geojson in activity_batch %}
229
- <div class="col">
230
- <div class="card">
231
- <div class="card-img-top" id="map-{{ activity.id }}" style="height: 200px; width: 100%;"></div>
232
- <script>
233
- let map{{ activity.id }} = add_map("{{ activity.id }}", {{ line_geojson | safe }})
234
- </script>
235
- <div class="card-body">
236
- <a href="{{ url_for('activity.show', id=activity.id) }}">
237
- <h5 class="card-title">{{ activity["name"] }}</h5>
238
- </a>
239
- <p class="card-text">
240
- <ul style='list-style-type: "🏆 "'>
241
- {% for reason in reasons %}
242
- <li>{{ reason }}</li>
243
- {% endfor %}
244
- </ul>
245
- </p>
246
- <p class="card-text"><small class="text-body-secondary"></small>{{ activity.kind }} with {{
247
- (activity.distance_km)|round(1) }} km / {{activity.elevation_gain|round|int}} m in {{
248
- activity.elapsed_time|td }} on {{ activity.start|dt }}</small></p>
249
- </div>
250
- </div>
251
- </div>
252
- {% endfor %}
253
- </div>
254
- {% endfor %}
45
+ <p>How much distance (or else) have you covered in each year up to that time of the year? This lets you see how you are
46
+ doing compared to previous years.</p>
255
47
 
48
+ {{ tabbed_vega(plot_per_year_cumulative) }}
256
49
 
257
50
  {% endblock %}
@@ -0,0 +1,3 @@
1
+ {% from "plot-macros.html.j2" import vega_direct %}
2
+
3
+ {{ vega_direct(chart_name, chart_json) }}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: geo-activity-playground
3
- Version: 0.45.0
3
+ Version: 1.1.0
4
4
  Summary: Analysis of geo data activities like rides, runs or hikes.
5
5
  License: MIT
6
6
  Author: Martin Ueding
@@ -28,6 +28,7 @@ Requires-Dist: gpxpy (>=1.5.0,<2.0.0)
28
28
  Requires-Dist: jinja2 (>=3.1.2,<4.0.0)
29
29
  Requires-Dist: matplotlib (>=3.10.1,<4.0.0)
30
30
  Requires-Dist: numpy (>=2.2.3,<3.0.0)
31
+ Requires-Dist: openpyxl (>=3.1.5,<4.0.0)
31
32
  Requires-Dist: pandas (>=2.2.3,<3.0.0)
32
33
  Requires-Dist: pyarrow (>=19.0.1,<20.0.0)
33
34
  Requires-Dist: python-dateutil (>=2.8.2,<3.0.0)