geo-activity-playground 0.29.0__py3-none-any.whl → 0.29.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.
- geo_activity_playground/core/activities.py +3 -6
- geo_activity_playground/core/time_conversion.py +1 -1
- geo_activity_playground/explorer/tile_visits.py +2 -2
- geo_activity_playground/importers/activity_parsers.py +28 -17
- geo_activity_playground/importers/csv_parser.py +1 -2
- geo_activity_playground/importers/directory.py +2 -1
- geo_activity_playground/webui/explorer/controller.py +2 -2
- geo_activity_playground/webui/settings/blueprint.py +2 -0
- geo_activity_playground/webui/settings/controller.py +4 -3
- geo_activity_playground/webui/square_planner/controller.py +2 -0
- {geo_activity_playground-0.29.0.dist-info → geo_activity_playground-0.29.1.dist-info}/METADATA +1 -1
- {geo_activity_playground-0.29.0.dist-info → geo_activity_playground-0.29.1.dist-info}/RECORD +15 -15
- {geo_activity_playground-0.29.0.dist-info → geo_activity_playground-0.29.1.dist-info}/LICENSE +0 -0
- {geo_activity_playground-0.29.0.dist-info → geo_activity_playground-0.29.1.dist-info}/WHEEL +0 -0
- {geo_activity_playground-0.29.0.dist-info → geo_activity_playground-0.29.1.dist-info}/entry_points.txt +0 -0
@@ -2,6 +2,7 @@ import datetime
|
|
2
2
|
import functools
|
3
3
|
import logging
|
4
4
|
import pickle
|
5
|
+
from typing import Any
|
5
6
|
from typing import Iterator
|
6
7
|
from typing import Optional
|
7
8
|
from typing import TypedDict
|
@@ -103,7 +104,7 @@ def build_activity_meta() -> None:
|
|
103
104
|
|
104
105
|
class ActivityRepository:
|
105
106
|
def __init__(self) -> None:
|
106
|
-
self.meta =
|
107
|
+
self.meta = pd.DataFrame()
|
107
108
|
|
108
109
|
def __len__(self) -> int:
|
109
110
|
return len(self.meta)
|
@@ -116,10 +117,6 @@ class ActivityRepository:
|
|
116
117
|
if activity_id in self.meta["id"]:
|
117
118
|
return True
|
118
119
|
|
119
|
-
for activity_meta in self._loose_activities:
|
120
|
-
if activity_meta["id"] == activity_id:
|
121
|
-
return True
|
122
|
-
|
123
120
|
return False
|
124
121
|
|
125
122
|
def last_activity_date(self) -> Optional[datetime.datetime]:
|
@@ -198,7 +195,7 @@ def make_geojson_color_line(time_series: pd.DataFrame) -> str:
|
|
198
195
|
return geojson.dumps(feature_collection)
|
199
196
|
|
200
197
|
|
201
|
-
def make_speed_color_bar(time_series: pd.DataFrame) -> dict[str,
|
198
|
+
def make_speed_color_bar(time_series: pd.DataFrame) -> dict[str, Any]:
|
202
199
|
speed_without_na = time_series["speed"].dropna()
|
203
200
|
low = min(speed_without_na)
|
204
201
|
high = max(speed_without_na)
|
@@ -59,7 +59,7 @@ class TileEvolutionState:
|
|
59
59
|
class TileState(TypedDict):
|
60
60
|
tile_visits: dict[int, dict[tuple[int, int], TileInfo]]
|
61
61
|
tile_history: dict[int, pd.DataFrame]
|
62
|
-
activities_per_tile: dict[int, set[int]]
|
62
|
+
activities_per_tile: dict[int, dict[tuple[int, int], set[int]]]
|
63
63
|
processed_activities: set[int]
|
64
64
|
evolution_state: dict[int, TileEvolutionState]
|
65
65
|
version: int
|
@@ -165,7 +165,7 @@ def _process_activity(
|
|
165
165
|
for zoom in reversed(range(20)):
|
166
166
|
activities_per_tile = tile_state["activities_per_tile"][zoom]
|
167
167
|
|
168
|
-
new_tile_history_soa = {
|
168
|
+
new_tile_history_soa: dict[str, list] = {
|
169
169
|
"activity_id": [],
|
170
170
|
"time": [],
|
171
171
|
"tile_x": [],
|
@@ -3,10 +3,10 @@ import gzip
|
|
3
3
|
import logging
|
4
4
|
import pathlib
|
5
5
|
import xml
|
6
|
+
from collections.abc import Iterator
|
6
7
|
|
7
8
|
import charset_normalizer
|
8
9
|
import dateutil.parser
|
9
|
-
import fitdecode
|
10
10
|
import fitdecode.exceptions
|
11
11
|
import gpxpy
|
12
12
|
import pandas as pd
|
@@ -246,26 +246,37 @@ def read_kml_activity(path: pathlib.Path, opener) -> pd.DataFrame:
|
|
246
246
|
with opener(path, "rb") as f:
|
247
247
|
kml_dict = xmltodict.parse(f)
|
248
248
|
doc = kml_dict["kml"]["Document"]
|
249
|
-
keypoint_folder = doc["Folder"]
|
250
|
-
placemark = keypoint_folder["Placemark"]
|
251
|
-
track = placemark["gx:Track"]
|
252
249
|
rows = []
|
253
|
-
for
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
250
|
+
for keypoint_folder in _list_or_scalar(doc["Folder"]):
|
251
|
+
for placemark in _list_or_scalar(keypoint_folder["Placemark"]):
|
252
|
+
for track in _list_or_scalar(placemark.get("gx:Track", [])):
|
253
|
+
for when, where in zip(track["when"], track["gx:coord"]):
|
254
|
+
time = dateutil.parser.parse(when)
|
255
|
+
time = convert_to_datetime_ns(time)
|
256
|
+
parts = where.split(" ")
|
257
|
+
if len(parts) == 2:
|
258
|
+
lon, lat = parts
|
259
|
+
alt = None
|
260
|
+
if len(parts) == 3:
|
261
|
+
lon, lat, alt = parts
|
262
|
+
row = {
|
263
|
+
"time": time,
|
264
|
+
"latitude": float(lat),
|
265
|
+
"longitude": float(lon),
|
266
|
+
}
|
267
|
+
if alt is not None:
|
268
|
+
row["altitude"] = float(alt)
|
269
|
+
rows.append(row)
|
266
270
|
return pd.DataFrame(rows)
|
267
271
|
|
268
272
|
|
273
|
+
def _list_or_scalar(thing) -> Iterator:
|
274
|
+
if isinstance(thing, list):
|
275
|
+
yield from thing
|
276
|
+
else:
|
277
|
+
yield thing
|
278
|
+
|
279
|
+
|
269
280
|
def read_simra_activity(path: pathlib.Path, opener) -> pd.DataFrame:
|
270
281
|
data = pd.read_csv(path, header=1)
|
271
282
|
data["time"] = data["timeStamp"].apply(
|
@@ -20,9 +20,8 @@ This module implements a "recursive descent parser" that parses this grammar.
|
|
20
20
|
|
21
21
|
def parse_csv(text: str) -> list[list]:
|
22
22
|
text = text.strip() + "\n"
|
23
|
-
result = {}
|
24
23
|
index = 0
|
25
|
-
result = []
|
24
|
+
result: list[list] = []
|
26
25
|
while index < len(text):
|
27
26
|
line, index = _parse_line(text, index)
|
28
27
|
result.append(line)
|
@@ -126,11 +126,12 @@ def _cache_single_file(path: pathlib.Path) -> Optional[tuple[pathlib.Path, str]]
|
|
126
126
|
raise
|
127
127
|
|
128
128
|
if len(timeseries) == 0:
|
129
|
-
return
|
129
|
+
return None
|
130
130
|
|
131
131
|
timeseries.to_parquet(timeseries_path)
|
132
132
|
with open(file_metadata_path, "wb") as f:
|
133
133
|
pickle.dump(activity_meta_from_file, f)
|
134
|
+
return None
|
134
135
|
|
135
136
|
|
136
137
|
def get_file_hash(path: pathlib.Path) -> int:
|
@@ -95,7 +95,7 @@ class ExplorerController:
|
|
95
95
|
x2, y2 = compute_tile(south, east, zoom)
|
96
96
|
tile_bounds = Bounds(x1, y1, x2 + 2, y2 + 2)
|
97
97
|
|
98
|
-
tile_histories = self._tile_visit_accessor.
|
98
|
+
tile_histories = self._tile_visit_accessor.tile_state["tile_history"]
|
99
99
|
tiles = tile_histories[zoom]
|
100
100
|
points = get_border_tiles(tiles, zoom, tile_bounds)
|
101
101
|
if suffix == "geojson":
|
@@ -108,7 +108,7 @@ class ExplorerController:
|
|
108
108
|
x2, y2 = compute_tile(south, east, zoom)
|
109
109
|
tile_bounds = Bounds(x1, y1, x2 + 2, y2 + 2)
|
110
110
|
|
111
|
-
tile_visits = self._tile_visit_accessor.
|
111
|
+
tile_visits = self._tile_visit_accessor.tile_state["tile_visits"]
|
112
112
|
tiles = tile_visits[zoom]
|
113
113
|
points = make_grid_points(
|
114
114
|
(tile for tile in tiles.keys() if tile_bounds.contains(*tile)), zoom
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import json
|
2
2
|
import re
|
3
3
|
import urllib.parse
|
4
|
+
from typing import Any
|
4
5
|
from typing import Optional
|
5
6
|
|
6
7
|
from flask import flash
|
@@ -70,7 +71,7 @@ class SettingsController:
|
|
70
71
|
flash("Updated equipment offsets.", category="success")
|
71
72
|
|
72
73
|
def render_heart_rate(self) -> dict:
|
73
|
-
result = {
|
74
|
+
result: dict[str, Any] = {
|
74
75
|
"birth_year": self._config_accessor().birth_year,
|
75
76
|
"heart_rate_resting": self._config_accessor().heart_rate_resting,
|
76
77
|
"heart_rate_maximum": self._config_accessor().heart_rate_maximum,
|
@@ -90,7 +91,7 @@ class SettingsController:
|
|
90
91
|
heart_rate_maximum: Optional[int],
|
91
92
|
) -> None:
|
92
93
|
self._config_accessor().birth_year = birth_year
|
93
|
-
self._config_accessor().heart_rate_resting = heart_rate_resting
|
94
|
+
self._config_accessor().heart_rate_resting = heart_rate_resting or 0
|
94
95
|
self._config_accessor().heart_rate_maximum = heart_rate_maximum
|
95
96
|
self._config_accessor.save()
|
96
97
|
flash("Updated heart rate data.", category="success")
|
@@ -251,7 +252,7 @@ class SettingsController:
|
|
251
252
|
return f"https://www.strava.com/oauth/authorize?{arg_string}"
|
252
253
|
|
253
254
|
def save_strava_code(self, code: str) -> None:
|
254
|
-
self._config_accessor().strava_client_id = self._strava_client_id
|
255
|
+
self._config_accessor().strava_client_id = int(self._strava_client_id)
|
255
256
|
self._config_accessor().strava_client_secret = self._strava_client_secret
|
256
257
|
self._config_accessor().strava_client_code = code
|
257
258
|
self._config_accessor.save()
|
@@ -79,6 +79,8 @@ class SquarePlannerController:
|
|
79
79
|
return make_grid_file_geojson(points)
|
80
80
|
elif suffix == "gpx":
|
81
81
|
return make_grid_file_gpx(points)
|
82
|
+
else:
|
83
|
+
raise RuntimeError(f"Unsupported suffix {suffix}.")
|
82
84
|
|
83
85
|
def _get_explored_tiles(self, zoom: int) -> set[tuple[int, int]]:
|
84
86
|
return set(self._tile_visits[zoom].keys())
|
{geo_activity_playground-0.29.0.dist-info → geo_activity_playground-0.29.1.dist-info}/RECORD
RENAMED
@@ -1,7 +1,7 @@
|
|
1
1
|
geo_activity_playground/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
2
|
geo_activity_playground/__main__.py,sha256=MBZn9K1m3PofiPNTtpsSTVCyB_Gz95TjVP-nb9v_-JE,3989
|
3
3
|
geo_activity_playground/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
4
|
-
geo_activity_playground/core/activities.py,sha256=
|
4
|
+
geo_activity_playground/core/activities.py,sha256=HcxgLsM2tE48eqZh1t1QBk9O7vxCV9MaL2QRp0loXu0,6509
|
5
5
|
geo_activity_playground/core/config.py,sha256=DsjZhiq2BZs94rjd7zgt_KTZIjVfxfntiEQZhgq8NeA,4617
|
6
6
|
geo_activity_playground/core/coordinates.py,sha256=tDfr9mlXhK6E_MMIJ0vYWVCoH0Lq8uyuaqUgaa8i0jg,966
|
7
7
|
geo_activity_playground/core/enrichment.py,sha256=CwZhW-svgPAYbdx3n9kvKlTgcsiCaeuJfSRCC4JxX6g,7411
|
@@ -14,15 +14,15 @@ geo_activity_playground/core/tasks.py,sha256=aMDBWJqp6ek2ao6G6Xa8GOSZbcQqXoWL74S
|
|
14
14
|
geo_activity_playground/core/test_tiles.py,sha256=zce1FxNfsSpOQt66jMehdQRVoNdl-oiFydx6iVBHZXM,764
|
15
15
|
geo_activity_playground/core/test_time_conversion.py,sha256=Sh6nZA3uCTOdZTZa3yOijtR0m74QtZu2mcWXsDNnyQI,984
|
16
16
|
geo_activity_playground/core/tiles.py,sha256=KpzD-h3kNzZ2ieLt6f2xHilSF3lHyfaEXPnrGvlIAz0,3379
|
17
|
-
geo_activity_playground/core/time_conversion.py,sha256=
|
17
|
+
geo_activity_playground/core/time_conversion.py,sha256=x5mXG6Y4GtdX7CBmwucGNSWBp9JQJDbZ7u0JkdUY1Vs,379
|
18
18
|
geo_activity_playground/explorer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
19
19
|
geo_activity_playground/explorer/grid_file.py,sha256=k6j6KBEk2a2BY-onE8SV5TJsERGGyOrlY4as__meWpA,3304
|
20
|
-
geo_activity_playground/explorer/tile_visits.py,sha256=
|
20
|
+
geo_activity_playground/explorer/tile_visits.py,sha256=CSHAjgzKWe1iB-zvaqgsR5Z_lFycpWqUfxnPCAWvYaU,14173
|
21
21
|
geo_activity_playground/explorer/video.py,sha256=ROAmV9shfJyqTgnXVD41KFORiwnRgVpEWenIq4hMCRM,4389
|
22
22
|
geo_activity_playground/importers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
23
|
-
geo_activity_playground/importers/activity_parsers.py,sha256=
|
24
|
-
geo_activity_playground/importers/csv_parser.py,sha256=
|
25
|
-
geo_activity_playground/importers/directory.py,sha256=
|
23
|
+
geo_activity_playground/importers/activity_parsers.py,sha256=XNQs0ziqAcVqIoiLAX5Ndmhb6v__29XdjUPvNvc7oBI,11082
|
24
|
+
geo_activity_playground/importers/csv_parser.py,sha256=O1pP5GLhWhnWcy2Lsrr9g17Zspuibpt-GtZ3ZS5eZF4,2143
|
25
|
+
geo_activity_playground/importers/directory.py,sha256=IPnr1xk3beznmPVjfWL6AQiEKA4WN5EDIfnzrM0Tzlc,5767
|
26
26
|
geo_activity_playground/importers/strava_api.py,sha256=pgWZp-cWOLkvlDE85lTiEKM8BCZYzOlAAdKoa2F7c6o,7780
|
27
27
|
geo_activity_playground/importers/strava_checkout.py,sha256=N-uGTkhBJMC7cPYjRRXHOSLwpK3wc6aaSrY2RQfSitA,9419
|
28
28
|
geo_activity_playground/importers/test_csv_parser.py,sha256=LXqva7GuSAfXYE2zZQrg-69lCtfy5MxLSq6BRwL_VyI,1191
|
@@ -56,7 +56,7 @@ geo_activity_playground/webui/equipment/controller.py,sha256=Sx9i2RCK7m4W6FgpDfR
|
|
56
56
|
geo_activity_playground/webui/equipment/templates/equipment/index.html.j2,sha256=FEfxB4XwVYELAOdjVlSlprjJH_kLmE-pNWEEXdPqc6I,1778
|
57
57
|
geo_activity_playground/webui/explorer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
58
58
|
geo_activity_playground/webui/explorer/blueprint.py,sha256=EKnBs8llqT6Wy1uac18dF2epp3TebF9p3iGlSbj6Vl0,2337
|
59
|
-
geo_activity_playground/webui/explorer/controller.py,sha256=
|
59
|
+
geo_activity_playground/webui/explorer/controller.py,sha256=pIzWh0TpLJgKQZlS325-QT7nA1q9ms7fRqQIp24PNfo,11705
|
60
60
|
geo_activity_playground/webui/explorer/templates/explorer/index.html.j2,sha256=u2htecx-XwINRiINHFN6EZDaRXVtiape1OCUZexTBU8,7049
|
61
61
|
geo_activity_playground/webui/heatmap/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
62
62
|
geo_activity_playground/webui/heatmap/blueprint.py,sha256=bjQu-HL3QN5UpJ6tHOifhcLGlPr_hIKvaRu78md4JqM,1470
|
@@ -65,8 +65,8 @@ geo_activity_playground/webui/heatmap/templates/heatmap/index.html.j2,sha256=YLe
|
|
65
65
|
geo_activity_playground/webui/plot_util.py,sha256=pTTQoqOCkLVjkgOit7mbry28kMruZIL8amZozSzEpxQ,283
|
66
66
|
geo_activity_playground/webui/search/blueprint.py,sha256=b3TCIplY60MWE2_VsKHuoV1LAgNwd_T5ft5t0CKALFI,642
|
67
67
|
geo_activity_playground/webui/search/templates/search/index.html.j2,sha256=FvNRoDfUlSzXjM_tqZY_fDhuhUDgbPaY73q56gdvF1A,1130
|
68
|
-
geo_activity_playground/webui/settings/blueprint.py,sha256=
|
69
|
-
geo_activity_playground/webui/settings/controller.py,sha256=
|
68
|
+
geo_activity_playground/webui/settings/blueprint.py,sha256=O5GqbbzETOYq5JESoI-F2br8hnk6xHyJzqWTQDnbNEE,7623
|
69
|
+
geo_activity_playground/webui/settings/controller.py,sha256=MIZVBfoGNvmJnB_ECV_x5eH2i6gDZvkWSQ4PcSKyLKs,9170
|
70
70
|
geo_activity_playground/webui/settings/templates/settings/admin-password.html.j2,sha256=VYwddpObD1RpeTH5Dm4y7VtmT7kwURDCIjxyzJeq08c,495
|
71
71
|
geo_activity_playground/webui/settings/templates/settings/color-schemes.html.j2,sha256=CaFbYkkU1yGTOlAzGq97u3tVgS79RIo7PEmiVjuZiBc,1226
|
72
72
|
geo_activity_playground/webui/settings/templates/settings/equipment-offsets.html.j2,sha256=ltaYwFe8S8Mi72ddmIp1vwqlu8MEXXjBGfbpN2WBTC4,1728
|
@@ -79,7 +79,7 @@ geo_activity_playground/webui/settings/templates/settings/sharepic.html.j2,sha25
|
|
79
79
|
geo_activity_playground/webui/settings/templates/settings/strava.html.j2,sha256=FrXgT-m1PgvsQWo9kMKpk8QenKeifSDBCZFqKgsHRxQ,1827
|
80
80
|
geo_activity_playground/webui/square_planner/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
81
81
|
geo_activity_playground/webui/square_planner/blueprint.py,sha256=r2VkSM547chX85g6c1BQ8NC-tkdqGdYp-2ZALBiiDTc,1320
|
82
|
-
geo_activity_playground/webui/square_planner/controller.py,sha256=
|
82
|
+
geo_activity_playground/webui/square_planner/controller.py,sha256=ML6ftOyr3tTh7D4DBcRP76CvkyTxqI5QWgMeG9wC8FE,3561
|
83
83
|
geo_activity_playground/webui/square_planner/templates/square_planner/index.html.j2,sha256=aIB0ql5qW4HXfp0ENksYYOk9vTgBitwyHJX5W7bqkeY,6512
|
84
84
|
geo_activity_playground/webui/static/android-chrome-192x192.png,sha256=yxZgo8Jw4hrgOgrn3tvi9G0AXWGFD29kjCuxC07WoT4,17610
|
85
85
|
geo_activity_playground/webui/static/android-chrome-384x384.png,sha256=bgeqAdyvDZBMch7rVi3qSawf0Zr4Go0EG8Ws_B8NApY,49297
|
@@ -107,8 +107,8 @@ geo_activity_playground/webui/upload/blueprint.py,sha256=xX9scEmleN_dL03jfhWRh5y
|
|
107
107
|
geo_activity_playground/webui/upload/controller.py,sha256=disRtrlvPiqsIFt9UaAokgtRtXCvosg7bXkAnN_qaxk,4102
|
108
108
|
geo_activity_playground/webui/upload/templates/upload/index.html.j2,sha256=I1Ix8tDS3YBdi-HdaNfjkzYXVVCjfUTe5PFTnap1ydc,775
|
109
109
|
geo_activity_playground/webui/upload/templates/upload/reload.html.j2,sha256=YZWX5eDeNyqKJdQAywDBcU8DZBm22rRBbZqFjrFrCvQ,556
|
110
|
-
geo_activity_playground-0.29.
|
111
|
-
geo_activity_playground-0.29.
|
112
|
-
geo_activity_playground-0.29.
|
113
|
-
geo_activity_playground-0.29.
|
114
|
-
geo_activity_playground-0.29.
|
110
|
+
geo_activity_playground-0.29.1.dist-info/LICENSE,sha256=4RpAwKO8bPkfXH2lnpeUW0eLkNWglyG4lbrLDU_MOwY,1070
|
111
|
+
geo_activity_playground-0.29.1.dist-info/METADATA,sha256=O9NvI6x-QQvVw7XklVLmq2pkz2UFTTg9PnLwAK6KhWY,1612
|
112
|
+
geo_activity_playground-0.29.1.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
|
113
|
+
geo_activity_playground-0.29.1.dist-info/entry_points.txt,sha256=pbNlLI6IIZIp7nPYCfAtiSiz2oxJSCl7DODD6SPkLKk,81
|
114
|
+
geo_activity_playground-0.29.1.dist-info/RECORD,,
|
{geo_activity_playground-0.29.0.dist-info → geo_activity_playground-0.29.1.dist-info}/LICENSE
RENAMED
File without changes
|
File without changes
|
File without changes
|