Compare commits
3 commits
093000bbc3
...
38f2e10c6d
Author | SHA1 | Date | |
---|---|---|---|
Edward Betts | 38f2e10c6d | ||
Edward Betts | cd8dfb74a4 | ||
Edward Betts | f8c523c674 |
|
@ -3,7 +3,7 @@
|
||||||
import collections
|
import collections
|
||||||
import datetime
|
import datetime
|
||||||
import typing
|
import typing
|
||||||
from collections import Counter
|
from collections import defaultdict
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
|
|
||||||
import emoji
|
import emoji
|
||||||
|
@ -190,12 +190,12 @@ class Trip:
|
||||||
|
|
||||||
Any travel item with a missing or None 'distance' field is ignored.
|
Any travel item with a missing or None 'distance' field is ignored.
|
||||||
"""
|
"""
|
||||||
transport_distances: Counter[float] = Counter()
|
transport_distances: defaultdict[str, float] = defaultdict(float)
|
||||||
|
|
||||||
for item in self.travel:
|
for item in self.travel:
|
||||||
distance = item.get("distance")
|
distance = item.get("distance")
|
||||||
if distance:
|
if distance:
|
||||||
transport_type = item.get("type", "unknown")
|
transport_type: str = item.get("type", "unknown")
|
||||||
transport_distances[transport_type] += distance
|
transport_distances[transport_type] += distance
|
||||||
|
|
||||||
return list(transport_distances.items())
|
return list(transport_distances.items())
|
||||||
|
|
|
@ -3,6 +3,10 @@
|
||||||
{% macro display_date(dt) %}{{ dt.strftime("%a %-d %b %Y") }}{% endmacro %}
|
{% macro display_date(dt) %}{{ dt.strftime("%a %-d %b %Y") }}{% endmacro %}
|
||||||
{% macro display_date_no_year(dt) %}{{ dt.strftime("%a %-d %b") }}{% endmacro %}
|
{% macro display_date_no_year(dt) %}{{ dt.strftime("%a %-d %b") }}{% endmacro %}
|
||||||
|
|
||||||
|
{% macro format_distance(distance) %}
|
||||||
|
{{ "{:,.0f} km / {:,.0f} miles".format(distance, distance / 1.60934) }}
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
{% macro trip_link(trip) %}
|
{% macro trip_link(trip) %}
|
||||||
<a href="{{ url_for("trip_page", start=trip.start.isoformat()) }}">{{ trip.title }}</a>
|
<a href="{{ url_for("trip_page", start=trip.start.isoformat()) }}">{{ trip.title }}</a>
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
|
|
||||||
{% from "macros.html" import trip_link, display_date_no_year, display_date, display_datetime, display_time with context %}
|
{% from "macros.html" import trip_link, display_date_no_year, display_date, display_datetime, display_time, format_distance with context %}
|
||||||
|
|
||||||
{% block title %}{{ heading }} - Edward Betts{% endblock %}
|
{% block title %}{{ heading }} - Edward Betts{% endblock %}
|
||||||
|
|
||||||
|
@ -52,6 +52,18 @@
|
||||||
{% 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>{{ items | count }} trips</p>
|
<p>{{ items | count }} trips</p>
|
||||||
|
|
||||||
|
<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 trip in items %}
|
{% for trip in items %}
|
||||||
{% set distances_by_transport_type = trip.distances_by_transport_type() %}
|
{% set distances_by_transport_type = trip.distances_by_transport_type() %}
|
||||||
{% set total_distance = trip.total_distance() %}
|
{% set total_distance = trip.total_distance() %}
|
||||||
|
@ -74,15 +86,17 @@
|
||||||
<div>Start: {{ display_date_no_year(trip.start) }} (end date missing)</div>
|
<div>Start: {{ display_date_no_year(trip.start) }} (end date missing)</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if total_distance %}
|
{% if total_distance %}
|
||||||
<div>Total distance:
|
<div>
|
||||||
{{ "{:,.0f} km / {:,.0f} miles".format(total_distance, total_distance / 1.60934) }}
|
Total distance:
|
||||||
|
{{ format_distance(total_distance) }}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if distances_by_transport_type %}
|
{% if distances_by_transport_type %}
|
||||||
{% for transport_type, distance in distances_by_transport_type %}
|
{% for transport_type, distance in distances_by_transport_type %}
|
||||||
<div>{{ transport_type | title }} distance:
|
<div>
|
||||||
{{ "{:,.0f} km / {:,.0f} miles".format(distance, distance / 1.60934) }}
|
{{ transport_type | title }}
|
||||||
|
distance: {{format_distance(distance) }}
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -108,9 +122,14 @@
|
||||||
{% if e.element_type == "flight" %}
|
{% if e.element_type == "flight" %}
|
||||||
<span class="text-nowrap"><strong>airline:</strong> {{ e.detail.airline_name }}</span>
|
<span class="text-nowrap"><strong>airline:</strong> {{ e.detail.airline_name }}</span>
|
||||||
<span class="text-nowrap"><strong>flight number:</strong> {{ e.detail.airline }}{{ e.detail.flight_number }}</span>
|
<span class="text-nowrap"><strong>flight number:</strong> {{ e.detail.airline }}{{ e.detail.flight_number }}</span>
|
||||||
|
{% if e.detail.duration %}
|
||||||
<span class="text-nowrap"><strong>duration:</strong> {{ e.detail.duration }}</span>
|
<span class="text-nowrap"><strong>duration:</strong> {{ e.detail.duration }}</span>
|
||||||
|
{% endif %}
|
||||||
{# <pre>{{ e.detail | pprint }}</pre> #}
|
{# <pre>{{ e.detail | pprint }}</pre> #}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if e.detail.distance %}
|
||||||
|
<span class="text-nowrap"><strong>distance:</strong> {{ format_distance(e.detail.distance) }}</span>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
26
web_view.py
26
web_view.py
|
@ -8,6 +8,7 @@ import operator
|
||||||
import os.path
|
import os.path
|
||||||
import sys
|
import sys
|
||||||
import traceback
|
import traceback
|
||||||
|
from collections import defaultdict
|
||||||
from datetime import date, datetime, timedelta
|
from datetime import date, datetime, timedelta
|
||||||
|
|
||||||
import flask
|
import flask
|
||||||
|
@ -286,6 +287,27 @@ def trip_list() -> werkzeug.Response:
|
||||||
return flask.redirect(flask.url_for("trip_future_list"))
|
return flask.redirect(flask.url_for("trip_future_list"))
|
||||||
|
|
||||||
|
|
||||||
|
def calc_total_distance(trips: list[Trip]) -> float:
|
||||||
|
"""Total distance for trips."""
|
||||||
|
total = 0.0
|
||||||
|
for item in trips:
|
||||||
|
dist = item.total_distance()
|
||||||
|
if dist:
|
||||||
|
total += dist
|
||||||
|
|
||||||
|
return total
|
||||||
|
|
||||||
|
|
||||||
|
def sum_distances_by_transport_type(trips: list[Trip]) -> list[tuple[str, float]]:
|
||||||
|
"""Sum distances by transport type."""
|
||||||
|
distances_by_transport_type: defaultdict[str, float] = defaultdict(float)
|
||||||
|
for trip in trips:
|
||||||
|
for transport_type, dist in trip.distances_by_transport_type():
|
||||||
|
distances_by_transport_type[transport_type] += dist
|
||||||
|
|
||||||
|
return list(distances_by_transport_type.items())
|
||||||
|
|
||||||
|
|
||||||
@app.route("/trip/past")
|
@app.route("/trip/past")
|
||||||
def trip_past_list() -> str:
|
def trip_past_list() -> str:
|
||||||
"""Page showing a list of past trips."""
|
"""Page showing a list of past trips."""
|
||||||
|
@ -307,6 +329,8 @@ def trip_past_list() -> str:
|
||||||
get_country=agenda.get_country,
|
get_country=agenda.get_country,
|
||||||
format_list_with_ampersand=format_list_with_ampersand,
|
format_list_with_ampersand=format_list_with_ampersand,
|
||||||
fx_rate=agenda.fx.get_rates(app.config),
|
fx_rate=agenda.fx.get_rates(app.config),
|
||||||
|
total_distance=calc_total_distance(past),
|
||||||
|
distances_by_transport_type=sum_distances_by_transport_type(past),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -337,6 +361,8 @@ def trip_future_list() -> str:
|
||||||
get_country=agenda.get_country,
|
get_country=agenda.get_country,
|
||||||
format_list_with_ampersand=format_list_with_ampersand,
|
format_list_with_ampersand=format_list_with_ampersand,
|
||||||
fx_rate=agenda.fx.get_rates(app.config),
|
fx_rate=agenda.fx.get_rates(app.config),
|
||||||
|
total_distance=calc_total_distance(current + future),
|
||||||
|
distances_by_transport_type=sum_distances_by_transport_type(current + future),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue