geo-activity-playground 0.32.0__py3-none-any.whl → 0.33.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/core/config.py +4 -1
- geo_activity_playground/core/heatmap.py +3 -20
- geo_activity_playground/core/tiles.py +8 -5
- geo_activity_playground/webui/activity/controller.py +3 -5
- geo_activity_playground/webui/activity/templates/activity/day.html.j2 +1 -1
- geo_activity_playground/webui/activity/templates/activity/lines.html.j2 +1 -1
- geo_activity_playground/webui/activity/templates/activity/name.html.j2 +3 -2
- geo_activity_playground/webui/activity/templates/activity/show.html.j2 +2 -2
- geo_activity_playground/webui/app.py +14 -2
- geo_activity_playground/webui/explorer/templates/explorer/index.html.j2 +20 -44
- geo_activity_playground/webui/heatmap/blueprint.py +5 -2
- geo_activity_playground/webui/heatmap/heatmap_controller.py +14 -4
- geo_activity_playground/webui/heatmap/templates/heatmap/index.html.j2 +1 -1
- geo_activity_playground/webui/settings/blueprint.py +44 -33
- geo_activity_playground/webui/settings/templates/settings/color-schemes.html.j2 +11 -2
- geo_activity_playground/webui/settings/templates/settings/privacy-zones.html.j2 +1 -1
- geo_activity_playground/webui/square_planner/templates/square_planner/index.html.j2 +1 -1
- geo_activity_playground/webui/summary/controller.py +8 -14
- geo_activity_playground/webui/summary/templates/summary/index.html.j2 +18 -5
- geo_activity_playground/webui/templates/home.html.j2 +1 -1
- geo_activity_playground/webui/tile/blueprint.py +3 -2
- geo_activity_playground/webui/tile/controller.py +7 -3
- {geo_activity_playground-0.32.0.dist-info → geo_activity_playground-0.33.0.dist-info}/METADATA +1 -1
- {geo_activity_playground-0.32.0.dist-info → geo_activity_playground-0.33.0.dist-info}/RECORD +27 -27
- {geo_activity_playground-0.32.0.dist-info → geo_activity_playground-0.33.0.dist-info}/LICENSE +0 -0
- {geo_activity_playground-0.32.0.dist-info → geo_activity_playground-0.33.0.dist-info}/WHEEL +0 -0
- {geo_activity_playground-0.32.0.dist-info → geo_activity_playground-0.33.0.dist-info}/entry_points.txt +0 -0
@@ -21,8 +21,9 @@ logger = logging.getLogger(__name__)
|
|
21
21
|
@dataclasses.dataclass
|
22
22
|
class Config:
|
23
23
|
birth_year: Optional[int] = None
|
24
|
-
color_scheme_for_counts: str = "
|
24
|
+
color_scheme_for_counts: str = "teals"
|
25
25
|
color_scheme_for_kind: str = "category10"
|
26
|
+
color_scheme_for_heatmap: str = "hot"
|
26
27
|
equipment_offsets: dict[str, float] = dataclasses.field(default_factory=dict)
|
27
28
|
explorer_zoom_levels: list[int] = dataclasses.field(
|
28
29
|
default_factory=lambda: [14, 17]
|
@@ -43,6 +44,8 @@ class Config:
|
|
43
44
|
strava_client_code: Optional[str] = None
|
44
45
|
time_diff_threshold_seconds: Optional[int] = 30
|
45
46
|
upload_password: Optional[str] = None
|
47
|
+
map_tile_url: str = "https://tile.openstreetmap.org/{zoom}/{x}/{y}.png"
|
48
|
+
map_tile_attribution: str = '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> | <a href="https://www.openstreetmap.org/fixthemap">Correct Map</a>'
|
46
49
|
|
47
50
|
|
48
51
|
class ConfigAccessor:
|
@@ -6,6 +6,7 @@ import logging
|
|
6
6
|
|
7
7
|
import numpy as np
|
8
8
|
|
9
|
+
from geo_activity_playground.core.config import Config
|
9
10
|
from geo_activity_playground.core.tiles import compute_tile_float
|
10
11
|
from geo_activity_playground.core.tiles import get_tile
|
11
12
|
from geo_activity_playground.core.tiles import get_tile_upper_left_lat_lon
|
@@ -123,30 +124,12 @@ def get_sensible_zoom_level(
|
|
123
124
|
)
|
124
125
|
|
125
126
|
|
126
|
-
def build_map_from_tiles(tile_bounds: TileBounds) -> np.ndarray:
|
127
|
-
background = np.zeros((*PixelBounds.from_tile_bounds(tile_bounds).shape, 3))
|
128
|
-
|
129
|
-
for x in range(tile_bounds.x_tile_min, tile_bounds.x_tile_max):
|
130
|
-
for y in range(tile_bounds.y_tile_min, tile_bounds.y_tile_max):
|
131
|
-
tile = np.array(get_tile(tile_bounds.zoom, x, y)) / 255
|
132
|
-
|
133
|
-
i = y - tile_bounds.y_tile_min
|
134
|
-
j = x - tile_bounds.x_tile_min
|
135
|
-
|
136
|
-
background[
|
137
|
-
i * OSM_TILE_SIZE : (i + 1) * OSM_TILE_SIZE,
|
138
|
-
j * OSM_TILE_SIZE : (j + 1) * OSM_TILE_SIZE,
|
139
|
-
:,
|
140
|
-
] = tile[:, :, :3]
|
141
|
-
|
142
|
-
return background
|
143
|
-
|
144
|
-
|
145
127
|
def build_map_from_tiles_around_center(
|
146
128
|
center: tuple[float, float],
|
147
129
|
zoom: int,
|
148
130
|
target: tuple[int, int],
|
149
131
|
inner_target: tuple[int, int],
|
132
|
+
config: Config,
|
150
133
|
) -> np.ndarray:
|
151
134
|
background = np.zeros((target[1], target[0], 3))
|
152
135
|
|
@@ -196,7 +179,7 @@ def build_map_from_tiles_around_center(
|
|
196
179
|
if source_x_max < 0 or source_y_max < 0:
|
197
180
|
continue
|
198
181
|
|
199
|
-
tile = np.array(get_tile(zoom, x, y)) / 255
|
182
|
+
tile = np.array(get_tile(zoom, x, y, config.map_tile_url)) / 255
|
200
183
|
|
201
184
|
background[target_y_min:target_y_max, target_x_min:target_x_max] = tile[
|
202
185
|
source_y_min:source_y_max, source_x_min:source_x_max, :3
|
@@ -3,6 +3,7 @@ import logging
|
|
3
3
|
import math
|
4
4
|
import pathlib
|
5
5
|
import time
|
6
|
+
import urllib.parse
|
6
7
|
from typing import Iterator
|
7
8
|
from typing import Optional
|
8
9
|
|
@@ -13,8 +14,10 @@ from PIL import Image
|
|
13
14
|
logger = logging.getLogger(__name__)
|
14
15
|
|
15
16
|
|
16
|
-
def osm_tile_path(x: int, y: int, zoom: int) -> pathlib.Path:
|
17
|
-
|
17
|
+
def osm_tile_path(x: int, y: int, zoom: int, url_template: str) -> pathlib.Path:
|
18
|
+
base_dir = pathlib.Path("Open Street Map Tiles")
|
19
|
+
dir_for_source = base_dir / urllib.parse.quote_plus(url_template)
|
20
|
+
path = dir_for_source / f"{zoom}/{x}/{y}.png"
|
18
21
|
path.parent.mkdir(parents=True, exist_ok=True)
|
19
22
|
return path
|
20
23
|
|
@@ -62,11 +65,11 @@ def download_file(url: str, destination: pathlib.Path):
|
|
62
65
|
|
63
66
|
|
64
67
|
@functools.lru_cache()
|
65
|
-
def get_tile(zoom: int, x: int, y: int) -> Image.Image:
|
66
|
-
destination = osm_tile_path(x, y, zoom)
|
68
|
+
def get_tile(zoom: int, x: int, y: int, url_template: str) -> Image.Image:
|
69
|
+
destination = osm_tile_path(x, y, zoom, url_template)
|
67
70
|
if not destination.exists():
|
68
71
|
logger.info(f"Downloading OSM tile {x=}, {y=}, {zoom=} …")
|
69
|
-
url =
|
72
|
+
url = url_template.format(x=x, y=y, zoom=zoom)
|
70
73
|
download_file(url, destination)
|
71
74
|
with Image.open(destination) as image:
|
72
75
|
image.load()
|
@@ -21,12 +21,8 @@ from geo_activity_playground.core.activities import make_geojson_from_time_serie
|
|
21
21
|
from geo_activity_playground.core.activities import make_speed_color_bar
|
22
22
|
from geo_activity_playground.core.config import Config
|
23
23
|
from geo_activity_playground.core.heart_rate import HeartRateZoneComputer
|
24
|
-
from geo_activity_playground.core.heatmap import add_margin_to_geo_bounds
|
25
|
-
from geo_activity_playground.core.heatmap import build_map_from_tiles
|
26
24
|
from geo_activity_playground.core.heatmap import build_map_from_tiles_around_center
|
27
25
|
from geo_activity_playground.core.heatmap import GeoBounds
|
28
|
-
from geo_activity_playground.core.heatmap import get_bounds
|
29
|
-
from geo_activity_playground.core.heatmap import get_sensible_zoom_level
|
30
26
|
from geo_activity_playground.core.heatmap import OSM_MAX_ZOOM
|
31
27
|
from geo_activity_playground.core.heatmap import OSM_TILE_SIZE
|
32
28
|
from geo_activity_playground.core.heatmap import PixelBounds
|
@@ -130,7 +126,7 @@ class ActivityController:
|
|
130
126
|
if len(time_series) == 0:
|
131
127
|
time_series = self._repository.get_time_series(id)
|
132
128
|
return make_sharepic(
|
133
|
-
activity, time_series, self._config.sharepic_suppressed_fields
|
129
|
+
activity, time_series, self._config.sharepic_suppressed_fields, self._config
|
134
130
|
)
|
135
131
|
|
136
132
|
def render_day(self, year: int, month: int, day: int) -> dict:
|
@@ -460,6 +456,7 @@ def make_sharepic(
|
|
460
456
|
activity: ActivityMeta,
|
461
457
|
time_series: pd.DataFrame,
|
462
458
|
sharepic_suppressed_fields: list[str],
|
459
|
+
config: Config,
|
463
460
|
) -> bytes:
|
464
461
|
tile_x = time_series["x"]
|
465
462
|
tile_y = time_series["y"]
|
@@ -492,6 +489,7 @@ def make_sharepic(
|
|
492
489
|
zoom,
|
493
490
|
(target_width, target_height),
|
494
491
|
(target_width, target_map_height),
|
492
|
+
config,
|
495
493
|
)
|
496
494
|
|
497
495
|
img = Image.fromarray((background * 255).astype("uint8"), "RGB")
|
@@ -17,7 +17,7 @@
|
|
17
17
|
});
|
18
18
|
L.tileLayer('/tile/grayscale/{z}/{x}/{y}.png', {
|
19
19
|
maxZoom: 19,
|
20
|
-
attribution: '
|
20
|
+
attribution: '{{ map_tile_attribution|safe }}'
|
21
21
|
}).addTo(map);
|
22
22
|
|
23
23
|
let geojson = L.geoJSON({{ geojson| safe }}, {
|
@@ -21,7 +21,7 @@
|
|
21
21
|
});
|
22
22
|
L.tileLayer('/tile/grayscale/{z}/{x}/{y}.png', {
|
23
23
|
maxZoom: 19,
|
24
|
-
attribution: '
|
24
|
+
attribution: '{{ map_tile_attribution|safe }}'
|
25
25
|
}).addTo(map);
|
26
26
|
|
27
27
|
let geojson = L.geoJSON({{ geojson| safe }}, {
|
@@ -17,7 +17,7 @@
|
|
17
17
|
});
|
18
18
|
L.tileLayer('/tile/grayscale/{z}/{x}/{y}.png', {
|
19
19
|
maxZoom: 19,
|
20
|
-
attribution: '
|
20
|
+
attribution: '{{ map_tile_attribution|safe }}'
|
21
21
|
}).addTo(map);
|
22
22
|
|
23
23
|
let geojson = L.geoJSON({{ geojson| safe }}, {
|
@@ -64,7 +64,8 @@
|
|
64
64
|
<tbody>
|
65
65
|
{% for activity in activities %}
|
66
66
|
<tr>
|
67
|
-
<td><span style="color: {{ activity['color'] }};">█</span> <a
|
67
|
+
<td><span style="color: {{ activity['color'] }};">█</span> <a
|
68
|
+
href="{{ url_for('activity.show', id=activity.id) }}">{{
|
68
69
|
activity.name }}</a></td>
|
69
70
|
<td>{{ activity.start|dt }}</td>
|
70
71
|
<td>{{ activity.distance_km | round(1) }}</td>
|
@@ -52,7 +52,7 @@
|
|
52
52
|
});
|
53
53
|
L.tileLayer('/tile/pastel/{z}/{x}/{y}.png', {
|
54
54
|
maxZoom: 19,
|
55
|
-
attribution: '
|
55
|
+
attribution: '{{ map_tile_attribution|safe }}'
|
56
56
|
}).addTo(map);
|
57
57
|
|
58
58
|
let geojson = L.geoJSON({{ color_line_geojson| safe }}, {
|
@@ -160,7 +160,7 @@
|
|
160
160
|
})
|
161
161
|
L.tileLayer('/tile/color/{z}/{x}/{y}.png', {
|
162
162
|
maxZoom: 19,
|
163
|
-
attribution: '
|
163
|
+
attribution: '{{ map_tile_attribution|safe }}'
|
164
164
|
}).addTo(map)
|
165
165
|
|
166
166
|
let geojson_layer = L.geoJSON(geojson).addTo(map)
|
@@ -3,6 +3,8 @@ import importlib
|
|
3
3
|
import json
|
4
4
|
import pathlib
|
5
5
|
import secrets
|
6
|
+
import shutil
|
7
|
+
import urllib.parse
|
6
8
|
|
7
9
|
from flask import Flask
|
8
10
|
from flask import render_template
|
@@ -97,7 +99,8 @@ def web_ui_main(
|
|
97
99
|
url_prefix="/explorer",
|
98
100
|
)
|
99
101
|
app.register_blueprint(
|
100
|
-
make_heatmap_blueprint(repository, tile_visit_accessor),
|
102
|
+
make_heatmap_blueprint(repository, tile_visit_accessor, config_accessor()),
|
103
|
+
url_prefix="/heatmap",
|
101
104
|
)
|
102
105
|
app.register_blueprint(
|
103
106
|
make_settings_blueprint(config_accessor, authenticator),
|
@@ -115,7 +118,7 @@ def web_ui_main(
|
|
115
118
|
make_summary_blueprint(repository, config_accessor()),
|
116
119
|
url_prefix="/summary",
|
117
120
|
)
|
118
|
-
app.register_blueprint(make_tile_blueprint(), url_prefix="/tile")
|
121
|
+
app.register_blueprint(make_tile_blueprint(config_accessor()), url_prefix="/tile")
|
119
122
|
app.register_blueprint(
|
120
123
|
make_upload_blueprint(
|
121
124
|
repository, tile_visit_accessor, config_accessor(), authenticator
|
@@ -123,11 +126,20 @@ def web_ui_main(
|
|
123
126
|
url_prefix="/upload",
|
124
127
|
)
|
125
128
|
|
129
|
+
base_dir = pathlib.Path("Open Street Map Tiles")
|
130
|
+
dir_for_source = base_dir / urllib.parse.quote_plus(config_accessor().map_tile_url)
|
131
|
+
if base_dir.exists() and not dir_for_source.exists():
|
132
|
+
subdirs = base_dir.glob("*")
|
133
|
+
dir_for_source.mkdir()
|
134
|
+
for subdir in subdirs:
|
135
|
+
shutil.move(subdir, dir_for_source)
|
136
|
+
|
126
137
|
@app.context_processor
|
127
138
|
def inject_global_variables() -> dict:
|
128
139
|
return {
|
129
140
|
"version": _try_get_version(),
|
130
141
|
"num_activities": len(repository),
|
142
|
+
"map_tile_attribution": config_accessor().map_tile_attribution,
|
131
143
|
}
|
132
144
|
|
133
145
|
app.run(host=host, port=port)
|
@@ -73,7 +73,7 @@
|
|
73
73
|
})
|
74
74
|
L.tileLayer('/tile/grayscale/{z}/{x}/{y}.png', {
|
75
75
|
maxZoom: 19,
|
76
|
-
attribution: '
|
76
|
+
attribution: '{{ map_tile_attribution|safe }}'
|
77
77
|
}).addTo(map)
|
78
78
|
let explorer_layer_cluster_color = L.geoJSON(explorer_geojson, {
|
79
79
|
style: function (feature) {
|
@@ -87,58 +87,34 @@
|
|
87
87
|
let explorer_layer_first_age_color = L.geoJSON(explorer_geojson, {
|
88
88
|
style: function (feature) {
|
89
89
|
return {
|
90
|
-
color: "#440154", fillColor: feature.properties.first_age_color,
|
91
|
-
weight: 0.5
|
90
|
+
color: " #440154", fillColor: feature.properties.first_age_color, weight: 0.5
|
92
91
|
}
|
93
92
|
},
|
94
93
|
onEachFeature: onEachFeature
|
95
|
-
})
|
96
|
-
|
97
|
-
|
98
|
-
return {
|
99
|
-
color: "#440154", fillColor: feature.properties.last_age_color, weight:
|
100
|
-
0.5
|
101
|
-
}
|
102
|
-
},
|
103
|
-
onEachFeature: onEachFeature
|
104
|
-
})
|
105
|
-
|
106
|
-
let bbox = {{ center.bbox| safe }}
|
107
|
-
if (bbox) {
|
108
|
-
map.fitBounds(L.geoJSON(bbox).getBounds())
|
109
|
-
}
|
110
|
-
|
111
|
-
let explorer_square_layer = L.geoJSON(square_geojson,
|
112
|
-
{
|
113
|
-
style: function (feature) {
|
94
|
+
}) let explorer_layer_last_age_color = L.geoJSON(explorer_geojson, {
|
95
|
+
style:
|
96
|
+
function (feature) {
|
114
97
|
return {
|
115
|
-
color: "
|
98
|
+
color: "#440154", fillColor: feature.properties.last_age_color, weight:
|
99
|
+
0.5
|
116
100
|
}
|
117
|
-
}
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
function changeColor(method) {
|
101
|
+
}, onEachFeature: onEachFeature
|
102
|
+
}) let bbox = {{ center.bbox| safe }} if (bbox) {
|
103
|
+
map.fitBounds(L.geoJSON(bbox).getBounds())
|
104
|
+
} let explorer_square_layer = L.geoJSON(square_geojson, {
|
105
|
+
style: function (feature) { return { color: "blue", fill: false, weight: 2 } }
|
106
|
+
}).addTo(map)
|
107
|
+
active_layer = explorer_layer_cluster_color function changeColor(method) {
|
124
108
|
map.removeLayer(active_layer)
|
125
|
-
if (method == "cluster") {
|
126
|
-
active_layer = explorer_layer_cluster_color
|
127
|
-
} else if (method == "first") {
|
109
|
+
if (method == "cluster") { active_layer = explorer_layer_cluster_color } else if (method == "first") {
|
128
110
|
active_layer = explorer_layer_first_age_color
|
129
111
|
} else if (method == "last") {
|
130
112
|
active_layer = explorer_layer_last_age_color
|
131
|
-
}
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
bounds = map.getBounds()
|
137
|
-
zoom = "{{ zoom }}"
|
138
|
-
window.location.href =
|
139
|
-
`/explorer/${zoom}/${bounds.getNorth()}/${bounds.getEast()}/${bounds.getSouth()}/${bounds.getWest()}/${suffix}`
|
140
|
-
}
|
141
|
-
</script>
|
113
|
+
} map.addLayer(active_layer)
|
114
|
+
} function downloadAs(suffix) {
|
115
|
+
bounds = map.getBounds() zoom = "{{ zoom }}"
|
116
|
+
window.location.href = `/explorer/${zoom}/${bounds.getNorth()}/${bounds.getEast()}/${bounds.getSouth()}/${bounds.getWest()}/${suffix}`
|
117
|
+
} </script>
|
142
118
|
</div>
|
143
119
|
</div>
|
144
120
|
|
@@ -6,12 +6,15 @@ from flask import Response
|
|
6
6
|
from ...core.activities import ActivityRepository
|
7
7
|
from ...explorer.tile_visits import TileVisitAccessor
|
8
8
|
from .heatmap_controller import HeatmapController
|
9
|
+
from geo_activity_playground.core.config import Config
|
9
10
|
|
10
11
|
|
11
12
|
def make_heatmap_blueprint(
|
12
|
-
repository: ActivityRepository,
|
13
|
+
repository: ActivityRepository,
|
14
|
+
tile_visit_accessor: TileVisitAccessor,
|
15
|
+
config: Config,
|
13
16
|
) -> Blueprint:
|
14
|
-
heatmap_controller = HeatmapController(repository, tile_visit_accessor)
|
17
|
+
heatmap_controller = HeatmapController(repository, tile_visit_accessor, config)
|
15
18
|
blueprint = Blueprint("heatmap", __name__, template_folder="templates")
|
16
19
|
|
17
20
|
@blueprint.route("/")
|
@@ -8,6 +8,7 @@ from PIL import Image
|
|
8
8
|
from PIL import ImageDraw
|
9
9
|
|
10
10
|
from geo_activity_playground.core.activities import ActivityRepository
|
11
|
+
from geo_activity_playground.core.config import Config
|
11
12
|
from geo_activity_playground.core.heatmap import convert_to_grayscale
|
12
13
|
from geo_activity_playground.core.heatmap import GeoBounds
|
13
14
|
from geo_activity_playground.core.heatmap import get_sensible_zoom_level
|
@@ -29,10 +30,14 @@ OSM_TILE_SIZE = 256 # OSM tile size in pixel
|
|
29
30
|
|
30
31
|
class HeatmapController:
|
31
32
|
def __init__(
|
32
|
-
self,
|
33
|
+
self,
|
34
|
+
repository: ActivityRepository,
|
35
|
+
tile_visit_accessor: TileVisitAccessor,
|
36
|
+
config: Config,
|
33
37
|
) -> None:
|
34
38
|
self._repository = repository
|
35
39
|
self._tile_visit_accessor = tile_visit_accessor
|
40
|
+
self._config = config
|
36
41
|
|
37
42
|
self.tile_histories = self._tile_visit_accessor.tile_state["tile_history"]
|
38
43
|
self.tile_evolution_states = self._tile_visit_accessor.tile_state[
|
@@ -140,11 +145,11 @@ class HeatmapController:
|
|
140
145
|
tile_counts = np.sqrt(tile_counts) / 5
|
141
146
|
tile_counts[tile_counts > 1.0] = 1.0
|
142
147
|
|
143
|
-
cmap = pl.get_cmap(
|
148
|
+
cmap = pl.get_cmap(self._config.color_scheme_for_heatmap)
|
144
149
|
data_color = cmap(tile_counts)
|
145
150
|
data_color[data_color == cmap(0.0)] = 0.0 # remove background color
|
146
151
|
|
147
|
-
map_tile = np.array(get_tile(z, x, y)) / 255
|
152
|
+
map_tile = np.array(get_tile(z, x, y, self._config.map_tile_url)) / 255
|
148
153
|
map_tile = convert_to_grayscale(map_tile)
|
149
154
|
map_tile = 1.0 - map_tile # invert colors
|
150
155
|
for c in range(3):
|
@@ -168,7 +173,12 @@ class HeatmapController:
|
|
168
173
|
background = np.zeros((*pixel_bounds.shape, 3))
|
169
174
|
for x in range(tile_bounds.x_tile_min, tile_bounds.x_tile_max):
|
170
175
|
for y in range(tile_bounds.y_tile_min, tile_bounds.y_tile_max):
|
171
|
-
tile =
|
176
|
+
tile = (
|
177
|
+
np.array(
|
178
|
+
get_tile(tile_bounds.zoom, x, y, self._config.map_tile_url)
|
179
|
+
)
|
180
|
+
/ 255
|
181
|
+
)
|
172
182
|
|
173
183
|
i = y - tile_bounds.y_tile_min
|
174
184
|
j = x - tile_bounds.x_tile_min
|
@@ -35,7 +35,7 @@
|
|
35
35
|
});
|
36
36
|
L.tileLayer('/heatmap/tile/{z}/{x}/{y}/{{ kinds_str }}.png', {
|
37
37
|
maxZoom: 19,
|
38
|
-
attribution: '
|
38
|
+
attribution: '{{ map_tile_attribution|safe }}'
|
39
39
|
}).addTo(map)
|
40
40
|
|
41
41
|
let bbox = {{ center.bbox| safe }}
|
@@ -15,6 +15,43 @@ from geo_activity_playground.webui.authenticator import needs_authentication
|
|
15
15
|
from geo_activity_playground.webui.settings.controller import SettingsController
|
16
16
|
|
17
17
|
|
18
|
+
VEGA_COLOR_SCHEMES_CONTINUOUS = [
|
19
|
+
"lightgreyred",
|
20
|
+
"lightgreyteal",
|
21
|
+
"lightmulti",
|
22
|
+
"lightorange",
|
23
|
+
"lighttealblue",
|
24
|
+
"blues",
|
25
|
+
"tealblues",
|
26
|
+
"teals",
|
27
|
+
"greens",
|
28
|
+
"browns",
|
29
|
+
"oranges",
|
30
|
+
"reds",
|
31
|
+
"purples",
|
32
|
+
"warmgreys",
|
33
|
+
"greys",
|
34
|
+
]
|
35
|
+
|
36
|
+
MATPLOTLIB_COLOR_SCHEMES_CONTINUOUS = [
|
37
|
+
"afmhot",
|
38
|
+
"bone",
|
39
|
+
"cividis",
|
40
|
+
"copper",
|
41
|
+
"gist_gray",
|
42
|
+
"gist_heat",
|
43
|
+
"gnuplot2",
|
44
|
+
"gray",
|
45
|
+
"Greys_r",
|
46
|
+
"hot",
|
47
|
+
"inferno",
|
48
|
+
"magma",
|
49
|
+
"pink",
|
50
|
+
"plasma",
|
51
|
+
"viridis",
|
52
|
+
]
|
53
|
+
|
54
|
+
|
18
55
|
def int_or_none(s: str) -> Optional[int]:
|
19
56
|
if s:
|
20
57
|
try:
|
@@ -56,44 +93,16 @@ def make_settings_blueprint(
|
|
56
93
|
config_accessor().color_scheme_for_kind = request.form[
|
57
94
|
"color_scheme_for_kind"
|
58
95
|
]
|
96
|
+
config_accessor().color_scheme_for_heatmap = request.form[
|
97
|
+
"color_scheme_for_heatmap"
|
98
|
+
]
|
59
99
|
config_accessor.save()
|
60
100
|
flash("Updated color schemes.", category="success")
|
101
|
+
|
61
102
|
return render_template(
|
62
103
|
"settings/color-schemes.html.j2",
|
63
104
|
color_scheme_for_counts=config_accessor().color_scheme_for_counts,
|
64
|
-
color_scheme_for_counts_avail=
|
65
|
-
"viridis",
|
66
|
-
"magma",
|
67
|
-
"inferno",
|
68
|
-
"plasma",
|
69
|
-
"cividis",
|
70
|
-
"turbo",
|
71
|
-
"bluegreen",
|
72
|
-
"bluepurple",
|
73
|
-
"goldgreen",
|
74
|
-
"goldorange",
|
75
|
-
"goldred",
|
76
|
-
"greenblue",
|
77
|
-
"orangered",
|
78
|
-
"purplebluegreen",
|
79
|
-
"purpleblue",
|
80
|
-
"purplered",
|
81
|
-
"redpurple",
|
82
|
-
"yellowgreenblue",
|
83
|
-
"yellowgreen",
|
84
|
-
"yelloworangebrown",
|
85
|
-
"yelloworangered",
|
86
|
-
"darkblue",
|
87
|
-
"darkgold",
|
88
|
-
"darkgreen",
|
89
|
-
"darkmulti",
|
90
|
-
"darkred",
|
91
|
-
"lightgreyred",
|
92
|
-
"lightgreyteal",
|
93
|
-
"lightmulti",
|
94
|
-
"lightorange",
|
95
|
-
"lighttealblue",
|
96
|
-
],
|
105
|
+
color_scheme_for_counts_avail=VEGA_COLOR_SCHEMES_CONTINUOUS,
|
97
106
|
color_scheme_for_kind=config_accessor().color_scheme_for_kind,
|
98
107
|
color_scheme_for_kind_avail=[
|
99
108
|
"accent",
|
@@ -111,6 +120,8 @@ def make_settings_blueprint(
|
|
111
120
|
"tableau10",
|
112
121
|
"tableau20",
|
113
122
|
],
|
123
|
+
color_scheme_for_heatmap=config_accessor().color_scheme_for_heatmap,
|
124
|
+
color_scheme_for_heatmap_avail=MATPLOTLIB_COLOR_SCHEMES_CONTINUOUS,
|
114
125
|
)
|
115
126
|
|
116
127
|
@blueprint.route("/equipment-offsets", methods=["GET", "POST"])
|
@@ -18,8 +18,17 @@
|
|
18
18
|
</div>
|
19
19
|
|
20
20
|
<div class="mb-3">
|
21
|
-
<label class="form-label">Color scheme for
|
22
|
-
<select class="form-select" aria-label="Color scheme for heatmaps" name="
|
21
|
+
<label class="form-label">Color scheme for interactive heatmap</label>
|
22
|
+
<select class="form-select" aria-label="Color scheme for heatmaps" name="color_scheme_for_heatmap">
|
23
|
+
{% for cs in color_scheme_for_heatmap_avail %}
|
24
|
+
<option {% if cs==color_scheme_for_heatmap %} selected {% endif %}>{{ cs }}</option>
|
25
|
+
{% endfor %}
|
26
|
+
</select>
|
27
|
+
</div>
|
28
|
+
|
29
|
+
<div class="mb-3">
|
30
|
+
<label class="form-label">Color scheme for count plots</label>
|
31
|
+
<select class="form-select" aria-label="Color scheme for count plots" name="color_scheme_for_counts">
|
23
32
|
{% for cs in color_scheme_for_counts_avail %}
|
24
33
|
<option {% if cs==color_scheme_for_counts %} selected {% endif %}>{{ cs }}</option>
|
25
34
|
{% endfor %}
|
@@ -20,7 +20,7 @@
|
|
20
20
|
})
|
21
21
|
L.tileLayer('/tile/color/{z}/{x}/{y}.png', {
|
22
22
|
maxZoom: 19,
|
23
|
-
attribution: '
|
23
|
+
attribution: '{{ map_tile_attribution|safe }}'
|
24
24
|
}).addTo(map)
|
25
25
|
|
26
26
|
let geojson_layer = L.geoJSON(geojson).addTo(map)
|
@@ -106,7 +106,7 @@
|
|
106
106
|
|
107
107
|
L.tileLayer('/tile/grayscale/{z}/{x}/{y}.png', {
|
108
108
|
maxZoom: 19,
|
109
|
-
attribution: '
|
109
|
+
attribution: '{{ map_tile_attribution|safe }}'
|
110
110
|
}).addTo(map)
|
111
111
|
|
112
112
|
let explorer_geojson = {{ explored_geojson| safe }}
|
@@ -31,7 +31,7 @@ class SummaryController:
|
|
31
31
|
)
|
32
32
|
|
33
33
|
return {
|
34
|
-
"
|
34
|
+
"plot_distance_heatmaps": plot_distance_heatmaps(df, self._config),
|
35
35
|
"plot_monthly_distance": plot_monthly_distance(df, kind_scale),
|
36
36
|
"plot_yearly_distance": plot_yearly_distance(year_kind_total, kind_scale),
|
37
37
|
"plot_year_cumulative": plot_year_cumulative(df),
|
@@ -112,17 +112,10 @@ def embellished_activities(meta: pd.DataFrame) -> pd.DataFrame:
|
|
112
112
|
return df
|
113
113
|
|
114
114
|
|
115
|
-
def
|
116
|
-
return
|
117
|
-
alt.Chart(
|
118
|
-
meta.loc[
|
119
|
-
(
|
120
|
-
meta["start"]
|
121
|
-
>= pd.to_datetime(
|
122
|
-
datetime.datetime.now() - datetime.timedelta(days=2 * 365)
|
123
|
-
)
|
124
|
-
)
|
125
|
-
],
|
115
|
+
def plot_distance_heatmaps(meta: pd.DataFrame, config: Config) -> dict[int, str]:
|
116
|
+
return {
|
117
|
+
year: alt.Chart(
|
118
|
+
meta.loc[(meta["year"] == year)],
|
126
119
|
title="Daily Distance Heatmap",
|
127
120
|
)
|
128
121
|
.mark_rect()
|
@@ -130,7 +123,7 @@ def plot_distance_heatmap(meta: pd.DataFrame, config: Config) -> str:
|
|
130
123
|
alt.X("date(start):O", title="Day of month"),
|
131
124
|
alt.Y(
|
132
125
|
"yearmonth(start):O",
|
133
|
-
scale=alt.Scale(reverse=True),
|
126
|
+
# scale=alt.Scale(reverse=True),
|
134
127
|
title="Year and month",
|
135
128
|
),
|
136
129
|
alt.Color(
|
@@ -146,7 +139,8 @@ def plot_distance_heatmap(meta: pd.DataFrame, config: Config) -> str:
|
|
146
139
|
],
|
147
140
|
)
|
148
141
|
.to_json(format="vega")
|
149
|
-
|
142
|
+
for year in sorted(meta["year"].unique())
|
143
|
+
}
|
150
144
|
|
151
145
|
|
152
146
|
def plot_monthly_distance(meta: pd.DataFrame, kind_scale: alt.Scale) -> str:
|
@@ -76,13 +76,26 @@
|
|
76
76
|
<p>Next we take one row per month, each column is a day-of-month. The brighter a box, the more distance you have covered
|
77
77
|
on that day. This makes it easy to spot those days where you really covered a lot of distance!</p>
|
78
78
|
|
79
|
-
|
80
|
-
|
81
|
-
|
79
|
+
|
80
|
+
<ul class="nav nav-pills mb-3" id="myTab" role="tablist">
|
81
|
+
{% for year, plot in plot_distance_heatmaps.items() %}
|
82
|
+
<li class="nav-item" role="presentation">
|
83
|
+
<button class="nav-link {% if loop.last %} active {% endif %}" id="heatmap-{{ year }}" data-bs-toggle="tab"
|
84
|
+
data-bs-target="#heatmap-{{ year }}-pane" type="button" role="tab" aria-controls="heatmap-{{ year }}-pane"
|
85
|
+
aria-selected="{{ loop.last }}">{{ year }}</button>
|
86
|
+
</li>
|
87
|
+
{% endfor %}
|
88
|
+
</ul>
|
89
|
+
|
90
|
+
<div class="tab-content mb-3" id="myTabContent">
|
91
|
+
{% for year, plot in plot_distance_heatmaps.items() %}
|
92
|
+
<div class="tab-pane fade {% if loop.last %} show active {% endif %}" id="heatmap-{{ year }}-pane" role="tabpanel"
|
93
|
+
aria-labelledby="heatmap-{{ year }}" tabindex="0">
|
94
|
+
{{ vega_direct("plot_distance_heatmap_%d"|format(year), plot) }}
|
82
95
|
</div>
|
96
|
+
{% endfor %}
|
83
97
|
</div>
|
84
98
|
|
85
|
-
|
86
99
|
<h2>Hall of Fame</h2>
|
87
100
|
|
88
101
|
<script>
|
@@ -92,7 +105,7 @@
|
|
92
105
|
})
|
93
106
|
L.tileLayer('/tile/color/{z}/{x}/{y}.png', {
|
94
107
|
maxZoom: 19,
|
95
|
-
attribution: '
|
108
|
+
attribution: '{{ map_tile_attribution|safe }}'
|
96
109
|
}).addTo(map)
|
97
110
|
|
98
111
|
let geojson_layer = L.geoJSON(geojson).addTo(map)
|
@@ -26,7 +26,7 @@
|
|
26
26
|
})
|
27
27
|
L.tileLayer('/tile/color/{z}/{x}/{y}.png', {
|
28
28
|
maxZoom: 19,
|
29
|
-
attribution: '
|
29
|
+
attribution: '{{ map_tile_attribution|safe }}'
|
30
30
|
}).addTo(map)
|
31
31
|
|
32
32
|
let geojson_layer = L.geoJSON(geojson).addTo(map)
|
@@ -2,12 +2,13 @@ from flask import Blueprint
|
|
2
2
|
from flask import Response
|
3
3
|
|
4
4
|
from .controller import TileController
|
5
|
+
from geo_activity_playground.core.config import Config
|
5
6
|
|
6
7
|
|
7
|
-
def make_tile_blueprint() -> Blueprint:
|
8
|
+
def make_tile_blueprint(config: Config) -> Blueprint:
|
8
9
|
blueprint = Blueprint("tiles", __name__, template_folder="templates")
|
9
10
|
|
10
|
-
tile_controller = TileController()
|
11
|
+
tile_controller = TileController(config)
|
11
12
|
|
12
13
|
@blueprint.route("/color/<z>/<x>/<y>.png")
|
13
14
|
def tile_color(x: str, y: str, z: str):
|
@@ -3,18 +3,22 @@ import io
|
|
3
3
|
import matplotlib.pyplot as pl
|
4
4
|
import numpy as np
|
5
5
|
|
6
|
+
from geo_activity_playground.core.config import Config
|
6
7
|
from geo_activity_playground.core.tiles import get_tile
|
7
8
|
|
8
9
|
|
9
10
|
class TileController:
|
11
|
+
def __init__(self, config: Config):
|
12
|
+
self._config = config
|
13
|
+
|
10
14
|
def render_color(self, x: int, y: int, z: int) -> bytes:
|
11
|
-
map_tile = np.array(get_tile(z, x, y)) / 255
|
15
|
+
map_tile = np.array(get_tile(z, x, y, self._config.map_tile_url)) / 255
|
12
16
|
f = io.BytesIO()
|
13
17
|
pl.imsave(f, map_tile, format="png")
|
14
18
|
return bytes(f.getbuffer())
|
15
19
|
|
16
20
|
def render_grayscale(self, x: int, y: int, z: int) -> bytes:
|
17
|
-
map_tile = np.array(get_tile(z, x, y)) / 255
|
21
|
+
map_tile = np.array(get_tile(z, x, y, self._config.map_tile_url)) / 255
|
18
22
|
map_tile = np.sum(map_tile * [0.2126, 0.7152, 0.0722], axis=2) # to grayscale
|
19
23
|
map_tile = np.dstack((map_tile, map_tile, map_tile)) # to rgb
|
20
24
|
f = io.BytesIO()
|
@@ -22,7 +26,7 @@ class TileController:
|
|
22
26
|
return bytes(f.getbuffer())
|
23
27
|
|
24
28
|
def render_pastel(self, x: int, y: int, z: int) -> bytes:
|
25
|
-
map_tile = np.array(get_tile(z, x, y)) / 255
|
29
|
+
map_tile = np.array(get_tile(z, x, y, self._config.map_tile_url)) / 255
|
26
30
|
averaged_tile = np.sum(map_tile * [0.2126, 0.7152, 0.0722], axis=2)
|
27
31
|
grayscale_tile = np.dstack((averaged_tile, averaged_tile, averaged_tile))
|
28
32
|
factor = 0.7
|
{geo_activity_playground-0.32.0.dist-info → geo_activity_playground-0.33.0.dist-info}/RECORD
RENAMED
@@ -2,18 +2,18 @@ geo_activity_playground/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG
|
|
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
4
|
geo_activity_playground/core/activities.py,sha256=soxMtdijnkZ1bYZU0q6wuM8NPNFoUpLwYp3IvBOaKJY,6927
|
5
|
-
geo_activity_playground/core/config.py,sha256=
|
5
|
+
geo_activity_playground/core/config.py,sha256=uqiwk7CgcuGx8JemHSsRKjRwyNT1YTb7V0gX0OJhfaI,5109
|
6
6
|
geo_activity_playground/core/coordinates.py,sha256=tDfr9mlXhK6E_MMIJ0vYWVCoH0Lq8uyuaqUgaa8i0jg,966
|
7
7
|
geo_activity_playground/core/enrichment.py,sha256=fUmk6avy_rqePlHmJQFTQhAxjgIRaxxmq18N2OSXBBg,7771
|
8
8
|
geo_activity_playground/core/heart_rate.py,sha256=IwMt58TpjOYqpAxtsj07zP2ttpN_J3GZeiv-qGhYyJc,1598
|
9
|
-
geo_activity_playground/core/heatmap.py,sha256=
|
9
|
+
geo_activity_playground/core/heatmap.py,sha256=iTxefUTjTToPrKpVbauJHXkqxpNppXOEK6vvKuNkHkk,5906
|
10
10
|
geo_activity_playground/core/paths.py,sha256=RBeUi38riP_msTGPy1TsPRNiblzE-lFivaJSLULE8b0,2503
|
11
11
|
geo_activity_playground/core/privacy_zones.py,sha256=4TumHsVUN1uW6RG3ArqTXDykPVipF98DCxVBe7YNdO8,512
|
12
12
|
geo_activity_playground/core/similarity.py,sha256=Jo8jRViuORCxdIGvyaflgsQhwu9S_jn10a450FRL18A,3159
|
13
13
|
geo_activity_playground/core/tasks.py,sha256=aMDBWJqp6ek2ao6G6Xa8GOSZbcQqXoWL74SGRowRPIk,2942
|
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
|
-
geo_activity_playground/core/tiles.py,sha256=
|
16
|
+
geo_activity_playground/core/tiles.py,sha256=qUe4h3rzHJb8xThAgUKSLElt8S6zID_OuaWXDkWLwAU,3539
|
17
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
|
@@ -31,13 +31,13 @@ geo_activity_playground/importers/test_strava_api.py,sha256=4vX7wDr1a9aRh8myxNrI
|
|
31
31
|
geo_activity_playground/webui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
32
32
|
geo_activity_playground/webui/activity/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
33
33
|
geo_activity_playground/webui/activity/blueprint.py,sha256=Ub2mC9S9TII7CJaaWahnbNtT76uOGKNDWE0-j2C56CA,3893
|
34
|
-
geo_activity_playground/webui/activity/controller.py,sha256=
|
35
|
-
geo_activity_playground/webui/activity/templates/activity/day.html.j2,sha256=
|
34
|
+
geo_activity_playground/webui/activity/controller.py,sha256=t4-9-Gxchc959AaOOflSTYhNiGBuJT2nu1UZ0Vv_nxU,19343
|
35
|
+
geo_activity_playground/webui/activity/templates/activity/day.html.j2,sha256=Gitp3IR913YTjzlz_OiWIe3VSN4OmFGZVGPuMVINCg4,2693
|
36
36
|
geo_activity_playground/webui/activity/templates/activity/edit.html.j2,sha256=ckcTTxcQOhmvvAGNTEOtWCUG4LhvO4HfQImlIa5qKs8,1530
|
37
|
-
geo_activity_playground/webui/activity/templates/activity/lines.html.j2,sha256=
|
38
|
-
geo_activity_playground/webui/activity/templates/activity/name.html.j2,sha256=
|
39
|
-
geo_activity_playground/webui/activity/templates/activity/show.html.j2,sha256=
|
40
|
-
geo_activity_playground/webui/app.py,sha256=
|
37
|
+
geo_activity_playground/webui/activity/templates/activity/lines.html.j2,sha256=_ZDg1ruW-9UMJfOudy1-uY_-IcSSaagq7tPCih5Bb8g,1079
|
38
|
+
geo_activity_playground/webui/activity/templates/activity/name.html.j2,sha256=tKviMqMouHEGv3xBQVIsJgwj_hjwAsmGVefM3UMqlYg,2437
|
39
|
+
geo_activity_playground/webui/activity/templates/activity/show.html.j2,sha256=bEx37UGSTeeJl7gN4fjyOpINFQwZ5Zm-HOKpLqcJGfs,6905
|
40
|
+
geo_activity_playground/webui/app.py,sha256=nWbgxRHg0DThi44VFb04OIVwxnqIVmkr3cnO9ucE1Oo,5118
|
41
41
|
geo_activity_playground/webui/auth/blueprint.py,sha256=Lx-ZvMnfHLC1CMre1xPQI3k_pCtQoZvgRhtmafULzoE,812
|
42
42
|
geo_activity_playground/webui/auth/templates/auth/index.html.j2,sha256=ILQ5HvTEYc3OrtOAIFt1VrqWorVD70V9DC342znmP70,579
|
43
43
|
geo_activity_playground/webui/authenticator.py,sha256=k278OEVuOfAmTGT4F2X4pqSTwwkK_FA87EIhAeysEqc,1416
|
@@ -58,32 +58,32 @@ geo_activity_playground/webui/equipment/templates/equipment/index.html.j2,sha256
|
|
58
58
|
geo_activity_playground/webui/explorer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
59
59
|
geo_activity_playground/webui/explorer/blueprint.py,sha256=EKnBs8llqT6Wy1uac18dF2epp3TebF9p3iGlSbj6Vl0,2337
|
60
60
|
geo_activity_playground/webui/explorer/controller.py,sha256=pIzWh0TpLJgKQZlS325-QT7nA1q9ms7fRqQIp24PNfo,11705
|
61
|
-
geo_activity_playground/webui/explorer/templates/explorer/index.html.j2,sha256=
|
61
|
+
geo_activity_playground/webui/explorer/templates/explorer/index.html.j2,sha256=PnAL0uDNjnziwbkCOpIWPb7KmS4c1dP-VLxjyXppUYc,6701
|
62
62
|
geo_activity_playground/webui/heatmap/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
63
|
-
geo_activity_playground/webui/heatmap/blueprint.py,sha256=
|
64
|
-
geo_activity_playground/webui/heatmap/heatmap_controller.py,sha256=
|
65
|
-
geo_activity_playground/webui/heatmap/templates/heatmap/index.html.j2,sha256=
|
63
|
+
geo_activity_playground/webui/heatmap/blueprint.py,sha256=ZEImDIwT3uiDIKapqCU49llvyqG79n7ZEu1GHgoLZqo,1558
|
64
|
+
geo_activity_playground/webui/heatmap/heatmap_controller.py,sha256=Qw9MGW3TFWlG2JkA_r9RHgYq4hvPiJaZeAg5D9lIFC0,7821
|
65
|
+
geo_activity_playground/webui/heatmap/templates/heatmap/index.html.j2,sha256=BMjqbZ-btSFawuNDxgZxOkF5JvhD_p9DOBJ-4-1IKnU,1833
|
66
66
|
geo_activity_playground/webui/plot_util.py,sha256=pTTQoqOCkLVjkgOit7mbry28kMruZIL8amZozSzEpxQ,283
|
67
67
|
geo_activity_playground/webui/search/blueprint.py,sha256=7TDsiqEowMyHNlFImk-hCGso69KOieG4rfJnLRHpRz8,3300
|
68
68
|
geo_activity_playground/webui/search/templates/search/index.html.j2,sha256=d39uhteoY6JOZePqhLIYLERqkckW3oghMnTUZa7X1J8,3798
|
69
|
-
geo_activity_playground/webui/settings/blueprint.py,sha256=
|
69
|
+
geo_activity_playground/webui/settings/blueprint.py,sha256=GIrCOBNw-uNWDmKj4uduYOiKpoTLEfFbGmUmXkoBqro,9405
|
70
70
|
geo_activity_playground/webui/settings/controller.py,sha256=MIZVBfoGNvmJnB_ECV_x5eH2i6gDZvkWSQ4PcSKyLKs,9170
|
71
71
|
geo_activity_playground/webui/settings/templates/settings/admin-password.html.j2,sha256=VYwddpObD1RpeTH5Dm4y7VtmT7kwURDCIjxyzJeq08c,495
|
72
|
-
geo_activity_playground/webui/settings/templates/settings/color-schemes.html.j2,sha256=
|
72
|
+
geo_activity_playground/webui/settings/templates/settings/color-schemes.html.j2,sha256=iR91Wxd2_TMuIo9dBDZBrWSUGHNwTwzC6O8oNH-XBt4,1653
|
73
73
|
geo_activity_playground/webui/settings/templates/settings/equipment-offsets.html.j2,sha256=ltaYwFe8S8Mi72ddmIp1vwqlu8MEXXjBGfbpN2WBTC4,1728
|
74
74
|
geo_activity_playground/webui/settings/templates/settings/heart-rate.html.j2,sha256=UPT3MegRgSeff36lhCo0l3ZwhqNSIg5gM6h2s32GkCY,4255
|
75
75
|
geo_activity_playground/webui/settings/templates/settings/index.html.j2,sha256=r7HBq91BKBrWT2_TNR7OcLokuOcUK-Czyi_zOjveIRk,5287
|
76
76
|
geo_activity_playground/webui/settings/templates/settings/kind-renames.html.j2,sha256=yWVIMJq0XOpeTLglEqLxlQAG0mVhaCVw9j0Iu4nIrgI,757
|
77
77
|
geo_activity_playground/webui/settings/templates/settings/kinds-without-achievements.html.j2,sha256=IdUfXon1Pu8zX3NirKb28ypshLHOvZRpz2T4bJrzrak,1067
|
78
78
|
geo_activity_playground/webui/settings/templates/settings/metadata-extraction.html.j2,sha256=EUHZ-MWnSPAkiad0CHSj9UUkRUQwItTbKYJcZz9TVi0,2314
|
79
|
-
geo_activity_playground/webui/settings/templates/settings/privacy-zones.html.j2,sha256=
|
79
|
+
geo_activity_playground/webui/settings/templates/settings/privacy-zones.html.j2,sha256=OBKHlOezJauaDerLpOAJYq7wL-KxsWMn-BpSKJ93I0c,3051
|
80
80
|
geo_activity_playground/webui/settings/templates/settings/segmentation.html.j2,sha256=QV72TZcIxqql-vEsq2lKHzo5UxoxeeXkRA9se46GWKU,1187
|
81
81
|
geo_activity_playground/webui/settings/templates/settings/sharepic.html.j2,sha256=qZkfEpd4CtKKMaSSVadqvNEgMRYLV-0X-pw5-nJvukk,678
|
82
82
|
geo_activity_playground/webui/settings/templates/settings/strava.html.j2,sha256=FrXgT-m1PgvsQWo9kMKpk8QenKeifSDBCZFqKgsHRxQ,1827
|
83
83
|
geo_activity_playground/webui/square_planner/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
84
84
|
geo_activity_playground/webui/square_planner/blueprint.py,sha256=r2VkSM547chX85g6c1BQ8NC-tkdqGdYp-2ZALBiiDTc,1320
|
85
85
|
geo_activity_playground/webui/square_planner/controller.py,sha256=ML6ftOyr3tTh7D4DBcRP76CvkyTxqI5QWgMeG9wC8FE,3561
|
86
|
-
geo_activity_playground/webui/square_planner/templates/square_planner/index.html.j2,sha256=
|
86
|
+
geo_activity_playground/webui/square_planner/templates/square_planner/index.html.j2,sha256=xFbYBQtkOl3U4WGkvIuU_5uazGHn8ObvQfNgPGq0Gqg,6469
|
87
87
|
geo_activity_playground/webui/static/android-chrome-192x192.png,sha256=yxZgo8Jw4hrgOgrn3tvi9G0AXWGFD29kjCuxC07WoT4,17610
|
88
88
|
geo_activity_playground/webui/static/android-chrome-512x512.png,sha256=Uiv62gQpUjMOdp9d6exzd6IyOi5zgQdgjIVVWYw5m98,38891
|
89
89
|
geo_activity_playground/webui/static/apple-touch-icon.png,sha256=TNLa0YIS1mbWajvIQthC2bGve6ET3DbJzrAbs6Pf3Ps,13046
|
@@ -100,20 +100,20 @@ geo_activity_playground/webui/static/web-app-manifest-192x192.png,sha256=eEImN6i
|
|
100
100
|
geo_activity_playground/webui/static/web-app-manifest-512x512.png,sha256=vU9oQ4HnQerFDZVzcAT9twj4_Doc6_9v9wVvoRI-f_E,48318
|
101
101
|
geo_activity_playground/webui/summary/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
102
102
|
geo_activity_playground/webui/summary/blueprint.py,sha256=tfA2aPF19yKwkQOb5lPQBySoQYYhTn49Iuh0SYvsGP8,593
|
103
|
-
geo_activity_playground/webui/summary/controller.py,sha256=
|
104
|
-
geo_activity_playground/webui/summary/templates/summary/index.html.j2,sha256=
|
105
|
-
geo_activity_playground/webui/templates/home.html.j2,sha256=
|
103
|
+
geo_activity_playground/webui/summary/controller.py,sha256=V3zBLNL_Yc_Ft-ZBaWnlLXhr8VsvTpipPUZ-G9sgUXs,9312
|
104
|
+
geo_activity_playground/webui/summary/templates/summary/index.html.j2,sha256=ctOx3Qjx6nRDpUtFf1DlJhK_gtU77Vwx_S6euLz9-W4,5183
|
105
|
+
geo_activity_playground/webui/templates/home.html.j2,sha256=JNQxpjDfXhLAJbZ7RaNBNe9u48nbvlEBrnU_Zizt544,2131
|
106
106
|
geo_activity_playground/webui/templates/page.html.j2,sha256=znTbtD2NALrhmUN_Q-F1ElGlKtecoUv8vOCcUtojrdI,11134
|
107
107
|
geo_activity_playground/webui/tile/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
108
|
-
geo_activity_playground/webui/tile/blueprint.py,sha256=
|
109
|
-
geo_activity_playground/webui/tile/controller.py,sha256=
|
108
|
+
geo_activity_playground/webui/tile/blueprint.py,sha256=q0sw_F8L367Df01yjZijikEIglFBgg9lN61sbTAEOKQ,1018
|
109
|
+
geo_activity_playground/webui/tile/controller.py,sha256=XjUTbyAMeQET1D3mFtT8r5-xMcMOaELPZWtQ1Xp7Cuw,1428
|
110
110
|
geo_activity_playground/webui/upload/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
111
111
|
geo_activity_playground/webui/upload/blueprint.py,sha256=xX9scEmleN_dL03jfhWRh5yI1WsFyhxUFiS_Ul2HWy4,1428
|
112
112
|
geo_activity_playground/webui/upload/controller.py,sha256=EvoUnmKBo3QS2TLak7-yVZ16sEDyEB6Nf2MN_scHuhQ,4080
|
113
113
|
geo_activity_playground/webui/upload/templates/upload/index.html.j2,sha256=I1Ix8tDS3YBdi-HdaNfjkzYXVVCjfUTe5PFTnap1ydc,775
|
114
114
|
geo_activity_playground/webui/upload/templates/upload/reload.html.j2,sha256=YZWX5eDeNyqKJdQAywDBcU8DZBm22rRBbZqFjrFrCvQ,556
|
115
|
-
geo_activity_playground-0.
|
116
|
-
geo_activity_playground-0.
|
117
|
-
geo_activity_playground-0.
|
118
|
-
geo_activity_playground-0.
|
119
|
-
geo_activity_playground-0.
|
115
|
+
geo_activity_playground-0.33.0.dist-info/LICENSE,sha256=4RpAwKO8bPkfXH2lnpeUW0eLkNWglyG4lbrLDU_MOwY,1070
|
116
|
+
geo_activity_playground-0.33.0.dist-info/METADATA,sha256=b7mpW0SMMsW1p2C-wZ0ZxpWXssdYXkNOmZ-43dnNwLI,1612
|
117
|
+
geo_activity_playground-0.33.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
118
|
+
geo_activity_playground-0.33.0.dist-info/entry_points.txt,sha256=pbNlLI6IIZIp7nPYCfAtiSiz2oxJSCl7DODD6SPkLKk,81
|
119
|
+
geo_activity_playground-0.33.0.dist-info/RECORD,,
|
{geo_activity_playground-0.32.0.dist-info → geo_activity_playground-0.33.0.dist-info}/LICENSE
RENAMED
File without changes
|
File without changes
|
File without changes
|