From 4143190a8a5fbaab05d779e211bcf917af18bace Mon Sep 17 00:00:00 2001 From: Edward Betts Date: Thu, 30 Oct 2025 17:30:27 +0000 Subject: [PATCH] Accommodation must be within 5km of conference --- validate_yaml.py | 45 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/validate_yaml.py b/validate_yaml.py index 6cf4028..f49bf49 100755 --- a/validate_yaml.py +++ b/validate_yaml.py @@ -4,9 +4,11 @@ import os import sys import typing -from datetime import date, timedelta, datetime +from datetime import date, datetime, timedelta +from typing import Tuple, TypeVar import yaml +from geopy.distance import distance from rich.pretty import pprint import agenda @@ -32,6 +34,29 @@ def check_currency(item: agenda.types.StrDict) -> None: sys.exit(-1) +def get_coords(item): + if "latitude" in item and "longitude" in item: + return (item["latitude"], item["longitude"]) + else: + return None + + +T = TypeVar("T") + + +def remove_nones(items: list[T | None]) -> list[T]: + """Return a new list with None values removed.""" + return [item for item in items if item is not None] + + +LatLon = Tuple[float, float] + + +def distance_km(a: LatLon, b: LatLon) -> float: + """Return the great-circle distance between two (lat, lon) points in km.""" + return distance(a, b).km + + def check_trips() -> None: """Check trips and ensure they are in chronological order.""" filepath = os.path.join(data_dir, "trips.yaml") @@ -42,12 +67,14 @@ def check_trips() -> None: for trip_data in trips_data: current_trip = normalize_datetime(trip_data["trip"]) if prev_trip and current_trip < prev_trip: - print(f"Out of order trip found:") + print("Out of order trip found:") print( - f" Previous: {prev_trip_data.get('trip')} - {prev_trip_data.get('name', 'No name')}" + f" Previous: {prev_trip_data.get('trip')} - " + + f"{prev_trip_data.get('name', 'No name')}" ) print( - f" Current: {trip_data.get('trip')} - {trip_data.get('name', 'No name')}" + f" Current: {trip_data.get('trip')} - " + + f"{trip_data.get('name', 'No name')}" ) assert False, "Trips are not in chronological order by trip date." prev_trip = current_trip @@ -56,6 +83,16 @@ def check_trips() -> None: trip_list = agenda.trip.build_trip_list(data_dir) print(len(trip_list), "trips") + for trip in trip_list: + if not trip.accommodation or not trip.conferences: + continue + accommodation_coords = remove_nones([get_coords(a) for a in trip.accommodation]) + conference_coords = remove_nones([get_coords(c) for c in trip.conferences]) + if len(accommodation_coords) != 1 or len(conference_coords) != 1: + continue + dist = distance_km(conference_coords[0], accommodation_coords[0]) + assert dist < 5.0 + coords, routes = agenda.trip.get_coordinates_and_routes(trip_list, data_dir) print(len(coords), "coords") print(len(routes), "routes")