geo-activity-playground 0.23.0__py3-none-any.whl → 0.24.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. geo_activity_playground/__main__.py +1 -1
  2. geo_activity_playground/core/activities.py +18 -12
  3. geo_activity_playground/core/activity_parsers.py +8 -32
  4. geo_activity_playground/core/cache_migrations.py +24 -0
  5. geo_activity_playground/core/heatmap.py +21 -21
  6. geo_activity_playground/core/privacy_zones.py +16 -0
  7. geo_activity_playground/core/similarity.py +1 -1
  8. geo_activity_playground/core/test_time_conversion.py +37 -0
  9. geo_activity_playground/core/time_conversion.py +14 -0
  10. geo_activity_playground/explorer/tile_visits.py +44 -32
  11. geo_activity_playground/importers/__init__.py +0 -0
  12. geo_activity_playground/importers/directory.py +7 -2
  13. geo_activity_playground/importers/strava_api.py +8 -1
  14. geo_activity_playground/importers/strava_checkout.py +4 -3
  15. geo_activity_playground/webui/__init__.py +0 -0
  16. geo_activity_playground/webui/activity/__init__.py +0 -0
  17. geo_activity_playground/webui/activity/blueprint.py +58 -0
  18. geo_activity_playground/webui/{activity_controller.py → activity/controller.py} +128 -18
  19. geo_activity_playground/webui/{templates/activity-day.html.j2 → activity/templates/activity/day.html.j2} +14 -2
  20. geo_activity_playground/webui/{templates/activity-name.html.j2 → activity/templates/activity/name.html.j2} +1 -1
  21. geo_activity_playground/webui/{templates/activity.html.j2 → activity/templates/activity/show.html.j2} +9 -4
  22. geo_activity_playground/webui/app.py +54 -283
  23. geo_activity_playground/webui/calendar/__init__.py +0 -0
  24. geo_activity_playground/webui/calendar/blueprint.py +26 -0
  25. geo_activity_playground/webui/{calendar_controller.py → calendar/controller.py} +5 -5
  26. geo_activity_playground/webui/{templates/calendar.html.j2 → calendar/templates/calendar/index.html.j2} +3 -2
  27. geo_activity_playground/webui/{templates/calendar-month.html.j2 → calendar/templates/calendar/month.html.j2} +2 -2
  28. geo_activity_playground/webui/eddington/__init__.py +0 -0
  29. geo_activity_playground/webui/eddington/blueprint.py +19 -0
  30. geo_activity_playground/webui/{eddington_controller.py → eddington/controller.py} +14 -6
  31. geo_activity_playground/webui/eddington/templates/eddington/index.html.j2 +56 -0
  32. geo_activity_playground/webui/entry_controller.py +1 -1
  33. geo_activity_playground/webui/equipment/__init__.py +0 -0
  34. geo_activity_playground/webui/equipment/blueprint.py +19 -0
  35. geo_activity_playground/webui/{equipment_controller.py → equipment/controller.py} +5 -3
  36. geo_activity_playground/webui/explorer/__init__.py +0 -0
  37. geo_activity_playground/webui/explorer/blueprint.py +54 -0
  38. geo_activity_playground/webui/{templates/explorer.html.j2 → explorer/templates/explorer/index.html.j2} +2 -2
  39. geo_activity_playground/webui/heatmap/__init__.py +0 -0
  40. geo_activity_playground/webui/heatmap/blueprint.py +41 -0
  41. geo_activity_playground/webui/{heatmap_controller.py → heatmap/heatmap_controller.py} +38 -11
  42. geo_activity_playground/webui/{templates/heatmap.html.j2 → heatmap/templates/heatmap/index.html.j2} +17 -2
  43. geo_activity_playground/webui/search_controller.py +1 -9
  44. geo_activity_playground/webui/square_planner/__init__.py +0 -0
  45. geo_activity_playground/webui/square_planner/blueprint.py +38 -0
  46. geo_activity_playground/webui/summary/__init__.py +0 -0
  47. geo_activity_playground/webui/summary/blueprint.py +16 -0
  48. geo_activity_playground/webui/summary/controller.py +268 -0
  49. geo_activity_playground/webui/summary/templates/summary/index.html.j2 +135 -0
  50. geo_activity_playground/webui/templates/{index.html.j2 → home.html.j2} +1 -1
  51. geo_activity_playground/webui/templates/page.html.j2 +22 -19
  52. geo_activity_playground/webui/templates/search.html.j2 +1 -1
  53. geo_activity_playground/webui/tile/__init__.py +0 -0
  54. geo_activity_playground/webui/tile/blueprint.py +31 -0
  55. geo_activity_playground/webui/upload/__init__.py +0 -0
  56. geo_activity_playground/webui/upload/blueprint.py +28 -0
  57. geo_activity_playground/webui/{upload_controller.py → upload/controller.py} +1 -0
  58. geo_activity_playground/webui/{templates/upload.html.j2 → upload/templates/upload/index.html.j2} +1 -1
  59. {geo_activity_playground-0.23.0.dist-info → geo_activity_playground-0.24.1.dist-info}/METADATA +2 -1
  60. geo_activity_playground-0.24.1.dist-info/RECORD +95 -0
  61. geo_activity_playground/webui/config_controller.py +0 -12
  62. geo_activity_playground/webui/locations_controller.py +0 -28
  63. geo_activity_playground/webui/summary_controller.py +0 -60
  64. geo_activity_playground/webui/templates/config.html.j2 +0 -24
  65. geo_activity_playground/webui/templates/eddington.html.j2 +0 -18
  66. geo_activity_playground/webui/templates/locations.html.j2 +0 -38
  67. geo_activity_playground/webui/templates/summary.html.j2 +0 -21
  68. geo_activity_playground-0.23.0.dist-info/RECORD +0 -74
  69. /geo_activity_playground/webui/{templates/activity-lines.html.j2 → activity/templates/activity/lines.html.j2} +0 -0
  70. /geo_activity_playground/webui/{templates/equipment.html.j2 → equipment/templates/equipment/index.html.j2} +0 -0
  71. /geo_activity_playground/webui/{explorer_controller.py → explorer/controller.py} +0 -0
  72. /geo_activity_playground/webui/{square_planner_controller.py → square_planner/controller.py} +0 -0
  73. /geo_activity_playground/webui/{templates/square-planner.html.j2 → square_planner/templates/square_planner/index.html.j2} +0 -0
  74. /geo_activity_playground/webui/{tile_controller.py → tile/controller.py} +0 -0
  75. {geo_activity_playground-0.23.0.dist-info → geo_activity_playground-0.24.1.dist-info}/LICENSE +0 -0
  76. {geo_activity_playground-0.23.0.dist-info → geo_activity_playground-0.24.1.dist-info}/WHEEL +0 -0
  77. {geo_activity_playground-0.23.0.dist-info → geo_activity_playground-0.24.1.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,135 @@
1
+ {% extends "page.html.j2" %}
2
+
3
+ {% block container %}
4
+
5
+
6
+ <h1>Summary Statistics</h1>
7
+
8
+ <h2>Distances</h2>
9
+
10
+ <p>This is your weekly distance for the past rolling year, split by activity kind.</p>
11
+
12
+ <div class="row mb-3">
13
+ <div class="col">
14
+ {{ vega_direct("plot_weekly_distance", plot_weekly_distance) }}
15
+ </div>
16
+ </div>
17
+
18
+ <p>Similarly, you find the same data but aggregated by whole months for the past two years. Also split by activity kind.
19
+ </p>
20
+
21
+ <div class="row mb-3">
22
+ <div class="col">
23
+ {{ vega_direct("plot_monthly_distance", plot_monthly_distance) }}
24
+ </div>
25
+ </div>
26
+
27
+
28
+ <p>How much distance have you covered in each year up to that time of the year? The first plot gives you each year as
29
+ one line. The second plot shows you how distance you have covered in each year and with which activity kinds.</p>
30
+
31
+ <div class="row mb-3">
32
+ <div class="col-md-6">
33
+ {{ vega_direct("plot_year_cumulative", plot_year_cumulative) }}
34
+ </div>
35
+ <div class="col-md-6">
36
+ {{ vega_direct("plot_yearly_distance", plot_yearly_distance) }}
37
+ </div>
38
+ </div>
39
+
40
+ <div class="row mb-3">
41
+ <div class="col-md-4">
42
+ <p>What's the average distance per activity? This naturally differs per activity and perhaps also varies with
43
+ the years. This table gives you all the mean values.</p>
44
+ </div>
45
+
46
+ <div class="col-md-8">
47
+ <table class="table">
48
+ <thead>
49
+ <tr>
50
+ <th style="text-align: right;">Year</th>
51
+ {% for col in tabulate_year_kind_mean['columns'][1:] %}
52
+ <th style="text-align: right;">{{ col }}</th>
53
+ {% endfor %}
54
+ </tr>
55
+ </thead>
56
+ <tbody>
57
+ {% for row in tabulate_year_kind_mean['data'] %}
58
+ <tr>
59
+ {% for value in row %}
60
+ <td align="right">
61
+ {% if value == value %}
62
+ {{ value | round(2) }}
63
+ {% if not loop.first %}
64
+ km
65
+ {% endif %}
66
+ {% endif %}
67
+ </td>
68
+ {% endfor %}
69
+ </tr>
70
+ {% endfor %}
71
+ </tbody>
72
+ </table>
73
+ </div>
74
+ </div>
75
+
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
+ on that day. This makes it easy to spot those days where you really covered a lot of distance!</p>
78
+
79
+ <div class="row mb-3">
80
+ <div class="col">
81
+ {{ vega_direct("plot_distance_heatmap", plot_distance_heatmap) }}
82
+ </div>
83
+ </div>
84
+
85
+
86
+ <h2>Hall of Fame</h2>
87
+
88
+ <script>
89
+ function add_map(id, geojson) {
90
+ let map = L.map(`map-${id}`, {
91
+ fullscreenControl: true
92
+ })
93
+ L.tileLayer('/tile/color/{z}/{x}/{y}.png', {
94
+ maxZoom: 19,
95
+ attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
96
+ }).addTo(map)
97
+
98
+ let geojson_layer = L.geoJSON(geojson).addTo(map)
99
+ map.fitBounds(geojson_layer.getBounds())
100
+ return map
101
+ }
102
+ </script>
103
+
104
+ {% for activity_batch in nominations|batch(3) %}
105
+ <div class="row row-cols-1 row-cols-md-3 g-4 mb-3">
106
+ {% for activity, reasons, line_geojson in activity_batch %}
107
+ <div class="col">
108
+ <div class="card">
109
+ <div class="card-img-top" id="map-{{ activity.id }}" style="height: 200px; width: 100%;"></div>
110
+ <script>
111
+ let map{{ activity.id }} = add_map("{{ activity.id }}", {{ line_geojson | safe }})
112
+ </script>
113
+ <div class="card-body">
114
+ <a href="{{ url_for('activity.show', id=activity.id) }}">
115
+ <h5 class="card-title">{{ activity["name"] }}</h5>
116
+ </a>
117
+ <p class="card-text">
118
+ <ul style='list-style-type: "🏆 "'>
119
+ {% for reason in reasons %}
120
+ <li>{{ reason }}</li>
121
+ {% endfor %}
122
+ </ul>
123
+ </p>
124
+ <p class="card-text"><small class="text-body-secondary"></small>{{ activity.kind }} with {{
125
+ (activity.distance_km)|round(1) }} km in {{
126
+ activity.elapsed_time }} on {{ activity.start }}</small></p>
127
+ </div>
128
+ </div>
129
+ </div>
130
+ {% endfor %}
131
+ </div>
132
+ {% endfor %}
133
+
134
+
135
+ {% endblock %}
@@ -51,7 +51,7 @@
51
51
  let map{{ elem.activity.id }} = add_map("{{ elem.activity.id }}", {{ elem.line_geojson | safe }})
52
52
  </script>
53
53
  <div class="card-body">
54
- <a href="/activity/{{ elem.activity.id }}">
54
+ <a href="{{ url_for('activity.show', id=elem.activity.id) }}">
55
55
  <h5 class="card-title">{{ elem.activity["name"] }}</h5>
56
56
  </a>
57
57
  <p class="card-text">{{ elem.activity.kind }} with {{ (elem.activity.distance_km)|round(1) }} km in {{
@@ -49,7 +49,7 @@
49
49
  <div class="container">
50
50
  <nav class="navbar navbar-expand-lg bg-body-secondary mb-3">
51
51
  <div class="container-fluid">
52
- <a class="navbar-brand" href="/">Geo Actvitity Playground</a>
52
+ <a class="navbar-brand" href="{{ url_for('index') }}">Geo Actvitity Playground</a>
53
53
  <button class="navbar-toggler" type="button" data-bs-toggle="collapse"
54
54
  data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent"
55
55
  aria-expanded="false" aria-label="Toggle navigation">
@@ -57,35 +57,38 @@
57
57
  </button>
58
58
  <div class="collapse navbar-collapse" id="navbarSupportedContent">
59
59
  <ul class="navbar-nav me-auto mb-2 mb-lg-0">
60
+
60
61
  <li class="nav-item">
61
- <a class="nav-link active" aria-current="page" href="/">Home</a>
62
- </li>
63
- <li class="nav-item">
64
- <a class="nav-link active" aria-current="page" href="/summary">Summary</a>
65
- </li>
66
- <li class="nav-item">
67
- <a class="nav-link active" aria-current="page" href="/calendar">Calendar</a>
62
+ <a class="nav-link active" aria-current="page"
63
+ href="{{ url_for('summary.index') }}">Summary</a>
68
64
  </li>
69
65
  <li class="nav-item">
70
- <a class="nav-link active" aria-current="page" href="/explorer/14">Explorer</a>
66
+ <a class="nav-link active" aria-current="page"
67
+ href="{{ url_for('calendar.index') }}">Calendar</a>
71
68
  </li>
72
69
  <li class="nav-item">
73
- <a class="nav-link active" aria-current="page" href="/explorer/17">Squadratinhos</a>
70
+ <a class="nav-link active" aria-current="page"
71
+ href="{{ url_for('explorer.map', zoom=14) }}">Explorer</a>
74
72
  </li>
75
73
  <li class="nav-item">
76
- <a class="nav-link active" aria-current="page" href="/heatmap">Heatmap</a>
74
+ <a class="nav-link active" aria-current="page"
75
+ href="{{ url_for('explorer.map', zoom=17) }}">Squadratinhos</a>
77
76
  </li>
78
77
  <li class="nav-item">
79
- <a class="nav-link active" aria-current="page" href="/eddington">Eddington</a>
78
+ <a class="nav-link active" aria-current="page"
79
+ href="{{ url_for('heatmap.index') }}">Heatmap</a>
80
80
  </li>
81
81
  <li class="nav-item">
82
- <a class="nav-link active" aria-current="page" href="/locations">Locations</a>
82
+ <a class="nav-link active" aria-current="page"
83
+ href="{{ url_for('eddington.index') }}">Eddington</a>
83
84
  </li>
84
85
  <li class="nav-item">
85
- <a class="nav-link active" aria-current="page" href="/equipment">Equipment</a>
86
+ <a class="nav-link active" aria-current="page"
87
+ href="{{ url_for('equipment.index') }}">Equipment</a>
86
88
  </li>
87
89
  <li class="nav-item">
88
- <a class="nav-link active" aria-current="page" href="/upload">Upload</a>
90
+ <a class="nav-link active" aria-current="page"
91
+ href="{{ url_for('upload.index') }}">Upload</a>
89
92
  </li>
90
93
  </ul>
91
94
  </div>
@@ -122,13 +125,13 @@
122
125
  <div class="row border-top py-3 my-4">
123
126
  <ul class="nav col-12 justify-content-end">
124
127
  <li class="nav-item"><a href="https://github.com/martin-ueding/geo-activity-playground"
125
- class="nav-link px-2 text-muted">GitHub</a></li>
128
+ class="nav-link px-2 text-muted" target="_blank">GitHub</a></li>
126
129
  <li class="nav-item"><a href="https://martin-ueding.github.io/geo-activity-playground/"
127
- class="nav-link px-2 text-muted">Documentation</a></li>
130
+ class="nav-link px-2 text-muted" target="_blank">Documentation</a></li>
128
131
  <li class="nav-item"><a href="https://bonn.social/tags/GeoActivityPlayground"
129
- class="nav-link px-2 text-muted">Mastodon</a></li>
132
+ class="nav-link px-2 text-muted" target="_blank">Mastodon</a></li>
130
133
  <li class="nav-item"><a href="https://pypi.org/project/geo-activity-playground/"
131
- class="nav-link px-2 text-muted">PyPI</a></li>
134
+ class="nav-link px-2 text-muted" target="_blank">PyPI</a></li>
132
135
  <li class="nav-item"><a href="https://martin-ueding.de/" class="nav-link px-2 text-muted">Martin
133
136
  Ueding</a></li>
134
137
  </ul>
@@ -23,7 +23,7 @@
23
23
  <tbody>
24
24
  {% for activity in activities %}
25
25
  <tr>
26
- <td>{{ activity.name }}</td>
26
+ <td><a href="{{ url_for('activity.show', id=activity.id) }}">{{ activity['name'] }}</a></td>
27
27
  <td>{{ activity.start }}</td>
28
28
  <td>{{ activity.kind }}</td>
29
29
  <td>{{ '%.1f' % activity["distance_km"] }} km</td>
File without changes
@@ -0,0 +1,31 @@
1
+ from flask import Blueprint
2
+ from flask import Response
3
+
4
+ from .controller import TileController
5
+
6
+
7
+ def make_tile_blueprint() -> Blueprint:
8
+ blueprint = Blueprint("tiles", __name__, template_folder="templates")
9
+
10
+ tile_controller = TileController()
11
+
12
+ @blueprint.route("/color/<z>/<x>/<y>.png")
13
+ def tile_color(x: str, y: str, z: str):
14
+ return Response(
15
+ tile_controller.render_color(int(x), int(y), int(z)), mimetype="image/png"
16
+ )
17
+
18
+ @blueprint.route("/grayscale/<z>/<x>/<y>.png")
19
+ def tile_grayscale(x: str, y: str, z: str):
20
+ return Response(
21
+ tile_controller.render_grayscale(int(x), int(y), int(z)),
22
+ mimetype="image/png",
23
+ )
24
+
25
+ @blueprint.route("/pastel/<z>/<x>/<y>.png")
26
+ def tile_pastel(x: str, y: str, z: str):
27
+ return Response(
28
+ tile_controller.render_pastel(int(x), int(y), int(z)), mimetype="image/png"
29
+ )
30
+
31
+ return blueprint
File without changes
@@ -0,0 +1,28 @@
1
+ from flask import Blueprint
2
+ from flask import render_template
3
+
4
+ from ...core.activities import ActivityRepository
5
+ from ...explorer.tile_visits import TileVisitAccessor
6
+ from .controller import UploadController
7
+
8
+
9
+ def make_upload_blueprint(
10
+ repository: ActivityRepository,
11
+ tile_visit_accessor: TileVisitAccessor,
12
+ config: dict,
13
+ ) -> Blueprint:
14
+ blueprint = Blueprint("upload", __name__, template_folder="templates")
15
+
16
+ upload_controller = UploadController(repository, tile_visit_accessor, config)
17
+
18
+ @blueprint.route("/")
19
+ def index():
20
+ return render_template(
21
+ "upload/index.html.j2", **upload_controller.render_form()
22
+ )
23
+
24
+ @blueprint.route("/receive", methods=["POST"])
25
+ def receive():
26
+ return upload_controller.receive()
27
+
28
+ return blueprint
@@ -96,6 +96,7 @@ def scan_for_activities(
96
96
  if pathlib.Path("Activities").exists():
97
97
  import_from_directory(
98
98
  repository,
99
+ config.get("kind", {}),
99
100
  config.get("metadata_extraction_regexes", []),
100
101
  )
101
102
  if pathlib.Path("Strava Export").exists():
@@ -6,7 +6,7 @@
6
6
  <h1>Upload Activity</h1>
7
7
 
8
8
  {% if has_upload %}
9
- <form method="post" enctype="multipart/form-data" action="/upload/receive">
9
+ <form method="post" enctype="multipart/form-data" action="{{ url_for(".receive") }}">
10
10
  <div class="mb-3">
11
11
  <label for="file1" class="form-label">Activity file</label>
12
12
  <input type="file" name="file" id="file1" class="form-control">
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: geo-activity-playground
3
- Version: 0.23.0
3
+ Version: 0.24.1
4
4
  Summary: Analysis of geo data activities like rides, runs or hikes.
5
5
  License: MIT
6
6
  Author: Martin Ueding
@@ -29,6 +29,7 @@ Requires-Dist: pyarrow (>=16.1.0,<17.0.0)
29
29
  Requires-Dist: python-dateutil (>=2.8.2,<3.0.0)
30
30
  Requires-Dist: requests (>=2.28.1,<3.0.0)
31
31
  Requires-Dist: scipy (>=1.8.1,<2.0.0)
32
+ Requires-Dist: shapely (>=2.0.5,<3.0.0)
32
33
  Requires-Dist: stravalib (>=1.3.3,<2.0.0)
33
34
  Requires-Dist: tcxreader (>=0.4.5,<0.5.0)
34
35
  Requires-Dist: tomli (>=2.0.1,<3.0.0) ; python_version < "3.11"
@@ -0,0 +1,95 @@
1
+ geo_activity_playground/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ geo_activity_playground/__main__.py,sha256=pAl5_cWjuNyGmE_zMoPtG7Gc7r7lNk3psn9CAxzP2fU,4131
3
+ geo_activity_playground/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ geo_activity_playground/core/activities.py,sha256=giZYepqGK3NujGpcCrYvF0rYDyVMopIMdXrvWBvbRm4,11606
5
+ geo_activity_playground/core/activity_parsers.py,sha256=pjYjnaAXsWfUNOoomYWOmmFZO5Qs076RWM-pqNdo7BA,10905
6
+ geo_activity_playground/core/cache_migrations.py,sha256=tkGA0h69-m-0Ek7JjvfVOX45YXLXkh_ZvC2TKB_fvbA,4281
7
+ geo_activity_playground/core/config.py,sha256=YjqCiEmIAa-GM1-JfBctMEsl8-I56pZyyDdTyPduOzw,477
8
+ geo_activity_playground/core/coordinates.py,sha256=tDfr9mlXhK6E_MMIJ0vYWVCoH0Lq8uyuaqUgaa8i0jg,966
9
+ geo_activity_playground/core/heatmap.py,sha256=bRLQHzmTEsQbX8XWeg85x_lRGk272UoYRiCnoxZ5da0,4189
10
+ geo_activity_playground/core/paths.py,sha256=EX4yQQyAmWRxTYS0QvFCbGz9v1J0z_1QYfd5hjTmaRw,808
11
+ geo_activity_playground/core/privacy_zones.py,sha256=4TumHsVUN1uW6RG3ArqTXDykPVipF98DCxVBe7YNdO8,512
12
+ geo_activity_playground/core/similarity.py,sha256=Jo8jRViuORCxdIGvyaflgsQhwu9S_jn10a450FRL18A,3159
13
+ geo_activity_playground/core/tasks.py,sha256=lcfLeYpla819v2BTf53zvT0xEB4I6OpSfqfF_xlsLwM,1817
14
+ geo_activity_playground/core/test_tiles.py,sha256=zce1FxNfsSpOQt66jMehdQRVoNdl-oiFydx6iVBHZXM,764
15
+ geo_activity_playground/core/test_time_conversion.py,sha256=Sh6nZA3uCTOdZTZa3yOijtR0m74QtZu2mcWXsDNnyQI,984
16
+ geo_activity_playground/core/tiles.py,sha256=VxPu9vdfKnxDxaYo5JSYmka9Dt3TDxg0zo3cYVJXVHc,3359
17
+ geo_activity_playground/core/time_conversion.py,sha256=9J6aTlqJhWvsknQkoECNL-CIG-8BKs6ZatJJ9XJnTsg,367
18
+ geo_activity_playground/explorer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
+ geo_activity_playground/explorer/grid_file.py,sha256=k6j6KBEk2a2BY-onE8SV5TJsERGGyOrlY4as__meWpA,3304
20
+ geo_activity_playground/explorer/tile_visits.py,sha256=fkn2Pgk-pBmC0ywDa0g2T9f4L2sdi5GaqGMbs4tow_g,12157
21
+ geo_activity_playground/explorer/video.py,sha256=ROAmV9shfJyqTgnXVD41KFORiwnRgVpEWenIq4hMCRM,4389
22
+ geo_activity_playground/importers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
+ geo_activity_playground/importers/directory.py,sha256=6KUxMMJELq1WWQSbqAWt6ZVlZh7Np3LMJNkt6jPN5eI,4506
24
+ geo_activity_playground/importers/strava_api.py,sha256=FJYamDBmHmB8uA9dNc0h0j7EgZPCofCspL2Wfq-PrTg,7869
25
+ geo_activity_playground/importers/strava_checkout.py,sha256=nvZX7skevqMWdW9Gxzt4VhwCaI3wv2z5g-ODv6ZWxng,8078
26
+ geo_activity_playground/importers/test_directory.py,sha256=ljXokx7q0OgtHvEdHftcQYEmZJUDVv3OOF5opklxdT4,724
27
+ geo_activity_playground/importers/test_strava_api.py,sha256=4vX7wDr1a9aRh8myxNrIq6RwDBbP8ZeoXXPc10CAbW4,431
28
+ geo_activity_playground/webui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
29
+ geo_activity_playground/webui/activity/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
30
+ geo_activity_playground/webui/activity/blueprint.py,sha256=gGMes5ycXi2rMixVYs4NQgzTU1Vttgu50prYAe3--Hs,1749
31
+ geo_activity_playground/webui/activity/controller.py,sha256=CoNi9dJlGS-pZMEh14eZqWkbbLRHvQ01PEk8jRXpmgU,16665
32
+ geo_activity_playground/webui/activity/templates/activity/day.html.j2,sha256=r3qKl9uTzOko4R-ZzyYAZt1j61JSevYP4g0Yi06HHPg,2702
33
+ geo_activity_playground/webui/activity/templates/activity/lines.html.j2,sha256=5gB1aDjRgi_RventenRfC10_FtMT4ch_VuWvA9AMlBY,1121
34
+ geo_activity_playground/webui/activity/templates/activity/name.html.j2,sha256=RDLEt6ip8_ngmdLgaC5jg92Dk-F2umGwKkd8cWmvVko,2400
35
+ geo_activity_playground/webui/activity/templates/activity/show.html.j2,sha256=40eEbOypq0ZzebPgUXZy6fWjcGuMtcF_IFMNvc1_CXY,5148
36
+ geo_activity_playground/webui/app.py,sha256=MCkWkeBTLXyqIE-GLhgGRsQYAtUPf9mUh6csbkoOvw8,4575
37
+ geo_activity_playground/webui/calendar/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
+ geo_activity_playground/webui/calendar/blueprint.py,sha256=rlnhgU2DWAcdLMRq7m77NzrM_aDyp4s3kuuQHuzjHhg,782
39
+ geo_activity_playground/webui/calendar/controller.py,sha256=QpSAkR2s1sbLSu6P_fNNTccgGglOzEH2PIv1XwKxeVY,2778
40
+ geo_activity_playground/webui/calendar/templates/calendar/index.html.j2,sha256=xoR6R4cUgTQNRHQv3m3f4Bc-yCjJEsJj5d4_CWlJsRo,1427
41
+ geo_activity_playground/webui/calendar/templates/calendar/month.html.j2,sha256=sRIiNo_Rp9CHary6e-lnpKJKOuAonoDEBvKMxzbTLQE,1802
42
+ geo_activity_playground/webui/eddington/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
43
+ geo_activity_playground/webui/eddington/blueprint.py,sha256=evIvueLfDWVTxJ9pRguqmZ9-Pybd2WmBRst_-7vX2QA,551
44
+ geo_activity_playground/webui/eddington/controller.py,sha256=L4YssL088UMamp4qgzEtilzhaKGZsyfVUScuw-fmTjE,2888
45
+ geo_activity_playground/webui/eddington/templates/eddington/index.html.j2,sha256=XHKeUymQMS5x00PLOVlg-nSRCz_jHB2pvD8QunULWJ4,1839
46
+ geo_activity_playground/webui/entry_controller.py,sha256=v8twD3LJ0SoVtvzJoDKnU8dTtMZAKvhNU2AEH2Z87OA,1886
47
+ geo_activity_playground/webui/equipment/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
48
+ geo_activity_playground/webui/equipment/blueprint.py,sha256=YbOAsjk05BMeUlD6wGfxE1amvlLsFjG4HMJn5SBrVRU,551
49
+ geo_activity_playground/webui/equipment/controller.py,sha256=ST8MEgk5UxTiIM0sQUpKr1TJ2uPRm55V6DI3brPokUo,2390
50
+ geo_activity_playground/webui/equipment/templates/equipment/index.html.j2,sha256=dNuezVKJNJZbQ0y2-AYlXNHpncTbtOSDNLqNswRTxaI,1320
51
+ geo_activity_playground/webui/explorer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
52
+ geo_activity_playground/webui/explorer/blueprint.py,sha256=jHE6bb4H2GmYaix9P452Cyrn_30z_Nm705AZ0WNm4HQ,1950
53
+ geo_activity_playground/webui/explorer/controller.py,sha256=8d0FFrG55ZlPQ5seQC2DegxIkPGIW7pvw8Jm4eJt3fg,10634
54
+ geo_activity_playground/webui/explorer/templates/explorer/index.html.j2,sha256=OxNt2_VwH-cmVXJrDNfeD-dNB9IrwBjdhhQEqkXxHj0,6529
55
+ geo_activity_playground/webui/heatmap/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
56
+ geo_activity_playground/webui/heatmap/blueprint.py,sha256=bjQu-HL3QN5UpJ6tHOifhcLGlPr_hIKvaRu78md4JqM,1470
57
+ geo_activity_playground/webui/heatmap/heatmap_controller.py,sha256=fM92NfeJ_qhXkuAT01Btkzeb_SbAgExxql_OH1G31os,6477
58
+ geo_activity_playground/webui/heatmap/templates/heatmap/index.html.j2,sha256=YLeu6P4djl8G4qAXR6DhetseqrbOodN7aN4coocknc4,1875
59
+ geo_activity_playground/webui/search_controller.py,sha256=PzMf7b8tiJKZIZoPvQ9A2hOrzoKV9cS3jq05w2fK94c,532
60
+ geo_activity_playground/webui/square_planner/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
61
+ geo_activity_playground/webui/square_planner/blueprint.py,sha256=r2VkSM547chX85g6c1BQ8NC-tkdqGdYp-2ZALBiiDTc,1320
62
+ geo_activity_playground/webui/square_planner/controller.py,sha256=wYcNEviDgqyYxSrnwMD_5LnYXIazVH9plGX8RxG6oco,3464
63
+ geo_activity_playground/webui/square_planner/templates/square_planner/index.html.j2,sha256=aIB0ql5qW4HXfp0ENksYYOk9vTgBitwyHJX5W7bqkeY,6512
64
+ geo_activity_playground/webui/static/android-chrome-192x192.png,sha256=yxZgo8Jw4hrgOgrn3tvi9G0AXWGFD29kjCuxC07WoT4,17610
65
+ geo_activity_playground/webui/static/android-chrome-384x384.png,sha256=bgeqAdyvDZBMch7rVi3qSawf0Zr4Go0EG8Ws_B8NApY,49297
66
+ geo_activity_playground/webui/static/android-chrome-512x512.png,sha256=Uiv62gQpUjMOdp9d6exzd6IyOi5zgQdgjIVVWYw5m98,38891
67
+ geo_activity_playground/webui/static/apple-touch-icon.png,sha256=NsVMubJtVzslhql4GZlwTWm4cNRowgcEOT53RuZV190,16549
68
+ geo_activity_playground/webui/static/browserconfig.xml,sha256=u5EvU6U1jKSDiXHW0i4rXrs0lT_tmS82otbJnvmccrk,253
69
+ geo_activity_playground/webui/static/favicon-16x16.png,sha256=Yy8lRjGB7itDaeUI_l_Toq3OO0gzgPGnqIfM3CqcQy0,1419
70
+ geo_activity_playground/webui/static/favicon-32x32.png,sha256=K52R99pLGgWHnjFPPkVieBm051Er-sTCiMvgLr9Alrg,2587
71
+ geo_activity_playground/webui/static/favicon.ico,sha256=uVNZlrF22zn1lcCS_9wAoWLhBt1mpGSGMmHZwwskIVc,12014
72
+ geo_activity_playground/webui/static/mstile-150x150.png,sha256=j1ANUQJ1Xi1DR2sGqYZztob2ypfGw04eNtGpN9SxExA,11964
73
+ geo_activity_playground/webui/static/safari-pinned-tab.svg,sha256=OzoEVGY0igWRXM1NiM3SRKugdICBN7aB_XuxaC3Mu9Q,8371
74
+ geo_activity_playground/webui/static/site.webmanifest,sha256=4vYxdPMpwTdB8EmOvHkkYcjZ8Yrci3pOwwY3o_VwACA,440
75
+ geo_activity_playground/webui/strava_controller.py,sha256=-DZ1Ae-0cWx5tia2dJpGfsBBoIya0QO7IC2qa1-7Q_U,779
76
+ geo_activity_playground/webui/summary/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
77
+ geo_activity_playground/webui/summary/blueprint.py,sha256=kzQ6MDOycQKfDcVoEUmL7HYHJA_gu8DlzVHwO37-_jA,514
78
+ geo_activity_playground/webui/summary/controller.py,sha256=zwJq9HIppk_3kBeRvl2ZF2kJfqvCaSSSWrqFHOrSPWc,8673
79
+ geo_activity_playground/webui/summary/templates/summary/index.html.j2,sha256=rsII1eMY-xNugh8A9SecnEcDZqkEOWYIfiHAGroQYuM,4442
80
+ geo_activity_playground/webui/templates/home.html.j2,sha256=23MLQJ1k447NMLcgOGgTSNiPXFvdC2bQvACkDZbGo5k,2182
81
+ geo_activity_playground/webui/templates/page.html.j2,sha256=aeTYem0CpOOPvWa5KzVKH1BiPJlF0LHqChL1IhpAUO0,7292
82
+ geo_activity_playground/webui/templates/search.html.j2,sha256=FvNRoDfUlSzXjM_tqZY_fDhuhUDgbPaY73q56gdvF1A,1130
83
+ geo_activity_playground/webui/templates/strava-connect.html.j2,sha256=vLMqTnTV-DZJ1FHRjpm4OMgbABMwZQvbs8Ru9baKeBg,1111
84
+ geo_activity_playground/webui/tile/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
85
+ geo_activity_playground/webui/tile/blueprint.py,sha256=cK0o2Z3BrLycgF9zw0F8s9qF-JaYDbF5Gog-GXDtUZ8,943
86
+ geo_activity_playground/webui/tile/controller.py,sha256=PISh4vKs27b-LxFfTARtr5RAwHFresA1Kw1MDcERSRU,1221
87
+ geo_activity_playground/webui/upload/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
88
+ geo_activity_playground/webui/upload/blueprint.py,sha256=2l5q1LYtjgLF_3CAyPvCLx-wMebp14OJvgZBzGILdmQ,801
89
+ geo_activity_playground/webui/upload/controller.py,sha256=QrHfqRxroLuzBBNNSheUx-qJ9ww1sXT1oPdpS7Jx_ro,4092
90
+ geo_activity_playground/webui/upload/templates/upload/index.html.j2,sha256=hfXkEXaz_MkM46rU56423D6V6WtK-EAXPszSY-_-Tx8,1471
91
+ geo_activity_playground-0.24.1.dist-info/LICENSE,sha256=4RpAwKO8bPkfXH2lnpeUW0eLkNWglyG4lbrLDU_MOwY,1070
92
+ geo_activity_playground-0.24.1.dist-info/METADATA,sha256=59LmZVNZAf8R-8Lbab3__MuB4tWbW_KuApJsIcDzJxo,1665
93
+ geo_activity_playground-0.24.1.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
94
+ geo_activity_playground-0.24.1.dist-info/entry_points.txt,sha256=pbNlLI6IIZIp7nPYCfAtiSiz2oxJSCl7DODD6SPkLKk,81
95
+ geo_activity_playground-0.24.1.dist-info/RECORD,,
@@ -1,12 +0,0 @@
1
- from geo_activity_playground.core.activities import ActivityRepository
2
-
3
-
4
- class ConfigController:
5
- def __init__(self, repository: ActivityRepository) -> None:
6
- self._repository = repository
7
-
8
- def action_index(self) -> dict:
9
- return {}
10
-
11
- def action_save(self, form_input) -> dict:
12
- return {}
@@ -1,28 +0,0 @@
1
- import geojson
2
-
3
- from ..core.activities import ActivityRepository
4
-
5
-
6
- class LocationsController:
7
- def __init__(self, repository: ActivityRepository) -> None:
8
- self._repository = repository
9
-
10
- def render_index(self) -> dict:
11
- activity_endpoints = []
12
- for activity in self._repository.iter_activities():
13
- activity_endpoints.append(
14
- (activity["start_latitude"], activity["start_longitude"])
15
- )
16
- activity_endpoints.append(
17
- (activity["end_latitude"], activity["end_longitude"])
18
- )
19
-
20
- activity_endpoints_geojson = geojson.dumps(
21
- geojson.FeatureCollection(
22
- [
23
- geojson.Feature(geometry=geojson.Point((longitude, latitude)))
24
- for latitude, longitude in activity_endpoints
25
- ]
26
- )
27
- )
28
- return {"activity_endpoints_geojson": activity_endpoints_geojson}
@@ -1,60 +0,0 @@
1
- import functools
2
-
3
- import altair as alt
4
- import pandas as pd
5
-
6
- from geo_activity_playground.core.activities import ActivityRepository
7
-
8
-
9
- class SummaryController:
10
- def __init__(self, repository: ActivityRepository) -> None:
11
- self._repository = repository
12
-
13
- @functools.cache
14
- def render(self) -> dict:
15
- return {
16
- "distance_heatmap_meta_plot": distance_heatmap_meta_plot(
17
- self._repository.meta
18
- ),
19
- "year_on_year_distance_meta_plot": year_on_year_distance_meta_plot(
20
- self._repository.meta
21
- ),
22
- }
23
-
24
-
25
- def distance_heatmap_meta_plot(meta: pd.DataFrame) -> str:
26
- return (
27
- alt.Chart(meta)
28
- .mark_rect()
29
- .encode(
30
- alt.X("date(start):O", title="Day of month"),
31
- alt.Y(
32
- "yearmonth(start):O",
33
- scale=alt.Scale(reverse=True),
34
- title="Year and month",
35
- ),
36
- alt.Color("sum(distance_km)", scale=alt.Scale(scheme="viridis")),
37
- [
38
- alt.Tooltip("yearmonthdate(start)", title="Date"),
39
- alt.Tooltip(
40
- "sum(distance_km)", format=".1f", title="Total distance / km"
41
- ),
42
- alt.Tooltip("count(distance_km)", title="Number of activities"),
43
- ],
44
- )
45
- .to_json(format="vega")
46
- )
47
-
48
-
49
- def year_on_year_distance_meta_plot(meta: pd.DataFrame) -> str:
50
- return (
51
- alt.Chart(meta, title="Year on Year Distance")
52
- .mark_bar()
53
- .encode(
54
- alt.X("month(start)"),
55
- alt.Y("sum(distance_km)"),
56
- alt.Color("kind", scale=alt.Scale(scheme="category10"), title="Kind"),
57
- )
58
- .facet(facet="year(start):O", columns=4)
59
- .to_json(format="vega")
60
- )
@@ -1,24 +0,0 @@
1
- {% extends "page.html.j2" %}
2
-
3
- {% block container %}
4
-
5
- <h1 class="mb-3">Configuration</h1>
6
-
7
- <div class="row mb-3">
8
- <div class="col-md-4">
9
- <form action="/config/save" method="POST">
10
- <div class="mb-3">
11
- <label for="exampleFormControlInput1" class="form-label">Email address</label>
12
- <input type="email" class="form-control" id="exampleFormControlInput1" placeholder="name@example.com" />
13
- </div>
14
- <div class="mb-3">
15
- <label for="exampleFormControlTextarea1" class="form-label">Example textarea</label>
16
- <textarea class="form-control" id="exampleFormControlTextarea1" rows="3"></textarea>
17
- </div>
18
- </form>
19
- </div>
20
- </div>
21
-
22
- <input type="submit" value="Save" />
23
-
24
- {% endblock %}
@@ -1,18 +0,0 @@
1
- {% extends "page.html.j2" %}
2
-
3
- {% block container %}
4
- <div class="row mb-1">
5
- <div class="col">
6
- <h1>Eddington Number</h1>
7
-
8
- <p>Your Eddington number is {{ eddington_number }}. That means that on {{ eddington_number }} separate days you
9
- have recorded activities exceeding {{ eddington_number }} km.</p>
10
- </div>
11
- </div>
12
-
13
- <div class="row mb-1">
14
- <div class="col">
15
- {{ vega_direct("eddington-log", logarithmic_plot) }}
16
- </div>
17
- </div>
18
- {% endblock %}
@@ -1,38 +0,0 @@
1
- {% extends "page.html.j2" %}
2
-
3
- {% block container %}
4
- <div class="row mb-3">
5
- <div class="col">
6
- <h1>Locations</h1>
7
- </div>
8
- </div>
9
-
10
- <div class="row mb-3">
11
- <div class="col-8">
12
- <div id="activity-map" style="height: 500px;"></div>
13
- <script>
14
- function onEachFeature(feature, layer) {
15
- layer.bindPopup(`${feature.geometry.coordinates}`)
16
- }
17
-
18
-
19
- let map = L.map('activity-map', {
20
- fullscreenControl: true
21
- });
22
- L.tileLayer('/tile/color/{z}/{x}/{y}.png', {
23
- maxZoom: 19,
24
- attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
25
- }).addTo(map);
26
-
27
- let geojson = L.geoJSON({{ activity_endpoints_geojson| safe }}, { onEachFeature: onEachFeature })
28
- let markers = L.markerClusterGroup();
29
- markers.addLayer(geojson);
30
- map.addLayer(markers);
31
-
32
- map.fitBounds(geojson.getBounds());
33
- </script>
34
- </div>
35
- </div>
36
-
37
-
38
- {% endblock %}
@@ -1,21 +0,0 @@
1
- {% extends "page.html.j2" %}
2
-
3
- {% block container %}
4
- <div class="row mb-1">
5
- <div class="col">
6
- <h1>Summary Statistics</h1>
7
- </div>
8
- </div>
9
-
10
- <div class="row mb-1">
11
- <div class="col">
12
- {{ vega_direct("year_on_year_distance_meta_plot", year_on_year_distance_meta_plot) }}
13
- </div>
14
- </div>
15
-
16
- <div class="row mb-1">
17
- <div class="col">
18
- {{ vega_direct("distance_heatmap_meta_plot", distance_heatmap_meta_plot) }}
19
- </div>
20
- </div>
21
- {% endblock %}