Add Circle line fare to Transfer column and Total
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>
This commit is contained in:
parent
89a536dfd3
commit
35097fda4f
4 changed files with 43 additions and 4 deletions
6
app.py
6
app.py
|
|
@ -226,8 +226,12 @@ def results(station_crs, slug, travel_date):
|
|||
trip["eurostar_plus_price"] = es.get("plus_price")
|
||||
trip["eurostar_plus_seats"] = es.get("plus_seats")
|
||||
gwr_p = trip.get("ticket_price")
|
||||
circle_svcs = trip.get("circle_services")
|
||||
circle_fare = circle_svcs[0]["fare"] if circle_svcs else 0
|
||||
trip["total_price"] = (
|
||||
gwr_p + es_price if (gwr_p is not None and es_price is not None) else None
|
||||
gwr_p + es_price + circle_fare
|
||||
if (gwr_p is not None and es_price is not None)
|
||||
else None
|
||||
)
|
||||
|
||||
# If the API returned journeys but every price is None, tickets aren't on sale yet
|
||||
|
|
|
|||
|
|
@ -181,10 +181,10 @@
|
|||
<span class="nowrap">{{ row.connection_duration }}{% if row.connection_minutes < 80 %} <span title="Tight connection">⚠️</span>{% endif %}</span>
|
||||
{% if row.circle_services %}
|
||||
{% set c = row.circle_services[0] %}
|
||||
<br><span class="text-xs text-muted nowrap">Circle {{ c.depart }} → KX {{ c.arrive_kx }}</span>
|
||||
<br><span class="text-xs text-muted nowrap">Circle {{ c.depart }} → KX {{ c.arrive_kx }} · £{{ "%.2f"|format(c.fare) }}</span>
|
||||
{% if row.circle_services | length > 1 %}
|
||||
{% set c2 = row.circle_services[1] %}
|
||||
<br><span class="text-xs text-muted nowrap" style="opacity:0.7">next {{ c2.depart }} → KX {{ c2.arrive_kx }}</span>
|
||||
<br><span class="text-xs text-muted nowrap" style="opacity:0.7">next {{ c2.depart }} → KX {{ c2.arrive_kx }} · £{{ "%.2f"|format(c2.fare) }}</span>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</td>
|
||||
|
|
|
|||
30
tfl_fare.py
Normal file
30
tfl_fare.py
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
"""TfL single fare calculations for journeys within Zone 1."""
|
||||
|
||||
from datetime import datetime, time
|
||||
|
||||
import holidays
|
||||
|
||||
CIRCLE_LINE_PEAK = 3.10
|
||||
CIRCLE_LINE_OFF_PEAK = 3.00
|
||||
|
||||
_ENGLAND_HOLIDAYS = holidays.country_holidays("GB", subdiv="ENG")
|
||||
|
||||
_AM_PEAK_START = time(6, 30)
|
||||
_AM_PEAK_END = time(9, 30)
|
||||
_PM_PEAK_START = time(16, 0)
|
||||
_PM_PEAK_END = time(19, 0)
|
||||
|
||||
|
||||
def circle_line_fare(depart_dt: datetime) -> float:
|
||||
"""Return the TfL Circle line single fare for a given departure datetime.
|
||||
|
||||
Peak (£3.10): Monday–Friday (excluding public holidays),
|
||||
06:30–09:30 and 16:00–19:00.
|
||||
Off-peak (£3.00): all other times, weekends, and public holidays.
|
||||
"""
|
||||
if depart_dt.date() in _ENGLAND_HOLIDAYS or depart_dt.weekday() >= 5:
|
||||
return CIRCLE_LINE_OFF_PEAK
|
||||
t = depart_dt.time()
|
||||
if _AM_PEAK_START <= t < _AM_PEAK_END or _PM_PEAK_START <= t < _PM_PEAK_END:
|
||||
return CIRCLE_LINE_PEAK
|
||||
return CIRCLE_LINE_OFF_PEAK
|
||||
|
|
@ -5,6 +5,7 @@ Combine GWR station→Paddington trains with Eurostar St Pancras→destination t
|
|||
from datetime import datetime, timedelta
|
||||
|
||||
import circle_line
|
||||
from tfl_fare import circle_line_fare
|
||||
|
||||
MIN_CONNECTION_MINUTES = 50
|
||||
MAX_CONNECTION_MINUTES = 110
|
||||
|
|
@ -31,7 +32,11 @@ def _circle_line_services(arrive_paddington: datetime) -> list[dict]:
|
|||
)
|
||||
services = circle_line.upcoming_services(earliest_board, count=2)
|
||||
return [
|
||||
{"depart": dep.strftime(TIME_FMT), "arrive_kx": arr.strftime(TIME_FMT)}
|
||||
{
|
||||
"depart": dep.strftime(TIME_FMT),
|
||||
"arrive_kx": arr.strftime(TIME_FMT),
|
||||
"fare": circle_line_fare(dep),
|
||||
}
|
||||
for dep, arr in services
|
||||
]
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue