Annotated all functions with mypy --strict-compatible types (-> None, dict[str,
Any], Generator types, etc.), added # type: ignore for untyped third-party libs
(lxml), and reformatted with black. All 18 source files now pass mypy --strict
with zero errors.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace native date inputs with always-open custom calendar; return
journeys show two months side-by-side with Airbnb-style range selection
- Add min-connection filter (30/40/50/60 min) for the inbound leg of
return journeys, separate from the outbound connection filter
- Fix total journey time: naive datetime subtraction across CET/BST was
1 h too long outbound and 1 h too short inbound
- Filter inbound circle line suggestions when connection ≥ 40 min: only
show services arriving ≥ 5 min before GWR departure at Paddington
- Add Std / SP labels to Eurostar fare lines so users can distinguish
Standard from Standard Premier
- Row selection with a fixed summary bar showing NR + Eurostar + circle
totals; selection is preserved in the URL
- Load walk-on fares sequentially, outbound section first
- Mobile: card-grid table layout, hide headcode/platform on small screens
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
For return journeys, replace the single combined date navigation row with two
separate rows so outbound and return dates can be adjusted independently.
For inbound underground options, show one service before the earliest catchable
(as an "aim for this" option) rather than the next service after it, which
often arrived too late to connect with the GWR train.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add tfl_fare.py with circle_line_fare() which returns £3.10 (peak) or
£3.00 (off-peak) based on TfL Zone 1 pricing. Peak applies Monday–Friday
(excluding England public holidays) 06:30–09:30 and 16:00–19:00.
Annotate each circle service with its fare in trip_planner.py, display
it alongside the Circle line times in the Transfer column, and include
it in the journey Total.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Support any station with direct trains to Paddington; station CRS code
is now part of the URL (/results/<crs>/<slug>/<date>)
- Load station list from data/direct_to_paddington.tsv; show dropdown on
index page; 404 for unknown station codes
- Fetch live GWR walk-on fares via api.gwr.com for all stations (SSS/SVS/SDS
with restrictions already applied per train); cache 30 days
- Scrape Paddington arrival platform numbers from RTT
- Show unreachable morning Eurostars (before first reachable service only)
- Circle line: show actual KX St Pancras arrival times (not check-in estimate)
and add a second backup service in the transfer column
- Widen page max-width to 1100px for longer station names
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Parse Circle Line times from TransXChange XML (output_txc_01CIR_.xml) with
separate weekday/Saturday/Sunday schedules, replacing the approximated
every-10-minutes pattern. Subtract 1 hour timezone offset (CET/CEST vs
GMT/BST) when computing Eurostar journey duration, shown for both viable
and unreachable services.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Index page connection time dropdowns now iterate over valid_min_connections
and valid_max_connections passed from the view, so any change to the sets
in app.py is reflected automatically (also adds the missing 45 min option).
Add ⚠️ next to transfer times under 80 minutes in the results table;
store connection_minutes in each trip dict to support the comparison.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add cheapest_gwr_ticket() to trip_planner.py encoding the SSS/SVS/SDS
walk-on single restrictions for Bristol Temple Meads → Paddington: on
weekdays, Super Off-Peak (£45) is valid before 05:05 or from 09:58,
Off-Peak (£63.60) from 08:26, and Anytime (£138.70) covers the gap.
Weekends have no restrictions. The fare is included in each trip dict
and displayed in a new GWR Fare column on the results page.
Also wire up find_unreachable_morning_eurostars() into the results view
so early Eurostar services unreachable from Bristol appear in the table,
with tests covering both features.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>