geo-activity-playground 0.24.1__tar.gz → 0.24.2__tar.gz

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 (94) hide show
  1. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/PKG-INFO +1 -1
  2. geo_activity_playground-0.24.2/geo_activity_playground/webui/equipment/controller.py +114 -0
  3. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/equipment/templates/equipment/index.html.j2 +14 -3
  4. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/summary/controller.py +11 -8
  5. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/pyproject.toml +1 -1
  6. geo_activity_playground-0.24.1/geo_activity_playground/webui/equipment/controller.py +0 -73
  7. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/LICENSE +0 -0
  8. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/__init__.py +0 -0
  9. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/__main__.py +0 -0
  10. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/core/__init__.py +0 -0
  11. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/core/activities.py +0 -0
  12. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/core/activity_parsers.py +0 -0
  13. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/core/cache_migrations.py +0 -0
  14. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/core/config.py +0 -0
  15. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/core/coordinates.py +0 -0
  16. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/core/heatmap.py +0 -0
  17. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/core/paths.py +0 -0
  18. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/core/privacy_zones.py +0 -0
  19. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/core/similarity.py +0 -0
  20. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/core/tasks.py +0 -0
  21. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/core/test_tiles.py +0 -0
  22. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/core/test_time_conversion.py +0 -0
  23. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/core/tiles.py +0 -0
  24. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/core/time_conversion.py +0 -0
  25. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/explorer/__init__.py +0 -0
  26. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/explorer/grid_file.py +0 -0
  27. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/explorer/tile_visits.py +0 -0
  28. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/explorer/video.py +0 -0
  29. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/importers/__init__.py +0 -0
  30. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/importers/directory.py +0 -0
  31. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/importers/strava_api.py +0 -0
  32. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/importers/strava_checkout.py +0 -0
  33. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/importers/test_directory.py +0 -0
  34. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/importers/test_strava_api.py +0 -0
  35. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/__init__.py +0 -0
  36. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/activity/__init__.py +0 -0
  37. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/activity/blueprint.py +0 -0
  38. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/activity/controller.py +0 -0
  39. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/activity/templates/activity/day.html.j2 +0 -0
  40. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/activity/templates/activity/lines.html.j2 +0 -0
  41. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/activity/templates/activity/name.html.j2 +0 -0
  42. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/activity/templates/activity/show.html.j2 +0 -0
  43. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/app.py +0 -0
  44. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/calendar/__init__.py +0 -0
  45. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/calendar/blueprint.py +0 -0
  46. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/calendar/controller.py +0 -0
  47. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/calendar/templates/calendar/index.html.j2 +0 -0
  48. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/calendar/templates/calendar/month.html.j2 +0 -0
  49. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/eddington/__init__.py +0 -0
  50. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/eddington/blueprint.py +0 -0
  51. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/eddington/controller.py +0 -0
  52. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/eddington/templates/eddington/index.html.j2 +0 -0
  53. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/entry_controller.py +0 -0
  54. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/equipment/__init__.py +0 -0
  55. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/equipment/blueprint.py +0 -0
  56. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/explorer/__init__.py +0 -0
  57. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/explorer/blueprint.py +0 -0
  58. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/explorer/controller.py +0 -0
  59. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/explorer/templates/explorer/index.html.j2 +0 -0
  60. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/heatmap/__init__.py +0 -0
  61. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/heatmap/blueprint.py +0 -0
  62. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/heatmap/heatmap_controller.py +0 -0
  63. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/heatmap/templates/heatmap/index.html.j2 +0 -0
  64. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/search_controller.py +0 -0
  65. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/square_planner/__init__.py +0 -0
  66. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/square_planner/blueprint.py +0 -0
  67. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/square_planner/controller.py +0 -0
  68. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/square_planner/templates/square_planner/index.html.j2 +0 -0
  69. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/static/android-chrome-192x192.png +0 -0
  70. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/static/android-chrome-384x384.png +0 -0
  71. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/static/android-chrome-512x512.png +0 -0
  72. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/static/apple-touch-icon.png +0 -0
  73. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/static/browserconfig.xml +0 -0
  74. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/static/favicon-16x16.png +0 -0
  75. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/static/favicon-32x32.png +0 -0
  76. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/static/favicon.ico +0 -0
  77. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/static/mstile-150x150.png +0 -0
  78. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/static/safari-pinned-tab.svg +0 -0
  79. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/static/site.webmanifest +0 -0
  80. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/strava_controller.py +0 -0
  81. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/summary/__init__.py +0 -0
  82. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/summary/blueprint.py +0 -0
  83. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/summary/templates/summary/index.html.j2 +0 -0
  84. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/templates/home.html.j2 +0 -0
  85. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/templates/page.html.j2 +0 -0
  86. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/templates/search.html.j2 +0 -0
  87. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/templates/strava-connect.html.j2 +0 -0
  88. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/tile/__init__.py +0 -0
  89. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/tile/blueprint.py +0 -0
  90. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/tile/controller.py +0 -0
  91. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/upload/__init__.py +0 -0
  92. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/upload/blueprint.py +0 -0
  93. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/upload/controller.py +0 -0
  94. {geo_activity_playground-0.24.1 → geo_activity_playground-0.24.2}/geo_activity_playground/webui/upload/templates/upload/index.html.j2 +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: geo-activity-playground
3
- Version: 0.24.1
3
+ Version: 0.24.2
4
4
  Summary: Analysis of geo data activities like rides, runs or hikes.
5
5
  License: MIT
6
6
  Author: Martin Ueding
@@ -0,0 +1,114 @@
1
+ import altair as alt
2
+ import pandas as pd
3
+
4
+ from geo_activity_playground.core.activities import ActivityRepository
5
+ from geo_activity_playground.core.config import get_config
6
+
7
+
8
+ class EquipmentController:
9
+ def __init__(self, repository: ActivityRepository) -> None:
10
+ self._repository = repository
11
+
12
+ def render(self) -> dict:
13
+ kind_per_equipment = self._repository.meta.groupby("equipment").apply(
14
+ lambda group: group.groupby("kind")
15
+ .apply(lambda group2: sum(group2["distance_km"]), include_groups=False)
16
+ .idxmax(),
17
+ include_groups=False,
18
+ )
19
+
20
+ equipment_summary = (
21
+ self._repository.meta.groupby("equipment")
22
+ .apply(
23
+ lambda group: pd.Series(
24
+ {
25
+ "total_distance_km": group["distance_km"].sum(),
26
+ "first_use": group["start"].iloc[0],
27
+ "last_use": group["start"].iloc[-1],
28
+ },
29
+ ),
30
+ include_groups=False,
31
+ )
32
+ .sort_values("last_use", ascending=False)
33
+ )
34
+
35
+ equipment_summary["primarily_used_for"] = None
36
+ for equipment, kind in kind_per_equipment.items():
37
+ equipment_summary.loc[equipment, "primarily_used_for"] = kind
38
+
39
+ equipment_variables = {}
40
+ for equipment in equipment_summary.index:
41
+ selection = self._repository.meta.loc[
42
+ self._repository.meta["equipment"] == equipment
43
+ ]
44
+ total_distances = pd.DataFrame(
45
+ {
46
+ "time": selection["start"],
47
+ "total_distance_km": selection["distance_km"].cumsum(),
48
+ }
49
+ )
50
+
51
+ total_distances_plot = (
52
+ alt.Chart(
53
+ total_distances,
54
+ height=300,
55
+ width=300,
56
+ title="Usage over Time",
57
+ )
58
+ .mark_line(interpolate="step-after")
59
+ .encode(
60
+ alt.X("time", title="Date"),
61
+ alt.Y("total_distance_km", title="Cumulative distance / km"),
62
+ )
63
+ .interactive()
64
+ .to_json(format="vega")
65
+ )
66
+
67
+ yearly_distance_plot = (
68
+ alt.Chart(
69
+ selection,
70
+ height=300,
71
+ title="Yearly distance",
72
+ )
73
+ .mark_bar()
74
+ .encode(
75
+ alt.X("year(start):O", title="Year"),
76
+ alt.Y("sum(distance_km)", title="Distance / km"),
77
+ )
78
+ .to_json(format="vega")
79
+ )
80
+
81
+ usages_plot = (
82
+ alt.Chart(
83
+ selection,
84
+ height=300,
85
+ title="Kinds",
86
+ )
87
+ .mark_bar()
88
+ .encode(
89
+ alt.X("kind", title="Year"),
90
+ alt.Y("sum(distance_km)", title="Distance / km"),
91
+ )
92
+ .to_json(format="vega")
93
+ )
94
+
95
+ equipment_variables[equipment] = {
96
+ "total_distances_plot": total_distances_plot,
97
+ "total_distances_plot_id": f"total_distances_plot_{hash(equipment)}",
98
+ "yearly_distance_plot": yearly_distance_plot,
99
+ "yearly_distance_plot_id": f"yearly_distance_plot_{hash(equipment)}",
100
+ "usages_plot": usages_plot,
101
+ "usages_plot_id": f"usages_plot_{hash(equipment)}",
102
+ }
103
+
104
+ config = get_config()
105
+ if "offsets" in config:
106
+ for equipment, offset in config["offsets"].items():
107
+ equipment_summary.loc[equipment, "total_distance_km"] += offset
108
+
109
+ return {
110
+ "equipment_variables": equipment_variables,
111
+ "equipment_summary": equipment_summary.reset_index().to_dict(
112
+ orient="records"
113
+ ),
114
+ }
@@ -13,6 +13,7 @@
13
13
  <thead>
14
14
  <tr>
15
15
  <th>Equipment</th>
16
+ <th>Primarily used for</th>
16
17
  <th style="text-align: right;">Distance / km</th>
17
18
  <th style="text-align: right;">First use</th>
18
19
  <th style="text-align: right;">Last use</th>
@@ -22,6 +23,7 @@
22
23
  {% for equipment in equipment_summary %}
23
24
  <tr>
24
25
  <td>{{ equipment.equipment }}</td>
26
+ <td>{{ equipment.primarily_used_for }}</td>
25
27
  <td style="text-align: right;">{{ equipment.total_distance_km|int }}</td>
26
28
  <td style="text-align: right;">{{ equipment.first_use.date() }}</td>
27
29
  <td style="text-align: right;">{{ equipment.last_use.date() }}</td>
@@ -34,13 +36,22 @@
34
36
 
35
37
  <div class="row mb-3">
36
38
  <div class="col">
37
- <h2>Usage over time</h2>
39
+ <h2>Details for each equipment</h2>
38
40
  </div>
39
41
  </div>
40
42
 
43
+ {% for equipment, data in equipment_variables.items() %}
44
+ <h3>{{ equipment }}</h3>
41
45
  <div class="row mb-3">
42
- <div class="col">
43
- {{ vega_direct("total_distances_plot", total_distances_plot) }}
46
+ <div class="col-md-4">
47
+ {{ vega_direct(data.total_distances_plot_id, data.total_distances_plot) }}
48
+ </div>
49
+ <div class="col-md-4">
50
+ {{ vega_direct(data.yearly_distance_plot_id, data.yearly_distance_plot) }}
51
+ </div>
52
+ <div class="col-md-4">
53
+ {{ vega_direct(data.usages_plot_id, data.usages_plot) }}
44
54
  </div>
45
55
  </div>
56
+ {% endfor %}
46
57
  {% endblock %}
@@ -61,11 +61,13 @@ def nominate_activities(meta: pd.DataFrame) -> dict[int, list[str]]:
61
61
  i = subset["elapsed_time"].idxmax()
62
62
  nominations[i].append(f"Longest elapsed time: {meta.loc[i].elapsed_time}")
63
63
 
64
- i = subset["calories"].idxmax()
65
- nominations[i].append(f"Most calories burnt: {meta.loc[i].calories:.0f} kcal")
64
+ if "calories" in subset.columns:
65
+ i = subset["calories"].idxmax()
66
+ nominations[i].append(f"Most calories burnt: {meta.loc[i].calories:.0f} kcal")
66
67
 
67
- i = subset["steps"].idxmax()
68
- nominations[i].append(f"Most steps: {meta.loc[i].steps:.0f}")
68
+ if "steps" in subset:
69
+ i = subset["steps"].idxmax()
70
+ nominations[i].append(f"Most steps: {meta.loc[i].steps:.0f}")
69
71
 
70
72
  for kind, group in meta.groupby("kind"):
71
73
  for key, text in [
@@ -83,10 +85,11 @@ def nominate_activities(meta: pd.DataFrame) -> dict[int, list[str]]:
83
85
  ),
84
86
  ("steps", lambda row: f"Most steps for {row.kind}: {row.steps:.0f}"),
85
87
  ]:
86
- series = group[key]
87
- i = series.idxmax()
88
- if not pd.isna(i):
89
- nominations[i].append(text(meta.loc[i]))
88
+ if key in group.columns:
89
+ series = group[key]
90
+ i = series.idxmax()
91
+ if not pd.isna(i):
92
+ nominations[i].append(text(meta.loc[i]))
90
93
 
91
94
  return nominations
92
95
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "geo-activity-playground"
3
- version = "0.24.1"
3
+ version = "0.24.2"
4
4
  description = "Analysis of geo data activities like rides, runs or hikes."
5
5
  authors = ["Martin Ueding <mu@martin-ueding.de>"]
6
6
  license = "MIT"
@@ -1,73 +0,0 @@
1
- import altair as alt
2
- import pandas as pd
3
-
4
- from geo_activity_playground.core.activities import ActivityRepository
5
- from geo_activity_playground.core.config import get_config
6
-
7
-
8
- class EquipmentController:
9
- def __init__(self, repository: ActivityRepository) -> None:
10
- self._repository = repository
11
-
12
- def render(self) -> dict:
13
- total_distances = (
14
- self._repository.meta.groupby("equipment")
15
- .apply(
16
- lambda group: pd.DataFrame(
17
- {
18
- "time": group["start"],
19
- "total_distance_km": group["distance_km"].cumsum(),
20
- }
21
- ),
22
- include_groups=False,
23
- )
24
- .reset_index()
25
- )
26
-
27
- plot = (
28
- alt.Chart(
29
- total_distances,
30
- height=250,
31
- width=250,
32
- title="Equipment Usage over Time",
33
- )
34
- .mark_line(interpolate="step-after")
35
- .encode(
36
- alt.X("time", title="Date"),
37
- alt.Y("total_distance_km", title="Cumulative distance / km"),
38
- )
39
- .facet("equipment", columns=4, title="Equipment")
40
- .resolve_scale(y="independent")
41
- .resolve_axis(x="independent")
42
- .interactive()
43
- .to_json(format="vega")
44
- )
45
-
46
- equipment_summary = (
47
- self._repository.meta.groupby("equipment")
48
- .apply(
49
- lambda group: pd.DataFrame(
50
- {
51
- "total_distance_km": group["distance_km"].sum(),
52
- "first_use": group["start"].iloc[0],
53
- "last_use": group["start"].iloc[-1],
54
- },
55
- index=[0],
56
- ),
57
- include_groups=False,
58
- )
59
- .reset_index()
60
- .sort_values("last_use", ascending=False)
61
- )
62
-
63
- config = get_config()
64
- if "offsets" in config:
65
- for equipment, offset in config["offsets"].items():
66
- equipment_summary.loc[
67
- equipment_summary["equipment"] == equipment, "total_distance_km"
68
- ] += offset
69
-
70
- return {
71
- "total_distances_plot": plot,
72
- "equipment_summary": equipment_summary.to_dict(orient="records"),
73
- }