geo-activity-playground 1.9.2__py3-none-any.whl → 1.9.4__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/parametric_plot.py +16 -0
- geo_activity_playground/importers/activity_parsers.py +2 -2
- geo_activity_playground/importers/directory.py +43 -3
- geo_activity_playground/importers/strava_checkout.py +12 -4
- geo_activity_playground/webui/blueprints/export_blueprint.py +2 -1
- geo_activity_playground/webui/columns.py +2 -2
- {geo_activity_playground-1.9.2.dist-info → geo_activity_playground-1.9.4.dist-info}/METADATA +1 -1
- {geo_activity_playground-1.9.2.dist-info → geo_activity_playground-1.9.4.dist-info}/RECORD +11 -11
- {geo_activity_playground-1.9.2.dist-info → geo_activity_playground-1.9.4.dist-info}/LICENSE +0 -0
- {geo_activity_playground-1.9.2.dist-info → geo_activity_playground-1.9.4.dist-info}/WHEEL +0 -0
- {geo_activity_playground-1.9.2.dist-info → geo_activity_playground-1.9.4.dist-info}/entry_points.txt +0 -0
@@ -66,8 +66,24 @@ GROUP_BY_VARIABLES = {
|
|
66
66
|
VARIABLES_1 = {"": "", **DISCRETE_VARIABLES}
|
67
67
|
VARIABLES_2 = {"": "", **DISCRETE_VARIABLES, **CONTINUOUS_VARIABLES}
|
68
68
|
|
69
|
+
RENAMES = {
|
70
|
+
"year(start):O": "year(start_local):O",
|
71
|
+
"yearquarter(start)": "yearquarter(start_local)",
|
72
|
+
"yearquartermonth(start)": "yearquartermonth(start_local)",
|
73
|
+
"yearmonth(start)": "yearmonth(start_local)",
|
74
|
+
"quarter(start)": "quarter(start_local)",
|
75
|
+
"quartermonth(start)": "quartermonth(start_local)",
|
76
|
+
"month(start)": "month(start_local)",
|
77
|
+
"date(start)": "date(start_local)",
|
78
|
+
"weekday(start)": "weekday(start_local)",
|
79
|
+
}
|
80
|
+
|
69
81
|
|
70
82
|
def make_parametric_plot(df: pd.DataFrame, spec: PlotSpec) -> dict[str, str]:
|
83
|
+
# Update renamed fields.
|
84
|
+
for field in spec.FIELDS:
|
85
|
+
setattr(spec, field, RENAMES.get(getattr(spec, field), getattr(spec, field)))
|
86
|
+
|
71
87
|
if spec.group_by:
|
72
88
|
grouped = df.groupby(spec.group_by)
|
73
89
|
else:
|
@@ -219,12 +219,12 @@ def read_gpx_activity(path: pathlib.Path, open) -> pd.DataFrame:
|
|
219
219
|
datum.tag
|
220
220
|
== "{http://www.garmin.com/xmlschemas/TrackPointExtension/v1}hr"
|
221
221
|
):
|
222
|
-
row["heartrate"] = int(datum.text)
|
222
|
+
row["heartrate"] = int(float(datum.text))
|
223
223
|
if (
|
224
224
|
datum.tag
|
225
225
|
== "{http://www.garmin.com/xmlschemas/TrackPointExtension/v1}cad"
|
226
226
|
):
|
227
|
-
row["cadence"] = int(datum.text)
|
227
|
+
row["cadence"] = int(float(datum.text))
|
228
228
|
|
229
229
|
points.append(row)
|
230
230
|
df = pd.DataFrame(points)
|
@@ -1,3 +1,4 @@
|
|
1
|
+
import hashlib
|
1
2
|
import logging
|
2
3
|
import pathlib
|
3
4
|
import re
|
@@ -51,6 +52,17 @@ def import_from_directory(
|
|
51
52
|
is None
|
52
53
|
]
|
53
54
|
|
55
|
+
for activity in DB.session.scalars(
|
56
|
+
sqlalchemy.select(Activity).filter(
|
57
|
+
Activity.upstream_id.is_(sqlalchemy.null()),
|
58
|
+
Activity.path.is_not(sqlalchemy.null()),
|
59
|
+
)
|
60
|
+
):
|
61
|
+
assert activity.path is not None
|
62
|
+
if pathlib.Path(activity.path).exists():
|
63
|
+
activity.upstream_id = file_sha256(pathlib.Path(activity.path))
|
64
|
+
DB.session.commit()
|
65
|
+
|
54
66
|
for i, activity_path in enumerate(
|
55
67
|
tqdm(paths_to_import, desc="Importing activity files", delay=0)
|
56
68
|
):
|
@@ -58,10 +70,24 @@ def import_from_directory(
|
|
58
70
|
activity = DB.session.scalar(
|
59
71
|
sqlalchemy.select(Activity).filter(Activity.path == str(activity_path))
|
60
72
|
)
|
61
|
-
if activity is None:
|
62
|
-
|
63
|
-
|
73
|
+
if activity is not None:
|
74
|
+
continue
|
75
|
+
|
76
|
+
with_same_hash = DB.session.scalars(
|
77
|
+
sqlalchemy.select(Activity).filter(
|
78
|
+
Activity.upstream_id == file_sha256(activity_path)
|
64
79
|
)
|
80
|
+
).all()
|
81
|
+
if with_same_hash:
|
82
|
+
if len(with_same_hash) == 1:
|
83
|
+
continue
|
84
|
+
else:
|
85
|
+
logger.warning(
|
86
|
+
"The following activities are duplicates: "
|
87
|
+
+ ", ".join(str(activity.id) for activity in with_same_hash)
|
88
|
+
)
|
89
|
+
|
90
|
+
import_from_file(activity_path, repository, tile_visit_accessor, config, i)
|
65
91
|
|
66
92
|
|
67
93
|
def import_from_file(
|
@@ -87,6 +113,7 @@ def import_from_file(
|
|
87
113
|
return
|
88
114
|
|
89
115
|
activity.path = str(path)
|
116
|
+
activity.upstream_id = file_sha256(path)
|
90
117
|
if activity.name is None:
|
91
118
|
activity.name = path.name.removesuffix("".join(path.suffixes))
|
92
119
|
|
@@ -120,3 +147,16 @@ def _get_metadata_from_path(
|
|
120
147
|
if m := re.search(regex, str(path.relative_to(ACTIVITY_DIR))):
|
121
148
|
return m.groupdict()
|
122
149
|
return {}
|
150
|
+
|
151
|
+
|
152
|
+
def file_sha256(filename: pathlib.Path) -> str:
|
153
|
+
"""
|
154
|
+
Based on https://stackoverflow.com/a/44873382/653152.
|
155
|
+
"""
|
156
|
+
h = hashlib.sha256(usedforsecurity=False)
|
157
|
+
b = bytearray(128 * 1024)
|
158
|
+
mv = memoryview(b)
|
159
|
+
with open(filename, "rb", buffering=0) as f:
|
160
|
+
while n := f.readinto(mv):
|
161
|
+
h.update(mv[:n])
|
162
|
+
return h.hexdigest()
|
@@ -19,8 +19,6 @@ from ..core.datamodel import get_or_make_equipment
|
|
19
19
|
from ..core.datamodel import get_or_make_kind
|
20
20
|
from ..core.enrichment import update_and_commit
|
21
21
|
from ..core.paths import activity_extracted_meta_dir
|
22
|
-
from ..core.tasks import get_state
|
23
|
-
from ..core.tasks import set_state
|
24
22
|
from ..core.tasks import work_tracker_path
|
25
23
|
from ..core.tasks import WorkTracker
|
26
24
|
from .activity_parsers import ActivityParseError
|
@@ -132,6 +130,11 @@ EXPECTED_COLUMNS = [
|
|
132
130
|
"Average Grade Adjusted Pace",
|
133
131
|
"Timer Time",
|
134
132
|
"Total Cycles",
|
133
|
+
"Regeneration",
|
134
|
+
"Mit Haustier",
|
135
|
+
"Wettbewerb",
|
136
|
+
"Langer Lauf",
|
137
|
+
"Für einen guten Zweck",
|
135
138
|
"Media",
|
136
139
|
]
|
137
140
|
|
@@ -161,7 +164,12 @@ def import_from_strava_checkout(config: Config) -> None:
|
|
161
164
|
if header[0] == EXPECTED_COLUMNS[0]:
|
162
165
|
dayfirst = False
|
163
166
|
elif header[0] == "Aktivitäts-ID":
|
164
|
-
|
167
|
+
new_header = list(EXPECTED_COLUMNS)
|
168
|
+
if len(new_header) > len(header):
|
169
|
+
new_header = new_header[: len(header)]
|
170
|
+
elif len(new_header) < len(header):
|
171
|
+
new_header += [f"Ignored_{i}" for i in range(len(header) - len(new_header))]
|
172
|
+
header = new_header
|
165
173
|
dayfirst = True
|
166
174
|
else:
|
167
175
|
logger.error(
|
@@ -194,7 +202,7 @@ def import_from_strava_checkout(config: Config) -> None:
|
|
194
202
|
|
195
203
|
start_datetime = dateutil.parser.parse(
|
196
204
|
row["Activity Date"], dayfirst=dayfirst
|
197
|
-
).replace(tzinfo=zoneinfo.ZoneInfo("
|
205
|
+
).replace(tzinfo=zoneinfo.ZoneInfo("UTC"))
|
198
206
|
|
199
207
|
activity_file = checkout_path / row["Filename"]
|
200
208
|
|
@@ -8,6 +8,7 @@ from ...core.export import export_all
|
|
8
8
|
from ..authenticator import Authenticator
|
9
9
|
from ..authenticator import needs_authentication
|
10
10
|
|
11
|
+
from datetime import date
|
11
12
|
|
12
13
|
def make_export_blueprint(authenticator: Authenticator) -> Blueprint:
|
13
14
|
blueprint = Blueprint("export", __name__, template_folder="templates")
|
@@ -25,7 +26,7 @@ def make_export_blueprint(authenticator: Authenticator) -> Blueprint:
|
|
25
26
|
return Response(
|
26
27
|
bytes(export_all(meta_format, activity_format)),
|
27
28
|
mimetype="application/zip",
|
28
|
-
headers={"Content-disposition": 'attachment; filename="export.zip"'}
|
29
|
+
headers={"Content-disposition": f'attachment; filename="GAP-export-{date.today().strftime("%Y-%m-%d")}.zip"'}
|
29
30
|
)
|
30
31
|
|
31
32
|
return blueprint
|
@@ -23,13 +23,13 @@ column_elevation_gain = ColumnDescription(
|
|
23
23
|
)
|
24
24
|
column_hours = ColumnDescription(
|
25
25
|
name="hours",
|
26
|
-
display_name="Elapsed
|
26
|
+
display_name="Elapsed Time",
|
27
27
|
unit="h",
|
28
28
|
format=".1f",
|
29
29
|
)
|
30
30
|
column_hours_moving = ColumnDescription(
|
31
31
|
name="hours_moving",
|
32
|
-
display_name="Moving
|
32
|
+
display_name="Moving Time",
|
33
33
|
unit="h",
|
34
34
|
format=".1f",
|
35
35
|
)
|
@@ -27,7 +27,7 @@ geo_activity_playground/core/export.py,sha256=ayOmhWL72263oP9NLIZRYCg_Db0GLUFhgN
|
|
27
27
|
geo_activity_playground/core/heart_rate.py,sha256=-S3WAhS7AOywrw_Lk5jfuo_fu6zvZQ1VtjwEKSycWpU,1542
|
28
28
|
geo_activity_playground/core/meta_search.py,sha256=Sevl4AtBwJZMW3VJ6ihRqwjC0M9fhJqX3MN6tw_hIFQ,6627
|
29
29
|
geo_activity_playground/core/missing_values.py,sha256=HjonaLV0PFMICnuMrbdUNnK9uy_8PBh_RxI5GuEMQK0,250
|
30
|
-
geo_activity_playground/core/parametric_plot.py,sha256=
|
30
|
+
geo_activity_playground/core/parametric_plot.py,sha256=sPaBnrcjvbzys0s0ge5OHtSSp1bJMaLtoO0UxXdffqo,6400
|
31
31
|
geo_activity_playground/core/paths.py,sha256=qQ4ujaIHmsxTGEWzf-76XS8FclEI2RC5COTUeuLEbDI,2938
|
32
32
|
geo_activity_playground/core/photos.py,sha256=pHdVUpgKfbyrTddZL_mgmsXQJ3k_IHKf70jtcIjjcCA,1229
|
33
33
|
geo_activity_playground/core/privacy_zones.py,sha256=4TumHsVUN1uW6RG3ArqTXDykPVipF98DCxVBe7YNdO8,512
|
@@ -52,11 +52,11 @@ geo_activity_playground/explorer/tile_visits.py,sha256=DzAmZmyLSeGe8mIg6-Kx1gXtC
|
|
52
52
|
geo_activity_playground/explorer/video.py,sha256=7j6Qv3HG6On7Tn7xh7Olwrx_fbQnfzS7CeRg3TEApHg,4397
|
53
53
|
geo_activity_playground/heatmap_video.py,sha256=I8i1uVvbbPUXVtvLAROaLy58nQoUPnuMCZkERWNkQjg,3318
|
54
54
|
geo_activity_playground/importers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
55
|
-
geo_activity_playground/importers/activity_parsers.py,sha256=
|
55
|
+
geo_activity_playground/importers/activity_parsers.py,sha256=lh7B_ZwZkcwZgrwLhptobcLfxvDIiPJRgWdE9fZzKw4,12475
|
56
56
|
geo_activity_playground/importers/csv_parser.py,sha256=O1pP5GLhWhnWcy2Lsrr9g17Zspuibpt-GtZ3ZS5eZF4,2143
|
57
|
-
geo_activity_playground/importers/directory.py,sha256=
|
57
|
+
geo_activity_playground/importers/directory.py,sha256=UBs-iWGZx_LkknytsRykAo_BaScUg0wYkfThpk5HG-8,5338
|
58
58
|
geo_activity_playground/importers/strava_api.py,sha256=1sRb_CD4tbsW-MwP6QPg7zpATlb6XpniS4rtH72iwkw,9606
|
59
|
-
geo_activity_playground/importers/strava_checkout.py,sha256=
|
59
|
+
geo_activity_playground/importers/strava_checkout.py,sha256=Tpln_IweoTIo-dkkTyRsVPGWesSu3S3C3ifd874NqUA,9590
|
60
60
|
geo_activity_playground/importers/test_csv_parser.py,sha256=nOTVTdlzIY0TDcbWp7xNyNaIO6Mkeu55hVziVl22QE4,1092
|
61
61
|
geo_activity_playground/importers/test_directory.py,sha256=_fn_-y98ZyElbG0BRxAmGFdtGobUShPU86SdEOpuv-A,691
|
62
62
|
geo_activity_playground/importers/test_strava_api.py,sha256=7b8bl5Rh2BctCmvTPEhCadxtUOq3mfzuadD6F5XxRio,398
|
@@ -72,7 +72,7 @@ geo_activity_playground/webui/blueprints/eddington_blueprints.py,sha256=s5o_U1rq
|
|
72
72
|
geo_activity_playground/webui/blueprints/entry_views.py,sha256=slGyYokGattdG-e5Ef9s_ys4ohVVAkFLFclEQS5fEr4,2954
|
73
73
|
geo_activity_playground/webui/blueprints/equipment_blueprint.py,sha256=6u81Hestr4FP6mix_avQp9jaK0In4WNdYaSwKL5cJDs,5757
|
74
74
|
geo_activity_playground/webui/blueprints/explorer_blueprint.py,sha256=fe4ZNROmpks-nP4Wsw2vc9t5_X508-6Xi1dv07O_NfQ,20979
|
75
|
-
geo_activity_playground/webui/blueprints/export_blueprint.py,sha256=
|
75
|
+
geo_activity_playground/webui/blueprints/export_blueprint.py,sha256=Rppuyk_TkP1GeDplxgKnRkyujDR-hGhD3oWRnNNCEjc,1102
|
76
76
|
geo_activity_playground/webui/blueprints/hall_of_fame_blueprint.py,sha256=NGVk8Xgwpt-YNX5_zgGWTMRctN_N4NCnMq10DSDteVg,3121
|
77
77
|
geo_activity_playground/webui/blueprints/heatmap_blueprint.py,sha256=prERVBOxq2xvmgyH_dwtLwMMMFILeu-6yZE9h9U_T9g,8418
|
78
78
|
geo_activity_playground/webui/blueprints/photo_blueprint.py,sha256=i4-AS9icK6pDypTdl-coTZyKldXtpukGiNbKsihfpl0,7299
|
@@ -84,7 +84,7 @@ geo_activity_playground/webui/blueprints/summary_blueprint.py,sha256=giVLJttJ2my
|
|
84
84
|
geo_activity_playground/webui/blueprints/tile_blueprint.py,sha256=YzZf9OrNdjhc1_j4MtO1DMcw1uCv29ueNsYd-mWqgbg,837
|
85
85
|
geo_activity_playground/webui/blueprints/time_zone_fixer_blueprint.py,sha256=PEHsk3kRHx2EvQ-6VPD4xeOmXGjh64GMAagFkQ0wbeg,2301
|
86
86
|
geo_activity_playground/webui/blueprints/upload_blueprint.py,sha256=VLyMic2ptBRcMyunGXl-6Auxs1jglIO5fYgRGPhH25s,4816
|
87
|
-
geo_activity_playground/webui/columns.py,sha256=
|
87
|
+
geo_activity_playground/webui/columns.py,sha256=C9Bg4J2Z8xbSZKdNParm1IKoR9nHStyroiBZDFdoZT4,1525
|
88
88
|
geo_activity_playground/webui/flasher.py,sha256=Covc1D9cO_jjokRWnvyiXCc2tfp3aZ8XkNqFdA1AXtk,500
|
89
89
|
geo_activity_playground/webui/plot_util.py,sha256=5Uesjj-xcMskQX2z9viDZYHSxLGrH2a5dHA1ogsJW9U,261
|
90
90
|
geo_activity_playground/webui/search_util.py,sha256=gH2cOM1FTAozZUlSQ4C1dR1xlV-8e82pD1PPi_pPBNY,2647
|
@@ -175,8 +175,8 @@ geo_activity_playground/webui/templates/summary/vega-chart.html.j2,sha256=mw8Hti
|
|
175
175
|
geo_activity_playground/webui/templates/time_zone_fixer/index.html.j2,sha256=s9r6BJMXmd7kLSyjkvH4xLi6e01S5bpGRcMgMMJyCAE,1760
|
176
176
|
geo_activity_playground/webui/templates/upload/index.html.j2,sha256=5W2gpm4eSvidOyJOCSZZbvTZaTkSWNrOWux3-oIm0zI,784
|
177
177
|
geo_activity_playground/webui/templates/upload/reload.html.j2,sha256=YZWX5eDeNyqKJdQAywDBcU8DZBm22rRBbZqFjrFrCvQ,556
|
178
|
-
geo_activity_playground-1.9.
|
179
|
-
geo_activity_playground-1.9.
|
180
|
-
geo_activity_playground-1.9.
|
181
|
-
geo_activity_playground-1.9.
|
182
|
-
geo_activity_playground-1.9.
|
178
|
+
geo_activity_playground-1.9.4.dist-info/LICENSE,sha256=4RpAwKO8bPkfXH2lnpeUW0eLkNWglyG4lbrLDU_MOwY,1070
|
179
|
+
geo_activity_playground-1.9.4.dist-info/METADATA,sha256=TWDOnevm__CRkjcmlnfI73azWUZey8R5clp-0w3kgi8,1937
|
180
|
+
geo_activity_playground-1.9.4.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
181
|
+
geo_activity_playground-1.9.4.dist-info/entry_points.txt,sha256=pbNlLI6IIZIp7nPYCfAtiSiz2oxJSCl7DODD6SPkLKk,81
|
182
|
+
geo_activity_playground-1.9.4.dist-info/RECORD,,
|
File without changes
|
File without changes
|
{geo_activity_playground-1.9.2.dist-info → geo_activity_playground-1.9.4.dist-info}/entry_points.txt
RENAMED
File without changes
|