geo-activity-playground 0.38.2__py3-none-any.whl → 0.39.1__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 (116) hide show
  1. geo_activity_playground/__main__.py +5 -47
  2. geo_activity_playground/alembic/README +1 -0
  3. geo_activity_playground/alembic/env.py +76 -0
  4. geo_activity_playground/alembic/script.py.mako +26 -0
  5. geo_activity_playground/alembic/versions/451e7836b53d_add_square_planner_bookmark.py +33 -0
  6. geo_activity_playground/alembic/versions/63d3b7f6f93c_initial_version.py +73 -0
  7. geo_activity_playground/alembic/versions/ab83b9d23127_add_upstream_id.py +28 -0
  8. geo_activity_playground/alembic/versions/b03491c593f6_add_crop_indices.py +30 -0
  9. geo_activity_playground/alembic/versions/e02e27876deb_add_square_planner_bookmark_name.py +28 -0
  10. geo_activity_playground/alembic/versions/script.py.mako +28 -0
  11. geo_activity_playground/core/activities.py +53 -136
  12. geo_activity_playground/core/config.py +3 -3
  13. geo_activity_playground/core/datamodel.py +257 -0
  14. geo_activity_playground/core/enrichment.py +90 -92
  15. geo_activity_playground/core/heart_rate.py +1 -2
  16. geo_activity_playground/core/parametric_plot.py +101 -0
  17. geo_activity_playground/core/paths.py +6 -7
  18. geo_activity_playground/core/raster_map.py +43 -4
  19. geo_activity_playground/core/similarity.py +1 -2
  20. geo_activity_playground/core/tasks.py +2 -2
  21. geo_activity_playground/core/test_meta_search.py +3 -3
  22. geo_activity_playground/core/test_summary_stats.py +1 -1
  23. geo_activity_playground/explorer/grid_file.py +2 -2
  24. geo_activity_playground/explorer/tile_visits.py +8 -10
  25. geo_activity_playground/heatmap_video.py +7 -8
  26. geo_activity_playground/importers/activity_parsers.py +2 -2
  27. geo_activity_playground/importers/directory.py +9 -10
  28. geo_activity_playground/importers/strava_api.py +9 -9
  29. geo_activity_playground/importers/strava_checkout.py +12 -13
  30. geo_activity_playground/importers/test_csv_parser.py +3 -3
  31. geo_activity_playground/importers/test_directory.py +1 -1
  32. geo_activity_playground/importers/test_strava_api.py +1 -1
  33. geo_activity_playground/webui/app.py +96 -86
  34. geo_activity_playground/webui/authenticator.py +1 -1
  35. geo_activity_playground/webui/{activity/controller.py → blueprints/activity_blueprint.py} +246 -108
  36. geo_activity_playground/webui/{auth_blueprint.py → blueprints/auth_blueprint.py} +1 -1
  37. geo_activity_playground/webui/blueprints/bubble_chart_blueprint.py +61 -0
  38. geo_activity_playground/webui/{calendar/controller.py → blueprints/calendar_blueprint.py} +19 -19
  39. geo_activity_playground/webui/{eddington_blueprint.py → blueprints/eddington_blueprint.py} +5 -5
  40. geo_activity_playground/webui/blueprints/entry_views.py +68 -0
  41. geo_activity_playground/webui/{equipment_blueprint.py → blueprints/equipment_blueprint.py} +37 -4
  42. geo_activity_playground/webui/{explorer/controller.py → blueprints/explorer_blueprint.py} +88 -54
  43. geo_activity_playground/webui/blueprints/heatmap_blueprint.py +233 -0
  44. geo_activity_playground/webui/blueprints/plot_builder_blueprint.py +43 -0
  45. geo_activity_playground/webui/{search_blueprint.py → blueprints/search_blueprint.py} +7 -11
  46. geo_activity_playground/webui/blueprints/settings_blueprint.py +446 -0
  47. geo_activity_playground/webui/{square_planner_blueprint.py → blueprints/square_planner_blueprint.py} +31 -6
  48. geo_activity_playground/webui/{summary_blueprint.py → blueprints/summary_blueprint.py} +11 -23
  49. geo_activity_playground/webui/blueprints/tile_blueprint.py +27 -0
  50. geo_activity_playground/webui/{upload_blueprint.py → blueprints/upload_blueprint.py} +13 -18
  51. geo_activity_playground/webui/flasher.py +26 -0
  52. geo_activity_playground/webui/plot_util.py +1 -1
  53. geo_activity_playground/webui/search_util.py +4 -6
  54. geo_activity_playground/webui/static/images/layers-2x.png +0 -0
  55. geo_activity_playground/webui/static/images/layers.png +0 -0
  56. geo_activity_playground/webui/static/images/marker-icon-2x.png +0 -0
  57. geo_activity_playground/webui/static/images/marker-icon.png +0 -0
  58. geo_activity_playground/webui/static/images/marker-shadow.png +0 -0
  59. geo_activity_playground/webui/templates/activity/day.html.j2 +81 -0
  60. geo_activity_playground/webui/templates/activity/edit.html.j2 +38 -0
  61. geo_activity_playground/webui/{activity/templates → templates}/activity/name.html.j2 +29 -27
  62. geo_activity_playground/webui/{activity/templates → templates}/activity/show.html.j2 +57 -33
  63. geo_activity_playground/webui/templates/activity/trim.html.j2 +68 -0
  64. geo_activity_playground/webui/templates/bubble_chart/index.html.j2 +26 -0
  65. geo_activity_playground/webui/templates/calendar/index.html.j2 +48 -0
  66. geo_activity_playground/webui/templates/calendar/month.html.j2 +57 -0
  67. geo_activity_playground/webui/templates/equipment/index.html.j2 +7 -0
  68. geo_activity_playground/webui/templates/home.html.j2 +6 -6
  69. geo_activity_playground/webui/templates/page.html.j2 +2 -1
  70. geo_activity_playground/webui/templates/plot_builder/index.html.j2 +44 -0
  71. geo_activity_playground/webui/{settings/templates → templates}/settings/index.html.j2 +9 -20
  72. geo_activity_playground/webui/templates/settings/manage-equipments.html.j2 +49 -0
  73. geo_activity_playground/webui/templates/settings/manage-kinds.html.j2 +48 -0
  74. geo_activity_playground/webui/{settings/templates → templates}/settings/privacy-zones.html.j2 +2 -0
  75. geo_activity_playground/webui/{settings/templates → templates}/settings/strava.html.j2 +2 -0
  76. geo_activity_playground/webui/templates/square_planner/index.html.j2 +63 -13
  77. {geo_activity_playground-0.38.2.dist-info → geo_activity_playground-0.39.1.dist-info}/METADATA +5 -1
  78. geo_activity_playground-0.39.1.dist-info/RECORD +136 -0
  79. geo_activity_playground/__init__.py +0 -0
  80. geo_activity_playground/core/__init__.py +0 -0
  81. geo_activity_playground/explorer/__init__.py +0 -0
  82. geo_activity_playground/importers/__init__.py +0 -0
  83. geo_activity_playground/webui/__init__.py +0 -0
  84. geo_activity_playground/webui/activity/__init__.py +0 -0
  85. geo_activity_playground/webui/activity/blueprint.py +0 -109
  86. geo_activity_playground/webui/activity/templates/activity/day.html.j2 +0 -80
  87. geo_activity_playground/webui/activity/templates/activity/edit.html.j2 +0 -42
  88. geo_activity_playground/webui/calendar/__init__.py +0 -0
  89. geo_activity_playground/webui/calendar/blueprint.py +0 -23
  90. geo_activity_playground/webui/calendar/templates/calendar/index.html.j2 +0 -46
  91. geo_activity_playground/webui/calendar/templates/calendar/month.html.j2 +0 -55
  92. geo_activity_playground/webui/entry_controller.py +0 -63
  93. geo_activity_playground/webui/explorer/__init__.py +0 -0
  94. geo_activity_playground/webui/explorer/blueprint.py +0 -62
  95. geo_activity_playground/webui/heatmap/__init__.py +0 -0
  96. geo_activity_playground/webui/heatmap/blueprint.py +0 -51
  97. geo_activity_playground/webui/heatmap/heatmap_controller.py +0 -216
  98. geo_activity_playground/webui/settings/blueprint.py +0 -262
  99. geo_activity_playground/webui/settings/controller.py +0 -272
  100. geo_activity_playground/webui/settings/templates/settings/equipment-offsets.html.j2 +0 -44
  101. geo_activity_playground/webui/settings/templates/settings/kind-renames.html.j2 +0 -25
  102. geo_activity_playground/webui/settings/templates/settings/kinds-without-achievements.html.j2 +0 -30
  103. geo_activity_playground/webui/tile_blueprint.py +0 -42
  104. geo_activity_playground-0.38.2.dist-info/RECORD +0 -129
  105. /geo_activity_playground/webui/{activity/templates → templates}/activity/lines.html.j2 +0 -0
  106. /geo_activity_playground/webui/{explorer/templates → templates}/explorer/index.html.j2 +0 -0
  107. /geo_activity_playground/webui/{heatmap/templates → templates}/heatmap/index.html.j2 +0 -0
  108. /geo_activity_playground/webui/{settings/templates → templates}/settings/admin-password.html.j2 +0 -0
  109. /geo_activity_playground/webui/{settings/templates → templates}/settings/color-schemes.html.j2 +0 -0
  110. /geo_activity_playground/webui/{settings/templates → templates}/settings/heart-rate.html.j2 +0 -0
  111. /geo_activity_playground/webui/{settings/templates → templates}/settings/metadata-extraction.html.j2 +0 -0
  112. /geo_activity_playground/webui/{settings/templates → templates}/settings/segmentation.html.j2 +0 -0
  113. /geo_activity_playground/webui/{settings/templates → templates}/settings/sharepic.html.j2 +0 -0
  114. {geo_activity_playground-0.38.2.dist-info → geo_activity_playground-0.39.1.dist-info}/LICENSE +0 -0
  115. {geo_activity_playground-0.38.2.dist-info → geo_activity_playground-0.39.1.dist-info}/WHEEL +0 -0
  116. {geo_activity_playground-0.38.2.dist-info → geo_activity_playground-0.39.1.dist-info}/entry_points.txt +0 -0
@@ -1,272 +0,0 @@
1
- import json
2
- import re
3
- import urllib.parse
4
- from typing import Any
5
- from typing import Optional
6
-
7
- from flask import flash
8
- from flask import url_for
9
-
10
- from geo_activity_playground.core.config import ConfigAccessor
11
- from geo_activity_playground.core.heart_rate import HeartRateZoneComputer
12
-
13
-
14
- SHAREPIC_FIELDS = {
15
- "calories": "Calories",
16
- "distance_km": "Distance",
17
- "elapsed_time": "Elapsed time",
18
- "equipment": "Equipment",
19
- "kind": "Kind",
20
- "name": "Name",
21
- "start": "Date",
22
- "Steps": "Steps",
23
- }
24
-
25
-
26
- class SettingsController:
27
- def __init__(self, config_accessor: ConfigAccessor) -> None:
28
- self._config_accessor = config_accessor
29
-
30
- def render_admin_password(self) -> dict:
31
- return {
32
- "password": self._config_accessor().upload_password,
33
- }
34
-
35
- def save_admin_password(self, password: str) -> None:
36
- self._config_accessor().upload_password = password
37
- self._config_accessor.save()
38
- flash("Updated admin password.", category="success")
39
-
40
- def render_equipment_offsets(self) -> dict:
41
- return {
42
- "equipment_offsets": self._config_accessor().equipment_offsets,
43
- }
44
-
45
- def save_equipment_offsets(
46
- self,
47
- equipments: list[str],
48
- offsets: list[str],
49
- ) -> None:
50
- assert len(equipments) == len(offsets)
51
- new_equipment_offsets = {}
52
- for equipment, offset_str in zip(equipments, offsets):
53
- if not equipment or not offset_str:
54
- continue
55
-
56
- try:
57
- offset = float(offset_str)
58
- except ValueError as e:
59
- flash(
60
- f"Cannot parse number {offset_str} for {equipment}: {e}",
61
- category="danger",
62
- )
63
- continue
64
-
65
- if not offset:
66
- continue
67
-
68
- new_equipment_offsets[equipment] = offset
69
- self._config_accessor().equipment_offsets = new_equipment_offsets
70
- self._config_accessor.save()
71
- flash("Updated equipment offsets.", category="success")
72
-
73
- def render_heart_rate(self) -> dict:
74
- result: dict[str, Any] = {
75
- "birth_year": self._config_accessor().birth_year,
76
- "heart_rate_resting": self._config_accessor().heart_rate_resting,
77
- "heart_rate_maximum": self._config_accessor().heart_rate_maximum,
78
- }
79
-
80
- self._heart_rate_computer = HeartRateZoneComputer(self._config_accessor())
81
- try:
82
- result["zone_boundaries"] = self._heart_rate_computer.zone_boundaries()
83
- except RuntimeError as e:
84
- pass
85
- return result
86
-
87
- def save_heart_rate(
88
- self,
89
- birth_year: Optional[int],
90
- heart_rate_resting: Optional[int],
91
- heart_rate_maximum: Optional[int],
92
- ) -> None:
93
- self._config_accessor().birth_year = birth_year
94
- self._config_accessor().heart_rate_resting = heart_rate_resting or 0
95
- self._config_accessor().heart_rate_maximum = heart_rate_maximum
96
- self._config_accessor.save()
97
- flash("Updated heart rate data.", category="success")
98
-
99
- def render_kinds_without_achievements(self) -> dict:
100
- return {
101
- "kinds_without_achievements": self._config_accessor().kinds_without_achievements,
102
- }
103
-
104
- def save_kinds_without_achievements(
105
- self,
106
- kinds: list[str],
107
- ) -> None:
108
- new_kinds = [kind.strip() for kind in kinds if kind.strip()]
109
- new_kinds.sort()
110
-
111
- self._config_accessor().kinds_without_achievements = new_kinds
112
- self._config_accessor.save()
113
- flash("Updated kinds without achievements.", category="success")
114
-
115
- def render_metadata_extraction(self) -> dict:
116
- return {
117
- "metadata_extraction_regexes": self._config_accessor().metadata_extraction_regexes,
118
- }
119
-
120
- def save_metadata_extraction(
121
- self,
122
- metadata_extraction_regexes: list[str],
123
- ) -> None:
124
- new_metadata_extraction_regexes = []
125
- for regex in metadata_extraction_regexes:
126
- try:
127
- re.compile(regex)
128
- except re.error as e:
129
- flash(
130
- f"Cannot parse regex {regex} due to error: {e}", category="danger"
131
- )
132
- else:
133
- new_metadata_extraction_regexes.append(regex)
134
-
135
- self._config_accessor().metadata_extraction_regexes = (
136
- new_metadata_extraction_regexes
137
- )
138
- self._config_accessor.save()
139
- flash("Updated metadata extraction settings.", category="success")
140
-
141
- def render_privacy_zones(self) -> dict:
142
- return {
143
- "privacy_zones": {
144
- name: _wrap_coordinates(coordinates)
145
- for name, coordinates in self._config_accessor().privacy_zones.items()
146
- }
147
- }
148
-
149
- def save_privacy_zones(
150
- self, zone_names: list[str], zone_geojsons: list[str]
151
- ) -> None:
152
- assert len(zone_names) == len(zone_geojsons)
153
- new_zone_config = {}
154
-
155
- for zone_name, zone_geojson_str in zip(zone_names, zone_geojsons):
156
- if not zone_name or not zone_geojson_str:
157
- continue
158
-
159
- try:
160
- zone_geojson = json.loads(zone_geojson_str)
161
- except json.decoder.JSONDecodeError as e:
162
- flash(
163
- f"Could not parse GeoJSON for {zone_name} due to the following error: {e}"
164
- )
165
- continue
166
-
167
- if not zone_geojson["type"] == "FeatureCollection":
168
- flash(
169
- f"Pasted GeoJSON for {zone_name} must be of type 'FeatureCollection'.",
170
- category="danger",
171
- )
172
- continue
173
-
174
- features = zone_geojson["features"]
175
-
176
- if not len(features) == 1:
177
- flash(
178
- f"Pasted GeoJSON for {zone_name} must contain exactly one feature. You cannot have multiple shapes for one privacy zone",
179
- category="danger",
180
- )
181
- continue
182
-
183
- feature = features[0]
184
- geometry = feature["geometry"]
185
-
186
- if not geometry["type"] == "Polygon":
187
- flash(
188
- f"Geometry for {zone_name} is not a polygon. You need to create a polygon (or circle or rectangle).",
189
- category="danger",
190
- )
191
- continue
192
-
193
- coordinates = geometry["coordinates"]
194
-
195
- if not len(coordinates) == 1:
196
- flash(
197
- f"Polygon for {zone_name} consists of multiple polygons. Please supply a simple one.",
198
- category="danger",
199
- )
200
- continue
201
-
202
- points = coordinates[0]
203
-
204
- new_zone_config[zone_name] = points
205
-
206
- self._config_accessor().privacy_zones = new_zone_config
207
- self._config_accessor.save()
208
- flash("Updated privacy zones.", category="success")
209
-
210
- def render_sharepic(self) -> dict:
211
-
212
- return {
213
- "names": [
214
- (
215
- name,
216
- label,
217
- name not in self._config_accessor().sharepic_suppressed_fields,
218
- )
219
- for name, label in SHAREPIC_FIELDS.items()
220
- ]
221
- }
222
-
223
- def save_sharepic(self, names: list[str]) -> None:
224
- self._config_accessor().sharepic_suppressed_fields = list(
225
- set(SHAREPIC_FIELDS) - set(names)
226
- )
227
- self._config_accessor.save()
228
- flash("Updated sharepic preferences.", category="success")
229
- pass
230
-
231
- def render_strava(self) -> dict:
232
- return {
233
- "strava_client_id": self._config_accessor().strava_client_id,
234
- "strava_client_secret": self._config_accessor().strava_client_secret,
235
- "strava_client_code": self._config_accessor().strava_client_code,
236
- }
237
-
238
- def save_strava(self, client_id: str, client_secret: str) -> str:
239
- self._strava_client_id = client_id
240
- self._strava_client_secret = client_secret
241
-
242
- payload = {
243
- "client_id": client_id,
244
- "redirect_uri": url_for(".strava_callback", _external=True),
245
- "response_type": "code",
246
- "scope": "activity:read_all",
247
- }
248
-
249
- arg_string = "&".join(
250
- f"{key}={urllib.parse.quote(value)}" for key, value in payload.items()
251
- )
252
- return f"https://www.strava.com/oauth/authorize?{arg_string}"
253
-
254
- def save_strava_code(self, code: str) -> None:
255
- self._config_accessor().strava_client_id = int(self._strava_client_id)
256
- self._config_accessor().strava_client_secret = self._strava_client_secret
257
- self._config_accessor().strava_client_code = code
258
- self._config_accessor.save()
259
- flash("Connected to Strava API", category="success")
260
-
261
-
262
- def _wrap_coordinates(coordinates: list[list[float]]) -> dict:
263
- return {
264
- "type": "FeatureCollection",
265
- "features": [
266
- {
267
- "type": "Feature",
268
- "properties": {},
269
- "geometry": {"coordinates": [coordinates], "type": "Polygon"},
270
- }
271
- ],
272
- }
@@ -1,44 +0,0 @@
1
- {% extends "page.html.j2" %}
2
-
3
- {% block container %}
4
-
5
- <h1 class="mb-3">Equipment Offsets</h1>
6
-
7
- <p>If you record every activity with an equipment but haven't started from the beginning, you might have a certain
8
- distance that is not accounted for. In order to have this reflected in the equipment overview, you can enter offsets
9
- here.</p>
10
-
11
- <form method="POST">
12
- <div class="row row-cols-1 row-cols-md-3 g-4 mb-3">
13
- {% for equipment, offset in equipment_offsets.items() %}
14
- <div class="col-md-4">
15
- <div class="mb-3">
16
- <label for="equipment_{{ loop.index }}" class="form-label">Equipment</label>
17
- <input type="text" class="form-control" id="equipment_{{ loop.index }}" name="equipment"
18
- value="{{ equipment }}" />
19
- </div>
20
- <div class="mb-3">
21
- <label for="offset_{{ loop.index }}" class="form-label">Offset / km</label>
22
- <input type="number" class="form-control" id="offset_{{ loop.index }}" name="offset"
23
- value="{{ offset }}" />
24
- </div>
25
- </div>
26
- {% endfor %}
27
-
28
- <div class="col-md-4">
29
- <div class="mb-3">
30
- <label for="equipment_new" class="form-label">Equipment</label>
31
- <input type="text" class="form-control" id="equipment_new" name="equipment" />
32
- </div>
33
- <div class="mb-3">
34
- <label for="offset_new" class="form-label">Offset / km</label>
35
- <input type="number" class="form-control" id="offset_new" name="offset" />
36
- </div>
37
- </div>
38
- </div>
39
-
40
- <button type="submit" class="btn btn-primary">Save</button>
41
- </form>
42
-
43
-
44
- {% endblock %}
@@ -1,25 +0,0 @@
1
- {% extends "page.html.j2" %}
2
-
3
- {% block container %}
4
-
5
- <h1 class="mb-3">Kind renaming</h1>
6
-
7
- <p>If you have used different apps for tracking, you might have that your bike rides have <i>kind</i> "ride", "Ride",
8
- "Radfahrt" and so on. In order to unify these, you can specify mappings from old to new names.</p>
9
-
10
- <p>If you want to unify these to "Ride", enter the following:</p>
11
-
12
- <pre><code>
13
- ride =&gt; Ride
14
- Radfahrt =&gt; Ride
15
- </code></pre>
16
-
17
- <form method="POST">
18
- <div class="mb-3">
19
- <label for="rules" class="form-label">Rules</label>
20
- <textarea class="form-control" id=rules" cols="80" rows="10" name="rules_str">{{ rules_str }}</textarea>
21
- </div>
22
- <button type="submit" class="btn btn-primary">Save</button>
23
- </form>
24
-
25
- {% endblock %}
@@ -1,30 +0,0 @@
1
- {% extends "page.html.j2" %}
2
-
3
- {% block container %}
4
-
5
- <h1 class="mb-3">Kinds without Achievements</h1>
6
-
7
- <p>Apart from bicycle rides and runs, you might also record your car and train rides. If you don't want to include these
8
- for achievements like explorer tiles, you can enter the activity kinds that should not be considered here.</p>
9
-
10
- <form method="POST">
11
- <div class="row">
12
- <div class="col-md-6">
13
- {% for kind in kinds_without_achievements %}
14
- <div class="mb-3">
15
- <label for="kind_{{ loop.index }}" class="form-label">Kind</label>
16
- <input type="text" class="form-control" id="kind_{{ loop.index }}" name="kind" value="{{ kind }}" />
17
- </div>
18
- {% endfor %}
19
- <div class="mb-3">
20
- <label for="regex_new" class="form-label">Kind</label>
21
- <input type="text" class="form-control" id="kind_new" name="kind" />
22
- </div>
23
- </div>
24
- </div>
25
-
26
- <button type="submit" class="btn btn-primary">Save</button>
27
- </form>
28
-
29
-
30
- {% endblock %}
@@ -1,42 +0,0 @@
1
- import io
2
-
3
- import matplotlib.pyplot as pl
4
- import numpy as np
5
- from flask import Blueprint
6
- from flask import Response
7
-
8
- from geo_activity_playground.core.config import Config
9
- from geo_activity_playground.core.raster_map import get_tile
10
-
11
-
12
- def make_tile_blueprint(config: Config) -> Blueprint:
13
- blueprint = Blueprint("tiles", __name__, template_folder="templates")
14
-
15
- @blueprint.route("/color/<int:z>/<int:x>/<int:y>.png")
16
- def tile_color(x: int, y: int, z: int):
17
- map_tile = np.array(get_tile(z, x, y, config.map_tile_url)) / 255
18
- f = io.BytesIO()
19
- pl.imsave(f, map_tile, format="png")
20
- return Response(bytes(f.getbuffer()), mimetype="image/png")
21
-
22
- @blueprint.route("/grayscale/<int:z>/<int:x>/<int:y>.png")
23
- def tile_grayscale(x: int, y: int, z: int):
24
- map_tile = np.array(get_tile(z, x, y, config.map_tile_url)) / 255
25
- map_tile = np.sum(map_tile * [0.2126, 0.7152, 0.0722], axis=2) # to grayscale
26
- map_tile = np.dstack((map_tile, map_tile, map_tile)) # to rgb
27
- f = io.BytesIO()
28
- pl.imsave(f, map_tile, format="png")
29
- return Response(bytes(f.getbuffer()), mimetype="image/png")
30
-
31
- @blueprint.route("/pastel/<int:z>/<int:x>/<int:y>.png")
32
- def tile_pastel(x: int, y: int, z: int):
33
- map_tile = np.array(get_tile(z, x, y, config.map_tile_url)) / 255
34
- averaged_tile = np.sum(map_tile * [0.2126, 0.7152, 0.0722], axis=2)
35
- grayscale_tile = np.dstack((averaged_tile, averaged_tile, averaged_tile))
36
- factor = 0.7
37
- pastel_tile = factor * grayscale_tile + (1 - factor) * map_tile
38
- f = io.BytesIO()
39
- pl.imsave(f, pastel_tile, format="png")
40
- return Response(bytes(f.getbuffer()), mimetype="image/png")
41
-
42
- return blueprint
@@ -1,129 +0,0 @@
1
- geo_activity_playground/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- geo_activity_playground/__main__.py,sha256=vFKB0Jjk8ImDHqok6Fddb5CRWHEnxyn5r4Zs0A1EsCQ,4585
3
- geo_activity_playground/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- geo_activity_playground/core/activities.py,sha256=hIn11bsriNhcalWRWPU8SYqM7cKEFI-n9voqSyT7Tdk,7695
5
- geo_activity_playground/core/config.py,sha256=oo0pSoBZVU__U81OzW2Qdw8C5Tq_pO7CWibA4CugZmc,5296
6
- geo_activity_playground/core/coordinates.py,sha256=tDfr9mlXhK6E_MMIJ0vYWVCoH0Lq8uyuaqUgaa8i0jg,966
7
- geo_activity_playground/core/enrichment.py,sha256=WbUsKifhLLQc2ntqcYs_KwRPrWvSMmMWTWBY6blJx8U,8240
8
- geo_activity_playground/core/heart_rate.py,sha256=IwMt58TpjOYqpAxtsj07zP2ttpN_J3GZeiv-qGhYyJc,1598
9
- geo_activity_playground/core/meta_search.py,sha256=naErjAC7ZCFhOF6d492kbegZxCdzbpGcJvjQLJTE4xE,5016
10
- geo_activity_playground/core/paths.py,sha256=RBeUi38riP_msTGPy1TsPRNiblzE-lFivaJSLULE8b0,2503
11
- geo_activity_playground/core/privacy_zones.py,sha256=4TumHsVUN1uW6RG3ArqTXDykPVipF98DCxVBe7YNdO8,512
12
- geo_activity_playground/core/raster_map.py,sha256=RrbpotWIIT1friSewSxRczk4FY6v8ofOO6kO1ERMWvM,6962
13
- geo_activity_playground/core/similarity.py,sha256=Jo8jRViuORCxdIGvyaflgsQhwu9S_jn10a450FRL18A,3159
14
- geo_activity_playground/core/summary_stats.py,sha256=v5FtWnE1imDF5axI6asVN55wCrlD73oZ6lvqzxsTN2c,1006
15
- geo_activity_playground/core/tasks.py,sha256=aMDBWJqp6ek2ao6G6Xa8GOSZbcQqXoWL74SGRowRPIk,2942
16
- geo_activity_playground/core/test_meta_search.py,sha256=kEFOphGfbWT0hW-4ivZHGEq3BTL01ODCxCK_KUSP61w,3175
17
- geo_activity_playground/core/test_summary_stats.py,sha256=OU2Epm1QFsEDYdWfCy5QUeFXqoIeG8Sk1tX8LbFj8Xk,3109
18
- geo_activity_playground/core/test_tiles.py,sha256=zce1FxNfsSpOQt66jMehdQRVoNdl-oiFydx6iVBHZXM,764
19
- geo_activity_playground/core/test_time_conversion.py,sha256=Sh6nZA3uCTOdZTZa3yOijtR0m74QtZu2mcWXsDNnyQI,984
20
- geo_activity_playground/core/tiles.py,sha256=lV6X1Uc9XQecu2LALIvxpnMcLsVtWx7JczJ5a_S1eZE,2139
21
- geo_activity_playground/core/time_conversion.py,sha256=x5mXG6Y4GtdX7CBmwucGNSWBp9JQJDbZ7u0JkdUY1Vs,379
22
- geo_activity_playground/explorer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
- geo_activity_playground/explorer/grid_file.py,sha256=k6j6KBEk2a2BY-onE8SV5TJsERGGyOrlY4as__meWpA,3304
24
- geo_activity_playground/explorer/tile_visits.py,sha256=CSHAjgzKWe1iB-zvaqgsR5Z_lFycpWqUfxnPCAWvYaU,14173
25
- geo_activity_playground/explorer/video.py,sha256=7j6Qv3HG6On7Tn7xh7Olwrx_fbQnfzS7CeRg3TEApHg,4397
26
- geo_activity_playground/heatmap_video.py,sha256=Oc3EAAsW27zhG28Rmy3i2GoN1rjm1UFgb53eSHr9GP8,3503
27
- geo_activity_playground/importers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
- geo_activity_playground/importers/activity_parsers.py,sha256=5MvtjmXruPAoUO1KlDycoj677NeETgODiyxsFjXNppg,11103
29
- geo_activity_playground/importers/csv_parser.py,sha256=O1pP5GLhWhnWcy2Lsrr9g17Zspuibpt-GtZ3ZS5eZF4,2143
30
- geo_activity_playground/importers/directory.py,sha256=v9YC65cSXMmZBDW094HHUfTC-4H98sEkatRZJ38OHos,5454
31
- geo_activity_playground/importers/strava_api.py,sha256=cJCZsLemhOlxTtZh0z_npidgae9SD5HyEUry2uvem_A,7775
32
- geo_activity_playground/importers/strava_checkout.py,sha256=dAKW1wVqlA5zRw25SvpYZZrEikJtaUluInyhJ0RfsFc,10002
33
- geo_activity_playground/importers/test_csv_parser.py,sha256=LXqva7GuSAfXYE2zZQrg-69lCtfy5MxLSq6BRwL_VyI,1191
34
- geo_activity_playground/importers/test_directory.py,sha256=ljXokx7q0OgtHvEdHftcQYEmZJUDVv3OOF5opklxdT4,724
35
- geo_activity_playground/importers/test_strava_api.py,sha256=4vX7wDr1a9aRh8myxNrIq6RwDBbP8ZeoXXPc10CAbW4,431
36
- geo_activity_playground/webui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
37
- geo_activity_playground/webui/activity/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
- geo_activity_playground/webui/activity/blueprint.py,sha256=J2f6zzBtwkrem51WDakLXKahVcOxMT2JKbbFgu0VFws,3914
39
- geo_activity_playground/webui/activity/controller.py,sha256=2nVbcVUc7BTccnfJzzw_XcgwyGte_7phUOrmZxF__s4,20159
40
- geo_activity_playground/webui/activity/templates/activity/day.html.j2,sha256=-511hLy5PiwASFeBgTc4KhygBbpPTe7FyfjkCH7PBE0,2605
41
- geo_activity_playground/webui/activity/templates/activity/edit.html.j2,sha256=ckcTTxcQOhmvvAGNTEOtWCUG4LhvO4HfQImlIa5qKs8,1530
42
- geo_activity_playground/webui/activity/templates/activity/lines.html.j2,sha256=_ZDg1ruW-9UMJfOudy1-uY_-IcSSaagq7tPCih5Bb8g,1079
43
- geo_activity_playground/webui/activity/templates/activity/name.html.j2,sha256=H2v1H92T-iIbA_tYnYP59bgXAY6HpgG368eCF7NDboY,2557
44
- geo_activity_playground/webui/activity/templates/activity/show.html.j2,sha256=kXFGhK7FliL4NiqF_z6HYwlODDMoc42_4fAwLLlpZv0,7753
45
- geo_activity_playground/webui/app.py,sha256=K5PT6jzeG7cWle5cdWEvha7XmQJPACnHbhKSZlgSynA,6173
46
- geo_activity_playground/webui/auth_blueprint.py,sha256=sERpBU6cXdBuVjMMiRQBGJMibFZCfrUXMPj4ukzd_Ug,783
47
- geo_activity_playground/webui/authenticator.py,sha256=k278OEVuOfAmTGT4F2X4pqSTwwkK_FA87EIhAeysEqc,1416
48
- geo_activity_playground/webui/calendar/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
49
- geo_activity_playground/webui/calendar/blueprint.py,sha256=Kjyx9lkJoM5tL8vNba0Y7HhJuFRVId4F-ONZsXpKyyg,721
50
- geo_activity_playground/webui/calendar/controller.py,sha256=QpSAkR2s1sbLSu6P_fNNTccgGglOzEH2PIv1XwKxeVY,2778
51
- geo_activity_playground/webui/calendar/templates/calendar/index.html.j2,sha256=xoR6R4cUgTQNRHQv3m3f4Bc-yCjJEsJj5d4_CWlJsRo,1427
52
- geo_activity_playground/webui/calendar/templates/calendar/month.html.j2,sha256=sRIiNo_Rp9CHary6e-lnpKJKOuAonoDEBvKMxzbTLQE,1802
53
- geo_activity_playground/webui/eddington_blueprint.py,sha256=D-VrFhyWIcn46BXo7_5vBXvW5rhyQqrnQ9Gc-WESd-Y,7031
54
- geo_activity_playground/webui/entry_controller.py,sha256=McxbyouKWHJ3a2R9agPazZoG7VHiFO1RvnkBr08dMH8,2168
55
- geo_activity_playground/webui/equipment_blueprint.py,sha256=GGQdE8h0T7WTUqP6mnB2J400VNgPbU7-kJAPpdTR4w8,4438
56
- geo_activity_playground/webui/explorer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
57
- geo_activity_playground/webui/explorer/blueprint.py,sha256=GJcNgtkR0Ya15lsc6896wNXQEiTL36Ltd-8w28iecEA,2249
58
- geo_activity_playground/webui/explorer/controller.py,sha256=pIzWh0TpLJgKQZlS325-QT7nA1q9ms7fRqQIp24PNfo,11705
59
- geo_activity_playground/webui/explorer/templates/explorer/index.html.j2,sha256=3t9ikAF6oMvEaVlS3Kb1tj9ngomIQlatzqPnqVsEDKA,6908
60
- geo_activity_playground/webui/heatmap/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
61
- geo_activity_playground/webui/heatmap/blueprint.py,sha256=UndzdkSBS_mvpDYDxlotkKxi6sP3hECXz3cb0H4Kdbk,1966
62
- geo_activity_playground/webui/heatmap/heatmap_controller.py,sha256=rKhPUEHQDY0ZoSY0CHywJLRbJThKuSp6ywkevlsBHcM,8591
63
- geo_activity_playground/webui/heatmap/templates/heatmap/index.html.j2,sha256=kTVvEt-GmSNebDlVMa6zwyIuP0mJcZQFuqj-IY8JV5U,1359
64
- geo_activity_playground/webui/plot_util.py,sha256=pTTQoqOCkLVjkgOit7mbry28kMruZIL8amZozSzEpxQ,283
65
- geo_activity_playground/webui/search_blueprint.py,sha256=6YELyCMRQ5uyh67mf11OjAFXPaCg_Iw1t1Bvci4mALI,2567
66
- geo_activity_playground/webui/search_util.py,sha256=jMY7DrJQVa9e8x7POE5QsReZL-SIyYaWvjUGB_R6kW0,2326
67
- geo_activity_playground/webui/settings/blueprint.py,sha256=l5H9kxjwMpqPQoF8moIp3r6oU-RQmuWr38yiHUZYU00,9391
68
- geo_activity_playground/webui/settings/controller.py,sha256=MIZVBfoGNvmJnB_ECV_x5eH2i6gDZvkWSQ4PcSKyLKs,9170
69
- geo_activity_playground/webui/settings/templates/settings/admin-password.html.j2,sha256=VYwddpObD1RpeTH5Dm4y7VtmT7kwURDCIjxyzJeq08c,495
70
- geo_activity_playground/webui/settings/templates/settings/color-schemes.html.j2,sha256=iR91Wxd2_TMuIo9dBDZBrWSUGHNwTwzC6O8oNH-XBt4,1653
71
- geo_activity_playground/webui/settings/templates/settings/equipment-offsets.html.j2,sha256=ltaYwFe8S8Mi72ddmIp1vwqlu8MEXXjBGfbpN2WBTC4,1728
72
- geo_activity_playground/webui/settings/templates/settings/heart-rate.html.j2,sha256=UPT3MegRgSeff36lhCo0l3ZwhqNSIg5gM6h2s32GkCY,4255
73
- geo_activity_playground/webui/settings/templates/settings/index.html.j2,sha256=r7HBq91BKBrWT2_TNR7OcLokuOcUK-Czyi_zOjveIRk,5287
74
- geo_activity_playground/webui/settings/templates/settings/kind-renames.html.j2,sha256=yWVIMJq0XOpeTLglEqLxlQAG0mVhaCVw9j0Iu4nIrgI,757
75
- geo_activity_playground/webui/settings/templates/settings/kinds-without-achievements.html.j2,sha256=IdUfXon1Pu8zX3NirKb28ypshLHOvZRpz2T4bJrzrak,1067
76
- geo_activity_playground/webui/settings/templates/settings/metadata-extraction.html.j2,sha256=0g9RlHFKipN45RaH_FANWnY1lfXUkKjtc_9B-vJ19LQ,2298
77
- geo_activity_playground/webui/settings/templates/settings/privacy-zones.html.j2,sha256=OBKHlOezJauaDerLpOAJYq7wL-KxsWMn-BpSKJ93I0c,3051
78
- geo_activity_playground/webui/settings/templates/settings/segmentation.html.j2,sha256=QV72TZcIxqql-vEsq2lKHzo5UxoxeeXkRA9se46GWKU,1187
79
- geo_activity_playground/webui/settings/templates/settings/sharepic.html.j2,sha256=qZkfEpd4CtKKMaSSVadqvNEgMRYLV-0X-pw5-nJvukk,678
80
- geo_activity_playground/webui/settings/templates/settings/strava.html.j2,sha256=FrXgT-m1PgvsQWo9kMKpk8QenKeifSDBCZFqKgsHRxQ,1827
81
- geo_activity_playground/webui/square_planner_blueprint.py,sha256=A-bTwSsT1JpMyQ6qVlXoitAW1u4OXAoNAbA61RrGgow,3975
82
- geo_activity_playground/webui/static/Leaflet.fullscreen.min.js,sha256=MMWj_yFOercjzhk8wKIIKyDCK7olXrwk_7R7TjDhGYs,3677
83
- geo_activity_playground/webui/static/MarkerCluster.Default.css,sha256=LWhzWaQGZRsWFrrJxg-6Zn8TT84k0_trtiHBc6qcGpY,1346
84
- geo_activity_playground/webui/static/MarkerCluster.css,sha256=-bdWuWOXMFkX0v9Cvr3OWClPiYefDQz9GGZP_7xZxdc,886
85
- geo_activity_playground/webui/static/android-chrome-192x192.png,sha256=yxZgo8Jw4hrgOgrn3tvi9G0AXWGFD29kjCuxC07WoT4,17610
86
- geo_activity_playground/webui/static/android-chrome-512x512.png,sha256=Uiv62gQpUjMOdp9d6exzd6IyOi5zgQdgjIVVWYw5m98,38891
87
- geo_activity_playground/webui/static/apple-touch-icon.png,sha256=TNLa0YIS1mbWajvIQthC2bGve6ET3DbJzrAbs6Pf3Ps,13046
88
- geo_activity_playground/webui/static/bootstrap-dark-mode.js,sha256=XfyhxIFgjDc6aEj0kYgKpG5zjS5gvyhWCJmNfUG4HJY,2622
89
- geo_activity_playground/webui/static/bootstrap.bundle.min.js,sha256=gvZPYrsDwbwYJLD5yeBfcNujPhRoGOY831wwbIzz3t0,80663
90
- geo_activity_playground/webui/static/bootstrap.min.css,sha256=MBffSnbbXwHCuZtgPYiwMQbfE7z-GOZ7fBPCNB06Z98,232948
91
- geo_activity_playground/webui/static/browserconfig.xml,sha256=u5EvU6U1jKSDiXHW0i4rXrs0lT_tmS82otbJnvmccrk,253
92
- geo_activity_playground/webui/static/favicon-16x16.png,sha256=Yy8lRjGB7itDaeUI_l_Toq3OO0gzgPGnqIfM3CqcQy0,1419
93
- geo_activity_playground/webui/static/favicon-32x32.png,sha256=K52R99pLGgWHnjFPPkVieBm051Er-sTCiMvgLr9Alrg,2587
94
- geo_activity_playground/webui/static/favicon-48x48.png,sha256=NIIuC1OV1umv2pETJH2yDUZhhzJDk0TERsbwA5tQM9A,2008
95
- geo_activity_playground/webui/static/favicon.ico,sha256=zAkbToeh1fq8rh6osWyEjr-cgdX-ec5viI0vPAwLn7A,15086
96
- geo_activity_playground/webui/static/favicon.svg,sha256=gwESIDvoxOpg3tHvbiAc-wVEM4fY0pFzWnX_guQcv1c,52247
97
- geo_activity_playground/webui/static/fullscreen.png,sha256=yDtz-dhjuAoo6q9xc00-_XNTrGwEWrN80pOneFdol4g,299
98
- geo_activity_playground/webui/static/fullscreen@2x.png,sha256=HVi2guZO6sekf2NggilbzjUTvJDweXpSMBS81fhtnX0,420
99
- geo_activity_playground/webui/static/leaflet.css,sha256=p4NxAoJBhIIN-hmNHrzRCf9tD_miZyoHS5obTRR9BMY,14806
100
- geo_activity_playground/webui/static/leaflet.fullscreen.css,sha256=YTbhDGEH5amI_JfotPMN7IByFpsN9e4tCBnv5oNdvHU,994
101
- geo_activity_playground/webui/static/leaflet.js,sha256=20nQCchB9co0qIjJZRGuk2_Z9VM-kNiyxNV1lvTlZBo,147552
102
- geo_activity_playground/webui/static/leaflet.markercluster.js,sha256=WL6HHfYfbFEkZOFdsJQeY7lJG_E5airjvqbznghUzRw,33724
103
- geo_activity_playground/webui/static/mstile-150x150.png,sha256=j1ANUQJ1Xi1DR2sGqYZztob2ypfGw04eNtGpN9SxExA,11964
104
- geo_activity_playground/webui/static/site.webmanifest,sha256=G5wl5Ahfz6wyDt-Z7ea-ywG1WS1S7ZQ_QX9TM2ox6Lk,450
105
- geo_activity_playground/webui/static/table-sort.min.js,sha256=sFeDrgkXTePr2ciJU9_mLh-Z8qtYhPIQMgOZtj0LwBY,8506
106
- geo_activity_playground/webui/static/vega-embed@6,sha256=EtAqz74-xZ75o33UgiouBOKWG1u7Zxu-Zh0iIXFbmdo,60630
107
- geo_activity_playground/webui/static/vega-lite@4,sha256=roXmcY9bUF91uB9V-eSEUHEgfwoXe6B1xoDPuIe5ou8,267999
108
- geo_activity_playground/webui/static/vega@5,sha256=5DLHUaY2P0ph2mKSDMfX69E88J2ClJ-PSGJI-Acdw84,514536
109
- geo_activity_playground/webui/static/web-app-manifest-192x192.png,sha256=eEImN6iWfSv-EnSNPL5WbX84PKakse_8VZMBPWWye3o,13582
110
- geo_activity_playground/webui/static/web-app-manifest-512x512.png,sha256=vU9oQ4HnQerFDZVzcAT9twj4_Doc6_9v9wVvoRI-f_E,48318
111
- geo_activity_playground/webui/summary_blueprint.py,sha256=ty8kOdG4_kmxE3ta_gHO6G51R1BSxM0NoB-YIgRVqYE,9884
112
- geo_activity_playground/webui/templates/auth/index.html.j2,sha256=ILQ5HvTEYc3OrtOAIFt1VrqWorVD70V9DC342znmP70,579
113
- geo_activity_playground/webui/templates/eddington/index.html.j2,sha256=_3oxzHhC_s9ATtvGmuIWKqvjIQYJNvdCxmYnOyN9QnY,3716
114
- geo_activity_playground/webui/templates/equipment/index.html.j2,sha256=4FsMPjse9iZsWZiwD9At95CdUa_pVf2g7UugygOH8vk,1672
115
- geo_activity_playground/webui/templates/home.html.j2,sha256=IdCqI_LLcYrpUjjCO-tbXR4s05XYrPOateiJ4idF3bo,2202
116
- geo_activity_playground/webui/templates/page.html.j2,sha256=CHRvO2HGHjBnMNffX7a-C-pm2544wErKOcW66lghKos,10785
117
- geo_activity_playground/webui/templates/search/index.html.j2,sha256=_kxTgsdbT8o-4ryW0pvyWE7a-rOs7xzGUpdSPp8Q1is,1320
118
- geo_activity_playground/webui/templates/search_form.html.j2,sha256=TG9xIql0HnhsXtbHZxl3GLBt6cGYjA8jPeBq11syQ3A,6512
119
- geo_activity_playground/webui/templates/square_planner/index.html.j2,sha256=xFbYBQtkOl3U4WGkvIuU_5uazGHn8ObvQfNgPGq0Gqg,6469
120
- geo_activity_playground/webui/templates/summary/index.html.j2,sha256=bM89LdumssVvmuI0EeI8mnzMYxSzNjWY_XWfzn-f6nI,5377
121
- geo_activity_playground/webui/templates/upload/index.html.j2,sha256=I1Ix8tDS3YBdi-HdaNfjkzYXVVCjfUTe5PFTnap1ydc,775
122
- geo_activity_playground/webui/templates/upload/reload.html.j2,sha256=YZWX5eDeNyqKJdQAywDBcU8DZBm22rRBbZqFjrFrCvQ,556
123
- geo_activity_playground/webui/tile_blueprint.py,sha256=QU8YRjhMf-lhPJGqrCjV49QBX0ATgTny96GYhqJwwyI,1755
124
- geo_activity_playground/webui/upload_blueprint.py,sha256=Ha3H5Dsl6YS6YYmFouXamU8viEpLIj1YIE9XJVCiakY,4368
125
- geo_activity_playground-0.38.2.dist-info/LICENSE,sha256=4RpAwKO8bPkfXH2lnpeUW0eLkNWglyG4lbrLDU_MOwY,1070
126
- geo_activity_playground-0.38.2.dist-info/METADATA,sha256=5ZDORngu-k9YCxDXKKPSK49AsIo5gRvRWa0sYGgBSiI,1578
127
- geo_activity_playground-0.38.2.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
128
- geo_activity_playground-0.38.2.dist-info/entry_points.txt,sha256=pbNlLI6IIZIp7nPYCfAtiSiz2oxJSCl7DODD6SPkLKk,81
129
- geo_activity_playground-0.38.2.dist-info/RECORD,,