From 523dc78b3585d3d3bbfc4562702d33c46f12cff7 Mon Sep 17 00:00:00 2001 From: Edward Betts Date: Tue, 3 Feb 2026 09:25:10 +0000 Subject: [PATCH] Add overall airline, airport, and station stats to trip summary Aggregate yearly stats into overall totals so the trip stats page shows flight segments by airline, airports used, and stations used in the summary section at the top. Co-Authored-By: Claude Opus 4.5 --- AGENTS.md | 4 ++++ agenda/stats.py | 23 +++++++++++++++++++++++ templates/trip/stats.html | 30 ++++++++++++++++++++++++++++++ web_view.py | 2 ++ 4 files changed, 59 insertions(+) diff --git a/AGENTS.md b/AGENTS.md index 87c46c9..dba80ce 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -33,3 +33,7 @@ This is a personal agenda web application built with Flask that tracks various e ## Notes - Trip stats new-country badges come from `agenda.stats.calculate_yearly_stats` via `year_stats.new_countries` (first-visit year, excluding `PREVIOUSLY_VISITED`). +- Trip stats are calculated in `agenda/stats.py`: + - `travel_legs()` extracts airlines, airports, and stations from individual trip travel legs + - `calculate_yearly_stats()` aggregates stats per year including flight/train counts, airlines, airports, stations + - `calculate_overall_stats()` aggregates yearly stats into overall totals for the summary section diff --git a/agenda/stats.py b/agenda/stats.py index f9002a1..2e4dc67 100644 --- a/agenda/stats.py +++ b/agenda/stats.py @@ -61,6 +61,29 @@ def conferences(trip: Trip, yearly_stats: Mapping[int, StrDict]) -> None: yearly_stats[c["start"].year]["conferences"] += 1 +def calculate_overall_stats(yearly_stats: dict[int, StrDict]) -> StrDict: + """Aggregate yearly stats into overall stats for airlines, airports, stations.""" + overall: StrDict = { + "airlines": Counter(), + "airports": Counter(), + "stations": Counter(), + "flight_count": 0, + "train_count": 0, + } + + for year_stats in yearly_stats.values(): + if "airlines" in year_stats: + overall["airlines"] += year_stats["airlines"] + if "airports" in year_stats: + overall["airports"] += year_stats["airports"] + if "stations" in year_stats: + overall["stations"] += year_stats["stations"] + overall["flight_count"] += year_stats.get("flight_count", 0) + overall["train_count"] += year_stats.get("train_count", 0) + + return overall + + def calculate_yearly_stats( trips: list[Trip], previously_visited: set[str] | None = None ) -> dict[int, StrDict]: diff --git a/templates/trip/stats.html b/templates/trip/stats.html index e7eb51e..f912177 100644 --- a/templates/trip/stats.html +++ b/templates/trip/stats.html @@ -20,6 +20,36 @@ {% endfor %} +
+ Flight segments: {{ overall_stats.flight_count }} + {% if overall_stats.airlines %} + ({{ overall_stats.airlines | count }} airlines) + [ by airline: + {% for airline, count in overall_stats.airlines.most_common() %} + {{ airline }}: {{ count }}{% if not loop.last %},{% endif %} + {% endfor %} ] + {% endif %} +
+ {% if overall_stats.airports %} +
+ Airports used: {{ overall_stats.airports | count }} + [ by airport: + {% for airport, count in overall_stats.airports.most_common() %} + {{ airport }}: {{ count }}{% if not loop.last %},{% endif %} + {% endfor %} ] +
+ {% endif %} +
Train segments: {{ overall_stats.train_count }}
+ {% if overall_stats.stations %} +
+ Stations used: {{ overall_stats.stations | count }} + [ by station: + {% for station, count in overall_stats.stations.most_common() %} + {{ station }}: {{ count }}{% if not loop.last %},{% endif %} + {% endfor %} ] +
+ {% endif %} + {% for year, year_stats in yearly_stats | dictsort(reverse=True) %} {% set countries = year_stats.countries | default([]) | sort(attribute="name") %} {% set new_countries = year_stats.new_countries | default([]) %} diff --git a/web_view.py b/web_view.py index a61e257..b9c5de6 100755 --- a/web_view.py +++ b/web_view.py @@ -811,6 +811,7 @@ def trip_stats() -> str: yearly_stats = agenda.stats.calculate_yearly_stats( trip_list, app.config.get("PREVIOUSLY_VISITED") ) + overall_stats = agenda.stats.calculate_overall_stats(yearly_stats) return flask.render_template( "trip/stats.html", @@ -818,6 +819,7 @@ def trip_stats() -> str: total_distance=calc_total_distance(trip_list), distances_by_transport_type=sum_distances_by_transport_type(trip_list), yearly_stats=yearly_stats, + overall_stats=overall_stats, conferences=conferences, previously_visited=app.config.get("PREVIOUSLY_VISITED", set), )