Generalize and enhance yearly statistics

The accommodation page has been updated to provide a more comprehensive and dynamic view of travel statistics.

Previously, the page only displayed hard-coded statistics for total nights away and abroad for the year 2024. This required manual updates each year and didn't provide historical context.

This commit introduces the following changes:

*   **Dynamically Calculate Yearly Stats:** The `accommodation_list` view in `web_view.py` now calculates statistics for every year found in the accommodation data. It correctly handles stays that span across multiple years.
*   **Display All Years:** The `accommodation.html` template now iterates through a list of all calculated yearly stats, displaying a summary for each year automatically.
*   **Add Percentage of Year:** The template also calculates and displays what percentage of the year the "total nights" and "nights abroad" represent. This includes logic to correctly account for leap years (366 days) for an accurate calculation.

These changes make the statistics more informative and ensure the page remains relevant over time without needing further manual code adjustments.
This commit is contained in:
Edward Betts 2025-07-23 22:52:22 +01:00
parent c5e88727ae
commit 672ca4b849
2 changed files with 28 additions and 13 deletions

View file

@ -37,9 +37,18 @@
<h1>Accommodation</h1>
<h3>Statistics</h3>
<ul>
<li>Total nights away in 2024: {{ total_nights_2024 }}</li>
<li>Total nights abroad in 2024: {{ nights_abroad_2024 }}</li>
{% for year, stats in year_stats %}
{% set days_in_year = 366 if (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0) else 365 %}
{% set total_percentage = (stats.total_nights / days_in_year) * 100 %}
{% set abroad_percentage = (stats.nights_abroad / days_in_year) * 100 %}
<li>
<strong>{{ year }}:</strong>
Total nights away: {{ stats.total_nights }} ({{ "%.1f"|format(total_percentage) }}%),
Total nights abroad: {{ stats.nights_abroad }} ({{ "%.1f"|format(abroad_percentage) }}%)
</li>
{% endfor %}
</ul>
<div class="grid-container">

View file

@ -374,22 +374,29 @@ def past_conference_list() -> str:
fx_rate=agenda.fx.get_rates(app.config),
)
@app.route("/accommodation")
def accommodation_list() -> str:
"""Page showing a list of past, present and future accommodation."""
data_dir = app.config["PERSONAL_DATA"]
items = travel.parse_yaml("accommodation", data_dir)
stays_in_2024 = [item for item in items if item["from"].year == 2024]
total_nights_2024 = sum(
(stay["to"].date() - stay["from"].date()).days for stay in stays_in_2024
)
# Create a dictionary to hold stats for each year
year_stats = defaultdict(lambda: {"total_nights": 0, "nights_abroad": 0})
nights_abroad_2024 = sum(
(stay["to"].date() - stay["from"].date()).days
for stay in stays_in_2024
if stay["country"] != "gb"
# Calculate stats for each year
for stay in items:
current_date = stay["from"].date()
end_date = stay["to"].date()
while current_date < end_date:
year = current_date.year
year_stats[year]["total_nights"] += 1
if stay.get("country") != "gb":
year_stats[year]["nights_abroad"] += 1
current_date += timedelta(days=1)
# Sort the stats by year in descending order
sorted_year_stats = sorted(
year_stats.items(), key=lambda item: item[0], reverse=True
)
trip_lookup = {}
@ -415,8 +422,7 @@ def accommodation_list() -> str:
past=past,
current=current,
future=future,
total_nights_2024=total_nights_2024,
nights_abroad_2024=nights_abroad_2024,
year_stats=sorted_year_stats,
get_country=agenda.get_country,
fx_rate=agenda.fx.get_rates(app.config),
)