Show exploration days before/after each conference on trip page

For each conference, calculate the number of free days available
before and after, relative to the trip boundary or adjacent
conference. Multi-conference trips show the gap between conferences
as "after" the first and "before" the second.

Closes #189

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Edward Betts 2026-04-23 14:29:29 +01:00
parent 3ba18f9019
commit 54e898bc11
3 changed files with 44 additions and 0 deletions

View file

@ -456,6 +456,39 @@ def coordinate_dict(item: StrDict, coord_type: str) -> StrDict:
}
def conference_free_days(trip: Trip) -> dict[str, tuple[int, int]]:
"""Return (days_before, days_after) exploration days for each conference.
Keyed by the conference start date as an ISO string. Days are relative to
the trip boundary or the adjacent conference's end/start for multi-conference
trips.
"""
if not trip.conferences or not trip.end:
return {}
def conf_attend_start(c: StrDict) -> date:
return as_date(c.get("attend_start") or c["start"])
def conf_attend_end(c: StrDict) -> date:
return as_date(c.get("attend_end") or c["end"])
sorted_confs = sorted(trip.conferences, key=conf_attend_start)
result: dict[str, tuple[int, int]] = {}
for i, conf in enumerate(sorted_confs):
before_boundary = conf_attend_end(sorted_confs[i - 1]) if i > 0 else trip.start
after_boundary = (
conf_attend_start(sorted_confs[i + 1])
if i < len(sorted_confs) - 1
else trip.end
)
days_before = (conf_attend_start(conf) - before_boundary).days
days_after = (after_boundary - conf_attend_end(conf)).days
result[str(conf["start"])] = (days_before, days_after)
return result
def collect_trip_coordinates(trip: Trip) -> list[StrDict]:
"""Extract and de-duplicate travel location coordinates from trip."""
coords = []