geo-activity-playground 0.7.0__py3-none-any.whl → 0.8.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.
- geo_activity_playground/__main__.py +3 -9
- geo_activity_playground/core/activities.py +24 -15
- geo_activity_playground/core/config.py +22 -0
- geo_activity_playground/explorer/grid_file.py +74 -34
- geo_activity_playground/importers/strava_api.py +2 -8
- geo_activity_playground/webui/activity_controller.py +4 -1
- geo_activity_playground/webui/explorer_controller.py +17 -11
- geo_activity_playground/webui/templates/explorer.html.j2 +19 -7
- geo_activity_playground/webui/templates/heatmap.html.j2 +1 -1
- {geo_activity_playground-0.7.0.dist-info → geo_activity_playground-0.8.0.dist-info}/METADATA +4 -2
- {geo_activity_playground-0.7.0.dist-info → geo_activity_playground-0.8.0.dist-info}/RECORD +13 -12
- {geo_activity_playground-0.7.0.dist-info → geo_activity_playground-0.8.0.dist-info}/WHEEL +0 -0
- {geo_activity_playground-0.7.0.dist-info → geo_activity_playground-0.8.0.dist-info}/entry_points.txt +0 -0
@@ -1,16 +1,11 @@
|
|
1
1
|
import argparse
|
2
2
|
import os
|
3
3
|
import pathlib
|
4
|
-
import tomllib
|
5
4
|
|
6
5
|
import coloredlogs
|
7
6
|
|
8
7
|
from geo_activity_playground.core.activities import ActivityRepository
|
9
|
-
from geo_activity_playground.core.
|
10
|
-
from geo_activity_playground.explorer.grid_file import get_border_tiles
|
11
|
-
from geo_activity_playground.explorer.grid_file import get_explored_tiles
|
12
|
-
from geo_activity_playground.explorer.grid_file import make_grid_file_geojson
|
13
|
-
from geo_activity_playground.explorer.grid_file import make_grid_file_gpx
|
8
|
+
from geo_activity_playground.core.config import get_config
|
14
9
|
from geo_activity_playground.explorer.video import explorer_video_main
|
15
10
|
from geo_activity_playground.heatmap import generate_heatmaps_per_cluster
|
16
11
|
from geo_activity_playground.importers.directory import import_from_directory
|
@@ -78,11 +73,10 @@ def main() -> None:
|
|
78
73
|
|
79
74
|
def make_activity_repository(basedir: pathlib.Path) -> ActivityRepository:
|
80
75
|
os.chdir(basedir)
|
76
|
+
config = get_config()
|
81
77
|
if pathlib.Path("Activities").exists():
|
82
78
|
import_from_directory()
|
83
|
-
elif
|
84
|
-
with open("config.toml", "rb") as f:
|
85
|
-
config = tomllib.load(f)
|
79
|
+
elif config:
|
86
80
|
if "strava" in config:
|
87
81
|
import_from_strava_api()
|
88
82
|
return ActivityRepository()
|
@@ -2,16 +2,15 @@ import dataclasses
|
|
2
2
|
import datetime
|
3
3
|
import functools
|
4
4
|
import logging
|
5
|
-
import pathlib
|
6
|
-
import tomllib
|
7
5
|
from typing import Iterator
|
8
6
|
from typing import Optional
|
9
7
|
|
10
8
|
import geojson
|
11
9
|
import matplotlib
|
12
|
-
import numpy as np
|
13
10
|
import pandas as pd
|
14
11
|
|
12
|
+
from geo_activity_playground.core.config import get_config
|
13
|
+
|
15
14
|
|
16
15
|
logger = logging.getLogger(__name__)
|
17
16
|
|
@@ -105,25 +104,35 @@ def make_geojson_color_line(time_series: pd.DataFrame) -> str:
|
|
105
104
|
def extract_heart_rate_zones(time_series: pd.DataFrame) -> Optional[pd.DataFrame]:
|
106
105
|
if "heartrate" not in time_series:
|
107
106
|
return None
|
108
|
-
|
109
|
-
if not config_path.exists():
|
110
|
-
logger.warning("Missing a config, cannot extract heart rate zones.")
|
111
|
-
return None
|
112
|
-
with open(config_path, "rb") as f:
|
113
|
-
config = tomllib.load(f)
|
114
|
-
|
107
|
+
config = get_config()
|
115
108
|
try:
|
116
|
-
|
109
|
+
heart_config = config["heart"]
|
117
110
|
except KeyError:
|
118
111
|
logger.warning(
|
119
|
-
"Missing config entry `heart
|
112
|
+
"Missing config entry `heart`, cannot determine heart rate zones."
|
113
|
+
)
|
114
|
+
return None
|
115
|
+
|
116
|
+
birthyear = heart_config.get("birthyear", None)
|
117
|
+
maximum = heart_config.get("maximum", None)
|
118
|
+
resting = heart_config.get("resting", None)
|
119
|
+
|
120
|
+
if not maximum and birthyear:
|
121
|
+
age = time_series["time"].iloc[0].year - birthyear
|
122
|
+
maximum = 220 - age
|
123
|
+
if not resting:
|
124
|
+
resting = 0
|
125
|
+
if not maximum:
|
126
|
+
logger.warning(
|
127
|
+
"Missing config entry `heart.maximum` or `heart.birthyear`, cannot determine heart rate zones."
|
120
128
|
)
|
121
129
|
return None
|
122
130
|
|
123
|
-
|
124
|
-
|
125
|
-
|
131
|
+
zones: pd.Series = (time_series["heartrate"] - resting) * 10 // (
|
132
|
+
maximum - resting
|
133
|
+
) - 4
|
126
134
|
zones.loc[zones < 0] = 0
|
135
|
+
zones.loc[zones > 5] = 5
|
127
136
|
df = pd.DataFrame({"heartzone": zones, "step": time_series["time"].diff()}).dropna()
|
128
137
|
duration_per_zone = df.groupby("heartzone").sum()["step"].dt.total_seconds() / 60
|
129
138
|
duration_per_zone.name = "minutes"
|
@@ -0,0 +1,22 @@
|
|
1
|
+
import functools
|
2
|
+
import logging
|
3
|
+
import pathlib
|
4
|
+
|
5
|
+
|
6
|
+
try:
|
7
|
+
import tomllib
|
8
|
+
except ModuleNotFoundError:
|
9
|
+
import tomli as tomllib
|
10
|
+
|
11
|
+
|
12
|
+
logger = logging.getLogger(__name__)
|
13
|
+
|
14
|
+
|
15
|
+
@functools.cache
|
16
|
+
def get_config() -> dict:
|
17
|
+
config_path = pathlib.Path("config.toml")
|
18
|
+
if not config_path.exists():
|
19
|
+
logger.warning("Missing a config, some features might be missing.")
|
20
|
+
return {}
|
21
|
+
with open(config_path, "rb") as f:
|
22
|
+
return tomllib.load(f)
|
@@ -1,3 +1,4 @@
|
|
1
|
+
import logging
|
1
2
|
import pathlib
|
2
3
|
from typing import Iterator
|
3
4
|
|
@@ -6,12 +7,16 @@ import gpxpy
|
|
6
7
|
import numpy as np
|
7
8
|
import pandas as pd
|
8
9
|
import scipy.ndimage
|
10
|
+
import sklearn.cluster
|
9
11
|
|
10
12
|
from geo_activity_playground.core.activities import ActivityRepository
|
11
13
|
from geo_activity_playground.core.tiles import get_tile_upper_left_lat_lon
|
12
14
|
from geo_activity_playground.explorer.converters import get_tile_history
|
13
15
|
|
14
16
|
|
17
|
+
logger = logging.getLogger(__name__)
|
18
|
+
|
19
|
+
|
15
20
|
def get_three_color_tiles(
|
16
21
|
tiles: pd.DataFrame, repository: ActivityRepository, zoom: int
|
17
22
|
) -> str:
|
@@ -19,7 +24,10 @@ def get_three_color_tiles(
|
|
19
24
|
a = np.zeros((2**zoom, 2**zoom), dtype=np.int8)
|
20
25
|
a[tiles["tile_x"], tiles["tile_y"]] = 1
|
21
26
|
|
22
|
-
tile_dict = {
|
27
|
+
tile_dict = {
|
28
|
+
elem: {"cluster": False, "square": False}
|
29
|
+
for elem in zip(tiles["tile_x"], tiles["tile_y"])
|
30
|
+
}
|
23
31
|
|
24
32
|
for x, y in tile_dict.keys():
|
25
33
|
if (
|
@@ -28,7 +36,7 @@ def get_three_color_tiles(
|
|
28
36
|
and (x, y + 1) in tile_dict
|
29
37
|
and (x, y - 1) in tile_dict
|
30
38
|
):
|
31
|
-
tile_dict[(x, y)] =
|
39
|
+
tile_dict[(x, y)]["cluster"] = True
|
32
40
|
|
33
41
|
# Compute biggest square.
|
34
42
|
square_size = 1
|
@@ -52,43 +60,75 @@ def get_three_color_tiles(
|
|
52
60
|
square_x, square_y, square_size = biggest
|
53
61
|
for x in range(square_x, square_x + square_size):
|
54
62
|
for y in range(square_y, square_y + square_size):
|
55
|
-
tile_dict[(x, y)] =
|
56
|
-
|
57
|
-
|
58
|
-
(row["tile_x"], row["tile_y"])
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
# Find non-zero tiles.
|
67
|
-
return geojson.dumps(
|
68
|
-
geojson.FeatureCollection(
|
69
|
-
features=[
|
70
|
-
make_explorer_tile(
|
71
|
-
x,
|
72
|
-
y,
|
73
|
-
{
|
74
|
-
"color": {1: "red", 2: "green", 3: "blue"}[v],
|
75
|
-
**tile_metadata[(x, y)],
|
76
|
-
},
|
77
|
-
zoom,
|
78
|
-
)
|
79
|
-
for (x, y), v in tile_dict.items()
|
80
|
-
]
|
63
|
+
tile_dict[(x, y)]["square"] = True
|
64
|
+
|
65
|
+
for index, row in tiles.iterrows():
|
66
|
+
tile_dict[(row["tile_x"], row["tile_y"])].update(
|
67
|
+
{
|
68
|
+
"first_visit": row["time"].date().isoformat(),
|
69
|
+
"activity_id": row["activity_id"],
|
70
|
+
"activity_name": repository.get_activity_by_id(row["activity_id"]).name,
|
71
|
+
"color": map_color(tile_dict[(row["tile_x"], row["tile_y"])]),
|
72
|
+
}
|
81
73
|
)
|
74
|
+
|
75
|
+
num_cluster_tiles = sum(value["cluster"] for value in tile_dict.values())
|
76
|
+
|
77
|
+
cluster_tiles = np.array(
|
78
|
+
[tile for tile, value in tile_dict.items() if value["cluster"]]
|
82
79
|
)
|
83
80
|
|
81
|
+
logger.info("Run DBSCAN cluster finding algorithm …")
|
82
|
+
dbscan = sklearn.cluster.DBSCAN(eps=1.1, min_samples=1)
|
83
|
+
labels = dbscan.fit_predict(cluster_tiles)
|
84
|
+
label_counts = dict(zip(*np.unique(labels, return_counts=True)))
|
85
|
+
max_cluster_size = max(
|
86
|
+
count for label, count in label_counts.items() if label != -1
|
87
|
+
)
|
88
|
+
for xy, label in zip(cluster_tiles, labels):
|
89
|
+
tile_dict[tuple(xy)]["cluster_id"] = int(label)
|
90
|
+
tile_dict[tuple(xy)]["this_cluster_size"] = int(label_counts[label])
|
91
|
+
|
92
|
+
# Find non-zero tiles.
|
93
|
+
result = {
|
94
|
+
"explored_geojson": geojson.dumps(
|
95
|
+
geojson.FeatureCollection(
|
96
|
+
features=[
|
97
|
+
make_explorer_tile(
|
98
|
+
x,
|
99
|
+
y,
|
100
|
+
tile_dict[(x, y)],
|
101
|
+
zoom,
|
102
|
+
)
|
103
|
+
for (x, y), v in tile_dict.items()
|
104
|
+
]
|
105
|
+
)
|
106
|
+
),
|
107
|
+
"max_cluster_size": max_cluster_size,
|
108
|
+
"num_cluster_tiles": num_cluster_tiles,
|
109
|
+
"num_tiles": len(tile_dict),
|
110
|
+
"square_size": square_size,
|
111
|
+
}
|
112
|
+
return result
|
113
|
+
|
114
|
+
|
115
|
+
def map_color(tile_meta: dict) -> str:
|
116
|
+
if tile_meta["square"]:
|
117
|
+
return "blue"
|
118
|
+
elif tile_meta["cluster"]:
|
119
|
+
return "green"
|
120
|
+
else:
|
121
|
+
return "red"
|
122
|
+
|
84
123
|
|
85
124
|
def get_border_tiles(tiles: pd.DataFrame, zoom: int) -> list[list[list[float]]]:
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
125
|
+
tile_set = set(zip(tiles["tile_x"], tiles["tile_y"]))
|
126
|
+
border_tiles = set()
|
127
|
+
for x, y in tile_set:
|
128
|
+
for neighbor in [(x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1)]:
|
129
|
+
if neighbor not in tile_set:
|
130
|
+
border_tiles.add(neighbor)
|
131
|
+
return make_grid_points(border_tiles, zoom)
|
92
132
|
|
93
133
|
|
94
134
|
def get_explored_tiles(tiles: pd.DataFrame, zoom: int) -> list[list[list[float]]]:
|
@@ -4,22 +4,16 @@ import json
|
|
4
4
|
import logging
|
5
5
|
import pathlib
|
6
6
|
import pickle
|
7
|
-
import tomllib
|
8
7
|
from typing import Any
|
9
8
|
|
10
9
|
import pandas as pd
|
11
10
|
from stravalib import Client
|
12
11
|
from stravalib.exc import RateLimitExceeded
|
13
12
|
|
14
|
-
|
15
|
-
logger = logging.getLogger(__name__)
|
13
|
+
from geo_activity_playground.core.config import get_config
|
16
14
|
|
17
15
|
|
18
|
-
|
19
|
-
def get_config() -> dict:
|
20
|
-
config_path = pathlib.Path("config.toml")
|
21
|
-
with open(config_path, "rb") as f:
|
22
|
-
return tomllib.load(f)
|
16
|
+
logger = logging.getLogger(__name__)
|
23
17
|
|
24
18
|
|
25
19
|
def get_state(path: pathlib.Path) -> Any:
|
@@ -19,6 +19,7 @@ class ActivityController:
|
|
19
19
|
activity = self._repository.get_activity_by_id(id)
|
20
20
|
|
21
21
|
time_series = self._repository.get_time_series(id)
|
22
|
+
time_series["distance/km"] = time_series["distance"] / 1000
|
22
23
|
line_json = make_geojson_from_time_series(time_series)
|
23
24
|
|
24
25
|
result = {
|
@@ -40,7 +41,9 @@ def distance_time_plot(time_series: pd.DataFrame) -> str:
|
|
40
41
|
return (
|
41
42
|
alt.Chart(time_series, title="Distance")
|
42
43
|
.mark_line()
|
43
|
-
.encode(
|
44
|
+
.encode(
|
45
|
+
alt.X("time", title="Time"), alt.Y("distance/km", title="Distance / km")
|
46
|
+
)
|
44
47
|
.interactive()
|
45
48
|
.to_json(format="vega")
|
46
49
|
)
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import functools
|
2
2
|
|
3
3
|
from geo_activity_playground.core.activities import ActivityRepository
|
4
|
+
from geo_activity_playground.core.tiles import get_tile_upper_left_lat_lon
|
4
5
|
from geo_activity_playground.explorer.converters import get_tile_history
|
5
6
|
from geo_activity_playground.explorer.grid_file import get_border_tiles
|
6
7
|
from geo_activity_playground.explorer.grid_file import get_explored_geojson
|
@@ -17,21 +18,26 @@ class ExplorerController:
|
|
17
18
|
@functools.cache
|
18
19
|
def render(self, zoom: int) -> dict:
|
19
20
|
tiles = get_tile_history(self._repository, zoom)
|
21
|
+
medians = tiles.median()
|
22
|
+
median_lat, median_lon = get_tile_upper_left_lat_lon(
|
23
|
+
medians["tile_x"], medians["tile_y"], zoom
|
24
|
+
)
|
20
25
|
|
21
|
-
|
26
|
+
explored = get_three_color_tiles(tiles, self._repository, zoom)
|
22
27
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
make_grid_file_gpx(points, "missing_tiles")
|
28
|
+
points = get_border_tiles(tiles, zoom)
|
29
|
+
missing_tiles_geojson = make_grid_file_geojson(points, "missing_tiles")
|
30
|
+
make_grid_file_gpx(points, "missing_tiles")
|
27
31
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
else:
|
32
|
-
missing_tiles_geojson = {}
|
32
|
+
points = get_explored_tiles(tiles, zoom)
|
33
|
+
explored_tiles_geojson = make_grid_file_geojson(points, "explored")
|
34
|
+
make_grid_file_gpx(points, "explored")
|
33
35
|
|
34
36
|
return {
|
35
|
-
"
|
37
|
+
"center": {
|
38
|
+
"latitude": median_lat,
|
39
|
+
"longitude": median_lon,
|
40
|
+
},
|
41
|
+
"explored": explored,
|
36
42
|
"missing_tiles_geojson": missing_tiles_geojson,
|
37
43
|
}
|
@@ -4,6 +4,11 @@
|
|
4
4
|
<div class="row mb-3">
|
5
5
|
<div class="col">
|
6
6
|
<h1>Explorer Tiles</h1>
|
7
|
+
<p>You have {{ explored.num_tiles }} explored tiles. There are {{ explored.num_cluster_tiles }} cluster tiles in
|
8
|
+
total. Your largest cluster consists of {{ explored.max_cluster_size }} tiles. Your largest square has size
|
9
|
+
{{
|
10
|
+
explored.square_size }}².
|
11
|
+
</p>
|
7
12
|
</div>
|
8
13
|
</div>
|
9
14
|
|
@@ -22,14 +27,21 @@
|
|
22
27
|
<script>
|
23
28
|
function onEachFeature(feature, layer) {
|
24
29
|
if (feature.properties && feature.properties.first_visit) {
|
25
|
-
|
30
|
+
let lines = [`First visit: ${feature.properties.first_visit}`,
|
31
|
+
`First activity: <a href=/activity/${feature.properties.activity_id}>${feature.properties.activity_name}</a>`]
|
32
|
+
if (feature.properties.this_cluster_size) {
|
33
|
+
lines.push(`This cluster size: ${feature.properties.this_cluster_size}`)
|
34
|
+
}
|
35
|
+
layer.bindPopup(lines.join('<br />'))
|
26
36
|
}
|
27
37
|
}
|
28
38
|
|
29
|
-
let explorer_geojson = {{ explored_geojson| safe}}
|
39
|
+
let explorer_geojson = {{ explored.explored_geojson| safe}}
|
30
40
|
let map = L.map('explorer-map', {
|
31
|
-
fullscreenControl: true
|
32
|
-
|
41
|
+
fullscreenControl: true,
|
42
|
+
center: [{{ center.latitude }}, {{ center.longitude }}],
|
43
|
+
zoom: 10
|
44
|
+
})
|
33
45
|
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
34
46
|
maxZoom: 19,
|
35
47
|
attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
|
@@ -38,7 +50,6 @@
|
|
38
50
|
style: function (feature) { return { color: feature.properties.color, fillColor: feature.properties.color, weight: 1 } },
|
39
51
|
onEachFeature: onEachFeature
|
40
52
|
}).addTo(map)
|
41
|
-
map.fitBounds(explorer_layer.getBounds())
|
42
53
|
</script>
|
43
54
|
</div>
|
44
55
|
</div>
|
@@ -59,14 +70,15 @@
|
|
59
70
|
<script>
|
60
71
|
let missing_geojson = {{ missing_tiles_geojson| safe}}
|
61
72
|
let missing_map = L.map('missing-map', {
|
62
|
-
fullscreenControl: true
|
73
|
+
fullscreenControl: true,
|
74
|
+
center: [{{ center.latitude }}, {{ center.longitude }}],
|
75
|
+
zoom: 10
|
63
76
|
});
|
64
77
|
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
65
78
|
maxZoom: 19,
|
66
79
|
attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
|
67
80
|
}).addTo(missing_map)
|
68
81
|
let missing_layer = L.geoJSON(missing_geojson).addTo(missing_map)
|
69
|
-
missing_map.fitBounds(missing_layer.getBounds())
|
70
82
|
</script>
|
71
83
|
</div>
|
72
84
|
</div>
|
{geo_activity_playground-0.7.0.dist-info → geo_activity_playground-0.8.0.dist-info}/METADATA
RENAMED
@@ -1,13 +1,14 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: geo-activity-playground
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.8.0
|
4
4
|
Summary: Analysis of geo data activities like rides, runs or hikes.
|
5
5
|
License: MIT
|
6
6
|
Author: Martin Ueding
|
7
7
|
Author-email: mu@martin-ueding.de
|
8
|
-
Requires-Python: >=3.
|
8
|
+
Requires-Python: >=3.9,<3.12
|
9
9
|
Classifier: License :: OSI Approved :: MIT License
|
10
10
|
Classifier: Programming Language :: Python :: 3
|
11
|
+
Classifier: Programming Language :: Python :: 3.9
|
11
12
|
Classifier: Programming Language :: Python :: 3.10
|
12
13
|
Classifier: Programming Language :: Python :: 3.11
|
13
14
|
Requires-Dist: Pillow (>=9.2.0,<10.0.0)
|
@@ -27,6 +28,7 @@ Requires-Dist: requests (>=2.28.1,<3.0.0)
|
|
27
28
|
Requires-Dist: scikit-learn (>=1.3.0,<2.0.0)
|
28
29
|
Requires-Dist: scipy (>=1.8.1,<2.0.0)
|
29
30
|
Requires-Dist: stravalib (>=1.3.3,<2.0.0)
|
31
|
+
Requires-Dist: tomli (>=2.0.1,<3.0.0) ; python_version < "3.11"
|
30
32
|
Requires-Dist: tqdm (>=4.64.0,<5.0.0)
|
31
33
|
Requires-Dist: vegafusion (>=1.4.3,<2.0.0)
|
32
34
|
Requires-Dist: vegafusion-python-embed (>=1.4.3,<2.0.0)
|
@@ -1,8 +1,9 @@
|
|
1
1
|
geo_activity_playground/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
-
geo_activity_playground/__main__.py,sha256=
|
2
|
+
geo_activity_playground/__main__.py,sha256=bGDI5TTWJakCBqlet-kqdDOmBgh9JbmV7v99g6GgT3A,2745
|
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=6f-pnIJ58ZMrcwXJ19LJUafmip9vUVPlGyBeVUVnIxw,4484
|
5
5
|
geo_activity_playground/core/activity_parsers.py,sha256=CaQB4jXm-4PjrXR7AcLkgZt82zGl4oCyLYlY0Zfx4H8,2135
|
6
|
+
geo_activity_playground/core/config.py,sha256=GNHEIeFI3dNRiFSMburn5URZHx0qkiitvePAx2toYUQ,456
|
6
7
|
geo_activity_playground/core/coordinates.py,sha256=SxU2xDPZD-KxL2VBM94_wUFKkcG27-wTLkuu22ByVps,573
|
7
8
|
geo_activity_playground/core/heatmap.py,sha256=BPhRNcieHgc5gSZdKRtYcv8Ljfwgi-teLr6VVBVlTkg,1289
|
8
9
|
geo_activity_playground/core/plots.py,sha256=7FX1QRT_haBq9lQsehaZQ_rXLcJNHO2Fx_bWuBXwPnw,2420
|
@@ -12,18 +13,18 @@ geo_activity_playground/core/test_tiles.py,sha256=ATIcCqwAQMpkPAZD9VO__uinpuuOyz
|
|
12
13
|
geo_activity_playground/core/tiles.py,sha256=aTC3roH8JMaEAMC_hUAwOz7_Yvvw7n4Vc-9y8pN05Pk,2399
|
13
14
|
geo_activity_playground/explorer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
14
15
|
geo_activity_playground/explorer/converters.py,sha256=UVU5qhnvAelY6rmqCnkqfDp1zYI_1LUatdJC0d16BWE,3051
|
15
|
-
geo_activity_playground/explorer/grid_file.py,sha256=
|
16
|
+
geo_activity_playground/explorer/grid_file.py,sha256=lER2TAJjsG8BMjbdoXiwW9GXZLM8bH-9EeF7z7yckgg,6828
|
16
17
|
geo_activity_playground/explorer/video.py,sha256=RGZik93ghfZuRILXf8pfUbPh5VV37_QRAR4FgOMfZqQ,4354
|
17
18
|
geo_activity_playground/heatmap.py,sha256=jg0yuFvYoSa8K0uGL6MCMhWFclXWO3DVyrsdSJcH380,8552
|
18
19
|
geo_activity_playground/importers/directory.py,sha256=Hk9YYJA2ssWaOyc6WFxKNwTo5DWZxXCW661spCyI7kQ,2622
|
19
|
-
geo_activity_playground/importers/strava_api.py,sha256=
|
20
|
-
geo_activity_playground/webui/activity_controller.py,sha256=
|
20
|
+
geo_activity_playground/importers/strava_api.py,sha256=3utIYnmw0nqY5oGBf-3VJPzGI1hTplYUfeWXoSuJ7gE,5749
|
21
|
+
geo_activity_playground/webui/activity_controller.py,sha256=sOYUYJGibYx6eGOxE17umSWubpybB8Xgcm07wB0v4LA,2941
|
21
22
|
geo_activity_playground/webui/app.py,sha256=9-TgDI1LojplwPxeorMqtObGWIw1sB5qepqWVHUl3s4,3532
|
22
23
|
geo_activity_playground/webui/calendar_controller.py,sha256=maQ1RlrD99pncOts3ue5ye4OHr6WB-E40eAzs8ZxwPI,2239
|
23
24
|
geo_activity_playground/webui/eddington_controller.py,sha256=b5mYkciv7Wkd5zord-WsdrV_8c-qpVi-8DG3jIUEKhs,2616
|
24
25
|
geo_activity_playground/webui/entry_controller.py,sha256=TixdwCDMKhHUVrbc6sAIjpvtmouHXtbQN0N641TB__s,1851
|
25
26
|
geo_activity_playground/webui/equipment_controller.py,sha256=2asTMDEYdMz8a_l5fXL1ULXoUaDHywoDl9mZnfZSn5Q,2011
|
26
|
-
geo_activity_playground/webui/explorer_controller.py,sha256=
|
27
|
+
geo_activity_playground/webui/explorer_controller.py,sha256=8OD9h7-UzlSU53tpA7LD0VsHbvRTka9U4CFjiuNQzGU,1766
|
27
28
|
geo_activity_playground/webui/heatmap_controller.py,sha256=twfp9IQwUz9qQCjO0zMwhWjQYmHRpHM-A8BPnCj3ErY,3636
|
28
29
|
geo_activity_playground/webui/static/android-chrome-192x192.png,sha256=30rNfBHxdLYC0Wx4cDkPZY-V17ZQZIc4PPLQBdz_w1U,20069
|
29
30
|
geo_activity_playground/webui/static/android-chrome-384x384.png,sha256=bgeqAdyvDZBMch7rVi3qSawf0Zr4Go0EG8Ws_B8NApY,49297
|
@@ -40,12 +41,12 @@ geo_activity_playground/webui/templates/calendar-month.html.j2,sha256=LVokl95lPl
|
|
40
41
|
geo_activity_playground/webui/templates/calendar.html.j2,sha256=b7a_YWhqyN2GYU7g4wIckU3UURTzNuL5fGe5SibVKM8,1099
|
41
42
|
geo_activity_playground/webui/templates/eddington.html.j2,sha256=yl75IzWeIkFpwPj8FjTrzJsz_f-qdETPmNnAGLPJuL8,487
|
42
43
|
geo_activity_playground/webui/templates/equipment.html.j2,sha256=BwZzbZ2AuFuiM_Fxu2KOqvhcgHd9yr1xL76ihb_6YKc,1317
|
43
|
-
geo_activity_playground/webui/templates/explorer.html.j2,sha256=
|
44
|
-
geo_activity_playground/webui/templates/heatmap.html.j2,sha256=
|
44
|
+
geo_activity_playground/webui/templates/explorer.html.j2,sha256=fVxPxicgDRvgOu1138E6bJs81CFvf1VkHuzGYAWW1ok,3399
|
45
|
+
geo_activity_playground/webui/templates/heatmap.html.j2,sha256=M56IKATu3TdlwXUgTK9w-vfoAubBv9oJrE3ot-wEf84,726
|
45
46
|
geo_activity_playground/webui/templates/index.html.j2,sha256=6b0cdqiGnqrC_hjEg-z6-IZFqXoZa7V0JurQ4Xd6YJw,1968
|
46
47
|
geo_activity_playground/webui/templates/page.html.j2,sha256=CWaDxYlXzJCWCuIsMma2-PCLrsEr38cSan01CGG00qU,5104
|
47
48
|
geo_activity_playground/webui/templates/summary-statistics.html.j2,sha256=WylEkNplyXIt2bqYdZg93xupeP9wmaq5AWnpYaPkr-8,453
|
48
|
-
geo_activity_playground-0.
|
49
|
-
geo_activity_playground-0.
|
50
|
-
geo_activity_playground-0.
|
51
|
-
geo_activity_playground-0.
|
49
|
+
geo_activity_playground-0.8.0.dist-info/METADATA,sha256=lAYsRY6bF3_FhEX9MODLVrJvQH-SuP25fEppUVkqPH0,1425
|
50
|
+
geo_activity_playground-0.8.0.dist-info/WHEEL,sha256=Zb28QaM1gQi8f4VCBhsUklF61CTlNYfs9YAZn-TOGFk,88
|
51
|
+
geo_activity_playground-0.8.0.dist-info/entry_points.txt,sha256=pbNlLI6IIZIp7nPYCfAtiSiz2oxJSCl7DODD6SPkLKk,81
|
52
|
+
geo_activity_playground-0.8.0.dist-info/RECORD,,
|
File without changes
|
{geo_activity_playground-0.7.0.dist-info → geo_activity_playground-0.8.0.dist-info}/entry_points.txt
RENAMED
File without changes
|