Find gaps that are available between travel

Closes: #86
This commit is contained in:
Edward Betts 2023-12-26 23:49:55 +00:00
parent 3823d33b4f
commit 69478e1543

View file

@ -272,6 +272,58 @@ def find_markets_during_stay(
return overlapping_markets return overlapping_markets
def find_gaps(events: list[Event], min_gap_days: int = 5) -> list[tuple[date, date]]:
"""Gaps of at least `min_gap_days` between events in a list of events."""
# Sort events by start date
gaps: list[tuple[date, date]] = []
previous_event_end = None
for event in events:
# Use start date for current event
start_date = event.as_date
# If previous event exists, calculate the gap
if previous_event_end:
gap_days = (start_date - previous_event_end).days
if gap_days >= (min_gap_days + 2):
start_end = (
previous_event_end + timedelta(days=1),
start_date - timedelta(days=1),
)
gaps.append(start_end)
# Update previous event end date
end = event.end_as_date if event.end_date else start_date
if not previous_event_end or end > previous_event_end:
previous_event_end = end
return gaps
def busy_event(e: Event) -> bool:
"""Busy."""
if e.name not in {
"event",
"accommodation",
"conference",
"dodainville",
"transport",
"meetup",
}:
return False
if e.name == "conference" and not e.going:
return False
if not e.title:
return True
if e.title == "LHG Run Club" or "Third Thursday Social" in e.title:
return False
lc_title = e.title.lower()
return "rebels" not in lc_title and "south west data social" not in lc_title
async def get_data( async def get_data(
now: datetime, config: flask.config.Config now: datetime, config: flask.config.Config
) -> typing.Mapping[str, str | object]: ) -> typing.Mapping[str, str | object]:
@ -304,7 +356,7 @@ async def get_data(
bristol_waste_collection_events(data_dir, today), bristol_waste_collection_events(data_dir, today),
) )
reply = { reply: dict[str, typing.Any] = {
"now": now, "now": now,
"gbpusd": gbpusd, "gbpusd": gbpusd,
"stock_markets": stock_market.open_and_close(), "stock_markets": stock_market.open_and_close(),
@ -394,8 +446,25 @@ async def get_data(
events.append(e) events.append(e)
events += [Event(name="today", date=today)] events += [Event(name="today", date=today)]
busy_events = [
e
for e in sorted(events, key=lambda e: e.as_date)
if e.as_date > today and e.as_date < next_year and busy_event(e)
]
gaps = find_gaps(busy_events)
events += [Event(name="gap", date=start, end_date=end) for start, end in gaps]
# Sort events by their datetime; the "today" event is prioritised
# at the top of the list for today. This is achieved by sorting first by
# the datetime attribute, and then ensuring that events with the name
# "today" are ordered before others on the same date.
events.sort(key=lambda e: (e.as_datetime, e.name != "today")) events.sort(key=lambda e: (e.as_datetime, e.name != "today"))
reply["gaps"] = gaps
observer = sun.bristol() observer = sun.bristol()
reply["sunrise"] = sun.sunrise(observer) reply["sunrise"] = sun.sunrise(observer)
reply["sunset"] = sun.sunset(observer) reply["sunset"] = sun.sunset(observer)