Add train route distance info

This commit is contained in:
Edward Betts 2024-04-05 15:58:44 +02:00
parent 5964899a00
commit 8ef67e0cee
6 changed files with 70 additions and 7 deletions

View file

@ -1,12 +1,14 @@
"""Travel."""
import json
import os
import typing
import flask
import yaml
from geopy.distance import geodesic
from .types import Event
from .types import Event, StrDict
Leg = dict[str, str]
@ -63,3 +65,47 @@ def flight_number(flight: Leg) -> str:
def all_events(data_dir: str) -> list[Event]:
"""Get all flights and rail journeys."""
return get_trains(data_dir) + get_flights(data_dir)
RouteDistances = dict[tuple[str, str], float]
def train_leg_distance(geojson_data: StrDict) -> float:
"""Calculate the total length of a LineString in kilometers from GeoJSON data."""
# Extract coordinates
first_object = geojson_data["features"][0]["geometry"]
assert first_object["type"] in ("LineString", "MultiLineString")
if first_object["type"] == "LineString":
coord_list = [first_object["coordinates"]]
else:
first_object["type"] == "MultiLineString"
coord_list = first_object["coordinates"]
# pprint(coordinates)
total_length_km = 0.0
for coordinates in coord_list:
total_length_km += sum(
float(geodesic(coordinates[i], coordinates[i + 1]).km)
for i in range(len(coordinates) - 1)
)
return total_length_km
def load_route_distances(data_dir: str) -> RouteDistances:
"""Load cache of route distances."""
route_distances: RouteDistances = {}
with open(os.path.join(data_dir, "route_distances.json")) as f:
for s1, s2, dist in json.load(f):
route_distances[(s1, s2)] = dist
return route_distances
def add_leg_route_distance(leg: StrDict, route_distances: RouteDistances) -> None:
s1, s2 = sorted([leg["from"], leg["to"]])
dist = route_distances.get((s1, s2))
if dist:
leg["distance"] = dist

View file

@ -98,6 +98,8 @@
| <a href="https://uk.flightaware.com/live/flight/{{ full_flight_number | replace("U2", "EZY") }}">FlightAware</a>
| <a href="{{ radarbox_url }}">radarbox</a>
</div>
<div class="grid-item">
</div>
{% endmacro %}
{% macro train_row(item) %}
@ -131,4 +133,9 @@
{% endif %}
{% endfor %}
</div>
<div class="grid-item text-end">
{% if item.distance %}
{{ "{:.1f} km / {:.1f} miles".format(item.distance, item.distance / 1.60934) }}
{% endif %}
</div>
{% endmacro %}

View file

@ -5,14 +5,14 @@
<style>
.grid-container {
display: grid;
grid-template-columns: repeat(8, auto);
grid-template-columns: repeat(9, auto);
gap: 10px;
justify-content: start;
}
.train-grid-container {
display: grid;
grid-template-columns: repeat(8, auto);
grid-template-columns: repeat(9, auto);
gap: 10px;
justify-content: start;
}

View file

@ -10,7 +10,7 @@
{% set conference_column_count = 7 %}
{% set accommodation_column_count = 7 %}
{% set travel_column_count = 8 %}
{% set travel_column_count = 9 %}
<style>
.conferences {
display: grid;

View file

@ -25,7 +25,7 @@
{% set conference_column_count = 7 %}
{% set accommodation_column_count = 7 %}
{% set travel_column_count = 8 %}
{% set travel_column_count = 9 %}
<style>
.conferences {
display: grid;

View file

@ -117,6 +117,15 @@ def travel_list() -> str:
if isinstance(item["depart"], datetime)
]
route_distances = agenda.travel.load_route_distances(app.config["DATA_DIR"])
for train in trains:
for leg in train["legs"]:
agenda.travel.add_leg_route_distance(leg, route_distances)
if all("distance" in leg for leg in train["legs"]):
train["distance"] = sum(leg["distance"] for leg in train["legs"])
return flask.render_template("travel.html", flights=flights, trains=trains)
@ -300,7 +309,6 @@ def human_readable_delta(future_date: date) -> str | None:
@app.route("/trip/<start>")
def trip_page(start: str) -> str:
"""Individual trip page."""
trip_list = [
trip
for trip in agenda.trip.build_trip_list()
@ -341,7 +349,9 @@ def trip_page(start: str) -> str:
for route in routes:
if "geojson_filename" in route:
route["geojson"] = agenda.trip.read_geojson(route.pop("geojson_filename"))
route["geojson"] = agenda.trip.read_geojson(
app.config["PERSONAL_DATA"], route.pop("geojson_filename")
)
if trip.end:
countries = {c.alpha_2 for c in trip.countries}