parent
12a2b739e8
commit
1e14a99419
|
@ -48,11 +48,12 @@
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% macro section(heading, item_list) %}
|
{% macro section(heading, item_list) %}
|
||||||
{% if item_list %}
|
|
||||||
{% set items = item_list | list %}
|
{% set items = item_list | list %}
|
||||||
<div class="heading"><h2>{{ heading }}</h2></div>
|
<div class="heading"><h2>{{ heading }}</h2></div>
|
||||||
|
<p><a href="{{ url_for("trip_stats") }}">Trip statistics</a></p>
|
||||||
<p>{{ items | count }} trips</p>
|
<p>{{ items | count }} trips</p>
|
||||||
|
|
||||||
|
{% if item_list %}
|
||||||
<div>Total distance: {{ format_distance(total_distance) }}</div>
|
<div>Total distance: {{ format_distance(total_distance) }}</div>
|
||||||
|
|
||||||
{% for transport_type, distance in distances_by_transport_type %}
|
{% for transport_type, distance in distances_by_transport_type %}
|
||||||
|
|
34
templates/trip/stats.html
Normal file
34
templates/trip/stats.html
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% from "macros.html" import format_distance with context %}
|
||||||
|
|
||||||
|
{% set heading = "Trip statistics" %}
|
||||||
|
|
||||||
|
{% block title %}{{ heading }} - Edward Betts{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="container">
|
||||||
|
<h1>Trip statistics</h1>
|
||||||
|
<div>Trips: {{ count }}</div>
|
||||||
|
<div>Total distance: {{ format_distance(total_distance) }}</div>
|
||||||
|
|
||||||
|
{% for transport_type, distance in distances_by_transport_type %}
|
||||||
|
<div>
|
||||||
|
{{ transport_type | title }}
|
||||||
|
distance: {{format_distance(distance) }}
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{% for year, year_stats in yearly_stats | dictsort %}
|
||||||
|
<h4>{{ year }}</h4>
|
||||||
|
<div>Trips in {{ year }}: {{ year_stats.count }}</div>
|
||||||
|
<div>Total distance in {{ year}}: {{ format_distance(year_stats.total_distance) }}</div>
|
||||||
|
{% for transport_type, distance in year_stats.distances_by_transport_type.items() %}
|
||||||
|
<div>
|
||||||
|
{{ transport_type | title }}
|
||||||
|
distance: {{format_distance(distance) }}
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
41
web_view.py
41
web_view.py
|
@ -526,6 +526,47 @@ def birthday_list() -> str:
|
||||||
return flask.render_template("birthday_list.html", items=items, today=today)
|
return flask.render_template("birthday_list.html", items=items, today=today)
|
||||||
|
|
||||||
|
|
||||||
|
def calculate_yearly_stats(trips: list[Trip]) -> dict[int, StrDict]:
|
||||||
|
"""Calculate total distance and distance by transport type grouped by year."""
|
||||||
|
yearly_stats: defaultdict[int, StrDict] = defaultdict(dict)
|
||||||
|
for trip in trips:
|
||||||
|
year = trip.start.year
|
||||||
|
dist = trip.total_distance()
|
||||||
|
yearly_stats[year].setdefault("count", 0)
|
||||||
|
yearly_stats[year]["count"] += 1
|
||||||
|
if dist:
|
||||||
|
yearly_stats[year]["total_distance"] = (
|
||||||
|
yearly_stats[year].get("total_distance", 0) + trip.total_distance()
|
||||||
|
)
|
||||||
|
for transport_type, distance in trip.distances_by_transport_type():
|
||||||
|
yearly_stats[year].setdefault("distances_by_transport_type", {})
|
||||||
|
yearly_stats[year]["distances_by_transport_type"][transport_type] = (
|
||||||
|
yearly_stats[year]["distances_by_transport_type"].get(transport_type, 0)
|
||||||
|
+ distance
|
||||||
|
)
|
||||||
|
return dict(yearly_stats)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/trip/stats")
|
||||||
|
def trip_stats() -> str:
|
||||||
|
"""Travel stats: distance and price by year and travel type."""
|
||||||
|
route_distances = agenda.travel.load_route_distances(app.config["DATA_DIR"])
|
||||||
|
trip_list = get_trip_list(route_distances)
|
||||||
|
today = date.today()
|
||||||
|
|
||||||
|
past = [item for item in trip_list if (item.end or item.start) < today]
|
||||||
|
|
||||||
|
yearly_stats = calculate_yearly_stats(past)
|
||||||
|
|
||||||
|
return flask.render_template(
|
||||||
|
"trip/stats.html",
|
||||||
|
count=len(past),
|
||||||
|
total_distance=calc_total_distance(past),
|
||||||
|
distances_by_transport_type=sum_distances_by_transport_type(past),
|
||||||
|
yearly_stats=yearly_stats,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@app.route("/callback")
|
@app.route("/callback")
|
||||||
def auth_callback() -> tuple[str, int] | werkzeug.Response:
|
def auth_callback() -> tuple[str, int] | werkzeug.Response:
|
||||||
"""Process the authentication callback."""
|
"""Process the authentication callback."""
|
||||||
|
|
Loading…
Reference in a new issue