Compare commits

...

3 commits

Author SHA1 Message Date
Edward Betts 3ad11b070a More tests 2025-07-16 06:54:35 +02:00
Edward Betts 9dd033ba77 Fix location tracking for all remaining weekend test failures
Expand return-home heuristic to cover more countries and reorganize logic
to prioritize trip-based location detection over individual travel data.

Key changes:
1. Add Balkan countries (GR, AL, XK, HR, etc.) to European heuristic
2. Add major international countries (US, CA, IN, JP, etc.) to heuristic
3. Change condition from >1 day to >=1 day for faster return detection
4. Move trip heuristic check before individual flight/accommodation lookup

This fixes cases where stopovers or connections (like Kosovo→Albania on
July 1) were overriding the trip-based "return home" logic. Now correctly
detects return home from all types of trips including Balkan and
international destinations.

All weekend location tests now pass - ensures locations show "Bristol"
when free (no events) or show trip locations when traveling.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-16 06:54:35 +02:00
Edward Betts fcd0e9c1cd Fix European trip return heuristic for weekend location tracking
Adjust European short trip heuristic from >3 days to >1 day to correctly
detect when user has returned home from European trips. This fixes the
April 29-30, 2023 case where the location incorrectly showed "Sankt Georg, Hamburg"
instead of "Bristol" when the user was free (no events scheduled) after
the foss-north trip ended on April 27.

The previous logic required more than 3 days to pass before assuming
return home from European countries, but for short European trips by
rail/ferry, users typically return within 1-2 days.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-16 06:54:26 +02:00
2 changed files with 61 additions and 43 deletions

View file

@ -274,36 +274,37 @@ def get_location_for_date(
get_country(acc.get("country", "gb")),
)
# Check if most recent travel was from a trip that ended in the UK
# If so, prioritize that over foreign accommodations within the trip
if most_recent_location and most_recent_date:
for trip in trips:
if (
trip.end
and trip.end < target_date
and trip.start <= most_recent_date <= trip.end
):
# The most recent travel was within a trip that has since ended
locations = trip.locations()
if locations:
final_city, final_country = locations[-1]
# If trip ended in UK, you should be home now
if (
hasattr(final_country, "alpha_2")
and final_country.alpha_2 == "GB"
):
return ("Bristol", get_country("gb"))
# Check for recent trips that have ended - prioritize this over individual travel data
# This handles cases where you're traveling home after a trip (e.g. stopovers, connections)
for trip in trips:
if trip.end and trip.end < target_date:
locations = trip.locations()
if locations:
final_city, final_country = locations[-1]
days_since_trip = (target_date - trip.end).days
# If trip ended in UK, you should be home now
if (
hasattr(final_country, "alpha_2")
and final_country.alpha_2 == "GB"
):
return ("Bristol", get_country("gb"))
# For short European trips (ended >3 days ago), assume returned home
# if no subsequent travel data shows you're still abroad
days_since_trip = (target_date - trip.end).days
if (
days_since_trip > 3
and hasattr(final_country, "alpha_2")
and final_country.alpha_2
in {"BE", "NL", "FR", "DE", "CH", "AT", "IT", "ES"}
):
return ("Bristol", get_country("gb"))
# For short trips to nearby countries or international trips
# (ended >=1 day ago), assume returned home if no subsequent travel data
if (
days_since_trip >= 1
and hasattr(final_country, "alpha_2")
and (
# European countries (close by rail/ferry)
final_country.alpha_2 in {"BE", "NL", "FR", "DE", "CH", "AT", "IT", "ES"}
# Nearby Balkan countries
or final_country.alpha_2 in {"GR", "AL", "XK", "HR", "SI", "MK", "BA", "ME", "RS", "BG", "RO"}
# International trips (assume return home after trip ends)
or final_country.alpha_2 in {"US", "CA", "IN", "JP", "CN", "AU", "NZ", "BR", "AR", "ZA"}
)
):
return ("Bristol", get_country("gb"))
# Return most recent location or default to Bristol
if most_recent_location:

View file

@ -1,5 +1,6 @@
from datetime import date, datetime
import agenda.busy
import agenda.travel as travel
import agenda.trip
from web_view import app
@ -9,20 +10,7 @@ def test_get_location_for_date() -> None:
app.config["SERVER_NAME"] = "test"
with app.app_context():
today = datetime.now().date()
start = date(today.year, 1, 1)
trips = [
t
for t in agenda.trip.build_trip_list()
if t.start
in [
date(2023, 2, 2),
date(2023, 9, 8),
date(2023, 11, 14),
date(2025, 2, 9),
date(2025, 7, 4),
]
]
assert len(trips) == 5
trips = agenda.trip.build_trip_list()
data_dir = app.config["PERSONAL_DATA"]
@ -31,6 +19,32 @@ def test_get_location_for_date() -> None:
accommodations = travel.parse_yaml("accommodation", data_dir)
airports = travel.parse_yaml("airports", data_dir)
for year in range(2023, 2025):
start = date(2023, 1, 1)
busy_events = agenda.busy.get_busy_events(start, app.config, trips)
weekends = agenda.busy.weekends(start, busy_events, trips, data_dir)
for weekend in weekends:
for day in "saturday", "sunday":
assert weekend[day + "_location"][0] == "Bristol" or bool(
weekend[day]
)
# Debug the April 29 issue
april_29_location = agenda.busy.get_location_for_date(
date(2023, 4, 29), trips, bookings, accommodations, airports
)
print(f"\nDirect call for April 29: {april_29_location}")
# Check what the foss-north trip looks like
foss_north_trip = None
for trip in trips:
if trip.title == "foss-north" and trip.start == date(2023, 4, 22):
foss_north_trip = trip
print(f"foss-north trip: {trip.start} to {trip.end}")
print(f"foss-north locations: {trip.locations()}")
break
l1 = agenda.busy.get_location_for_date(
date(2025, 2, 15), trips, bookings, accommodations, airports
)
@ -60,3 +74,6 @@ def test_get_location_for_date() -> None:
date(2025, 8, 2), trips, bookings, accommodations, airports
)
assert l2[0] == "Bristol"
# Fix the April 29 case
assert april_29_location[0] == "Bristol"