From 7acd7c59c5f3816c09eb5ff950cf937e79cee591 Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Sat, 16 Dec 2023 20:35:12 -0500 Subject: [PATCH 01/53] Using Gobble data --- common/constants/dates.ts | 2 +- server/chalicelib/parallel.py | 1 + server/chalicelib/s3.py | 18 +++++++++++++----- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/common/constants/dates.ts b/common/constants/dates.ts index 1893f7663..fc7f1062d 100644 --- a/common/constants/dates.ts +++ b/common/constants/dates.ts @@ -35,7 +35,7 @@ export const THREE_MONTHS_AGO_STRING = TODAY.subtract(90, 'days').format(DATE_FO const OVERVIEW_TRAIN_MIN_DATE = '2016-02-01'; const TRAIN_MIN_DATE = '2016-01-15'; const BUS_MIN_DATE = '2018-08-01'; -export const BUS_MAX_DATE = '2023-10-31'; +export const BUS_MAX_DATE = '2023-12-31'; const BUS_MAX_DAY = dayjs(BUS_MAX_DATE); export const BUS_MAX_DATE_MINUS_ONE_WEEK = dayjs(BUS_MAX_DATE) .subtract(7, 'days') diff --git a/server/chalicelib/parallel.py b/server/chalicelib/parallel.py index 7c1c14e69..27d6b7139 100644 --- a/server/chalicelib/parallel.py +++ b/server/chalicelib/parallel.py @@ -29,6 +29,7 @@ def month_range(start, end): # This is kinda funky, but is stil simpler than other approaches # pandas won't generate a monthly date_range that includes Jan and Feb for Jan31-Feb1 e.g. # So we generate a daily date_range and then resample it down (summing 0s as a no-op in the process) so it aligns. + # TODO: ^ Is this still true? It doesn't seem to be in testing. dates = pd.date_range(start, end, freq="1D", inclusive="both") series = pd.Series(0, index=dates) months = series.resample("1M").sum().index diff --git a/server/chalicelib/s3.py b/server/chalicelib/s3.py index 042ce13a4..1957512e4 100644 --- a/server/chalicelib/s3.py +++ b/server/chalicelib/s3.py @@ -32,12 +32,16 @@ def is_bus(stop_id): return ("-0-" in stop_id) or ("-1-" in stop_id) -def download_one_event_file(date, stop_id): +def download_one_event_file(date, stop_id, live=False): """As advertised: single event file from s3""" - year, month = date.year, date.month + year, month, day = date.year, date.month, date.day - folder = "monthly-bus-data" if is_bus(stop_id) else "monthly-data" - key = f"Events/{folder}/{stop_id}/Year={year}/Month={month}/events.csv.gz" + if live: + folder = "daily-bus-data" if is_bus(stop_id) else "daily-data" + key = f"Events-live/{folder}/{stop_id}/Year={year}/Month={month}/Day={day}/events.csv.gz" + else: + folder = "monthly-bus-data" if is_bus(stop_id) else "monthly-data" + key = f"Events/{folder}/{stop_id}/Year={year}/Month={month}/events.csv.gz" # Download events from S3 try: @@ -47,6 +51,8 @@ def download_one_event_file(date, stop_id): if ex.response["Error"]["Code"] == "NoSuchKey": # raise Exception(f"Data not available on S3 for key {key} ") from None print(f"WARNING: No data available on S3 for key: {key}") + if live == False: + return download_one_event_file(date, stop_id, live=True) return [] else: raise @@ -68,7 +74,9 @@ def parallel_download_events(datestop): def download_events(sdate, edate, stops): - datestops = itertools.product(parallel.month_range(sdate, edate), stops) + # This used to be month_range but updated to date_range to support live ranges + # If something breaks, this may be why + datestops = itertools.product(parallel.date_range(sdate, edate), stops) result = parallel_download_events(datestops) result = filter(lambda row: sdate.strftime("%Y-%m-%d") <= row["service_date"] <= edate.strftime("%Y-%m-%d"), result) return sorted(result, key=lambda row: row["event_time"]) From 06fda873a7c07499957e7add42705ae5550de827 Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Sun, 17 Dec 2023 19:16:56 -0500 Subject: [PATCH 02/53] Adding commuter rail data to data dashboard --- common/components/controls/ControlPanel.tsx | 12 +- .../controls/MobileControlPanel.tsx | 6 +- common/components/inputs/StationSelector.tsx | 5 +- .../nav/CommuterRailRouteSelection.tsx | 22 ++- common/components/nav/MenuDropdown.tsx | 21 +- common/components/nav/NavSection.tsx | 10 - common/components/nav/NavSectionHeader.tsx | 9 - .../widgets/StationSelectorWidget.tsx | 11 +- .../constants/cr_constants/cr-fitchburg.json | 181 ++++++++++++++++++ .../constants/cr_constants/cr-franklin.json | 181 ++++++++++++++++++ common/constants/cr_constants/cr-lowell.json | 81 ++++++++ common/constants/dashboardTabs.ts | 11 +- common/constants/dates.ts | 12 +- common/constants/pages.ts | 6 +- common/constants/stations.ts | 12 +- common/layouts/DashboardLayout.tsx | 9 +- common/state/dateStore.ts | 2 +- common/state/defaults/dateDefaults.ts | 17 +- common/types/lines.ts | 33 +++- common/types/router.ts | 5 +- common/utils/middleware.ts | 2 +- common/utils/router.tsx | 37 +++- common/utils/stations.ts | 23 ++- modules/dashboard/DesktopHeader.tsx | 12 +- modules/navigation/SideNavigation.tsx | 2 + pages/[line]/index.tsx | 4 +- pages/[line]/ridership.tsx | 4 +- pages/[line]/trips/multi/index.tsx | 4 +- pages/[line]/trips/single/index.tsx | 4 +- server/bus/gen_bus_data.sh | 2 +- server/scripts/generate_line_file.py | 30 +++ styles/dashboard.css | 5 + 32 files changed, 689 insertions(+), 86 deletions(-) delete mode 100644 common/components/nav/NavSection.tsx delete mode 100644 common/components/nav/NavSectionHeader.tsx create mode 100644 common/constants/cr_constants/cr-fitchburg.json create mode 100644 common/constants/cr_constants/cr-franklin.json create mode 100644 common/constants/cr_constants/cr-lowell.json create mode 100644 server/scripts/generate_line_file.py diff --git a/common/components/controls/ControlPanel.tsx b/common/components/controls/ControlPanel.tsx index 78b740274..db1d48bc6 100644 --- a/common/components/controls/ControlPanel.tsx +++ b/common/components/controls/ControlPanel.tsx @@ -1,7 +1,7 @@ import React from 'react'; import classNames from 'classnames'; import { lineColorBorder } from '../../styles/general'; -import type { BusRoute, Line } from '../../types/lines'; +import type { BusRoute, CommuterRailRoute, Line } from '../../types/lines'; import type { DateStoreSection } from '../../constants/pages'; import { StationSelectorWidget } from '../widgets/StationSelectorWidget'; import { DateControl } from './DateControl'; @@ -9,10 +9,16 @@ import { DateControl } from './DateControl'; interface ControlPanelProps { dateStoreSection: DateStoreSection; busRoute: BusRoute | undefined; + crRoute: CommuterRailRoute | undefined; line: Line | undefined; } -export const ControlPanel: React.FC = ({ dateStoreSection, line, busRoute }) => { +export const ControlPanel: React.FC = ({ + dateStoreSection, + line, + busRoute, + crRoute, +}) => { const getControls = () => { if ((dateStoreSection === 'singleTrips' || dateStoreSection === 'multiTrips') && line) { return ( @@ -21,7 +27,7 @@ export const ControlPanel: React.FC = ({ dateStoreSection, li dateStoreSection={dateStoreSection} queryType={dateStoreSection === 'singleTrips' ? 'single' : 'range'} /> - + ); } diff --git a/common/components/controls/MobileControlPanel.tsx b/common/components/controls/MobileControlPanel.tsx index 52509ca26..ca4111291 100644 --- a/common/components/controls/MobileControlPanel.tsx +++ b/common/components/controls/MobileControlPanel.tsx @@ -1,6 +1,6 @@ import React from 'react'; import classNames from 'classnames'; -import type { BusRoute, Line } from '../../types/lines'; +import type { BusRoute, CommuterRailRoute, Line } from '../../types/lines'; import type { DateStoreSection } from '../../constants/pages'; import { lineColorBackground } from '../../styles/general'; import { StationSelectorWidget } from '../widgets/StationSelectorWidget'; @@ -9,6 +9,7 @@ import { DateControl } from './DateControl'; interface MobileControlPanelProps { dateStoreSection: DateStoreSection; busRoute: BusRoute | undefined; + crRoute: CommuterRailRoute | undefined; line: Line | undefined; } @@ -16,6 +17,7 @@ export const MobileControlPanel: React.FC = ({ dateStoreSection, line, busRoute, + crRoute, }) => { const singleDate = dateStoreSection === 'singleTrips'; const getControls = () => { @@ -34,7 +36,7 @@ export const MobileControlPanel: React.FC = ({ lineColorBackground[line ?? 'DEFAULT'] )} > - + ); diff --git a/common/components/inputs/StationSelector.tsx b/common/components/inputs/StationSelector.tsx index 43e85dbf1..1c9149a3c 100644 --- a/common/components/inputs/StationSelector.tsx +++ b/common/components/inputs/StationSelector.tsx @@ -30,16 +30,17 @@ export const StationSelector: React.FC = ({ const { line, lineShort, - query: { busRoute }, + query: { busRoute, crRoute }, } = useDelimitatedRoute(); const mdBreakpoint = useBreakpoint('md'); const station = type === 'from' ? fromStation : toStation; - const stationOptions = optionsForField(type, lineShort, fromStation, busRoute); + const stationOptions = optionsForField(type, lineShort, fromStation, busRoute, crRoute); const branchLabelWidth = { 'line-red': 'w-8', 'line-green': 'w-12', DEFAULT: 'w-0', }; + return ( {({ open }) => ( diff --git a/common/components/nav/CommuterRailRouteSelection.tsx b/common/components/nav/CommuterRailRouteSelection.tsx index 8e32c7a6c..d5734b8bc 100644 --- a/common/components/nav/CommuterRailRouteSelection.tsx +++ b/common/components/nav/CommuterRailRouteSelection.tsx @@ -5,24 +5,26 @@ import { ChevronUpDownIcon } from '@heroicons/react/20/solid'; import { useRouter } from 'next/navigation'; import React, { Fragment } from 'react'; import { getCommuterRailRoutes } from '../../constants/stations'; -import { getBusRouteSelectionItemHref, useDelimitatedRoute } from '../../utils/router'; +import { getCommuterRailRouteSelectionItemHref, useDelimitatedRoute } from '../../utils/router'; +import { COMMUTER_RAIL_LINE_NAMES } from '../../types/lines'; -// TODO: This is a duplicate of common/components/nav/BusRouteSelection.tsx export const CommuterRailRouteSelection: React.FC = () => { const route = useDelimitatedRoute(); const router = useRouter(); const crRoutes = getCommuterRailRoutes(); - const selected = route.query.busRoute; + const selected = route.query.crRoute; return ( -
+
router.push(getBusRouteSelectionItemHref(key, route))} + onChange={(key) => router.push(getCommuterRailRouteSelectionItemHref(key, route))} >
- - {selected} + + + {selected && COMMUTER_RAIL_LINE_NAMES[selected]} + @@ -39,7 +41,7 @@ export const CommuterRailRouteSelection: React.FC = () => { key={personIdx} className={({ active }) => `relative cursor-pointer select-none py-2 pl-10 pr-4 ${ - active ? 'bg-amber-100 text-amber-900' : 'text-gray-900' + active ? 'bg-fuchsia-100 text-fuchsia-900' : 'text-gray-900' }` } value={crRoute} @@ -49,10 +51,10 @@ export const CommuterRailRouteSelection: React.FC = () => { - {crRoute} + {COMMUTER_RAIL_LINE_NAMES[crRoute]} {selected ? ( - + = ({ line, route, childre } }, [line]); + const href = React.useMemo(() => { + switch (line) { + case 'line-bus': + return `/bus/trips/single?busRoute=1&date=${BUS_DEFAULTS.singleTripConfig.date}`; + case 'line-commuter-rail': + return `/commuter-rail/trips/single?crRoute=cr-lowell&date=${COMMUTER_RAIL_DEFAULTS.singleTripConfig.date}`; + default: + return getLineSelectionItemHref(line, route); + } + }, [line, route]); + return (
- +
= ({ title, content }) => { - return
{content}
; -}; diff --git a/common/components/nav/NavSectionHeader.tsx b/common/components/nav/NavSectionHeader.tsx deleted file mode 100644 index 0396d1f54..000000000 --- a/common/components/nav/NavSectionHeader.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import React from 'react'; - -interface NavSectionHeaderProps { - title: string; -} - -export const NavSectionHeader: React.FC = ({ title }) => { - return

{title}

; -}; diff --git a/common/components/widgets/StationSelectorWidget.tsx b/common/components/widgets/StationSelectorWidget.tsx index 2bbc143d2..6af3206b3 100644 --- a/common/components/widgets/StationSelectorWidget.tsx +++ b/common/components/widgets/StationSelectorWidget.tsx @@ -11,23 +11,28 @@ import { optionsStation, stopIdsForStations, } from '../../utils/stations'; -import type { BusRoute, Line } from '../../types/lines'; +import type { BusRoute, CommuterRailRoute, Line } from '../../types/lines'; import { LINE_OBJECTS } from '../../constants/lines'; import type { Station } from '../../types/stations'; interface StationSelectorWidgetProps { line: Line; busRoute: BusRoute | undefined; + crRoute: CommuterRailRoute | undefined; } -export const StationSelectorWidget: React.FC = ({ line, busRoute }) => { +export const StationSelectorWidget: React.FC = ({ + line, + busRoute, + crRoute, +}) => { const updateQueryParams = useUpdateQuery(); const lineShort = LINE_OBJECTS[line].short; const { query: { from, to }, } = useDelimitatedRoute(); - const stations = optionsStation(lineShort, busRoute); + const stations = optionsStation(lineShort, busRoute, crRoute); const toStation = to ? getParentStationForStopId(to) : stations?.[stations.length - 2]; const fromStation = from ? getParentStationForStopId(from) : stations?.[1]; React.useEffect(() => { diff --git a/common/constants/cr_constants/cr-fitchburg.json b/common/constants/cr_constants/cr-fitchburg.json new file mode 100644 index 000000000..549661f1f --- /dev/null +++ b/common/constants/cr_constants/cr-fitchburg.json @@ -0,0 +1,181 @@ +{ + "cr-fitchburg": { + "type": "commuter-rail", + "direction": { + "0": "outbound", + "1": "inbound" + }, + "stations": [ + { + "stop_name": "Wachusett", + "station": "place-FR-3338", + "branches": null, + "order": 1, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "Fitchburg", + "station": "place-FR-0494", + "branches": null, + "order": 2, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "North Leominster", + "station": "place-FR-0451", + "branches": null, + "order": 3, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "Shirley", + "station": "place-FR-0394", + "branches": null, + "order": 4, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "Ayer", + "station": "place-FR-0361", + "branches": null, + "order": 5, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "Littleton/Route 495", + "station": "place-FR-0301", + "branches": null, + "order": 6, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "South Acton", + "station": "place-FR-0253", + "branches": null, + "order": 7, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "West Concord", + "station": "place-FR-0219", + "branches": null, + "order": 8, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "Concord", + "station": "place-FR-0201", + "branches": null, + "order": 9, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "Lincoln", + "station": "place-FR-0167", + "branches": null, + "order": 10, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "Kendal Green", + "station": "place-FR-0132", + "branches": null, + "order": 11, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "Brandeis/Roberts", + "station": "place-FR-0115", + "branches": null, + "order": 12, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "Waltham", + "station": "place-FR-0098", + "branches": null, + "order": 13, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "Waverley", + "station": "place-FR-0074", + "branches": null, + "order": 14, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "Belmont", + "station": "place-FR-0064", + "branches": null, + "order": 15, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "Porter", + "station": "place-portr", + "branches": null, + "order": 16, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "North Station", + "station": "place-north", + "branches": null, + "order": 17, + "stops": { + "0": [], + "1": [] + } + } + ] + } +} diff --git a/common/constants/cr_constants/cr-franklin.json b/common/constants/cr_constants/cr-franklin.json new file mode 100644 index 000000000..2484ceb5c --- /dev/null +++ b/common/constants/cr_constants/cr-franklin.json @@ -0,0 +1,181 @@ +{ + "cr-franklin": { + "type": "commuter-rail", + "direction": { + "0": "outbound", + "1": "inbound" + }, + "stations": [ + { + "stop_name": "Forge Park/495", + "station": "place-FB-0303", + "branches": null, + "order": 1, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "Franklin", + "station": "place-FB-0275", + "branches": null, + "order": 2, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "Norfolk", + "station": "place-FB-0230", + "branches": null, + "order": 3, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "Foxboro", + "station": "place-FS-0049", + "branches": null, + "order": 4, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "Walpole", + "station": "place-FB-0191", + "branches": null, + "order": 5, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "Windsor Gardens", + "station": "place-FB-0166", + "branches": null, + "order": 6, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "Norwood Central", + "station": "place-FB-0148", + "branches": null, + "order": 7, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "Norwood Depot", + "station": "place-FB-0143", + "branches": null, + "order": 8, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "Islington", + "station": "place-FB-0125", + "branches": null, + "order": 9, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "Dedham Corporate Center", + "station": "place-FB-0118", + "branches": null, + "order": 10, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "Endicott", + "station": "place-FB-0109", + "branches": null, + "order": 11, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "Readville", + "station": "place-DB-0095", + "branches": null, + "order": 12, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "Forest Hills", + "station": "place-forhl", + "branches": null, + "order": 13, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "Ruggles", + "station": "place-rugg", + "branches": null, + "order": 14, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "Back Bay", + "station": "place-bbsta", + "branches": null, + "order": 15, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "South Station", + "station": "place-sstat", + "branches": null, + "order": 16, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "Hyde Park", + "station": "place-NEC-2203", + "branches": null, + "order": 17, + "stops": { + "0": [], + "1": [] + } + } + ] + } +} \ No newline at end of file diff --git a/common/constants/cr_constants/cr-lowell.json b/common/constants/cr_constants/cr-lowell.json new file mode 100644 index 000000000..5ba1d898f --- /dev/null +++ b/common/constants/cr_constants/cr-lowell.json @@ -0,0 +1,81 @@ +{ + "cr-lowell": { + "type": "commuter-rail", + "direction": { + "0": "outbound", + "1": "inbound" + }, + "stations": [ + { + "stop_name": "Lowell", + "station": "place-NHRML-0254", + "branches": null, + "order": 1, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "North Billerica", + "station": "place-NHRML-0218", + "branches": null, + "order": 2, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "Wilmington", + "station": "place-NHRML-0152", + "branches": null, + "order": 3, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "Anderson/Woburn", + "station": "place-NHRML-0127", + "branches": null, + "order": 4, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "Wedgemere", + "station": "place-NHRML-0073", + "branches": null, + "order": 5, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "West Medford", + "station": "place-NHRML-0055", + "branches": null, + "order": 6, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "North Station", + "station": "place-north", + "branches": null, + "order": 7, + "stops": { + "0": [], + "1": [] + } + } + ] + } +} diff --git a/common/constants/dashboardTabs.ts b/common/constants/dashboardTabs.ts index 8e4084340..532f94b31 100644 --- a/common/constants/dashboardTabs.ts +++ b/common/constants/dashboardTabs.ts @@ -1,7 +1,5 @@ -import { BUS_DEFAULTS } from '../state/defaults/dateDefaults'; -import type { QueryParams } from '../types/router'; - -export type Tab = 'Subway' | 'Bus' | 'System'; +import { BUS_DEFAULTS, COMMUTER_RAIL_DEFAULTS } from '../state/defaults/dateDefaults'; +import type { QueryParams, Tab } from '../types/router'; export const DASHBOARD_TABS: { [key in Tab]: { name: Tab; path: string; disabled?: boolean; query?: QueryParams }; @@ -13,4 +11,9 @@ export const DASHBOARD_TABS: { path: '/bus/trips/single', query: { busRoute: '1', date: BUS_DEFAULTS.singleTripConfig.date }, }, + 'Commuter Rail': { + name: 'Commuter Rail', + path: '/commuter-rail', + query: { crRoute: 'cr-lowell', date: COMMUTER_RAIL_DEFAULTS.singleTripConfig.date }, + }, }; diff --git a/common/constants/dates.ts b/common/constants/dates.ts index 1893f7663..c42fdfde4 100644 --- a/common/constants/dates.ts +++ b/common/constants/dates.ts @@ -8,7 +8,7 @@ import type { DateSelectionDefaultOptions, SingleDateParams, } from '../components/inputs/DateSelection/types/DateSelectionTypes'; -import type { Tab } from './dashboardTabs'; +import type { Tab } from '../types/router'; dayjs.extend(utc); dayjs.extend(timezone); @@ -72,6 +72,14 @@ export const FLAT_PICKER_OPTIONS: { altFormat: 'M j, Y', dateFormat: 'Y-m-d', }, + 'Commuter Rail': { + enableTime: false, + minDate: TRAIN_MIN_DATE, + maxDate: TODAY_STRING, + altInput: true, + altFormat: 'M j, Y', + dateFormat: 'Y-m-d', + }, }; const SINGLE_RAPID_PRESETS: { @@ -143,6 +151,7 @@ export const SINGLE_PRESETS: { Subway: SINGLE_RAPID_PRESETS, Bus: SINGLE_BUS_PRESETS, System: SINGLE_RAPID_PRESETS, + 'Commuter Rail': SINGLE_RAPID_PRESETS, }; const RANGE_RAPID_PRESETS: { @@ -265,6 +274,7 @@ export const RANGE_PRESETS: { Subway: RANGE_RAPID_PRESETS, Bus: RANGE_BUS_PRESETS, System: RANGE_RAPID_PRESETS, + 'Commuter Rail': RANGE_RAPID_PRESETS, }; export type DatePresetKey = diff --git a/common/constants/pages.ts b/common/constants/pages.ts index 69f7c7950..b31acde31 100644 --- a/common/constants/pages.ts +++ b/common/constants/pages.ts @@ -66,7 +66,7 @@ export const ALL_PAGES: PageMap = { path: '/trips/single', name: 'Trips', title: 'Trips', - lines: ['line-red', 'line-blue', 'line-green', 'line-orange', 'line-bus'], + lines: ['line-red', 'line-blue', 'line-green', 'line-orange', 'line-bus', 'line-commuter-rail'], icon: faMapLocationDot, hasStationStore: true, dateStoreSection: 'singleTrips', @@ -76,7 +76,7 @@ export const ALL_PAGES: PageMap = { path: '/trips/multi', name: 'Multi-day trips', title: 'Multi-day trips', - lines: ['line-red', 'line-blue', 'line-green', 'line-orange', 'line-bus'], + lines: ['line-red', 'line-blue', 'line-green', 'line-orange', 'line-bus', 'line-commuter-rail'], icon: faCalendar, dateStoreSection: 'multiTrips', hasStationStore: true, @@ -141,7 +141,7 @@ export const ALL_PAGES: PageMap = { key: 'ridership', path: '/ridership', name: 'Ridership', - lines: ['line-red', 'line-blue', 'line-green', 'line-orange', 'line-bus'], + lines: ['line-red', 'line-blue', 'line-green', 'line-orange', 'line-bus', 'line-commuter-rail'], icon: faUsers, dateStoreSection: 'line', }, diff --git a/common/constants/stations.ts b/common/constants/stations.ts index 39f1c9466..66b6075b0 100644 --- a/common/constants/stations.ts +++ b/common/constants/stations.ts @@ -16,6 +16,10 @@ import bus_77 from './bus_constants/77.json'; import bus_111 from './bus_constants/111.json'; import bus_114_116_117 from './bus_constants/114-116-117.json'; +import cr_lowell from './cr_constants/cr-lowell.json'; +import cr_fitchburg from './cr_constants/cr-fitchburg.json'; +import cr_franklin from './cr_constants/cr-franklin.json'; + export const rtStations: { [key in Exclude]: LineMap } = stations_json; @@ -36,9 +40,13 @@ export const busStations: { [key: string]: LineMap } = { ...bus_114_116_117, }; -export const commuterRailStations: { [key: string]: LineMap } = {}; +export const commuterRailStations: { [key: string]: LineMap } = { + ...cr_lowell, + ...cr_fitchburg, + ...cr_franklin, +}; -export const stations = { ...rtStations, Bus: busStations }; +export const stations = { ...rtStations, Bus: busStations, 'Commuter Rail': commuterRailStations }; export const getBusRoutes = (): string[] => { return Object.keys(busStations); diff --git a/common/layouts/DashboardLayout.tsx b/common/layouts/DashboardLayout.tsx index 5e2938b20..6a5872660 100644 --- a/common/layouts/DashboardLayout.tsx +++ b/common/layouts/DashboardLayout.tsx @@ -14,7 +14,7 @@ interface DashboardLayoutProps { export const DashboardLayout: React.FC = ({ children }) => { const isMobile = !useBreakpoint('md'); const { line, page, query, tab } = useDelimitatedRoute(); - const { busRoute } = query; + const { busRoute, crRoute } = query; const dateStoreSection = page ? ALL_PAGES[page]?.dateStoreSection : undefined; const showControlParams = dateStoreSection && (line || tab === 'System') && dateStoreSection !== 'today'; @@ -30,7 +30,12 @@ export const DashboardLayout: React.FC = ({ children }) =>
{isMobile && showControlParams && ( - + )}
); diff --git a/common/state/dateStore.ts b/common/state/dateStore.ts index 3ced87efe..5154dbf00 100644 --- a/common/state/dateStore.ts +++ b/common/state/dateStore.ts @@ -1,6 +1,6 @@ import { create } from 'zustand'; import { OVERVIEW_OPTIONS, TODAY_STRING } from '../constants/dates'; -import type { Tab } from '../constants/dashboardTabs'; +import type { Tab } from '../types/router'; import type { LineSectionParams, MultiTripsSectionParams, diff --git a/common/state/defaults/dateDefaults.ts b/common/state/defaults/dateDefaults.ts index 11b919f97..9f163bda5 100644 --- a/common/state/defaults/dateDefaults.ts +++ b/common/state/defaults/dateDefaults.ts @@ -1,4 +1,3 @@ -import type { Tab } from '../../constants/dashboardTabs'; import type { DateStoreSection } from '../../constants/pages'; import type { DateStoreConfiguration } from '../types/dateStoreTypes'; import { @@ -11,6 +10,7 @@ import { TODAY_SERVICE_STARTED, } from '../../constants/dates'; import type { WithOptional } from '../../types/general'; +import type { Tab } from '../../types/router'; const SUBWAY_DEFAULTS: Partial = { lineConfig: { startDate: OVERVIEW_OPTIONS.year.startDate, endDate: TODAY_STRING }, @@ -36,6 +36,20 @@ export const BUS_DEFAULTS: WithOptional = { + lineConfig: { startDate: OVERVIEW_OPTIONS.year.startDate, endDate: TODAY_STRING }, + multiTripConfig: { + startDate: ONE_WEEK_AGO_STRING, + endDate: TODAY_STRING, + }, + singleTripConfig: { + date: TODAY_SERVICE_STARTED ? TODAY_STRING : YESTERDAY_STRING, + }, +}; + const SYSTEM_DEFAULTS: Partial = { systemConfig: { startDate: OVERVIEW_OPTIONS.year.startDate, endDate: TODAY_STRING }, }; @@ -44,6 +58,7 @@ const TAB_DATE_MAP: { [key in Tab]: Partial } = { Subway: SUBWAY_DEFAULTS, Bus: BUS_DEFAULTS, System: SYSTEM_DEFAULTS, + 'Commuter Rail': COMMUTER_RAIL_DEFAULTS, }; export const getDefaultDates = (dateStoreSection: DateStoreSection, tab: Tab) => { diff --git a/common/types/lines.ts b/common/types/lines.ts index d2fe41a74..59ab197c9 100644 --- a/common/types/lines.ts +++ b/common/types/lines.ts @@ -7,6 +7,8 @@ export type Line = | 'line-commuter-rail'; export type LineShort = 'Red' | 'Orange' | 'Green' | 'Blue' | 'Bus' | 'Commuter Rail'; export type LinePath = 'red' | 'orange' | 'green' | 'blue' | 'bus' | 'commuter-rail'; + +/** All currently available Bus Routes */ export type BusRoute = | '1' | '15' @@ -23,6 +25,14 @@ export type BusRoute = | '111' | '114/116/117'; +/** TODO: Expand list to all lines */ +export type CommuterRailRoute = + | 'cr-fitchburg' + | 'cr-franklin' + | 'cr-greenbush' + | 'cr-haverhill' + | 'cr-lowell'; + export type LineMetadata = { name: string; color: string; @@ -54,7 +64,7 @@ export const HEAVY_RAIL_LINES: Line[] = ['line-red', 'line-orange', 'line-blue'] export const LANDING_RAIL_LINES: Line[] = ['line-red', 'line-orange', 'line-blue', 'line-green']; export const RAIL_LINES = ['red', 'orange', 'green', 'blue']; -export const BUS_ROUTES = [ +export const BUS_ROUTES: BusRoute[] = [ '1', '15', '22', @@ -71,6 +81,21 @@ export const BUS_ROUTES = [ '114/116/117', ]; +export const COMMUTER_RAIL_ROUTES: CommuterRailRoute[] = [ + 'cr-fitchburg', + 'cr-franklin', + 'cr-greenbush', + 'cr-haverhill', + 'cr-lowell', +]; +export const COMMUTER_RAIL_LINE_NAMES: { [line in CommuterRailRoute]: string } = { + 'cr-fitchburg': 'Fitchburg Line', + 'cr-franklin': 'Franklin Line', + 'cr-greenbush': 'Greenbush Line', + 'cr-haverhill': 'Haverhill Line', + 'cr-lowell': 'Lowell Line', +}; + export const ALL_LINE_PATHS = RAIL_LINES.map((line) => { return { params: { @@ -84,3 +109,9 @@ export const BUS_PATH = { line: 'bus', }, }; + +export const COMMUTER_RAIL_PATH = { + params: { + line: 'commuter-rail', + }, +}; diff --git a/common/types/router.ts b/common/types/router.ts index 6c2ce32eb..684cbf73c 100644 --- a/common/types/router.ts +++ b/common/types/router.ts @@ -1,6 +1,6 @@ import type { OverviewDatePresetKey } from '../constants/dates'; import type { Page } from '../constants/pages'; -import type { BusRoute, Line, LinePath, LineShort } from './lines'; +import type { BusRoute, CommuterRailRoute, Line, LinePath, LineShort } from './lines'; export interface Route { line: Line | undefined; @@ -19,6 +19,7 @@ export type QueryParams = { endDate?: string; date?: string; busRoute?: BusRoute; + crRoute?: CommuterRailRoute; view?: OverviewDatePresetKey; to?: string; from?: string; @@ -26,4 +27,4 @@ export type QueryParams = { export type QueryTypeOptions = 'single' | 'range'; -export type Tab = 'Bus' | 'Subway' | 'System'; +export type Tab = 'Bus' | 'Subway' | 'Commuter Rail' | 'System'; diff --git a/common/utils/middleware.ts b/common/utils/middleware.ts index 63b55680b..f30cbc6e9 100644 --- a/common/utils/middleware.ts +++ b/common/utils/middleware.ts @@ -9,7 +9,7 @@ const getBusOrLine = ( ): { type: 'rail' | 'bus'; value: LinePath | BusRoute } | undefined => { if (RAIL_LINES.includes(lineString.toLowerCase())) return { type: 'rail', value: lineString.toLowerCase() as LinePath }; - if (BUS_ROUTES.includes(lineString.toString())) + if (BUS_ROUTES.includes(lineString.toString() as BusRoute)) return { type: 'bus', value: lineString as BusRoute }; }; diff --git a/common/utils/router.tsx b/common/utils/router.tsx index 4762a49b8..81dbb783d 100644 --- a/common/utils/router.tsx +++ b/common/utils/router.tsx @@ -1,5 +1,5 @@ import type { ParsedUrlQuery } from 'querystring'; -import { capitalize, isEqual, pickBy } from 'lodash'; +import { isEqual, pickBy, startCase, toLower } from 'lodash'; import { useRouter } from 'next/router'; import { useCallback } from 'react'; import type { Line, LinePath, LineShort } from '../types/lines'; @@ -15,12 +15,13 @@ import { useStationStore } from '../state/stationStore'; import { useDateStore } from '../state/dateStore'; import type { DateStore } from '../state/dateStore'; -const linePathToKeyMap: Record = { +const linePathToKeyMap: Record = { red: 'line-red', orange: 'line-orange', green: 'line-green', blue: 'line-blue', bus: 'line-bus', + 'commuter-rail': 'line-commuter-rail', }; const getParams = (params: ParsedUrlQuery | QueryParams) => { @@ -54,11 +55,13 @@ const getPage = (pathItems: string[], tab: Tab): string => { return pageArray[0]; }; -const getTab = (path: string) => { +const getTab = (path: LinePath) => { if (RAIL_LINES.includes(path)) { return 'Subway'; } else if (path === 'bus') { return 'Bus'; + } else if (path === 'commuter-rail') { + return 'Commuter Rail'; } else { return 'System'; } @@ -69,14 +72,14 @@ export const useDelimitatedRoute = (): Route => { const path = router.asPath.split('?'); const pathItems = path[0].split('/'); const queryParams = router.query; - const tab = getTab(pathItems[1] ?? 'System'); + const tab = getTab((pathItems[1] as LinePath) ?? 'System'); const page = getPage(pathItems, tab) as Page; const newParams = getParams(queryParams); return { line: linePathToKeyMap[pathItems[1]], linePath: pathItems[1] as LinePath, //TODO: Remove as - lineShort: capitalize(pathItems[1]) as LineShort, //TODO: Remove as + lineShort: startCase(toLower(pathItems[1]).replace('-', ' ')) as LineShort, //TODO: Remove as page: page, tab, query: router.isReady ? newParams : {}, @@ -180,6 +183,25 @@ export const getBusRouteSelectionItemHref = (newRoute: string, route: Route): st return href; }; +export const getCommuterRailRouteSelectionItemHref = (newRoute: string, route: Route): string => { + const { query, page } = route; + const currentPage = ALL_PAGES[page] ?? ALL_PAGES['singleTrips']; + const currentPath = currentPage.path; + const validPage = currentPage.lines.includes('line-commuter-rail'); + if (newRoute === route.query.crRoute || !validPage) { + return `/commuter-rail/trips/single?crRoute=${newRoute}`; + } + delete query.from; + delete query.to; + const queryParams = query + ? new URLSearchParams(Object.entries(query).filter(([key]) => key !== 'crRoute')) + : new URLSearchParams(); + queryParams.append('crRoute', newRoute); + let href = `/commuter-rail${currentPath}`; + href += `?${queryParams.toString() ?? ''}`; + return href; +}; + export const useGenerateHref = () => { const dateStore = useDateStore(); const stationStore = useStationStore(); @@ -242,6 +264,10 @@ const getBusRouteQueryParam = (query: QueryParams) => { if (query.busRoute) return { busRoute: query.busRoute }; }; +const getCRRouteQueryParam = (query: QueryParams) => { + if (query.crRoute) return { crRoute: query.crRoute }; +}; + const getStationQueryParams = ( currentPage: PageMetadata | undefined, newPage: PageMetadata, @@ -266,6 +292,7 @@ const getQueryParams = ( ...getStationQueryParams(currentPage, newPage, query, stationStore), ...getDateQueryParams(currentPage, newPage, query, dateStore), ...getBusRouteQueryParam(query), + ...getCRRouteQueryParam(query), }; }; diff --git a/common/utils/stations.ts b/common/utils/stations.ts index f6d7bb987..d81a43144 100644 --- a/common/utils/stations.ts +++ b/common/utils/stations.ts @@ -1,4 +1,4 @@ -import type { Line, LineShort } from '../types/lines'; +import type { BusRoute, CommuterRailRoute, Line, LineShort } from '../types/lines'; import { isLineMap, type Station } from '../types/stations'; import type { Location } from '../types/charts'; import type { Direction } from '../types/dataPoints'; @@ -8,13 +8,14 @@ export const optionsForField = ( type: 'from' | 'to', line: LineShort, fromStation: Station | null, - busRoute?: string + busRoute?: BusRoute, + crRoute?: CommuterRailRoute ) => { if (type === 'from') { - return optionsStation(line, busRoute); + return optionsStation(line, busRoute, crRoute); } if (type === 'to') { - return optionsStation(line, busRoute)?.filter((entry) => { + return optionsStation(line, busRoute, crRoute)?.filter((entry) => { if (fromStation && fromStation.branches && entry.branches) { return entry.branches.some((entryBranch) => fromStation.branches?.includes(entryBranch)); } @@ -23,7 +24,11 @@ export const optionsForField = ( } }; -export const optionsStation = (line: LineShort, busRoute?: string): Station[] | undefined => { +export const optionsStation = ( + line: LineShort, + busRoute?: BusRoute, + crRoute?: CommuterRailRoute +): Station[] | undefined => { if (!line || !stations[line]) { return undefined; } @@ -36,6 +41,14 @@ export const optionsStation = (line: LineShort, busRoute?: string): Station[] | return stations[line][busRoute].stations.sort((a, b) => a.order - b.order); } + if (line === 'Commuter Rail') { + if (!crRoute || !stations[line][crRoute]) { + return undefined; + } + + return stations[line][crRoute].stations.sort((a, b) => a.order - b.order); + } + return stations[line].stations.sort((a, b) => a.order - b.order); }; diff --git a/modules/dashboard/DesktopHeader.tsx b/modules/dashboard/DesktopHeader.tsx index ac7a8c54b..e5f2a804b 100644 --- a/modules/dashboard/DesktopHeader.tsx +++ b/modules/dashboard/DesktopHeader.tsx @@ -5,12 +5,13 @@ import { useDelimitatedRoute } from '../../common/utils/router'; import { ALL_PAGES } from '../../common/constants/pages'; import { ControlPanel } from '../../common/components/controls/ControlPanel'; import { lineColorBackground } from '../../common/styles/general'; +import { COMMUTER_RAIL_LINE_NAMES } from '../../common/types/lines'; export const DesktopHeader: React.FC = () => { const { line, page, - query: { busRoute }, + query: { busRoute, crRoute }, tab, } = useDelimitatedRoute(); const dateStoreSection = page ? ALL_PAGES[page]?.dateStoreSection : undefined; @@ -20,9 +21,11 @@ export const DesktopHeader: React.FC = () => { const getLineName = () => { if (busRoute) return `Route ${busRoute}`; + if (crRoute) return COMMUTER_RAIL_LINE_NAMES[crRoute]; if (line) return LINE_OBJECTS[line]?.name; if (tab === 'System') return 'System'; }; + return (
{
{showControls && ( - + )}
); diff --git a/modules/navigation/SideNavigation.tsx b/modules/navigation/SideNavigation.tsx index 7a9912c9d..a34a1c68f 100644 --- a/modules/navigation/SideNavigation.tsx +++ b/modules/navigation/SideNavigation.tsx @@ -6,6 +6,7 @@ import classNames from 'classnames'; import { SubwaySection } from '../../common/components/nav/SubwaySection'; import { BusSection } from '../../common/components/nav/BusSection'; import { useDelimitatedRoute } from '../../common/utils/router'; +import { CommuterRailSection } from '../../common/components/nav/CommuterRailSection'; interface SideNavigationProps { close?: () => void; @@ -58,6 +59,7 @@ export const SideNavigation: React.FC = ({ close }) => {
+ ); diff --git a/pages/[line]/index.tsx b/pages/[line]/index.tsx index 64662be5e..3d9fe451d 100644 --- a/pages/[line]/index.tsx +++ b/pages/[line]/index.tsx @@ -1,4 +1,4 @@ -import { ALL_LINE_PATHS, BUS_PATH } from '../../common/types/lines'; +import { ALL_LINE_PATHS, BUS_PATH, COMMUTER_RAIL_PATH } from '../../common/types/lines'; import { Overview } from '../../modules/dashboard/Overview'; export async function getStaticProps() { @@ -7,7 +7,7 @@ export async function getStaticProps() { export async function getStaticPaths() { return { - paths: [...ALL_LINE_PATHS, BUS_PATH], + paths: [...ALL_LINE_PATHS, BUS_PATH, COMMUTER_RAIL_PATH], fallback: false, }; } diff --git a/pages/[line]/ridership.tsx b/pages/[line]/ridership.tsx index 11009ff1f..ec86bb369 100644 --- a/pages/[line]/ridership.tsx +++ b/pages/[line]/ridership.tsx @@ -1,4 +1,4 @@ -import { ALL_LINE_PATHS, BUS_PATH } from '../../common/types/lines'; +import { ALL_LINE_PATHS, BUS_PATH, COMMUTER_RAIL_PATH } from '../../common/types/lines'; import { RidershipDetails } from '../../modules/ridership/RidershipDetails'; export async function getStaticProps() { @@ -7,7 +7,7 @@ export async function getStaticProps() { export async function getStaticPaths() { return { - paths: [...ALL_LINE_PATHS, BUS_PATH], + paths: [...ALL_LINE_PATHS, BUS_PATH, COMMUTER_RAIL_PATH], fallback: false, }; } diff --git a/pages/[line]/trips/multi/index.tsx b/pages/[line]/trips/multi/index.tsx index 7348b49bc..a31afb9c2 100644 --- a/pages/[line]/trips/multi/index.tsx +++ b/pages/[line]/trips/multi/index.tsx @@ -1,4 +1,4 @@ -import { ALL_LINE_PATHS, BUS_PATH } from '../../../../common/types/lines'; +import { ALL_LINE_PATHS, BUS_PATH, COMMUTER_RAIL_PATH } from '../../../../common/types/lines'; import { TripExplorer } from '../../../../modules/tripexplorer/TripExplorer'; export async function getStaticProps() { @@ -7,7 +7,7 @@ export async function getStaticProps() { export async function getStaticPaths() { return { - paths: [...ALL_LINE_PATHS, BUS_PATH], + paths: [...ALL_LINE_PATHS, BUS_PATH, COMMUTER_RAIL_PATH], fallback: false, }; } diff --git a/pages/[line]/trips/single/index.tsx b/pages/[line]/trips/single/index.tsx index 7348b49bc..a31afb9c2 100644 --- a/pages/[line]/trips/single/index.tsx +++ b/pages/[line]/trips/single/index.tsx @@ -1,4 +1,4 @@ -import { ALL_LINE_PATHS, BUS_PATH } from '../../../../common/types/lines'; +import { ALL_LINE_PATHS, BUS_PATH, COMMUTER_RAIL_PATH } from '../../../../common/types/lines'; import { TripExplorer } from '../../../../modules/tripexplorer/TripExplorer'; export async function getStaticProps() { @@ -7,7 +7,7 @@ export async function getStaticProps() { export async function getStaticPaths() { return { - paths: [...ALL_LINE_PATHS, BUS_PATH], + paths: [...ALL_LINE_PATHS, BUS_PATH, COMMUTER_RAIL_PATH], fallback: false, }; } diff --git a/server/bus/gen_bus_data.sh b/server/bus/gen_bus_data.sh index 0d085c5a8..705bcaca6 100755 --- a/server/bus/gen_bus_data.sh +++ b/server/bus/gen_bus_data.sh @@ -2,7 +2,7 @@ routes="$@" if [ -z "$routes" ]; then - routes="1" + routes="1 111 15 22 23 28 32 39 57 66 71 73 77 114 116 117" fi for y in `seq 2018 2023`; do diff --git a/server/scripts/generate_line_file.py b/server/scripts/generate_line_file.py new file mode 100644 index 000000000..09fd33b4c --- /dev/null +++ b/server/scripts/generate_line_file.py @@ -0,0 +1,30 @@ +import json +import requests + + +r_f = requests.get("https://api-v3.mbta.com/stops?filter%5Broute%5D=CR-Franklin") +stops = r_f.json() + +stops_formatted = [ + { + "stop_name": stop["attributes"]["name"], + "station": stop["id"], + "branches": None, + "order": index + 1, + "stops": {0: [], 1: []}, + } + for index, stop in enumerate(stops["data"]) +] + +output = { + "cr-franklin": { + "type": "commuter-rail", + "direction": {"0": "outbound", "1": "inbound"}, + "stations": stops_formatted, + } +} + + +out_json = json.dumps(output, indent=2) +with open("../common/constants/cr_constants/cr-franklin.json", "w") as f: + f.write(out_json) diff --git a/styles/dashboard.css b/styles/dashboard.css index 1280f2e34..7aefb6d11 100644 --- a/styles/dashboard.css +++ b/styles/dashboard.css @@ -158,4 +158,9 @@ .selected-date-line-bus { background: #FFE395 !important; border-color: #FFE395 !important; +} + +.selected-date-line-commuter-rail { + background: #a95896 !important; + border-color: #a95896 !important; } \ No newline at end of file From 74ce70ad75dcd74ca3c04ade026ad7a3b9306008 Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Wed, 20 Dec 2023 18:19:03 -0500 Subject: [PATCH 03/53] Treat bus the same as rapid for dates --- common/constants/dates.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/constants/dates.ts b/common/constants/dates.ts index fc7f1062d..772742503 100644 --- a/common/constants/dates.ts +++ b/common/constants/dates.ts @@ -59,7 +59,7 @@ export const FLAT_PICKER_OPTIONS: { Bus: { enableTime: false, minDate: BUS_MIN_DATE, - maxDate: BUS_MAX_DATE, + maxDate: TODAY_STRING, altInput: true, altFormat: 'M j, Y', dateFormat: 'Y-m-d', @@ -141,7 +141,7 @@ export const SINGLE_PRESETS: { [key in Tab]: { [key in DatePresetKey]?: DateSelectionDefaultOptions }; } = { Subway: SINGLE_RAPID_PRESETS, - Bus: SINGLE_BUS_PRESETS, + Bus: SINGLE_RAPID_PRESETS, System: SINGLE_RAPID_PRESETS, }; From 75c60ab0042c9703955df1c0801189f0bebd37a9 Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Thu, 21 Dec 2023 20:27:36 -0500 Subject: [PATCH 04/53] Better if statement --- server/chalicelib/s3.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/chalicelib/s3.py b/server/chalicelib/s3.py index 1957512e4..05b728543 100644 --- a/server/chalicelib/s3.py +++ b/server/chalicelib/s3.py @@ -51,7 +51,7 @@ def download_one_event_file(date, stop_id, live=False): if ex.response["Error"]["Code"] == "NoSuchKey": # raise Exception(f"Data not available on S3 for key {key} ") from None print(f"WARNING: No data available on S3 for key: {key}") - if live == False: + if not live: return download_one_event_file(date, stop_id, live=True) return [] else: From aa4093966069deb54771f4db072f807deff92c42 Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Thu, 21 Dec 2023 21:39:20 -0500 Subject: [PATCH 05/53] Handle date formats with timezones --- server/chalicelib/dates.py | 17 +++++++++++++++++ server/chalicelib/s3_historical.py | 24 +++++++++++------------- 2 files changed, 28 insertions(+), 13 deletions(-) create mode 100644 server/chalicelib/dates.py diff --git a/server/chalicelib/dates.py b/server/chalicelib/dates.py new file mode 100644 index 000000000..9e0e018f3 --- /dev/null +++ b/server/chalicelib/dates.py @@ -0,0 +1,17 @@ +from datetime import datetime + + +DATE_FORMAT_MASSDOT = "%Y-%m-%d %H:%M:%S" +DATE_FORMAT_TIMEZONE = "%Y-%m-%d %H:%M:%S%z" +DATE_FORMAT_OUT = "%Y-%m-%dT%H:%M:%S" + + +def parse_event_date(date_str: str): + if len(date_str) == 19: + return datetime.strptime(date_str, DATE_FORMAT_MASSDOT) + else: + return datetime.strptime(date_str, DATE_FORMAT_TIMEZONE) + + +def return_formatted_date(date: datetime): + return date.strftime(DATE_FORMAT_OUT) diff --git a/server/chalicelib/s3_historical.py b/server/chalicelib/s3_historical.py index e364d947f..fe542b8ed 100644 --- a/server/chalicelib/s3_historical.py +++ b/server/chalicelib/s3_historical.py @@ -3,9 +3,7 @@ from chalicelib.constants import EVENT_ARRIVAL, EVENT_DEPARTURE import itertools - -DATE_FORMAT_MASSDOT = "%Y-%m-%d %H:%M:%S" -DATE_FORMAT_OUT = "%Y-%m-%dT%H:%M:%S" +import dates def pairwise(iterable): @@ -46,15 +44,15 @@ def dwells(stop_ids, sdate, edate): and maybe_a_departure["event_type"] in EVENT_DEPARTURE and maybe_an_arrival["trip_id"] == maybe_a_departure["trip_id"] ): - dep_dt = datetime.strptime(maybe_a_departure["event_time"], DATE_FORMAT_MASSDOT) - arr_dt = datetime.strptime(maybe_an_arrival["event_time"], DATE_FORMAT_MASSDOT) + dep_dt = dates.parse_event_date(maybe_a_departure["event_time"]) + arr_dt = dates.parse_event_date(maybe_an_arrival["event_time"]) delta = dep_dt - arr_dt dwells.append( { "route_id": maybe_a_departure["route_id"], "direction": int(maybe_a_departure["direction_id"]), - "arr_dt": arr_dt.strftime(DATE_FORMAT_OUT), - "dep_dt": dep_dt.strftime(DATE_FORMAT_OUT), + "arr_dt": dates.return_formatted_date(arr_dt), + "dep_dt": dates.return_formatted_date(dep_dt), "dwell_time_sec": delta.total_seconds(), } ) @@ -74,8 +72,8 @@ def headways(stop_ids, sdate, edate): # Here, we should skip the headway # (though if trip_id is empty, we don't know). continue - this_dt = datetime.strptime(this["event_time"], DATE_FORMAT_MASSDOT) - prev_dt = datetime.strptime(prev["event_time"], DATE_FORMAT_MASSDOT) + this_dt = dates.parse_event_date(this["event_time"]) + prev_dt = dates.parse_event_date(prev["event_time"]) delta = this_dt - prev_dt headway_time_sec = delta.total_seconds() @@ -121,8 +119,8 @@ def travel_times(stops_a, stops_b, sdate, edate): dep = departure["event_time"] arr = arrival["event_time"] - dep_dt = datetime.strptime(dep, DATE_FORMAT_MASSDOT) - arr_dt = datetime.strptime(arr, DATE_FORMAT_MASSDOT) + dep_dt = dates.parse_event_date(dep) + arr_dt = dates.parse_event_date(arr) delta = arr_dt - dep_dt travel_time_sec = delta.total_seconds() @@ -143,8 +141,8 @@ def travel_times(stops_a, stops_b, sdate, edate): { "route_id": departure["route_id"], "direction": int(departure["direction_id"]), - "dep_dt": dep_dt.strftime(DATE_FORMAT_OUT), - "arr_dt": arr_dt.strftime(DATE_FORMAT_OUT), + "dep_dt": dates.return_formatted_date(dep_dt), + "arr_dt": dates.return_formatted_date(arr_dt), "travel_time_sec": travel_time_sec, "benchmark_travel_time_sec": benchmark, } From 30ddd1f423d7d00b757140360cd879cc4dc05d59 Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Thu, 21 Dec 2023 21:43:36 -0500 Subject: [PATCH 06/53] Renaming date_utils --- server/chalicelib/{dates.py => date_utils.py} | 0 server/chalicelib/s3_historical.py | 22 +++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) rename server/chalicelib/{dates.py => date_utils.py} (100%) diff --git a/server/chalicelib/dates.py b/server/chalicelib/date_utils.py similarity index 100% rename from server/chalicelib/dates.py rename to server/chalicelib/date_utils.py diff --git a/server/chalicelib/s3_historical.py b/server/chalicelib/s3_historical.py index fe542b8ed..021938c6b 100644 --- a/server/chalicelib/s3_historical.py +++ b/server/chalicelib/s3_historical.py @@ -3,7 +3,7 @@ from chalicelib.constants import EVENT_ARRIVAL, EVENT_DEPARTURE import itertools -import dates +import chalicelib.date_utils as date_utils def pairwise(iterable): @@ -44,15 +44,15 @@ def dwells(stop_ids, sdate, edate): and maybe_a_departure["event_type"] in EVENT_DEPARTURE and maybe_an_arrival["trip_id"] == maybe_a_departure["trip_id"] ): - dep_dt = dates.parse_event_date(maybe_a_departure["event_time"]) - arr_dt = dates.parse_event_date(maybe_an_arrival["event_time"]) + dep_dt = date_utils.parse_event_date(maybe_a_departure["event_time"]) + arr_dt = date_utils.parse_event_date(maybe_an_arrival["event_time"]) delta = dep_dt - arr_dt dwells.append( { "route_id": maybe_a_departure["route_id"], "direction": int(maybe_a_departure["direction_id"]), - "arr_dt": dates.return_formatted_date(arr_dt), - "dep_dt": dates.return_formatted_date(dep_dt), + "arr_dt": date_utils.return_formatted_date(arr_dt), + "dep_dt": date_utils.return_formatted_date(dep_dt), "dwell_time_sec": delta.total_seconds(), } ) @@ -72,8 +72,8 @@ def headways(stop_ids, sdate, edate): # Here, we should skip the headway # (though if trip_id is empty, we don't know). continue - this_dt = dates.parse_event_date(this["event_time"]) - prev_dt = dates.parse_event_date(prev["event_time"]) + this_dt = date_utils.parse_event_date(this["event_time"]) + prev_dt = date_utils.parse_event_date(prev["event_time"]) delta = this_dt - prev_dt headway_time_sec = delta.total_seconds() @@ -119,8 +119,8 @@ def travel_times(stops_a, stops_b, sdate, edate): dep = departure["event_time"] arr = arrival["event_time"] - dep_dt = dates.parse_event_date(dep) - arr_dt = dates.parse_event_date(arr) + dep_dt = date_utils.parse_event_date(dep) + arr_dt = date_utils.parse_event_date(arr) delta = arr_dt - dep_dt travel_time_sec = delta.total_seconds() @@ -141,8 +141,8 @@ def travel_times(stops_a, stops_b, sdate, edate): { "route_id": departure["route_id"], "direction": int(departure["direction_id"]), - "dep_dt": dates.return_formatted_date(dep_dt), - "arr_dt": dates.return_formatted_date(arr_dt), + "dep_dt": date_utils.return_formatted_date(dep_dt), + "arr_dt": date_utils.return_formatted_date(arr_dt), "travel_time_sec": travel_time_sec, "benchmark_travel_time_sec": benchmark, } From a122a8887cee86174926155b6f92362090c4ba13 Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Thu, 21 Dec 2023 21:47:26 -0500 Subject: [PATCH 07/53] Cleanup imports --- server/chalicelib/s3_historical.py | 1 - 1 file changed, 1 deletion(-) diff --git a/server/chalicelib/s3_historical.py b/server/chalicelib/s3_historical.py index 021938c6b..0c50d88eb 100644 --- a/server/chalicelib/s3_historical.py +++ b/server/chalicelib/s3_historical.py @@ -1,4 +1,3 @@ -from datetime import datetime from chalicelib import s3 from chalicelib.constants import EVENT_ARRIVAL, EVENT_DEPARTURE From 9532a70a97d9dcb18b3e57e7b6ce424a970fa4c5 Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Fri, 22 Dec 2023 13:09:28 -0500 Subject: [PATCH 08/53] Inject timezone into non-timezone datestamps --- server/chalicelib/date_utils.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/server/chalicelib/date_utils.py b/server/chalicelib/date_utils.py index 9e0e018f3..f84c82f66 100644 --- a/server/chalicelib/date_utils.py +++ b/server/chalicelib/date_utils.py @@ -1,14 +1,16 @@ from datetime import datetime +from zoneinfo import ZoneInfo DATE_FORMAT_MASSDOT = "%Y-%m-%d %H:%M:%S" DATE_FORMAT_TIMEZONE = "%Y-%m-%d %H:%M:%S%z" DATE_FORMAT_OUT = "%Y-%m-%dT%H:%M:%S" +EASTERN_TIME = ZoneInfo("US/Eastern") def parse_event_date(date_str: str): if len(date_str) == 19: - return datetime.strptime(date_str, DATE_FORMAT_MASSDOT) + return datetime.strptime(date_str, DATE_FORMAT_MASSDOT).replace(tzinfo=EASTERN_TIME) else: return datetime.strptime(date_str, DATE_FORMAT_TIMEZONE) From ee77537bc0d99c6936af605eec24c34df2c409c0 Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Fri, 22 Dec 2023 14:15:59 -0500 Subject: [PATCH 09/53] Set minimum commuter rail date --- common/constants/dates.ts | 3 ++- common/state/defaults/dateDefaults.ts | 11 +++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/common/constants/dates.ts b/common/constants/dates.ts index 644410cf0..ddd933fca 100644 --- a/common/constants/dates.ts +++ b/common/constants/dates.ts @@ -40,6 +40,7 @@ const BUS_MAX_DAY = dayjs(BUS_MAX_DATE); export const BUS_MAX_DATE_MINUS_ONE_WEEK = dayjs(BUS_MAX_DATE) .subtract(7, 'days') .format(DATE_FORMAT); +export const COMMUTER_RAIL_MIN_DATE = '2023-12-15'; export const getESTDayjs = (date: string) => { return dayjs(date).tz(est); @@ -74,7 +75,7 @@ export const FLAT_PICKER_OPTIONS: { }, 'Commuter Rail': { enableTime: false, - minDate: TRAIN_MIN_DATE, + minDate: COMMUTER_RAIL_MIN_DATE, maxDate: TODAY_STRING, altInput: true, altFormat: 'M j, Y', diff --git a/common/state/defaults/dateDefaults.ts b/common/state/defaults/dateDefaults.ts index 9f163bda5..fe5a3d03e 100644 --- a/common/state/defaults/dateDefaults.ts +++ b/common/state/defaults/dateDefaults.ts @@ -1,13 +1,12 @@ import type { DateStoreSection } from '../../constants/pages'; import type { DateStoreConfiguration } from '../types/dateStoreTypes'; import { - BUS_MAX_DATE, - BUS_MAX_DATE_MINUS_ONE_WEEK, ONE_WEEK_AGO_STRING, OVERVIEW_OPTIONS, TODAY_STRING, YESTERDAY_STRING, TODAY_SERVICE_STARTED, + COMMUTER_RAIL_MIN_DATE, } from '../../constants/dates'; import type { WithOptional } from '../../types/general'; import type { Tab } from '../../types/router'; @@ -28,11 +27,11 @@ export const BUS_DEFAULTS: WithOptional = { lineConfig: { startDate: OVERVIEW_OPTIONS.year.startDate, endDate: TODAY_STRING }, multiTripConfig: { - startDate: ONE_WEEK_AGO_STRING, + startDate: COMMUTER_RAIL_MIN_DATE, endDate: TODAY_STRING, }, singleTripConfig: { From 4577978fcc8162af2ca3dd92ca63659f0110b862 Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Fri, 22 Dec 2023 16:02:49 -0500 Subject: [PATCH 10/53] Adding some initial platform ids --- common/constants/cr_constants/cr-foxboro.json | 91 +++++++++++++++++++ common/constants/cr_constants/cr-lowell.json | 8 +- 2 files changed, 95 insertions(+), 4 deletions(-) create mode 100644 common/constants/cr_constants/cr-foxboro.json diff --git a/common/constants/cr_constants/cr-foxboro.json b/common/constants/cr_constants/cr-foxboro.json new file mode 100644 index 000000000..c80b06fb1 --- /dev/null +++ b/common/constants/cr_constants/cr-foxboro.json @@ -0,0 +1,91 @@ +{ + "cr-foxboro": { + "type": "commuter-rail", + "direction": { + "0": "outbound", + "1": "inbound" + }, + "stations": [ + { + "stop_name": "Providence", + "station": "place-NEC-1851", + "branches": null, + "order": 1, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "Pawtucket/Central Falls", + "station": "place-NEC-1891", + "branches": null, + "order": 2, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "Attleboro", + "station": "place-NEC-1969", + "branches": null, + "order": 3, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "Mansfield", + "station": "place-NEC-2040", + "branches": null, + "order": 4, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "South Station", + "station": "place-sstat", + "branches": null, + "order": 5, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "Back Bay", + "station": "place-bbsta", + "branches": null, + "order": 6, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "Dedham Corporate Center", + "station": "place-FB-0118", + "branches": null, + "order": 7, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "Foxboro", + "station": "place-FS-0049", + "branches": null, + "order": 8, + "stops": { + "0": [], + "1": [] + } + } + ] + } +} diff --git a/common/constants/cr_constants/cr-lowell.json b/common/constants/cr_constants/cr-lowell.json index 5ba1d898f..2b704b62e 100644 --- a/common/constants/cr_constants/cr-lowell.json +++ b/common/constants/cr_constants/cr-lowell.json @@ -23,7 +23,7 @@ "order": 2, "stops": { "0": [], - "1": [] + "1": ["NHRML-0218-02"] } }, { @@ -42,8 +42,8 @@ "branches": null, "order": 4, "stops": { - "0": [], - "1": [] + "0": ["NHRML-0127-01"], + "1": ["NHRML-0127-02"] } }, { @@ -62,7 +62,7 @@ "branches": null, "order": 6, "stops": { - "0": [], + "0": ["NHRML-0055-01"], "1": [] } }, From d137236579eea822d8d2abee588bb41b4f46ec2a Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Fri, 22 Dec 2023 16:08:48 -0500 Subject: [PATCH 11/53] Adding lowell line platform ids --- common/constants/cr_constants/cr-lowell.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/common/constants/cr_constants/cr-lowell.json b/common/constants/cr_constants/cr-lowell.json index 2b704b62e..7d92c2c41 100644 --- a/common/constants/cr_constants/cr-lowell.json +++ b/common/constants/cr_constants/cr-lowell.json @@ -12,8 +12,8 @@ "branches": null, "order": 1, "stops": { - "0": [], - "1": [] + "0": ["NHRML-0254-01"], + "1": ["NHRML-0254-02"] } }, { @@ -22,7 +22,7 @@ "branches": null, "order": 2, "stops": { - "0": [], + "0": ["NHRML-0218-01"], "1": ["NHRML-0218-02"] } }, @@ -32,8 +32,8 @@ "branches": null, "order": 3, "stops": { - "0": [], - "1": [] + "0": ["NHRML-0152-01"], + "1": ["NHRML-0152-02"] } }, { @@ -52,8 +52,8 @@ "branches": null, "order": 5, "stops": { - "0": [], - "1": [] + "0": ["NHRML-0073-01"], + "1": ["NHRML-0073-02"] } }, { @@ -63,7 +63,7 @@ "order": 6, "stops": { "0": ["NHRML-0055-01"], - "1": [] + "1": ["NHRML-0055-02"] } }, { From 20c5eec1cadf3da2ecde63021d70f11ea0a9126b Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Fri, 22 Dec 2023 17:31:06 -0500 Subject: [PATCH 12/53] Properly fetching CR stations --- common/components/nav/MenuDropdown.tsx | 2 +- .../constants/cr_constants/cr-fitchburg.json | 2 +- common/constants/cr_constants/cr-foxboro.json | 2 +- .../constants/cr_constants/cr-franklin.json | 4 +-- common/constants/cr_constants/cr-lowell.json | 2 +- common/constants/dashboardTabs.ts | 2 +- common/constants/stations.ts | 8 +++-- common/types/lines.ts | 33 ++++++++++--------- common/utils/stations.ts | 6 ++-- server/chalicelib/s3.py | 17 ++++++++-- 10 files changed, 48 insertions(+), 30 deletions(-) diff --git a/common/components/nav/MenuDropdown.tsx b/common/components/nav/MenuDropdown.tsx index cf52cdf4a..aa3d07158 100644 --- a/common/components/nav/MenuDropdown.tsx +++ b/common/components/nav/MenuDropdown.tsx @@ -43,7 +43,7 @@ export const MenuDropdown: React.FC = ({ line, route, childre case 'line-bus': return `/bus/trips/single?busRoute=1&date=${BUS_DEFAULTS.singleTripConfig.date}`; case 'line-commuter-rail': - return `/commuter-rail/trips/single?crRoute=cr-lowell&date=${COMMUTER_RAIL_DEFAULTS.singleTripConfig.date}`; + return `/commuter-rail/trips/single?crRoute=CR-Lowell&date=${COMMUTER_RAIL_DEFAULTS.singleTripConfig.date}`; default: return getLineSelectionItemHref(line, route); } diff --git a/common/constants/cr_constants/cr-fitchburg.json b/common/constants/cr_constants/cr-fitchburg.json index 549661f1f..5e116ba2c 100644 --- a/common/constants/cr_constants/cr-fitchburg.json +++ b/common/constants/cr_constants/cr-fitchburg.json @@ -1,5 +1,5 @@ { - "cr-fitchburg": { + "CR-Fitchburg": { "type": "commuter-rail", "direction": { "0": "outbound", diff --git a/common/constants/cr_constants/cr-foxboro.json b/common/constants/cr_constants/cr-foxboro.json index c80b06fb1..d26884a79 100644 --- a/common/constants/cr_constants/cr-foxboro.json +++ b/common/constants/cr_constants/cr-foxboro.json @@ -1,5 +1,5 @@ { - "cr-foxboro": { + "CR-Foxboro": { "type": "commuter-rail", "direction": { "0": "outbound", diff --git a/common/constants/cr_constants/cr-franklin.json b/common/constants/cr_constants/cr-franklin.json index 2484ceb5c..d4fbe0329 100644 --- a/common/constants/cr_constants/cr-franklin.json +++ b/common/constants/cr_constants/cr-franklin.json @@ -1,5 +1,5 @@ { - "cr-franklin": { + "CR-Franklin": { "type": "commuter-rail", "direction": { "0": "outbound", @@ -178,4 +178,4 @@ } ] } -} \ No newline at end of file +} diff --git a/common/constants/cr_constants/cr-lowell.json b/common/constants/cr_constants/cr-lowell.json index 7d92c2c41..83ed9abe3 100644 --- a/common/constants/cr_constants/cr-lowell.json +++ b/common/constants/cr_constants/cr-lowell.json @@ -1,5 +1,5 @@ { - "cr-lowell": { + "CR-Lowell": { "type": "commuter-rail", "direction": { "0": "outbound", diff --git a/common/constants/dashboardTabs.ts b/common/constants/dashboardTabs.ts index 532f94b31..bbfd46a21 100644 --- a/common/constants/dashboardTabs.ts +++ b/common/constants/dashboardTabs.ts @@ -14,6 +14,6 @@ export const DASHBOARD_TABS: { 'Commuter Rail': { name: 'Commuter Rail', path: '/commuter-rail', - query: { crRoute: 'cr-lowell', date: COMMUTER_RAIL_DEFAULTS.singleTripConfig.date }, + query: { crRoute: 'CR-Lowell', date: COMMUTER_RAIL_DEFAULTS.singleTripConfig.date }, }, }; diff --git a/common/constants/stations.ts b/common/constants/stations.ts index 66b6075b0..9af32db77 100644 --- a/common/constants/stations.ts +++ b/common/constants/stations.ts @@ -19,6 +19,7 @@ import bus_114_116_117 from './bus_constants/114-116-117.json'; import cr_lowell from './cr_constants/cr-lowell.json'; import cr_fitchburg from './cr_constants/cr-fitchburg.json'; import cr_franklin from './cr_constants/cr-franklin.json'; +import cr_foxboro from './cr_constants/cr-foxboro.json'; export const rtStations: { [key in Exclude]: LineMap } = stations_json; @@ -40,18 +41,19 @@ export const busStations: { [key: string]: LineMap } = { ...bus_114_116_117, }; -export const commuterRailStations: { [key: string]: LineMap } = { +export const crStations: { [key: string]: LineMap } = { ...cr_lowell, ...cr_fitchburg, ...cr_franklin, + ...cr_foxboro, }; -export const stations = { ...rtStations, Bus: busStations, 'Commuter Rail': commuterRailStations }; +export const stations = { ...rtStations, Bus: busStations, 'Commuter Rail': crStations }; export const getBusRoutes = (): string[] => { return Object.keys(busStations); }; export const getCommuterRailRoutes = (): string[] => { - return Object.keys(commuterRailStations); + return Object.keys(crStations); }; diff --git a/common/types/lines.ts b/common/types/lines.ts index 59ab197c9..9bc33e7fb 100644 --- a/common/types/lines.ts +++ b/common/types/lines.ts @@ -27,11 +27,12 @@ export type BusRoute = /** TODO: Expand list to all lines */ export type CommuterRailRoute = - | 'cr-fitchburg' - | 'cr-franklin' - | 'cr-greenbush' - | 'cr-haverhill' - | 'cr-lowell'; + | 'CR-Fitchburg' + | 'CR-Franklin' + | 'CR-Greenbush' + | 'CR-Haverhill' + | 'CR-Lowell' + | 'CR-Foxboro'; export type LineMetadata = { name: string; @@ -82,18 +83,20 @@ export const BUS_ROUTES: BusRoute[] = [ ]; export const COMMUTER_RAIL_ROUTES: CommuterRailRoute[] = [ - 'cr-fitchburg', - 'cr-franklin', - 'cr-greenbush', - 'cr-haverhill', - 'cr-lowell', + 'CR-Fitchburg', + 'CR-Franklin', + 'CR-Greenbush', + 'CR-Haverhill', + 'CR-Lowell', + 'CR-Foxboro', ]; export const COMMUTER_RAIL_LINE_NAMES: { [line in CommuterRailRoute]: string } = { - 'cr-fitchburg': 'Fitchburg Line', - 'cr-franklin': 'Franklin Line', - 'cr-greenbush': 'Greenbush Line', - 'cr-haverhill': 'Haverhill Line', - 'cr-lowell': 'Lowell Line', + 'CR-Fitchburg': 'Fitchburg Line', + 'CR-Franklin': 'Franklin Line', + 'CR-Greenbush': 'Greenbush Line', + 'CR-Haverhill': 'Haverhill Line', + 'CR-Lowell': 'Lowell Line', + 'CR-Foxboro': 'Foxboro Line', }; export const ALL_LINE_PATHS = RAIL_LINES.map((line) => { diff --git a/common/utils/stations.ts b/common/utils/stations.ts index d81a43144..7225fe596 100644 --- a/common/utils/stations.ts +++ b/common/utils/stations.ts @@ -2,7 +2,7 @@ import type { BusRoute, CommuterRailRoute, Line, LineShort } from '../types/line import { isLineMap, type Station } from '../types/stations'; import type { Location } from '../types/charts'; import type { Direction } from '../types/dataPoints'; -import { stations, rtStations, busStations } from '../constants/stations'; +import { stations, rtStations, busStations, crStations } from '../constants/stations'; export const optionsForField = ( type: 'from' | 'to', @@ -54,7 +54,7 @@ export const optionsStation = ( const createStationIndex = () => { const index: Record = {}; - Object.values({ ...rtStations, ...busStations }).forEach((line) => { + Object.values({ ...rtStations, ...busStations, ...crStations }).forEach((line) => { line.stations.forEach((station) => { index[station.station] = station; }); @@ -64,7 +64,7 @@ const createStationIndex = () => { const createParentStationIndex = () => { const index: Record = {}; - Object.values({ ...rtStations, ...busStations }).forEach((line) => { + Object.values({ ...rtStations, ...busStations, ...crStations }).forEach((line) => { line.stations.forEach((station) => { const allStopIds = [...(station.stops['0'] || []), ...(station.stops['1'] || [])]; allStopIds.forEach((stopId) => { diff --git a/server/chalicelib/s3.py b/server/chalicelib/s3.py index 05b728543..98e771f20 100644 --- a/server/chalicelib/s3.py +++ b/server/chalicelib/s3.py @@ -28,16 +28,29 @@ def upload(key, bytes, compress=True): s3.put_object(Bucket=BUCKET, Key=key, Body=bytes) -def is_bus(stop_id): +def is_bus(stop_id: str): return ("-0-" in stop_id) or ("-1-" in stop_id) +def is_cr(stop_id: str): + return stop_id.startswith("CR-") + + +def get_live_folder(stop_id: str): + if is_bus(stop_id): + return "daily-bus-data" + elif is_cr(stop_id): + return "daily-cr-data" + else: + return "daily-data" + + def download_one_event_file(date, stop_id, live=False): """As advertised: single event file from s3""" year, month, day = date.year, date.month, date.day if live: - folder = "daily-bus-data" if is_bus(stop_id) else "daily-data" + folder = get_live_folder(stop_id) key = f"Events-live/{folder}/{stop_id}/Year={year}/Month={month}/Day={day}/events.csv.gz" else: folder = "monthly-bus-data" if is_bus(stop_id) else "monthly-data" From 3a89a12a24f9c522fb7e1dc6ce832df8549a7344 Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Fri, 22 Dec 2023 19:02:53 -0500 Subject: [PATCH 13/53] Acutally fetching CR data --- common/api/datadashboard.ts | 8 ++ common/constants/cr_constants/cr-lowell.json | 24 ++-- common/types/api.ts | 3 +- .../tripexplorer/CommuterRailTripGraphs.tsx | 134 ++++++++++++++++++ modules/tripexplorer/TripGraphs.tsx | 12 ++ server/chalicelib/data_funcs.py | 18 ++- server/scripts/generate_line_file.py | 18 ++- 7 files changed, 193 insertions(+), 24 deletions(-) create mode 100644 modules/tripexplorer/CommuterRailTripGraphs.tsx diff --git a/common/api/datadashboard.ts b/common/api/datadashboard.ts index 3099bf14b..a2bf63eb2 100644 --- a/common/api/datadashboard.ts +++ b/common/api/datadashboard.ts @@ -141,6 +141,14 @@ export const useTripExplorerQueries: UseQueriesOverload = ( [QueryNameKeys.headways]: requests[1], }; } + + if (busOrSubway === 'cr') { + return { + [QueryNameKeys.traveltimes]: requests[0], + [QueryNameKeys.headways]: requests[1], + }; + } + return { [QueryNameKeys.traveltimes]: requests[0], [QueryNameKeys.headways]: requests[1], diff --git a/common/constants/cr_constants/cr-lowell.json b/common/constants/cr_constants/cr-lowell.json index 83ed9abe3..094b16d85 100644 --- a/common/constants/cr_constants/cr-lowell.json +++ b/common/constants/cr_constants/cr-lowell.json @@ -12,8 +12,8 @@ "branches": null, "order": 1, "stops": { - "0": ["NHRML-0254-01"], - "1": ["NHRML-0254-02"] + "0": ["CR-Lowell_0_NHRML-0254-01"], + "1": ["CR-Lowell_1_NHRML-0254-02", "CR-Lowell_1_NHRML-0254-04"] } }, { @@ -22,8 +22,8 @@ "branches": null, "order": 2, "stops": { - "0": ["NHRML-0218-01"], - "1": ["NHRML-0218-02"] + "0": ["CR-Lowell_0_NHRML-0218-01"], + "1": ["CR-Lowell_1_NHRML-0218-02"] } }, { @@ -32,8 +32,8 @@ "branches": null, "order": 3, "stops": { - "0": ["NHRML-0152-01"], - "1": ["NHRML-0152-02"] + "0": ["CR-Lowell_0_NHRML-0152-01"], + "1": ["CR-Lowell_1_NHRML-0152-02"] } }, { @@ -42,8 +42,8 @@ "branches": null, "order": 4, "stops": { - "0": ["NHRML-0127-01"], - "1": ["NHRML-0127-02"] + "0": ["CR-Lowell_0_NHRML-0127-01"], + "1": ["CR-Lowell_1_NHRML-0127-02"] } }, { @@ -52,8 +52,8 @@ "branches": null, "order": 5, "stops": { - "0": ["NHRML-0073-01"], - "1": ["NHRML-0073-02"] + "0": ["CR-Lowell_0_NHRML-0073-01"], + "1": ["CR-Lowell_1_NHRML-0073-02"] } }, { @@ -62,8 +62,8 @@ "branches": null, "order": 6, "stops": { - "0": ["NHRML-0055-01"], - "1": ["NHRML-0055-02"] + "0": ["CR-Lowell_0_NHRML-0055-01"], + "1": ["CR-Lowell_1_NHRML-0055-02"] } }, { diff --git a/common/types/api.ts b/common/types/api.ts index 1435a9c7d..12358de94 100644 --- a/common/types/api.ts +++ b/common/types/api.ts @@ -9,11 +9,12 @@ export enum QueryNameKeys { } export type QueryNameOptions = QueryNameKeys; -export type BusOrSubway = 'bus' | 'subway'; +export type BusOrSubway = 'bus' | 'cr' | 'subway'; export const QUERIES: { [key in BusOrSubway]: QueryNameOptions[] } = { subway: [QueryNameKeys.traveltimes, QueryNameKeys.headways, QueryNameKeys.dwells], bus: [QueryNameKeys.traveltimes, QueryNameKeys.headways], + cr: [QueryNameKeys.traveltimes, QueryNameKeys.headways], }; export enum SingleDayAPIParams { diff --git a/modules/tripexplorer/CommuterRailTripGraphs.tsx b/modules/tripexplorer/CommuterRailTripGraphs.tsx new file mode 100644 index 000000000..54da8a8e1 --- /dev/null +++ b/modules/tripexplorer/CommuterRailTripGraphs.tsx @@ -0,0 +1,134 @@ +import React from 'react'; +import { useTripExplorerQueries } from '../../common/api/datadashboard'; +import type { Station } from '../../common/types/stations'; +import type { AggregateAPIOptions, SingleDayAPIOptions } from '../../common/types/api'; +import { WidgetDiv } from '../../common/components/widgets/WidgetDiv'; +import { AggregateChartWrapper } from '../../common/components/charts/AggregateChartWrapper'; +import { ButtonGroup } from '../../common/components/general/ButtonGroup'; +import { WidgetTitle } from '../dashboard/WidgetTitle'; +import { getLocationDetails } from '../../common/utils/stations'; +import type { Line } from '../../common/types/lines'; +import { TravelTimesAggregateWrapper } from '../traveltimes/TravelTimesAggregateWrapper'; +import { HeadwaysAggregateWrapper } from '../headways/HeadwaysAggregateWrapper'; +import { TravelTimesSingleWrapper } from '../traveltimes/TravelTimesSingleWrapper'; +import { HeadwaysSingleWrapper } from '../headways/HeadwaysSingleWrapper'; + +interface CommuterRailTripGraphsProps { + fromStation: Station; + toStation: Station; + parameters: SingleDayAPIOptions | AggregateAPIOptions; // TODO + aggregate: boolean; + enabled: boolean; + line: Line | undefined; +} + +export const CommuterRailTripGraphs: React.FC = ({ + fromStation, + toStation, + parameters, + aggregate, + enabled, + line, +}) => { + const [peakTime, setPeakTime] = React.useState<'weekday' | 'weekend'>('weekday'); + + const { traveltimes, headways } = useTripExplorerQueries( + 'cr', + parameters, + // @ts-expect-error The overloading doesn't seem to handle this const + aggregate, + enabled + ); + const location = getLocationDetails(fromStation, toStation); + + return ( + <> + {aggregate ? ( + <> + + + + + + + + + + + + +
+ +
+
+ + ) : ( + <> + + + + + + + + + + + )} + + ); +}; diff --git a/modules/tripexplorer/TripGraphs.tsx b/modules/tripexplorer/TripGraphs.tsx index db6fa3815..d05a34221 100644 --- a/modules/tripexplorer/TripGraphs.tsx +++ b/modules/tripexplorer/TripGraphs.tsx @@ -6,6 +6,7 @@ import type { AggregateAPIOptions, SingleDayAPIOptions } from '../../common/type import { AggregateAPIParams, SingleDayAPIParams } from '../../common/types/api'; import { BusTripGraphs } from './BusTripGraphs'; import { SubwayTripGraphs } from './SubwayTripGraphs'; +import { CommuterRailTripGraphs } from './CommuterRailTripGraphs'; interface TripGraphsProps { fromStation: Station; @@ -47,6 +48,17 @@ export const TripGraphs: React.FC = ({ fromStation, toStation } line={line} /> ); + if (tab === 'Commuter Rail') + return ( + + ); return ( = 90 return archival or bus -def partition_S3_dates(start_date, end_date, bus=False): +def partition_S3_dates(start_date, end_date, bus=False, cr=False): """ Partitions dates by what data source they should be fetched from. S3 is used for archival data and for bus data. API is used for recent (within 90 days) subway data. @@ -68,7 +72,7 @@ def partition_S3_dates(start_date, end_date, bus=False): s3_dates = None api_dates = None - if end_date < CUTOFF or bus: + if end_date < CUTOFF or bus or cr: s3_dates = (start_date, end_date) elif CUTOFF <= start_date: api_dates = (start_date, end_date) @@ -81,12 +85,12 @@ def partition_S3_dates(start_date, end_date, bus=False): def headways(sdate, stops, edate=None): if edate is None: - if use_S3(sdate, is_bus(stops)): + if use_S3(sdate, is_bus(stops)) or use_S3(sdate, is_cr(stops)): return s3_historical.headways(stops, sdate, sdate) else: return process_mbta_headways(stops, sdate) - s3_interval, api_interval = partition_S3_dates(sdate, edate, is_bus(stops)) + s3_interval, api_interval = partition_S3_dates(sdate, edate, is_bus(stops), is_cr(stops)) all_data = [] if s3_interval: start, end = s3_interval @@ -132,12 +136,12 @@ def process_mbta_headways(stops, sdate, edate=None): def travel_times(sdate, from_stops, to_stops, edate=None): if edate is None: - if use_S3(sdate, is_bus(from_stops)): + if use_S3(sdate, is_bus(from_stops)) or use_S3(sdate, is_cr(from_stops)): return s3_historical.travel_times(from_stops, to_stops, sdate, sdate) else: return process_mbta_travel_times(from_stops, to_stops, sdate) - s3_interval, api_interval = partition_S3_dates(sdate, edate, is_bus(from_stops)) + s3_interval, api_interval = partition_S3_dates(sdate, edate, is_bus(from_stops), is_cr(from_stops)) all_data = [] if s3_interval: start, end = s3_interval @@ -181,7 +185,7 @@ def dwells(sdate, stops, edate=None): else: return process_mbta_dwells(stops, sdate) - s3_interval, api_interval = partition_S3_dates(sdate, edate, is_bus(stops)) + s3_interval, api_interval = partition_S3_dates(sdate, edate, is_bus(stops), is_cr(stops)) all_data = [] if s3_interval: start, end = s3_interval diff --git a/server/scripts/generate_line_file.py b/server/scripts/generate_line_file.py index 09fd33b4c..a38bf8e12 100644 --- a/server/scripts/generate_line_file.py +++ b/server/scripts/generate_line_file.py @@ -2,7 +2,7 @@ import requests -r_f = requests.get("https://api-v3.mbta.com/stops?filter%5Broute%5D=CR-Franklin") +r_f = requests.get("https://api-v3.mbta.com/stops?filter%5Broute%5D=CR-Kingston&include=child_stops") stops = r_f.json() stops_formatted = [ @@ -16,8 +16,18 @@ for index, stop in enumerate(stops["data"]) ] +for index, stop in enumerate(stops["data"]): + for platform in stop["relationships"]["child_stops"]["data"]: + if ( + platform["type"] == "stop" + and "door-" not in platform["id"] + and "node-" not in platform["id"] + and not platform["id"].isnumeric() + ): + print('"{}",'.format(platform["id"])) + output = { - "cr-franklin": { + "CR-Lowell": { "type": "commuter-rail", "direction": {"0": "outbound", "1": "inbound"}, "stations": stops_formatted, @@ -26,5 +36,5 @@ out_json = json.dumps(output, indent=2) -with open("../common/constants/cr_constants/cr-franklin.json", "w") as f: - f.write(out_json) +# with open("../common/constants/cr_constants/cr-foxboro.json", "w") as f: +# f.write(out_json) From a8ed493efedf5a24e4ac5ed19c7d3512a30e644d Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Sat, 23 Dec 2023 15:36:50 -0500 Subject: [PATCH 14/53] Adding franklin line ids --- .../constants/cr_constants/cr-franklin.json | 77 +++++++++++-------- common/constants/cr_constants/cr-lowell.json | 4 +- server/chalicelib/data_funcs.py | 2 +- server/chalicelib/s3.py | 2 +- server/chalicelib/s3_historical.py | 2 +- 5 files changed, 52 insertions(+), 35 deletions(-) diff --git a/common/constants/cr_constants/cr-franklin.json b/common/constants/cr_constants/cr-franklin.json index d4fbe0329..da3069a95 100644 --- a/common/constants/cr_constants/cr-franklin.json +++ b/common/constants/cr_constants/cr-franklin.json @@ -13,7 +13,7 @@ "order": 1, "stops": { "0": [], - "1": [] + "1": ["CR-Franklin_1_FB-0303-S"] } }, { @@ -22,8 +22,8 @@ "branches": null, "order": 2, "stops": { - "0": [], - "1": [] + "0": ["CR-Franklin_0_FB-0275-S"], + "1": ["CR-Franklin_1_FB-0275-S"] } }, { @@ -32,8 +32,8 @@ "branches": null, "order": 3, "stops": { - "0": [], - "1": [] + "0": ["CR-Franklin_0_FB-0230-S"], + "1": ["CR-Franklin_1_FB-0230-S"] } }, { @@ -43,7 +43,7 @@ "order": 4, "stops": { "0": [], - "1": [] + "1": ["CR-Franklin_1_FS-0049-S"] } }, { @@ -52,8 +52,8 @@ "branches": null, "order": 5, "stops": { - "0": [], - "1": [] + "0": ["CR-Franklin_0_FB-0191-S"], + "1": ["CR-Franklin_1_FB-0191-S"] } }, { @@ -62,8 +62,8 @@ "branches": null, "order": 6, "stops": { - "0": [], - "1": [] + "0": ["CR-Franklin_0_FB-0166-S"], + "1": ["CR-Franklin_1_FB-0166-S"] } }, { @@ -72,8 +72,8 @@ "branches": null, "order": 7, "stops": { - "0": [], - "1": [] + "0": ["CR-Franklin_0_FB-0148-01"], + "1": ["CR-Franklin_1_FB-0148-02"] } }, { @@ -82,8 +82,8 @@ "branches": null, "order": 8, "stops": { - "0": [], - "1": [] + "0": ["CR-Franklin_0_FB-0143-01"], + "1": ["CR-Franklin_1_FB-0143-02"] } }, { @@ -92,8 +92,8 @@ "branches": null, "order": 9, "stops": { - "0": [], - "1": [] + "0": ["CR-Franklin_0_FB-0125-01"], + "1": ["CR-Franklin_1_FB-0125-02"] } }, { @@ -102,8 +102,8 @@ "branches": null, "order": 10, "stops": { - "0": [], - "1": [] + "0": ["CR-Franklin_0_FB-0118-01"], + "1": ["CR-Franklin_1_FB-0118-02"] } }, { @@ -112,8 +112,8 @@ "branches": null, "order": 11, "stops": { - "0": [], - "1": [] + "0": ["CR-Franklin_0_FB-0109-01"], + "1": ["CR-Franklin_1_FB-0109-02"] } }, { @@ -122,8 +122,8 @@ "branches": null, "order": 12, "stops": { - "0": [], - "1": [] + "0": ["CR-Franklin_0_FB-0095-05"], + "1": ["CR-Franklin_1_FB-0095-05"] } }, { @@ -132,7 +132,7 @@ "branches": null, "order": 13, "stops": { - "0": [], + "0": ["CR-Franklin_0_NEC-2237-03"], "1": [] } }, @@ -142,8 +142,8 @@ "branches": null, "order": 14, "stops": { - "0": [], - "1": [] + "0": ["CR-Franklin_0_NEC-2265-01"], + "1": ["CR-Franklin_1_NEC-2265-03"] } }, { @@ -152,8 +152,8 @@ "branches": null, "order": 15, "stops": { - "0": [], - "1": [] + "0": ["CR-Franklin_0_NEC-2276-01"], + "1": ["CR-Franklin_1_NEC-2276-03"] } }, { @@ -162,8 +162,25 @@ "branches": null, "order": 16, "stops": { - "0": [], - "1": [] + "0": [ + "CR-Franklin_0_NEC-2287", + "CR-Franklin_0_DB-2205-01", + "CR-Franklin_0_DB-2222-01", + "CR-Franklin_0_DB-2230-01", + "CR-Franklin_0_DB-2240-01", + "CR-Franklin_0_DB-2249-01", + "CR-Franklin_0_DB-2258-01", + "CR-Franklin_0_DB-2265-01" + ], + "1": [ + "CR-Franklin_1_DB-2205-02", + "CR-Franklin_1_DB-2222-02", + "CR-Franklin_1_DB-2230-02", + "CR-Franklin_1_DB-2240-02", + "CR-Franklin_1_DB-2249-02", + "CR-Franklin_1_DB-2258-02", + "CR-Franklin_1_DB-2265-02" + ] } }, { @@ -172,7 +189,7 @@ "branches": null, "order": 17, "stops": { - "0": [], + "0": ["CR-Franklin_0_NEC-2203-03"], "1": [] } } diff --git a/common/constants/cr_constants/cr-lowell.json b/common/constants/cr_constants/cr-lowell.json index 094b16d85..9920df60b 100644 --- a/common/constants/cr_constants/cr-lowell.json +++ b/common/constants/cr_constants/cr-lowell.json @@ -72,8 +72,8 @@ "branches": null, "order": 7, "stops": { - "0": [], - "1": [] + "0": ["CR-Lowell_0_BNT-0000"], + "1": ["CR-Lowell_1_BNT-0000"] } } ] diff --git a/server/chalicelib/data_funcs.py b/server/chalicelib/data_funcs.py index 854249224..896327ed5 100644 --- a/server/chalicelib/data_funcs.py +++ b/server/chalicelib/data_funcs.py @@ -134,7 +134,7 @@ def process_mbta_headways(stops, sdate, edate=None): return sorted(headways, key=lambda x: x["current_dep_dt"]) -def travel_times(sdate, from_stops, to_stops, edate=None): +def travel_times(sdate: date, from_stops: list, to_stops: list, edate=None): if edate is None: if use_S3(sdate, is_bus(from_stops)) or use_S3(sdate, is_cr(from_stops)): return s3_historical.travel_times(from_stops, to_stops, sdate, sdate) diff --git a/server/chalicelib/s3.py b/server/chalicelib/s3.py index 98e771f20..38c1486b4 100644 --- a/server/chalicelib/s3.py +++ b/server/chalicelib/s3.py @@ -86,7 +86,7 @@ def parallel_download_events(datestop): return download_one_event_file(date, stop) -def download_events(sdate, edate, stops): +def download_events(sdate, edate, stops: list): # This used to be month_range but updated to date_range to support live ranges # If something breaks, this may be why datestops = itertools.product(parallel.date_range(sdate, edate), stops) diff --git a/server/chalicelib/s3_historical.py b/server/chalicelib/s3_historical.py index 0c50d88eb..d126edb8c 100644 --- a/server/chalicelib/s3_historical.py +++ b/server/chalicelib/s3_historical.py @@ -97,7 +97,7 @@ def headways(stop_ids, sdate, edate): return headways -def travel_times(stops_a, stops_b, sdate, edate): +def travel_times(stops_a: list, stops_b: list, sdate, edate): rows_by_time_a = s3.download_events(sdate, edate, stops_a) rows_by_time_b = s3.download_events(sdate, edate, stops_b) From 94b1f5a07e9eecfbe2d185edccc924bf8d3aed5c Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Sat, 23 Dec 2023 16:33:30 -0500 Subject: [PATCH 15/53] Populating stations --- .../constants/cr_constants/cr-fitchburg.json | 66 ++++++++--------- .../constants/cr_constants/cr-franklin.json | 10 ++- server/scripts/generate_line_file.py | 18 ++--- server/scripts/stops_to_parent.py | 70 +++++++++++++++++++ 4 files changed, 114 insertions(+), 50 deletions(-) create mode 100644 server/scripts/stops_to_parent.py diff --git a/common/constants/cr_constants/cr-fitchburg.json b/common/constants/cr_constants/cr-fitchburg.json index 5e116ba2c..6b831adec 100644 --- a/common/constants/cr_constants/cr-fitchburg.json +++ b/common/constants/cr_constants/cr-fitchburg.json @@ -13,7 +13,7 @@ "order": 1, "stops": { "0": [], - "1": [] + "1": ["CR-Fitchburg_1_FR-3338-CS"] } }, { @@ -22,8 +22,8 @@ "branches": null, "order": 2, "stops": { - "0": [], - "1": [] + "0": ["CR-Fitchburg_0_FR-0494-CS"], + "1": ["CR-Fitchburg_1_FR-0494-CS"] } }, { @@ -32,8 +32,8 @@ "branches": null, "order": 3, "stops": { - "0": [], - "1": [] + "0": ["CR-Fitchburg_0_FR-0451-01"], + "1": ["CR-Fitchburg_1_FR-0451-02"] } }, { @@ -42,8 +42,8 @@ "branches": null, "order": 4, "stops": { - "0": [], - "1": [] + "0": ["CR-Fitchburg_0_FR-0394-01"], + "1": ["CR-Fitchburg_1_FR-0394-02"] } }, { @@ -52,8 +52,8 @@ "branches": null, "order": 5, "stops": { - "0": [], - "1": [] + "0": ["CR-Fitchburg_0_FR-0361-01"], + "1": ["CR-Fitchburg_1_FR-0361-02"] } }, { @@ -62,8 +62,8 @@ "branches": null, "order": 6, "stops": { - "0": [], - "1": [] + "0": ["CR-Fitchburg_0_FR-0301-01"], + "1": ["CR-Fitchburg_1_FR-0301-02"] } }, { @@ -72,8 +72,8 @@ "branches": null, "order": 7, "stops": { - "0": [], - "1": [] + "0": ["CR-Fitchburg_0_FR-0253-01"], + "1": ["CR-Fitchburg_1_FR-0253-02"] } }, { @@ -82,8 +82,8 @@ "branches": null, "order": 8, "stops": { - "0": [], - "1": [] + "0": ["CR-Fitchburg_0_FR-0219-01"], + "1": ["CR-Fitchburg_1_FR-0219-02"] } }, { @@ -92,8 +92,8 @@ "branches": null, "order": 9, "stops": { - "0": [], - "1": [] + "0": ["CR-Fitchburg_0_FR-0201-01"], + "1": ["CR-Fitchburg_1_FR-0201-02"] } }, { @@ -102,8 +102,8 @@ "branches": null, "order": 10, "stops": { - "0": [], - "1": [] + "0": ["CR-Fitchburg_0_FR-0167-01"], + "1": ["CR-Fitchburg_1_FR-0167-02"] } }, { @@ -112,8 +112,8 @@ "branches": null, "order": 11, "stops": { - "0": [], - "1": [] + "0": ["CR-Fitchburg_0_FR-0132-01"], + "1": ["CR-Fitchburg_1_FR-0132-02"] } }, { @@ -122,8 +122,8 @@ "branches": null, "order": 12, "stops": { - "0": [], - "1": [] + "0": ["CR-Fitchburg_0_FR-0115-01"], + "1": ["CR-Fitchburg_1_FR-0115-02"] } }, { @@ -132,8 +132,8 @@ "branches": null, "order": 13, "stops": { - "0": [], - "1": [] + "0": ["CR-Fitchburg_0_FR-0098-01"], + "1": ["CR-Fitchburg_1_FR-0098-S"] } }, { @@ -142,8 +142,8 @@ "branches": null, "order": 14, "stops": { - "0": [], - "1": [] + "0": ["CR-Fitchburg_0_FR-0074-01"], + "1": ["CR-Fitchburg_1_FR-0074-02"] } }, { @@ -152,8 +152,8 @@ "branches": null, "order": 15, "stops": { - "0": [], - "1": [] + "0": ["CR-Fitchburg_0_FR-0064-01"], + "1": ["CR-Fitchburg_1_FR-0064-02"] } }, { @@ -162,8 +162,8 @@ "branches": null, "order": 16, "stops": { - "0": [], - "1": [] + "0": ["CR-Fitchburg_0_FR-0034-01"], + "1": ["CR-Fitchburg_1_FR-0034-02"] } }, { @@ -172,8 +172,8 @@ "branches": null, "order": 17, "stops": { - "0": [], - "1": [] + "0": ["CR-Fitchburg_0_BNT-0000"], + "1": ["CR-Fitchburg_0_BNT-0000-08"] } } ] diff --git a/common/constants/cr_constants/cr-franklin.json b/common/constants/cr_constants/cr-franklin.json index da3069a95..51918065e 100644 --- a/common/constants/cr_constants/cr-franklin.json +++ b/common/constants/cr_constants/cr-franklin.json @@ -122,8 +122,8 @@ "branches": null, "order": 12, "stops": { - "0": ["CR-Franklin_0_FB-0095-05"], - "1": ["CR-Franklin_1_FB-0095-05"] + "0": ["CR-Franklin_0_FB-0095-04", "CR-Franklin_0_FB-0095-05"], + "1": ["CR-Franklin_1_FB-0095-04", "CR-Franklin_1_FB-0095-05"] } }, { @@ -152,7 +152,11 @@ "branches": null, "order": 15, "stops": { - "0": ["CR-Franklin_0_NEC-2276-01"], + "0": [ + "CR-Franklin_0_NEC-2276-01", + "CR-Franklin_0_NEC-2276-01", + "CR-Franklin_0_NEC-2276-01" + ], "1": ["CR-Franklin_1_NEC-2276-03"] } }, diff --git a/server/scripts/generate_line_file.py b/server/scripts/generate_line_file.py index a38bf8e12..03b9da30c 100644 --- a/server/scripts/generate_line_file.py +++ b/server/scripts/generate_line_file.py @@ -2,7 +2,7 @@ import requests -r_f = requests.get("https://api-v3.mbta.com/stops?filter%5Broute%5D=CR-Kingston&include=child_stops") +r_f = requests.get("https://api-v3.mbta.com/stops?filter%5Broute%5D=CR-Franklin") stops = r_f.json() stops_formatted = [ @@ -16,18 +16,8 @@ for index, stop in enumerate(stops["data"]) ] -for index, stop in enumerate(stops["data"]): - for platform in stop["relationships"]["child_stops"]["data"]: - if ( - platform["type"] == "stop" - and "door-" not in platform["id"] - and "node-" not in platform["id"] - and not platform["id"].isnumeric() - ): - print('"{}",'.format(platform["id"])) - output = { - "CR-Lowell": { + "CR-Franklin": { "type": "commuter-rail", "direction": {"0": "outbound", "1": "inbound"}, "stations": stops_formatted, @@ -36,5 +26,5 @@ out_json = json.dumps(output, indent=2) -# with open("../common/constants/cr_constants/cr-foxboro.json", "w") as f: -# f.write(out_json) +with open("../common/constants/cr_constants/cr-franklin.json", "w") as f: + f.write(out_json) diff --git a/server/scripts/stops_to_parent.py b/server/scripts/stops_to_parent.py new file mode 100644 index 000000000..2c6fb3831 --- /dev/null +++ b/server/scripts/stops_to_parent.py @@ -0,0 +1,70 @@ +import json +import os +import requests + +MBTA_V3_API_KEY = os.environ.get("MBTA_V3_API_KEY", "") + +stop_names = [ + "CR-Fitchburg_0_BNT-0000", + "CR-Fitchburg_0_BNT-0000-08", + "CR-Fitchburg_0_FR-0034-01", + "CR-Fitchburg_0_FR-0064-01", + "CR-Fitchburg_0_FR-0074-01", + "CR-Fitchburg_0_FR-0098-01", + "CR-Fitchburg_0_FR-0115-01", + "CR-Fitchburg_0_FR-0132-01", + "CR-Fitchburg_0_FR-0167-01", + "CR-Fitchburg_0_FR-0201-01", + "CR-Fitchburg_0_FR-0219-01", + "CR-Fitchburg_0_FR-0253-01", + "CR-Fitchburg_0_FR-0301-01", + "CR-Fitchburg_0_FR-0361-01", + "CR-Fitchburg_0_FR-0394-01", + "CR-Fitchburg_0_FR-0451-01", + "CR-Fitchburg_0_FR-0494-CS", + "CR-Fitchburg_1_FR-0034-02", + "CR-Fitchburg_1_FR-0064-02", + "CR-Fitchburg_1_FR-0074-02", + "CR-Fitchburg_1_FR-0098-S", + "CR-Fitchburg_1_FR-0115-02", + "CR-Fitchburg_1_FR-0132-02", + "CR-Fitchburg_1_FR-0167-02", + "CR-Fitchburg_1_FR-0201-02", + "CR-Fitchburg_1_FR-0219-02", + "CR-Fitchburg_1_FR-0253-02", + "CR-Fitchburg_1_FR-0301-02", + "CR-Fitchburg_1_FR-0361-02", + "CR-Fitchburg_1_FR-0394-02", + "CR-Fitchburg_1_FR-0451-02", + "CR-Fitchburg_1_FR-0494-CS", + "CR-Fitchburg_1_FR-3338-CS", +] + +stop_ids = [] + +for stop in stop_names: + stop_ids.append({"id": stop[15:], "name": stop}) + +parent_children_map = {} + +for stop in stop_ids: + try: + r_f = requests.get( + "https://api-v3.mbta.com/stops/{}?include=parent_station&api_key={}".format(stop["id"], MBTA_V3_API_KEY) + ) + stop_details = r_f.json() + + parent_id = stop_details["data"]["relationships"]["parent_station"]["data"]["id"] + + if parent_id not in parent_children_map: + parent_children_map[parent_id] = [stop["name"]] + else: + parent_children_map[parent_id].append(stop["name"]) + except: + print("Error with stop: {}".format(stop["name"])) + +print(parent_children_map) + +out_json = json.dumps(parent_children_map, indent=2) +with open("./mapping.json", "w") as f: + f.write(out_json) From b23874efc77c5e3f959c3120ef8e48eec50fb14e Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Tue, 26 Dec 2023 11:39:37 -0500 Subject: [PATCH 16/53] Adding more lines --- .../constants/cr_constants/cr-greenbush.json | 111 ++++++++++ .../constants/cr_constants/cr-haverhill.json | 161 +++++++++++++++ common/constants/cr_constants/cr-lowell.json | 4 +- .../constants/cr_constants/cr-worcester.json | 195 ++++++++++++++++++ common/constants/stations.ts | 6 + common/types/lines.ts | 5 +- 6 files changed, 479 insertions(+), 3 deletions(-) create mode 100644 common/constants/cr_constants/cr-greenbush.json create mode 100644 common/constants/cr_constants/cr-haverhill.json create mode 100644 common/constants/cr_constants/cr-worcester.json diff --git a/common/constants/cr_constants/cr-greenbush.json b/common/constants/cr_constants/cr-greenbush.json new file mode 100644 index 000000000..401c92e64 --- /dev/null +++ b/common/constants/cr_constants/cr-greenbush.json @@ -0,0 +1,111 @@ +{ + "CR-Greenbush": { + "type": "commuter-rail", + "direction": { + "0": "outbound", + "1": "inbound" + }, + "stations": [ + { + "stop_name": "Greenbush", + "station": "place-GRB-0276", + "branches": null, + "order": 1, + "stops": { + "0": [], + "1": ["CR-Greenbush_1_GRB-0276-S"] + } + }, + { + "stop_name": "North Scituate", + "station": "place-GRB-0233", + "branches": null, + "order": 2, + "stops": { + "0": ["CR-Greenbush_0_GRB-0233-S"], + "1": ["CR-Greenbush_1_GRB-0233-S"] + } + }, + { + "stop_name": "Cohasset", + "station": "place-GRB-0199", + "branches": null, + "order": 3, + "stops": { + "0": ["CR-Greenbush_0_GRB-0199-S"], + "1": ["CR-Greenbush_1_GRB-0199-S"] + } + }, + { + "stop_name": "Nantasket Junction", + "station": "place-GRB-0183", + "branches": null, + "order": 4, + "stops": { + "0": ["CR-Greenbush_0_GRB-0183-S"], + "1": ["CR-Greenbush_1_GRB-0183-S"] + } + }, + { + "stop_name": "West Hingham", + "station": "place-GRB-0162", + "branches": null, + "order": 5, + "stops": { + "0": ["CR-Greenbush_0_GRB-0162-S"], + "1": ["CR-Greenbush_1_GRB-0162-S"] + } + }, + { + "stop_name": "East Weymouth", + "station": "place-GRB-0146", + "branches": null, + "order": 6, + "stops": { + "0": ["CR-Greenbush_0_GRB-0146-S"], + "1": ["CR-Greenbush_1_GRB-0146-S"] + } + }, + { + "stop_name": "Weymouth Landing/East Braintree", + "station": "place-GRB-0118", + "branches": null, + "order": 7, + "stops": { + "0": ["CR-Greenbush_0_GRB-0118-S"], + "1": ["CR-Greenbush_1_GRB-0118-S"] + } + }, + { + "stop_name": "Quincy Center", + "station": "place-qnctr", + "branches": null, + "order": 8, + "stops": { + "0": ["CR-Greenbush_0_MM-0079-S"], + "1": ["CR-Greenbush_1_MM-0079-S"] + } + }, + { + "stop_name": "JFK/UMass", + "station": "place-jfk", + "branches": null, + "order": 9, + "stops": { + "0": ["CR-Greenbush_0_MM-0023-S"], + "1": ["CR-Greenbush_1_MM-0023-S"] + } + }, + { + "stop_name": "South Station", + "station": "place-sstat", + "branches": null, + "order": 10, + "stops": { + "0": ["CR-Greenbush_0_NEC-2287"], + "1": ["CR-Greenbush_0_NEC-2287-13"] + } + } + ] + } +} diff --git a/common/constants/cr_constants/cr-haverhill.json b/common/constants/cr_constants/cr-haverhill.json new file mode 100644 index 000000000..b3e277408 --- /dev/null +++ b/common/constants/cr_constants/cr-haverhill.json @@ -0,0 +1,161 @@ +{ + "CR-Haverhill": { + "type": "commuter-rail", + "direction": { + "0": "outbound", + "1": "inbound" + }, + "stations": [ + { + "stop_name": "Haverhill", + "station": "place-WR-0329", + "branches": null, + "order": 1, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "Bradford", + "station": "place-WR-0325", + "branches": null, + "order": 2, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "Lawrence", + "station": "place-WR-0264", + "branches": null, + "order": 3, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "Andover", + "station": "place-WR-0228", + "branches": null, + "order": 4, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "Ballardvale", + "station": "place-WR-0205", + "branches": null, + "order": 5, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "North Wilmington", + "station": "place-WR-0163", + "branches": null, + "order": 6, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "Reading", + "station": "place-WR-0120", + "branches": null, + "order": 7, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "Wakefield", + "station": "place-WR-0099", + "branches": null, + "order": 8, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "Greenwood", + "station": "place-WR-0085", + "branches": null, + "order": 9, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "Melrose Highlands", + "station": "place-WR-0075", + "branches": null, + "order": 10, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "Melrose/Cedar Park", + "station": "place-WR-0067", + "branches": null, + "order": 11, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "Wyoming Hill", + "station": "place-WR-0062", + "branches": null, + "order": 12, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "Oak Grove", + "station": "place-ogmnl", + "branches": null, + "order": 13, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "Malden Center", + "station": "place-mlmnl", + "branches": null, + "order": 14, + "stops": { + "0": [], + "1": [] + } + }, + { + "stop_name": "North Station", + "station": "place-north", + "branches": null, + "order": 15, + "stops": { + "0": [], + "1": [] + } + } + ] + } +} diff --git a/common/constants/cr_constants/cr-lowell.json b/common/constants/cr_constants/cr-lowell.json index 9920df60b..4ae742ec4 100644 --- a/common/constants/cr_constants/cr-lowell.json +++ b/common/constants/cr_constants/cr-lowell.json @@ -72,8 +72,8 @@ "branches": null, "order": 7, "stops": { - "0": ["CR-Lowell_0_BNT-0000"], - "1": ["CR-Lowell_1_BNT-0000"] + "0": ["CR-Lowell_0_BNT-0000", "CR-Lowell_0_BNT-0000-09"], + "1": ["CR-Lowell_1_BNT-0000", "CR-Lowell_1_BNT-0000-09"] } } ] diff --git a/common/constants/cr_constants/cr-worcester.json b/common/constants/cr_constants/cr-worcester.json new file mode 100644 index 000000000..526bf9690 --- /dev/null +++ b/common/constants/cr_constants/cr-worcester.json @@ -0,0 +1,195 @@ +{ + "CR-Worcester": { + "type": "commuter-rail", + "direction": { + "0": "outbound", + "1": "inbound" + }, + "stations": [ + { + "stop_name": "Worcester", + "station": "place-WML-0442", + "branches": null, + "order": 1, + "stops": { + "0": [], + "1": ["CR-Worcester_1_WML-0442-CS"] + } + }, + { + "stop_name": "Grafton", + "station": "place-WML-0364", + "branches": null, + "order": 2, + "stops": { + "0": ["CR-Worcester_0_WML-0364-01"], + "1": ["CR-Worcester_1_WML-0364-02"] + } + }, + { + "stop_name": "Westborough", + "station": "place-WML-0340", + "branches": null, + "order": 3, + "stops": { + "0": ["CR-Worcester_0_WML-0340-01"], + "1": ["CR-Worcester_1_WML-0340-02"] + } + }, + { + "stop_name": "Southborough", + "station": "place-WML-0274", + "branches": null, + "order": 4, + "stops": { + "0": ["CR-Worcester_0_WML-0274-01"], + "1": ["CR-Worcester_1_WML-0274-02"] + } + }, + { + "stop_name": "Ashland", + "station": "place-WML-0252", + "branches": null, + "order": 5, + "stops": { + "0": ["CR-Worcester_0_WML-0252-01"], + "1": ["CR-Worcester_1_WML-0252-02"] + } + }, + { + "stop_name": "Framingham", + "station": "place-WML-0214", + "branches": null, + "order": 6, + "stops": { + "0": ["CR-Worcester_0_WML-0214-01", "CR-Worcester_0_WML-0214-02"], + "1": ["CR-Worcester_1_WML-0214-01", "CR-Worcester_1_WML-0214-02"] + } + }, + { + "stop_name": "West Natick", + "station": "place-WML-0199", + "branches": null, + "order": 7, + "stops": { + "0": ["CR-Worcester_0_WML-0199-01", "CR-Worcester_0_WML-0199-02"], + "1": ["CR-Worcester_1_WML-0199-01", "CR-Worcester_1_WML-0199-02"] + } + }, + { + "stop_name": "Natick Center", + "station": "place-WML-0177", + "branches": null, + "order": 8, + "stops": { + "0": ["CR-Worcester_0_WML-0177-01", "CR-Worcester_0_WML-0177-02"], + "1": ["CR-Worcester_1_WML-0177-01", "CR-Worcester_1_WML-0177-02"] + } + }, + { + "stop_name": "Wellesley Square", + "station": "place-WML-0147", + "branches": null, + "order": 9, + "stops": { + "0": ["CR-Worcester_0_WML-0147-01", "CR-Worcester_0_WML-0147-02"], + "1": ["CR-Worcester_1_WML-0147-01", "CR-Worcester_1_WML-0147-02"] + } + }, + { + "stop_name": "Wellesley Hills", + "station": "place-WML-0135", + "branches": null, + "order": 10, + "stops": { + "0": ["CR-Worcester_0_WML-0135-01", "CR-Worcester_0_WML-0135-02"], + "1": ["CR-Worcester_1_WML-0135-01", "CR-Worcester_1_WML-0135-02"] + } + }, + { + "stop_name": "Wellesley Farms", + "station": "place-WML-0125", + "branches": null, + "order": 11, + "stops": { + "0": ["CR-Worcester_0_WML-0125-01", "CR-Worcester_0_WML-0125-02"], + "1": ["CR-Worcester_1_WML-0125-01", "CR-Worcester_1_WML-0125-02"] + } + }, + { + "stop_name": "Auburndale", + "station": "place-WML-0102", + "branches": null, + "order": 12, + "stops": { + "0": ["CR-Worcester_0_WML-0102-02"], + "1": ["CR-Worcester_1_WML-0102-02"] + } + }, + { + "stop_name": "West Newton", + "station": "place-WML-0091", + "branches": null, + "order": 13, + "stops": { + "0": ["CR-Worcester_0_WML-0091-02"], + "1": ["CR-Worcester_1_WML-0091-02"] + } + }, + { + "stop_name": "Newtonville", + "station": "place-WML-0081", + "branches": null, + "order": 14, + "stops": { + "0": ["CR-Worcester_0_WML-0081-02"], + "1": ["CR-Worcester_1_WML-0081-02"] + } + }, + { + "stop_name": "Boston Landing", + "station": "place-WML-0035", + "branches": null, + "order": 15, + "stops": { + "0": ["CR-Worcester_0_WML-0035-01", "CR-Worcester_0_WML-0035-02"], + "1": ["CR-Worcester_1_WML-0035-01", "CR-Worcester_1_WML-0035-02"] + } + }, + { + "stop_name": "Lansdowne", + "station": "place-WML-0025", + "branches": null, + "order": 16, + "stops": { + "0": ["CR-Worcester_0_WML-0025-07"], + "1": ["CR-Worcester_1_WML-0025-05"] + } + }, + { + "stop_name": "Back Bay", + "station": "place-bbsta", + "branches": null, + "order": 17, + "stops": { + "0": ["CR-Worcester_0_WML-0012-07"], + "1": ["CR-Worcester_1_WML-0012-05"] + } + }, + { + "stop_name": "South Station", + "station": "place-sstat", + "branches": null, + "order": 18, + "stops": { + "0": [ + "CR-Worcester_0_NEC-2287", + "CR-Worcester_0_NEC-2287-01", + "CR-Worcester_0_NEC-2287-02" + ], + "1": [] + } + } + ] + } +} diff --git a/common/constants/stations.ts b/common/constants/stations.ts index 9af32db77..45d195fe5 100644 --- a/common/constants/stations.ts +++ b/common/constants/stations.ts @@ -20,6 +20,9 @@ import cr_lowell from './cr_constants/cr-lowell.json'; import cr_fitchburg from './cr_constants/cr-fitchburg.json'; import cr_franklin from './cr_constants/cr-franklin.json'; import cr_foxboro from './cr_constants/cr-foxboro.json'; +import cr_worcester from './cr_constants/cr-worcester.json'; +import cr_haverhill from './cr_constants/cr-haverhill.json'; +import cr_greenbush from './cr_constants/cr-greenbush.json'; export const rtStations: { [key in Exclude]: LineMap } = stations_json; @@ -46,6 +49,9 @@ export const crStations: { [key: string]: LineMap } = { ...cr_fitchburg, ...cr_franklin, ...cr_foxboro, + ...cr_worcester, + ...cr_haverhill, + ...cr_greenbush, }; export const stations = { ...rtStations, Bus: busStations, 'Commuter Rail': crStations }; diff --git a/common/types/lines.ts b/common/types/lines.ts index 9bc33e7fb..4e06b8c2d 100644 --- a/common/types/lines.ts +++ b/common/types/lines.ts @@ -32,7 +32,8 @@ export type CommuterRailRoute = | 'CR-Greenbush' | 'CR-Haverhill' | 'CR-Lowell' - | 'CR-Foxboro'; + | 'CR-Foxboro' + | 'CR-Worcester'; export type LineMetadata = { name: string; @@ -89,6 +90,7 @@ export const COMMUTER_RAIL_ROUTES: CommuterRailRoute[] = [ 'CR-Haverhill', 'CR-Lowell', 'CR-Foxboro', + 'CR-Worcester', ]; export const COMMUTER_RAIL_LINE_NAMES: { [line in CommuterRailRoute]: string } = { 'CR-Fitchburg': 'Fitchburg Line', @@ -97,6 +99,7 @@ export const COMMUTER_RAIL_LINE_NAMES: { [line in CommuterRailRoute]: string } = 'CR-Haverhill': 'Haverhill Line', 'CR-Lowell': 'Lowell Line', 'CR-Foxboro': 'Foxboro Line', + 'CR-Worcester': 'Worcester Line', }; export const ALL_LINE_PATHS = RAIL_LINES.map((line) => { From 90443ff904bd292c208b865d3af8ab97b7e7dadd Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Tue, 26 Dec 2023 11:51:58 -0500 Subject: [PATCH 17/53] Adding Haverhill stops --- .../constants/cr_constants/cr-haverhill.json | 56 +++++++++---------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/common/constants/cr_constants/cr-haverhill.json b/common/constants/cr_constants/cr-haverhill.json index b3e277408..919ced4f7 100644 --- a/common/constants/cr_constants/cr-haverhill.json +++ b/common/constants/cr_constants/cr-haverhill.json @@ -13,7 +13,7 @@ "order": 1, "stops": { "0": [], - "1": [] + "1": ["CR-Haverhill_1_WR-0329-02"] } }, { @@ -22,8 +22,8 @@ "branches": null, "order": 2, "stops": { - "0": [], - "1": [] + "0": ["CR-Haverhill_0_WR-0325-01"], + "1": ["CR-Haverhill_1_WR-0325-02"] } }, { @@ -32,8 +32,8 @@ "branches": null, "order": 3, "stops": { - "0": [], - "1": [] + "0": ["CR-Haverhill_0_WR-0264-02"], + "1": ["CR-Haverhill_1_WR-0264-02"] } }, { @@ -42,8 +42,8 @@ "branches": null, "order": 4, "stops": { - "0": [], - "1": [] + "0": ["CR-Haverhill_0_WR-0228-02"], + "1": ["CR-Haverhill_1_WR-0228-02"] } }, { @@ -52,8 +52,8 @@ "branches": null, "order": 5, "stops": { - "0": [], - "1": [] + "0": ["CR-Haverhill_0_WR-0205-02"], + "1": ["CR-Haverhill_1_WR-0205-02"] } }, { @@ -62,8 +62,8 @@ "branches": null, "order": 6, "stops": { - "0": [], - "1": [] + "0": ["CR-Haverhill_0_WR-0163-S"], + "1": ["CR-Haverhill_1_WR-0163-S"] } }, { @@ -72,8 +72,8 @@ "branches": null, "order": 7, "stops": { - "0": [], - "1": [] + "0": ["CR-Haverhill_0_WR-0120-S"], + "1": ["CR-Haverhill_1_WR-0120-S"] } }, { @@ -82,8 +82,8 @@ "branches": null, "order": 8, "stops": { - "0": [], - "1": [] + "0": ["CR-Haverhill_0_WR-0099-01"], + "1": ["CR-Haverhill_1_WR-0099-02"] } }, { @@ -92,8 +92,8 @@ "branches": null, "order": 9, "stops": { - "0": [], - "1": [] + "0": ["CR-Haverhill_0_WR-0085-01"], + "1": ["CR-Haverhill_1_WR-0085-02"] } }, { @@ -102,8 +102,8 @@ "branches": null, "order": 10, "stops": { - "0": [], - "1": [] + "0": ["CR-Haverhill_0_WR-0075-01"], + "1": ["CR-Haverhill_1_WR-0075-02"] } }, { @@ -112,8 +112,8 @@ "branches": null, "order": 11, "stops": { - "0": [], - "1": [] + "0": ["CR-Haverhill_0_WR-0067-01"], + "1": ["CR-Haverhill_1_WR-0067-02"] } }, { @@ -122,8 +122,8 @@ "branches": null, "order": 12, "stops": { - "0": [], - "1": [] + "0": ["CR-Haverhill_0_WR-0062-01"], + "1": ["CR-Haverhill_1_WR-0062-02"] } }, { @@ -132,8 +132,8 @@ "branches": null, "order": 13, "stops": { - "0": [], - "1": [] + "0": ["CR-Haverhill_0_WR-0053-S"], + "1": ["CR-Haverhill_1_WR-0053-S"] } }, { @@ -142,8 +142,8 @@ "branches": null, "order": 14, "stops": { - "0": [], - "1": [] + "0": ["CR-Haverhill_0_WR-0045-S"], + "1": ["CR-Haverhill_1_WR-0045-S"] } }, { @@ -152,7 +152,7 @@ "branches": null, "order": 15, "stops": { - "0": [], + "0": ["CR-Haverhill_0_BNT-0000", "CR-Haverhill_0_BNT-0000-01"], "1": [] } } From 43db5e0307ce0dbbd36139f46cfbd71fb188fcaa Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Tue, 26 Dec 2023 12:24:34 -0500 Subject: [PATCH 18/53] Updating min dates --- common/constants/dates.ts | 2 +- common/constants/stations.ts | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/common/constants/dates.ts b/common/constants/dates.ts index ddd933fca..8ed72c1b1 100644 --- a/common/constants/dates.ts +++ b/common/constants/dates.ts @@ -40,7 +40,7 @@ const BUS_MAX_DAY = dayjs(BUS_MAX_DATE); export const BUS_MAX_DATE_MINUS_ONE_WEEK = dayjs(BUS_MAX_DATE) .subtract(7, 'days') .format(DATE_FORMAT); -export const COMMUTER_RAIL_MIN_DATE = '2023-12-15'; +export const COMMUTER_RAIL_MIN_DATE = '2023-12-22'; export const getESTDayjs = (date: string) => { return dayjs(date).tz(est); diff --git a/common/constants/stations.ts b/common/constants/stations.ts index 45d195fe5..553e80927 100644 --- a/common/constants/stations.ts +++ b/common/constants/stations.ts @@ -19,7 +19,6 @@ import bus_114_116_117 from './bus_constants/114-116-117.json'; import cr_lowell from './cr_constants/cr-lowell.json'; import cr_fitchburg from './cr_constants/cr-fitchburg.json'; import cr_franklin from './cr_constants/cr-franklin.json'; -import cr_foxboro from './cr_constants/cr-foxboro.json'; import cr_worcester from './cr_constants/cr-worcester.json'; import cr_haverhill from './cr_constants/cr-haverhill.json'; import cr_greenbush from './cr_constants/cr-greenbush.json'; @@ -48,7 +47,6 @@ export const crStations: { [key: string]: LineMap } = { ...cr_lowell, ...cr_fitchburg, ...cr_franklin, - ...cr_foxboro, ...cr_worcester, ...cr_haverhill, ...cr_greenbush, From 772d10e00bf158863dc6675c9f1bcd9a11aa6c6d Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Tue, 26 Dec 2023 15:27:45 -0500 Subject: [PATCH 19/53] Adding more lines and better stop population --- .../constants/cr_constants/cr-fairmount.json | 105 +++++++++++ .../constants/cr_constants/cr-fitchburg.json | 8 +- .../constants/cr_constants/cr-franklin.json | 29 +-- .../constants/cr_constants/cr-greenbush.json | 4 +- .../constants/cr_constants/cr-haverhill.json | 7 +- .../constants/cr_constants/cr-kingston.json | 111 ++++++++++++ common/constants/cr_constants/cr-lowell.json | 8 +- .../cr_constants/cr-middleborough.json | 111 ++++++++++++ common/constants/cr_constants/cr-needham.json | 131 ++++++++++++++ .../constants/cr_constants/cr-providence.json | 165 ++++++++++++++++++ .../constants/cr_constants/cr-worcester.json | 24 +-- common/constants/stations.ts | 10 ++ common/types/lines.ts | 22 ++- server/scripts/generate_line_file.py | 64 ++++++- server/scripts/stops_to_parent.py | 48 ++--- 15 files changed, 760 insertions(+), 87 deletions(-) create mode 100644 common/constants/cr_constants/cr-fairmount.json create mode 100644 common/constants/cr_constants/cr-kingston.json create mode 100644 common/constants/cr_constants/cr-middleborough.json create mode 100644 common/constants/cr_constants/cr-needham.json create mode 100644 common/constants/cr_constants/cr-providence.json diff --git a/common/constants/cr_constants/cr-fairmount.json b/common/constants/cr_constants/cr-fairmount.json new file mode 100644 index 000000000..458489fdd --- /dev/null +++ b/common/constants/cr_constants/cr-fairmount.json @@ -0,0 +1,105 @@ +{ + "CR-Fairmount": { + "type": "commuter-rail", + "direction": { + "0": "outbound", + "1": "inbound" + }, + "stations": [ + { + "stop_name": "Readville", + "station": "place-DB-0095", + "branches": null, + "order": 1, + "stops": { + "0": [], + "1": ["CR-Fairmount_1_FB-0095-04"] + } + }, + { + "stop_name": "Fairmount", + "station": "place-DB-2205", + "branches": null, + "order": 2, + "stops": { + "0": ["CR-Fairmount_0_DB-2205-01"], + "1": ["CR-Fairmount_1_DB-2205-02"] + } + }, + { + "stop_name": "Blue Hill Avenue", + "station": "place-DB-2222", + "branches": null, + "order": 3, + "stops": { + "0": ["CR-Fairmount_0_DB-2222-01"], + "1": ["CR-Fairmount_1_DB-2222-02"] + } + }, + { + "stop_name": "Morton Street", + "station": "place-DB-2230", + "branches": null, + "order": 4, + "stops": { + "0": ["CR-Fairmount_0_DB-2230-01"], + "1": ["CR-Fairmount_1_DB-2230-02"] + } + }, + { + "stop_name": "Talbot Avenue", + "station": "place-DB-2240", + "branches": null, + "order": 5, + "stops": { + "0": ["CR-Fairmount_0_DB-2240-01"], + "1": ["CR-Fairmount_1_DB-2240-02"] + } + }, + { + "stop_name": "Four Corners/Geneva", + "station": "place-DB-2249", + "branches": null, + "order": 6, + "stops": { + "0": ["CR-Fairmount_0_DB-2249-01"], + "1": ["CR-Fairmount_1_DB-2249-02"] + } + }, + { + "stop_name": "Uphams Corner", + "station": "place-DB-2258", + "branches": null, + "order": 7, + "stops": { + "0": ["CR-Fairmount_0_DB-2258-01"], + "1": ["CR-Fairmount_1_DB-2258-02"] + } + }, + { + "stop_name": "Newmarket", + "station": "place-DB-2265", + "branches": null, + "order": 8, + "stops": { + "0": ["CR-Fairmount_0_DB-2265-01"], + "1": ["CR-Fairmount_1_DB-2265-02"] + } + }, + { + "stop_name": "South Station", + "station": "place-sstat", + "branches": null, + "order": 9, + "stops": { + "0": [ + "CR-Fairmount_0_NEC-2287-09", + "CR-Fairmount_0_NEC-2287-10", + "CR-Fairmount_0_NEC-2287" + ], + "1": [] + } + } + ] + } +} diff --git a/common/constants/cr_constants/cr-fitchburg.json b/common/constants/cr_constants/cr-fitchburg.json index 6b831adec..5545f516e 100644 --- a/common/constants/cr_constants/cr-fitchburg.json +++ b/common/constants/cr_constants/cr-fitchburg.json @@ -172,8 +172,12 @@ "branches": null, "order": 17, "stops": { - "0": ["CR-Fitchburg_0_BNT-0000"], - "1": ["CR-Fitchburg_0_BNT-0000-08"] + "0": [ + "CR-Fitchburg_0_BNT-0000-10", + "CR-Fitchburg_0_BNT-0000-08", + "CR-Fitchburg_0_BNT-0000" + ], + "1": [] } } ] diff --git a/common/constants/cr_constants/cr-franklin.json b/common/constants/cr_constants/cr-franklin.json index 51918065e..c024a7ebd 100644 --- a/common/constants/cr_constants/cr-franklin.json +++ b/common/constants/cr_constants/cr-franklin.json @@ -133,7 +133,7 @@ "order": 13, "stops": { "0": ["CR-Franklin_0_NEC-2237-03"], - "1": [] + "1": ["CR-Franklin_1_NEC-2237-03"] } }, { @@ -152,11 +152,7 @@ "branches": null, "order": 15, "stops": { - "0": [ - "CR-Franklin_0_NEC-2276-01", - "CR-Franklin_0_NEC-2276-01", - "CR-Franklin_0_NEC-2276-01" - ], + "0": ["CR-Franklin_0_NEC-2276-01"], "1": ["CR-Franklin_1_NEC-2276-03"] } }, @@ -166,25 +162,8 @@ "branches": null, "order": 16, "stops": { - "0": [ - "CR-Franklin_0_NEC-2287", - "CR-Franklin_0_DB-2205-01", - "CR-Franklin_0_DB-2222-01", - "CR-Franklin_0_DB-2230-01", - "CR-Franklin_0_DB-2240-01", - "CR-Franklin_0_DB-2249-01", - "CR-Franklin_0_DB-2258-01", - "CR-Franklin_0_DB-2265-01" - ], - "1": [ - "CR-Franklin_1_DB-2205-02", - "CR-Franklin_1_DB-2222-02", - "CR-Franklin_1_DB-2230-02", - "CR-Franklin_1_DB-2240-02", - "CR-Franklin_1_DB-2249-02", - "CR-Franklin_1_DB-2258-02", - "CR-Franklin_1_DB-2265-02" - ] + "0": ["CR-Franklin_0_NEC-2287"], + "1": [] } }, { diff --git a/common/constants/cr_constants/cr-greenbush.json b/common/constants/cr_constants/cr-greenbush.json index 401c92e64..2a5ddd80e 100644 --- a/common/constants/cr_constants/cr-greenbush.json +++ b/common/constants/cr_constants/cr-greenbush.json @@ -102,8 +102,8 @@ "branches": null, "order": 10, "stops": { - "0": ["CR-Greenbush_0_NEC-2287"], - "1": ["CR-Greenbush_0_NEC-2287-13"] + "0": ["CR-Greenbush_0_NEC-2287", "CR-Greenbush_0_NEC-2287-13"], + "1": [] } } ] diff --git a/common/constants/cr_constants/cr-haverhill.json b/common/constants/cr_constants/cr-haverhill.json index 919ced4f7..e19548dca 100644 --- a/common/constants/cr_constants/cr-haverhill.json +++ b/common/constants/cr_constants/cr-haverhill.json @@ -152,7 +152,12 @@ "branches": null, "order": 15, "stops": { - "0": ["CR-Haverhill_0_BNT-0000", "CR-Haverhill_0_BNT-0000-01"], + "0": [ + "CR-Haverhill_0_BNT-0000-03", + "CR-Haverhill_0_BNT-0000-05", + "CR-Haverhill_0_BNT-0000-01", + "CR-Haverhill_0_BNT-0000" + ], "1": [] } } diff --git a/common/constants/cr_constants/cr-kingston.json b/common/constants/cr_constants/cr-kingston.json new file mode 100644 index 000000000..e33eacfb2 --- /dev/null +++ b/common/constants/cr_constants/cr-kingston.json @@ -0,0 +1,111 @@ +{ + "CR-Kingston": { + "type": "commuter-rail", + "direction": { + "0": "outbound", + "1": "inbound" + }, + "stations": [ + { + "stop_name": "Kingston", + "station": "place-KB-0351", + "branches": null, + "order": 1, + "stops": { + "0": [], + "1": ["CR-Kingston_1_KB-0351-S"] + } + }, + { + "stop_name": "Halifax", + "station": "place-PB-0281", + "branches": null, + "order": 2, + "stops": { + "0": ["CR-Kingston_0_PB-0281-S"], + "1": ["CR-Kingston_1_PB-0281-S"] + } + }, + { + "stop_name": "Hanson", + "station": "place-PB-0245", + "branches": null, + "order": 3, + "stops": { + "0": ["CR-Kingston_0_PB-0245-S"], + "1": ["CR-Kingston_1_PB-0245-S"] + } + }, + { + "stop_name": "Whitman", + "station": "place-PB-0212", + "branches": null, + "order": 4, + "stops": { + "0": ["CR-Kingston_0_PB-0212-S"], + "1": ["CR-Kingston_1_PB-0212-S"] + } + }, + { + "stop_name": "Abington", + "station": "place-PB-0194", + "branches": null, + "order": 5, + "stops": { + "0": ["CR-Kingston_0_PB-0194-S"], + "1": ["CR-Kingston_1_PB-0194-S"] + } + }, + { + "stop_name": "South Weymouth", + "station": "place-PB-0158", + "branches": null, + "order": 6, + "stops": { + "0": ["CR-Kingston_0_PB-0158-S"], + "1": ["CR-Kingston_1_PB-0158-S"] + } + }, + { + "stop_name": "Braintree", + "station": "place-brntn", + "branches": null, + "order": 7, + "stops": { + "0": ["CR-Kingston_0_MM-0109-S"], + "1": ["CR-Kingston_1_MM-0109-S"] + } + }, + { + "stop_name": "Quincy Center", + "station": "place-qnctr", + "branches": null, + "order": 8, + "stops": { + "0": ["CR-Kingston_0_MM-0079-S"], + "1": ["CR-Kingston_1_MM-0079-S"] + } + }, + { + "stop_name": "JFK/UMass", + "station": "place-jfk", + "branches": null, + "order": 9, + "stops": { + "0": ["CR-Kingston_0_MM-0023-S"], + "1": ["CR-Kingston_1_MM-0023-S"] + } + }, + { + "stop_name": "South Station", + "station": "place-sstat", + "branches": null, + "order": 10, + "stops": { + "0": ["CR-Kingston_0_NEC-2287"], + "1": [] + } + } + ] + } +} diff --git a/common/constants/cr_constants/cr-lowell.json b/common/constants/cr_constants/cr-lowell.json index 4ae742ec4..0da4052e8 100644 --- a/common/constants/cr_constants/cr-lowell.json +++ b/common/constants/cr_constants/cr-lowell.json @@ -12,8 +12,8 @@ "branches": null, "order": 1, "stops": { - "0": ["CR-Lowell_0_NHRML-0254-01"], - "1": ["CR-Lowell_1_NHRML-0254-02", "CR-Lowell_1_NHRML-0254-04"] + "0": [], + "1": ["CR-Lowell_1_NHRML-0254-04"] } }, { @@ -72,8 +72,8 @@ "branches": null, "order": 7, "stops": { - "0": ["CR-Lowell_0_BNT-0000", "CR-Lowell_0_BNT-0000-09"], - "1": ["CR-Lowell_1_BNT-0000", "CR-Lowell_1_BNT-0000-09"] + "0": ["CR-Lowell_0_BNT-0000-09", "CR-Lowell_0_BNT-0000", "CR-Lowell_0_BNT-0000-10"], + "1": [] } } ] diff --git a/common/constants/cr_constants/cr-middleborough.json b/common/constants/cr_constants/cr-middleborough.json new file mode 100644 index 000000000..1d74b5335 --- /dev/null +++ b/common/constants/cr_constants/cr-middleborough.json @@ -0,0 +1,111 @@ +{ + "CR-Middleborough": { + "type": "commuter-rail", + "direction": { + "0": "outbound", + "1": "inbound" + }, + "stations": [ + { + "stop_name": "Middleborough/Lakeville", + "station": "place-MM-0356", + "branches": null, + "order": 1, + "stops": { + "0": [], + "1": ["CR-Middleborough_1_MM-0356-S"] + } + }, + { + "stop_name": "Bridgewater", + "station": "place-MM-0277", + "branches": null, + "order": 2, + "stops": { + "0": ["CR-Middleborough_0_MM-0277-S"], + "1": ["CR-Middleborough_1_MM-0277-S"] + } + }, + { + "stop_name": "Campello", + "station": "place-MM-0219", + "branches": null, + "order": 3, + "stops": { + "0": ["CR-Middleborough_0_MM-0219-S"], + "1": ["CR-Middleborough_1_MM-0219-S"] + } + }, + { + "stop_name": "Brockton", + "station": "place-MM-0200", + "branches": null, + "order": 4, + "stops": { + "0": ["CR-Middleborough_0_MM-0200-S"], + "1": ["CR-Middleborough_1_MM-0200-CS"] + } + }, + { + "stop_name": "Montello", + "station": "place-MM-0186", + "branches": null, + "order": 5, + "stops": { + "0": ["CR-Middleborough_0_MM-0186-S"], + "1": ["CR-Middleborough_1_MM-0186-CS"] + } + }, + { + "stop_name": "Holbrook/Randolph", + "station": "place-MM-0150", + "branches": null, + "order": 6, + "stops": { + "0": ["CR-Middleborough_0_MM-0150-S"], + "1": ["CR-Middleborough_1_MM-0150-S"] + } + }, + { + "stop_name": "Braintree", + "station": "place-brntn", + "branches": null, + "order": 7, + "stops": { + "0": ["CR-Middleborough_0_MM-0109-S"], + "1": ["CR-Middleborough_1_MM-0109-S"] + } + }, + { + "stop_name": "Quincy Center", + "station": "place-qnctr", + "branches": null, + "order": 8, + "stops": { + "0": ["CR-Middleborough_0_MM-0079-S"], + "1": ["CR-Middleborough_1_MM-0079-S"] + } + }, + { + "stop_name": "JFK/UMass", + "station": "place-jfk", + "branches": null, + "order": 9, + "stops": { + "0": ["CR-Middleborough_0_MM-0023-S"], + "1": ["CR-Middleborough_1_MM-0023-S"] + } + }, + { + "stop_name": "South Station", + "station": "place-sstat", + "branches": null, + "order": 10, + "stops": { + "0": ["CR-Middleborough_0_NEC-2287", "CR-Middleborough_0_NEC-2287-13"], + "1": [] + } + } + ] + } +} diff --git a/common/constants/cr_constants/cr-needham.json b/common/constants/cr_constants/cr-needham.json new file mode 100644 index 000000000..50431a67e --- /dev/null +++ b/common/constants/cr_constants/cr-needham.json @@ -0,0 +1,131 @@ +{ + "CR-Needham": { + "type": "commuter-rail", + "direction": { + "0": "outbound", + "1": "inbound" + }, + "stations": [ + { + "stop_name": "Needham Heights", + "station": "place-NB-0137", + "branches": null, + "order": 1, + "stops": { + "0": [], + "1": ["CR-Needham_1_NB-0137-S"] + } + }, + { + "stop_name": "Needham Center", + "station": "place-NB-0127", + "branches": null, + "order": 2, + "stops": { + "0": ["CR-Needham_0_NB-0127-S"], + "1": ["CR-Needham_1_NB-0127-S"] + } + }, + { + "stop_name": "Needham Junction", + "station": "place-NB-0120", + "branches": null, + "order": 3, + "stops": { + "0": ["CR-Needham_0_NB-0120-S"], + "1": ["CR-Needham_1_NB-0120-S"] + } + }, + { + "stop_name": "Hersey", + "station": "place-NB-0109", + "branches": null, + "order": 4, + "stops": { + "0": ["CR-Needham_0_NB-0109-S"], + "1": ["CR-Needham_1_NB-0109-S"] + } + }, + { + "stop_name": "West Roxbury", + "station": "place-NB-0080", + "branches": null, + "order": 5, + "stops": { + "0": ["CR-Needham_0_NB-0080-S"], + "1": ["CR-Needham_1_NB-0080-S"] + } + }, + { + "stop_name": "Highland", + "station": "place-NB-0076", + "branches": null, + "order": 6, + "stops": { + "0": ["CR-Needham_0_NB-0076-S"], + "1": ["CR-Needham_1_NB-0076-S"] + } + }, + { + "stop_name": "Bellevue", + "station": "place-NB-0072", + "branches": null, + "order": 7, + "stops": { + "0": ["CR-Needham_0_NB-0072-S"], + "1": ["CR-Needham_1_NB-0072-S"] + } + }, + { + "stop_name": "Roslindale Village", + "station": "place-NB-0064", + "branches": null, + "order": 8, + "stops": { + "0": ["CR-Needham_0_NB-0064-S"], + "1": ["CR-Needham_1_NB-0064-S"] + } + }, + { + "stop_name": "Forest Hills", + "station": "place-forhl", + "branches": null, + "order": 9, + "stops": { + "0": ["CR-Needham_0_NEC-2237-03", "CR-Needham_0_NEC-2237-05"], + "1": ["CR-Needham_1_NEC-2237-05"] + } + }, + { + "stop_name": "Ruggles", + "station": "place-rugg", + "branches": null, + "order": 10, + "stops": { + "0": ["CR-Needham_0_NEC-2265-01", "CR-Needham_0_NEC-2265-03"], + "1": ["CR-Needham_1_NEC-2265-03"] + } + }, + { + "stop_name": "Back Bay", + "station": "place-bbsta", + "branches": null, + "order": 11, + "stops": { + "0": ["CR-Needham_0_NEC-2276-03", "CR-Needham_0_NEC-2276-01"], + "1": ["CR-Needham_1_NEC-2276-03"] + } + }, + { + "stop_name": "South Station", + "station": "place-sstat", + "branches": null, + "order": 12, + "stops": { + "0": ["CR-Needham_0_NEC-2287-04", "CR-Needham_0_NEC-2287"], + "1": [] + } + } + ] + } +} diff --git a/common/constants/cr_constants/cr-providence.json b/common/constants/cr_constants/cr-providence.json new file mode 100644 index 000000000..6b076c7ba --- /dev/null +++ b/common/constants/cr_constants/cr-providence.json @@ -0,0 +1,165 @@ +{ + "CR-Providence": { + "type": "commuter-rail", + "direction": { + "0": "outbound", + "1": "inbound" + }, + "stations": [ + { + "stop_name": "Wickford Junction", + "station": "place-NEC-1659", + "branches": null, + "order": 1, + "stops": { + "0": [], + "1": ["CR-Providence_1_NEC-1659-03"] + } + }, + { + "stop_name": "TF Green Airport", + "station": "place-NEC-1768", + "branches": null, + "order": 2, + "stops": { + "0": ["CR-Providence_0_NEC-1768-03"], + "1": ["CR-Providence_1_NEC-1768-03"] + } + }, + { + "stop_name": "Providence", + "station": "place-NEC-1851", + "branches": null, + "order": 3, + "stops": { + "0": ["CR-Providence_0_NEC-1851-03"], + "1": ["CR-Providence_1_NEC-1851-03"] + } + }, + { + "stop_name": "Pawtucket/Central Falls", + "station": "place-NEC-1891", + "branches": null, + "order": 4, + "stops": { + "0": ["CR-Providence_0_NEC-1891-01"], + "1": ["CR-Providence_1_NEC-1891-02"] + } + }, + { + "stop_name": "Attleboro", + "station": "place-NEC-1969", + "branches": null, + "order": 5, + "stops": { + "0": ["CR-Providence_0_NEC-1969-03"], + "1": ["CR-Providence_1_NEC-1969-04"] + } + }, + { + "stop_name": "Mansfield", + "station": "place-NEC-2040", + "branches": null, + "order": 6, + "stops": { + "0": ["CR-Providence_0_NEC-2040-01"], + "1": ["CR-Providence_1_NEC-2040-02"] + } + }, + { + "stop_name": "Sharon", + "station": "place-NEC-2108", + "branches": null, + "order": 7, + "stops": { + "0": ["CR-Providence_0_NEC-2108-01"], + "1": ["CR-Providence_1_NEC-2108-02"] + } + }, + { + "stop_name": "Stoughton", + "station": "place-SB-0189", + "branches": null, + "order": 8, + "stops": { + "0": [], + "1": ["CR-Providence_1_SB-0189-S"] + } + }, + { + "stop_name": "Canton Center", + "station": "place-SB-0156", + "branches": null, + "order": 9, + "stops": { + "0": ["CR-Providence_0_SB-0156-S"], + "1": ["CR-Providence_1_SB-0156-S"] + } + }, + { + "stop_name": "Canton Junction", + "station": "place-NEC-2139", + "branches": null, + "order": 10, + "stops": { + "0": ["CR-Providence_0_SB-0150-04", "CR-Providence_0_NEC-2139-01"], + "1": ["CR-Providence_1_NEC-2139-02", "CR-Providence_1_SB-0150-06"] + } + }, + { + "stop_name": "Route 128", + "station": "place-NEC-2173", + "branches": null, + "order": 11, + "stops": { + "0": ["CR-Providence_0_NEC-2173-01"], + "1": ["CR-Providence_1_NEC-2173-02"] + } + }, + { + "stop_name": "Hyde Park", + "station": "place-NEC-2203", + "branches": null, + "order": 12, + "stops": { + "0": ["CR-Providence_0_NEC-2203-03"], + "1": ["CR-Providence_1_NEC-2203-02"] + } + }, + { + "stop_name": "Ruggles", + "station": "place-rugg", + "branches": null, + "order": 13, + "stops": { + "0": ["CR-Providence_0_NEC-2265-03", "CR-Providence_0_NEC-2265-01"], + "1": ["CR-Providence_1_NEC-2265-02"] + } + }, + { + "stop_name": "Back Bay", + "station": "place-bbsta", + "branches": null, + "order": 14, + "stops": { + "0": ["CR-Providence_0_NEC-2276-03", "CR-Providence_0_NEC-2276-01"], + "1": ["CR-Providence_1_NEC-2276-02"] + } + }, + { + "stop_name": "South Station", + "station": "place-sstat", + "branches": null, + "order": 15, + "stops": { + "0": [ + "CR-Providence_0_NEC-2287-03", + "CR-Providence_0_NEC-2287", + "CR-Providence_0_NEC-2287-05" + ], + "1": [] + } + } + ] + } +} diff --git a/common/constants/cr_constants/cr-worcester.json b/common/constants/cr_constants/cr-worcester.json index 526bf9690..1b11cd78b 100644 --- a/common/constants/cr_constants/cr-worcester.json +++ b/common/constants/cr_constants/cr-worcester.json @@ -62,7 +62,7 @@ "branches": null, "order": 6, "stops": { - "0": ["CR-Worcester_0_WML-0214-01", "CR-Worcester_0_WML-0214-02"], + "0": ["CR-Worcester_0_WML-0214-02", "CR-Worcester_0_WML-0214-01"], "1": ["CR-Worcester_1_WML-0214-01", "CR-Worcester_1_WML-0214-02"] } }, @@ -73,7 +73,7 @@ "order": 7, "stops": { "0": ["CR-Worcester_0_WML-0199-01", "CR-Worcester_0_WML-0199-02"], - "1": ["CR-Worcester_1_WML-0199-01", "CR-Worcester_1_WML-0199-02"] + "1": ["CR-Worcester_1_WML-0199-02", "CR-Worcester_1_WML-0199-01"] } }, { @@ -82,8 +82,8 @@ "branches": null, "order": 8, "stops": { - "0": ["CR-Worcester_0_WML-0177-01", "CR-Worcester_0_WML-0177-02"], - "1": ["CR-Worcester_1_WML-0177-01", "CR-Worcester_1_WML-0177-02"] + "0": ["CR-Worcester_0_WML-0177-02", "CR-Worcester_0_WML-0177-01"], + "1": ["CR-Worcester_1_WML-0177-02", "CR-Worcester_1_WML-0177-01"] } }, { @@ -92,7 +92,7 @@ "branches": null, "order": 9, "stops": { - "0": ["CR-Worcester_0_WML-0147-01", "CR-Worcester_0_WML-0147-02"], + "0": ["CR-Worcester_0_WML-0147-02", "CR-Worcester_0_WML-0147-01"], "1": ["CR-Worcester_1_WML-0147-01", "CR-Worcester_1_WML-0147-02"] } }, @@ -102,8 +102,8 @@ "branches": null, "order": 10, "stops": { - "0": ["CR-Worcester_0_WML-0135-01", "CR-Worcester_0_WML-0135-02"], - "1": ["CR-Worcester_1_WML-0135-01", "CR-Worcester_1_WML-0135-02"] + "0": ["CR-Worcester_0_WML-0135-02", "CR-Worcester_0_WML-0135-01"], + "1": ["CR-Worcester_1_WML-0135-02", "CR-Worcester_1_WML-0135-01"] } }, { @@ -113,7 +113,7 @@ "order": 11, "stops": { "0": ["CR-Worcester_0_WML-0125-01", "CR-Worcester_0_WML-0125-02"], - "1": ["CR-Worcester_1_WML-0125-01", "CR-Worcester_1_WML-0125-02"] + "1": ["CR-Worcester_1_WML-0125-02", "CR-Worcester_1_WML-0125-01"] } }, { @@ -152,8 +152,8 @@ "branches": null, "order": 15, "stops": { - "0": ["CR-Worcester_0_WML-0035-01", "CR-Worcester_0_WML-0035-02"], - "1": ["CR-Worcester_1_WML-0035-01", "CR-Worcester_1_WML-0035-02"] + "0": ["CR-Worcester_0_WML-0035-02", "CR-Worcester_0_WML-0035-01"], + "1": ["CR-Worcester_1_WML-0035-02", "CR-Worcester_1_WML-0035-01"] } }, { @@ -183,9 +183,9 @@ "order": 18, "stops": { "0": [ - "CR-Worcester_0_NEC-2287", "CR-Worcester_0_NEC-2287-01", - "CR-Worcester_0_NEC-2287-02" + "CR-Worcester_0_NEC-2287-02", + "CR-Worcester_0_NEC-2287" ], "1": [] } diff --git a/common/constants/stations.ts b/common/constants/stations.ts index 553e80927..16fab0211 100644 --- a/common/constants/stations.ts +++ b/common/constants/stations.ts @@ -22,6 +22,11 @@ import cr_franklin from './cr_constants/cr-franklin.json'; import cr_worcester from './cr_constants/cr-worcester.json'; import cr_haverhill from './cr_constants/cr-haverhill.json'; import cr_greenbush from './cr_constants/cr-greenbush.json'; +import cr_fairmount from './cr_constants/cr-fairmount.json'; +import cr_kingston from './cr_constants/cr-kingston.json'; +import cr_middleborough from './cr_constants/cr-middleborough.json'; +import cr_needham from './cr_constants/cr-needham.json'; +import cr_providence from './cr_constants/cr-providence.json'; export const rtStations: { [key in Exclude]: LineMap } = stations_json; @@ -50,6 +55,11 @@ export const crStations: { [key: string]: LineMap } = { ...cr_worcester, ...cr_haverhill, ...cr_greenbush, + ...cr_fairmount, + ...cr_kingston, + ...cr_middleborough, + ...cr_needham, + ...cr_providence, }; export const stations = { ...rtStations, Bus: busStations, 'Commuter Rail': crStations }; diff --git a/common/types/lines.ts b/common/types/lines.ts index 4e06b8c2d..e898c5334 100644 --- a/common/types/lines.ts +++ b/common/types/lines.ts @@ -33,7 +33,13 @@ export type CommuterRailRoute = | 'CR-Haverhill' | 'CR-Lowell' | 'CR-Foxboro' - | 'CR-Worcester'; + | 'CR-Worcester' + | 'CR-Fairmount' + | 'CR-Kingston' + | 'CR-Middleborough' + | 'CR-Needham' + | 'CR-Newburyport' + | 'CR-Providence'; export type LineMetadata = { name: string; @@ -84,13 +90,19 @@ export const BUS_ROUTES: BusRoute[] = [ ]; export const COMMUTER_RAIL_ROUTES: CommuterRailRoute[] = [ + 'CR-Fairmount', 'CR-Fitchburg', + 'CR-Worcester', 'CR-Franklin', 'CR-Greenbush', 'CR-Haverhill', + 'CR-Kingston', 'CR-Lowell', + 'CR-Middleborough', + 'CR-Needham', + 'CR-Newburyport', + 'CR-Providence', 'CR-Foxboro', - 'CR-Worcester', ]; export const COMMUTER_RAIL_LINE_NAMES: { [line in CommuterRailRoute]: string } = { 'CR-Fitchburg': 'Fitchburg Line', @@ -100,6 +112,12 @@ export const COMMUTER_RAIL_LINE_NAMES: { [line in CommuterRailRoute]: string } = 'CR-Lowell': 'Lowell Line', 'CR-Foxboro': 'Foxboro Line', 'CR-Worcester': 'Worcester Line', + 'CR-Fairmount': 'Fairmount Line', + 'CR-Kingston': 'Kingston/Plymouth Line', + 'CR-Middleborough': 'Middleborough Line', + 'CR-Needham': 'Needham Line', + 'CR-Newburyport': 'Newburyport/Rockport Line', + 'CR-Providence': 'Providence/Stoughton Line', }; export const ALL_LINE_PATHS = RAIL_LINES.map((line) => { diff --git a/server/scripts/generate_line_file.py b/server/scripts/generate_line_file.py index 03b9da30c..390ca6b80 100644 --- a/server/scripts/generate_line_file.py +++ b/server/scripts/generate_line_file.py @@ -1,23 +1,79 @@ import json +import os import requests +import boto3 +import botocore +MBTA_V3_API_KEY = os.environ.get("MBTA_V3_API_KEY", "") -r_f = requests.get("https://api-v3.mbta.com/stops?filter%5Broute%5D=CR-Franklin") +LINE_KEY = "CR-Providence" +BUCKET = "tm-mbta-performance" + + +def get_line_stops(): + s3 = boto3.client("s3", config=botocore.client.Config(max_pool_connections=15)) + + objects = s3.list_objects_v2(Bucket=BUCKET, Prefix="Events-live/daily-cr-data/{}".format(LINE_KEY)) + + stop_names = set() + + for obj in objects["Contents"]: + stop_names.add(obj["Key"].split("/")[2]) + + stop_ids = [] + + for stop in stop_names: + stop_ids.append({"id": stop[(len(LINE_KEY) + 3) :], "name": stop}) + + parent_children_map = {} + + for stop in stop_ids: + try: + r_f = requests.get( + "https://api-v3.mbta.com/stops/{}?include=parent_station&api_key={}".format(stop["id"], MBTA_V3_API_KEY) + ) + stop_details = r_f.json() + + parent_id = stop_details["data"]["relationships"]["parent_station"]["data"]["id"] + + if parent_id not in parent_children_map: + if is_inbound_or_outbound(stop["name"]) == "0": + parent_children_map[parent_id] = {"0": [stop["name"]], "1": []} + else: + parent_children_map[parent_id] = {"0": [], "1": [stop["name"]]} + else: + parent_children_map[parent_id][is_inbound_or_outbound(stop["name"])].append(stop["name"]) + except: + print("Error with stop: {}".format(stop["name"])) + + return parent_children_map + + +def is_inbound_or_outbound(stop_id: str): + if "_0_" in stop_id: + return "0" + elif "_1_" in stop_id: + return "1" + + +r_f = requests.get("https://api-v3.mbta.com/stops?filter%5Broute%5D={}".format(LINE_KEY)) stops = r_f.json() +stop_layout = get_line_stops() + stops_formatted = [ { "stop_name": stop["attributes"]["name"], "station": stop["id"], "branches": None, "order": index + 1, - "stops": {0: [], 1: []}, + "stops": stop_layout[stop["id"]], } for index, stop in enumerate(stops["data"]) ] output = { - "CR-Franklin": { + LINE_KEY: { "type": "commuter-rail", "direction": {"0": "outbound", "1": "inbound"}, "stations": stops_formatted, @@ -26,5 +82,5 @@ out_json = json.dumps(output, indent=2) -with open("../common/constants/cr_constants/cr-franklin.json", "w") as f: +with open("../common/constants/cr_constants/{}.json".format(LINE_KEY.lower()), "w") as f: f.write(out_json) diff --git a/server/scripts/stops_to_parent.py b/server/scripts/stops_to_parent.py index 2c6fb3831..62775c03e 100644 --- a/server/scripts/stops_to_parent.py +++ b/server/scripts/stops_to_parent.py @@ -1,44 +1,22 @@ import json import os import requests +import boto3 +import botocore MBTA_V3_API_KEY = os.environ.get("MBTA_V3_API_KEY", "") -stop_names = [ - "CR-Fitchburg_0_BNT-0000", - "CR-Fitchburg_0_BNT-0000-08", - "CR-Fitchburg_0_FR-0034-01", - "CR-Fitchburg_0_FR-0064-01", - "CR-Fitchburg_0_FR-0074-01", - "CR-Fitchburg_0_FR-0098-01", - "CR-Fitchburg_0_FR-0115-01", - "CR-Fitchburg_0_FR-0132-01", - "CR-Fitchburg_0_FR-0167-01", - "CR-Fitchburg_0_FR-0201-01", - "CR-Fitchburg_0_FR-0219-01", - "CR-Fitchburg_0_FR-0253-01", - "CR-Fitchburg_0_FR-0301-01", - "CR-Fitchburg_0_FR-0361-01", - "CR-Fitchburg_0_FR-0394-01", - "CR-Fitchburg_0_FR-0451-01", - "CR-Fitchburg_0_FR-0494-CS", - "CR-Fitchburg_1_FR-0034-02", - "CR-Fitchburg_1_FR-0064-02", - "CR-Fitchburg_1_FR-0074-02", - "CR-Fitchburg_1_FR-0098-S", - "CR-Fitchburg_1_FR-0115-02", - "CR-Fitchburg_1_FR-0132-02", - "CR-Fitchburg_1_FR-0167-02", - "CR-Fitchburg_1_FR-0201-02", - "CR-Fitchburg_1_FR-0219-02", - "CR-Fitchburg_1_FR-0253-02", - "CR-Fitchburg_1_FR-0301-02", - "CR-Fitchburg_1_FR-0361-02", - "CR-Fitchburg_1_FR-0394-02", - "CR-Fitchburg_1_FR-0451-02", - "CR-Fitchburg_1_FR-0494-CS", - "CR-Fitchburg_1_FR-3338-CS", -] +LINE_KEY = "CR-Fitchburg" + +BUCKET = "tm-mbta-performance" +s3 = boto3.client("s3", config=botocore.client.Config(max_pool_connections=15)) + +objects = s3.list_objects_v2(Bucket=BUCKET, Prefix="Events-live/daily-cr-data/{}".format(LINE_KEY)) + +stop_names = set() + +for obj in objects["Contents"]: + stop_names.add(obj["Key"].split("/")[2]) stop_ids = [] From 85528276803e09d6c1b3b82cebf2d5b5192e3125 Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Tue, 26 Dec 2023 16:11:37 -0500 Subject: [PATCH 20/53] Clean up scripts --- server/scripts/generate_line_file.py | 32 +++++++++---------- server/scripts/stops_to_parent.py | 48 ---------------------------- 2 files changed, 15 insertions(+), 65 deletions(-) delete mode 100644 server/scripts/stops_to_parent.py diff --git a/server/scripts/generate_line_file.py b/server/scripts/generate_line_file.py index 390ca6b80..7d794e5f6 100644 --- a/server/scripts/generate_line_file.py +++ b/server/scripts/generate_line_file.py @@ -22,29 +22,27 @@ def get_line_stops(): stop_ids = [] + stop_prefix_len = len(LINE_KEY) + 3 for stop in stop_names: - stop_ids.append({"id": stop[(len(LINE_KEY) + 3) :], "name": stop}) + stop_ids.append({"id": stop[stop_prefix_len:], "name": stop}) parent_children_map = {} for stop in stop_ids: - try: - r_f = requests.get( - "https://api-v3.mbta.com/stops/{}?include=parent_station&api_key={}".format(stop["id"], MBTA_V3_API_KEY) - ) - stop_details = r_f.json() - - parent_id = stop_details["data"]["relationships"]["parent_station"]["data"]["id"] - - if parent_id not in parent_children_map: - if is_inbound_or_outbound(stop["name"]) == "0": - parent_children_map[parent_id] = {"0": [stop["name"]], "1": []} - else: - parent_children_map[parent_id] = {"0": [], "1": [stop["name"]]} + r_f = requests.get( + "https://api-v3.mbta.com/stops/{}?include=parent_station&api_key={}".format(stop["id"], MBTA_V3_API_KEY) + ) + stop_details = r_f.json() + + parent_id = stop_details["data"]["relationships"]["parent_station"]["data"]["id"] + + if parent_id not in parent_children_map: + if is_inbound_or_outbound(stop["name"]) == "0": + parent_children_map[parent_id] = {"0": [stop["name"]], "1": []} else: - parent_children_map[parent_id][is_inbound_or_outbound(stop["name"])].append(stop["name"]) - except: - print("Error with stop: {}".format(stop["name"])) + parent_children_map[parent_id] = {"0": [], "1": [stop["name"]]} + else: + parent_children_map[parent_id][is_inbound_or_outbound(stop["name"])].append(stop["name"]) return parent_children_map diff --git a/server/scripts/stops_to_parent.py b/server/scripts/stops_to_parent.py deleted file mode 100644 index 62775c03e..000000000 --- a/server/scripts/stops_to_parent.py +++ /dev/null @@ -1,48 +0,0 @@ -import json -import os -import requests -import boto3 -import botocore - -MBTA_V3_API_KEY = os.environ.get("MBTA_V3_API_KEY", "") - -LINE_KEY = "CR-Fitchburg" - -BUCKET = "tm-mbta-performance" -s3 = boto3.client("s3", config=botocore.client.Config(max_pool_connections=15)) - -objects = s3.list_objects_v2(Bucket=BUCKET, Prefix="Events-live/daily-cr-data/{}".format(LINE_KEY)) - -stop_names = set() - -for obj in objects["Contents"]: - stop_names.add(obj["Key"].split("/")[2]) - -stop_ids = [] - -for stop in stop_names: - stop_ids.append({"id": stop[15:], "name": stop}) - -parent_children_map = {} - -for stop in stop_ids: - try: - r_f = requests.get( - "https://api-v3.mbta.com/stops/{}?include=parent_station&api_key={}".format(stop["id"], MBTA_V3_API_KEY) - ) - stop_details = r_f.json() - - parent_id = stop_details["data"]["relationships"]["parent_station"]["data"]["id"] - - if parent_id not in parent_children_map: - parent_children_map[parent_id] = [stop["name"]] - else: - parent_children_map[parent_id].append(stop["name"]) - except: - print("Error with stop: {}".format(stop["name"])) - -print(parent_children_map) - -out_json = json.dumps(parent_children_map, indent=2) -with open("./mapping.json", "w") as f: - f.write(out_json) From 5917d97c0b00c4f47529820e96ac1fd50e3d2f10 Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Tue, 26 Dec 2023 20:56:28 -0500 Subject: [PATCH 21/53] Allowing commuter rail ridership fetching --- common/constants/baselines.ts | 24 +++++++++++++++++++++++- common/constants/colors.ts | 11 ++++++----- modules/ridership/RidershipDetails.tsx | 9 ++++----- modules/ridership/RidershipGraph.tsx | 5 +++-- modules/ridership/RidershipWidget.tsx | 10 ++++------ modules/ridership/utils/utils.ts | 21 ++++++++++++++++++++- 6 files changed, 60 insertions(+), 20 deletions(-) diff --git a/common/constants/baselines.ts b/common/constants/baselines.ts index 70a65ec7f..0e6ddca23 100644 --- a/common/constants/baselines.ts +++ b/common/constants/baselines.ts @@ -1,3 +1,5 @@ +import type { BusRoute, CommuterRailRoute, Line } from '../types/lines'; + // These are manually chosen based off the peak *monthly* scheduled service. Selecting highest value " export const PEAK_SCHEDULED_SERVICE = { 'line-red': 223, @@ -17,7 +19,14 @@ export const PEAK_SPEED = { }; // These are manually chosen based off the peak value. Need to be updated when all data is generated. -export const PEAK_RIDERSHIP = { +export const PEAK_RIDERSHIP: { + [key in + | Exclude + | Exclude + | CommuterRailRoute + | '114116117' + | 'DEFAULT']: number; +} = { 'line-red': 213703, 'line-orange': 169578, 'line-blue': 60129, @@ -36,6 +45,19 @@ export const PEAK_RIDERSHIP = { '77': 8015, '111': 11258, '114116117': 12867, + 'CR-Fitchburg': 0, + 'CR-Franklin': 0, + 'CR-Greenbush': 0, + 'CR-Haverhill': 0, + 'CR-Lowell': 0, + 'CR-Foxboro': 0, + 'CR-Worcester': 0, + 'CR-Fairmount': 0, + 'CR-Kingston': 0, + 'CR-Middleborough': 0, + 'CR-Needham': 0, + 'CR-Newburyport': 0, + 'CR-Providence': 0, DEFAULT: 520580, }; diff --git a/common/constants/colors.ts b/common/constants/colors.ts index 51646f430..4fa0018a5 100644 --- a/common/constants/colors.ts +++ b/common/constants/colors.ts @@ -44,11 +44,12 @@ export const CHART_COLORS = { }; export const LINE_COLORS = { - 'line-red': '#D13434', - 'line-orange': '#ed8b00', - 'line-blue': '#003da5', - 'line-green': '#00834d', - 'line-bus': '#ffc72c', + 'line-red': COLORS.mbta.red, + 'line-orange': COLORS.mbta.orange, + 'line-blue': COLORS.mbta.blue, + 'line-green': COLORS.mbta.green, + 'line-bus': COLORS.mbta.bus, + 'line-commuter-rail': COLORS.mbta.commuterRail, default: '#303030', }; diff --git a/modules/ridership/RidershipDetails.tsx b/modules/ridership/RidershipDetails.tsx index 2fd36cee8..7c2844f3e 100644 --- a/modules/ridership/RidershipDetails.tsx +++ b/modules/ridership/RidershipDetails.tsx @@ -3,22 +3,21 @@ import { useDelimitatedRoute } from '../../common/utils/router'; import { useRidershipData } from '../../common/api/hooks/ridership'; import { PageWrapper } from '../../common/layouts/PageWrapper'; import { Layout } from '../../common/layouts/layoutTypes'; -import { RIDERSHIP_KEYS } from '../../common/types/lines'; import { ChartPlaceHolder } from '../../common/components/graphics/ChartPlaceHolder'; import { ChartPageDiv } from '../../common/components/charts/ChartPageDiv'; import { WidgetDiv } from '../../common/components/widgets/WidgetDiv'; import { SPEED_RANGE_PARAM_MAP } from '../speed/constants/speeds'; import { WidgetTitle } from '../dashboard/WidgetTitle'; import { RidershipGraphWrapper } from './RidershipGraphWrapper'; +import { getRidershipLineId } from './utils/utils'; export function RidershipDetails() { const { line, - query: { startDate, endDate, busRoute }, + query: { startDate, endDate, busRoute, crRoute }, } = useDelimitatedRoute(); const config = SPEED_RANGE_PARAM_MAP.week; - const lineId = busRoute ? `line-${busRoute.replaceAll('/', '')}` : RIDERSHIP_KEYS[line ?? '']; - const lineOrRoute = busRoute ? `line-${busRoute.replaceAll('/', '')}` : line; + const lineId = getRidershipLineId(line, busRoute, crRoute); const enabled = Boolean(startDate && endDate && lineId); const ridership = useRidershipData( @@ -29,7 +28,7 @@ export function RidershipDetails() { }, enabled ); - const ridershipDataReady = !ridership.isError && startDate && endDate && lineOrRoute && line; + const ridershipDataReady = !ridership.isError && startDate && endDate && line && lineId; return ( diff --git a/modules/ridership/RidershipGraph.tsx b/modules/ridership/RidershipGraph.tsx index f5516cc3c..1cbef1739 100644 --- a/modules/ridership/RidershipGraph.tsx +++ b/modules/ridership/RidershipGraph.tsx @@ -36,16 +36,17 @@ export const RidershipGraph: React.FC = ({ const { line, linePath, - query: { busRoute }, + query: { busRoute, crRoute }, } = useDelimitatedRoute(); const { tooltipFormat, unit, callbacks } = config; const isMobile = !useBreakpoint('md'); const ref = useRef(); const chart = useMemo(() => { - const routeIndex = busRoute ? busRoute.replaceAll('/', '') : line; + const routeIndex = busRoute ? busRoute.replaceAll('/', '') : crRoute ?? line; const labels = data.map((point) => point.date); const lineColor = LINE_COLORS[line ?? 'default']; + return ( diff --git a/modules/ridership/RidershipWidget.tsx b/modules/ridership/RidershipWidget.tsx index 61d16e727..cd1746c08 100644 --- a/modules/ridership/RidershipWidget.tsx +++ b/modules/ridership/RidershipWidget.tsx @@ -7,24 +7,22 @@ import { OVERVIEW_OPTIONS, TODAY_STRING } from '../../common/constants/dates'; import { getSpeedGraphConfig } from '../speed/constants/speeds'; import { HomescreenWidgetTitle } from '../dashboard/HomescreenWidgetTitle'; import { useRidershipData } from '../../common/api/hooks/ridership'; -import { RIDERSHIP_KEYS } from '../../common/types/lines'; import { RidershipGraphWrapper } from './RidershipGraphWrapper'; +import { getRidershipLineId } from './utils/utils'; export const RidershipWidget: React.FC = () => { const { line, query } = useDelimitatedRoute(); const { startDate } = OVERVIEW_OPTIONS[query.view ?? 'year']; const endDate = TODAY_STRING; const config = getSpeedGraphConfig(dayjs(startDate), dayjs(endDate)); - const lineId = query.busRoute - ? `line-${query.busRoute.replaceAll('/', '')}` - : RIDERSHIP_KEYS[line ?? '']; - const lineOrRoute = query.busRoute ? `line-${query.busRoute.replaceAll('/', '')}` : line; + const lineId = getRidershipLineId(line, query.busRoute, query.crRoute); + const ridership = useRidershipData({ line_id: lineId, start_date: startDate, end_date: endDate, }); - const serviceReady = !ridership.isError && lineId && line && lineOrRoute; + const serviceReady = !ridership.isError && lineId && line; return ( diff --git a/modules/ridership/utils/utils.ts b/modules/ridership/utils/utils.ts index 4f57414d9..e8b771459 100644 --- a/modules/ridership/utils/utils.ts +++ b/modules/ridership/utils/utils.ts @@ -1,6 +1,11 @@ import type { RidershipCount } from '../../../common/types/dataPoints'; import { PEAK_RIDERSHIP } from '../../../common/constants/baselines'; -import type { BusRoute, Line } from '../../../common/types/lines'; +import { + RIDERSHIP_KEYS, + type BusRoute, + type CommuterRailRoute, + type Line, +} from '../../../common/types/lines'; export const getRidershipWidgetValues = ( ridership: RidershipCount[], @@ -17,3 +22,17 @@ export const getRidershipWidgetValues = ( ridership[ridership.length - 1]?.count / PEAK_RIDERSHIP[routeIndex ?? 'DEFAULT']; return { average: average, percentage: percentage, peak: peak }; }; + +export const getRidershipLineId = ( + line: Line | undefined, + busRoute?: BusRoute, + crRoute?: CommuterRailRoute +): string => { + if (busRoute) { + return `line-${busRoute.replaceAll('/', '')}`; + } else if (crRoute) { + return `line-${crRoute.substring(3)}`; + } else { + return RIDERSHIP_KEYS[line ?? '']; + } +}; From e17b3923ece1da26dab580e555db435ea65190bf Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Tue, 26 Dec 2023 21:46:14 -0500 Subject: [PATCH 22/53] Updating line files --- .../constants/cr_constants/cr-fairmount.json | 4 +- .../constants/cr_constants/cr-fitchburg.json | 1 + .../constants/cr_constants/cr-franklin.json | 8 +-- .../constants/cr_constants/cr-greenbush.json | 2 +- .../constants/cr_constants/cr-haverhill.json | 6 +- .../constants/cr_constants/cr-kingston.json | 2 +- common/constants/cr_constants/cr-lowell.json | 8 ++- common/constants/cr_constants/cr-needham.json | 4 +- .../constants/cr_constants/cr-providence.json | 10 +-- .../constants/cr_constants/cr-worcester.json | 18 ++--- server/scripts/generate_line_file.py | 70 +++++++++++-------- 11 files changed, 78 insertions(+), 55 deletions(-) diff --git a/common/constants/cr_constants/cr-fairmount.json b/common/constants/cr_constants/cr-fairmount.json index 458489fdd..c9e45f1c8 100644 --- a/common/constants/cr_constants/cr-fairmount.json +++ b/common/constants/cr_constants/cr-fairmount.json @@ -93,9 +93,9 @@ "order": 9, "stops": { "0": [ - "CR-Fairmount_0_NEC-2287-09", "CR-Fairmount_0_NEC-2287-10", - "CR-Fairmount_0_NEC-2287" + "CR-Fairmount_0_NEC-2287", + "CR-Fairmount_0_NEC-2287-09" ], "1": [] } diff --git a/common/constants/cr_constants/cr-fitchburg.json b/common/constants/cr_constants/cr-fitchburg.json index 5545f516e..765fc902e 100644 --- a/common/constants/cr_constants/cr-fitchburg.json +++ b/common/constants/cr_constants/cr-fitchburg.json @@ -174,6 +174,7 @@ "stops": { "0": [ "CR-Fitchburg_0_BNT-0000-10", + "CR-Fitchburg_0_BNT-0000-09", "CR-Fitchburg_0_BNT-0000-08", "CR-Fitchburg_0_BNT-0000" ], diff --git a/common/constants/cr_constants/cr-franklin.json b/common/constants/cr_constants/cr-franklin.json index c024a7ebd..9ea176f21 100644 --- a/common/constants/cr_constants/cr-franklin.json +++ b/common/constants/cr_constants/cr-franklin.json @@ -122,8 +122,8 @@ "branches": null, "order": 12, "stops": { - "0": ["CR-Franklin_0_FB-0095-04", "CR-Franklin_0_FB-0095-05"], - "1": ["CR-Franklin_1_FB-0095-04", "CR-Franklin_1_FB-0095-05"] + "0": ["CR-Franklin_0_FB-0095-05", "CR-Franklin_0_FB-0095-04"], + "1": ["CR-Franklin_1_FB-0095-05", "CR-Franklin_1_FB-0095-04"] } }, { @@ -142,7 +142,7 @@ "branches": null, "order": 14, "stops": { - "0": ["CR-Franklin_0_NEC-2265-01"], + "0": ["CR-Franklin_0_NEC-2265-01", "CR-Franklin_0_NEC-2265-03"], "1": ["CR-Franklin_1_NEC-2265-03"] } }, @@ -152,7 +152,7 @@ "branches": null, "order": 15, "stops": { - "0": ["CR-Franklin_0_NEC-2276-01"], + "0": ["CR-Franklin_0_NEC-2276-01", "CR-Franklin_0_NEC-2276-03"], "1": ["CR-Franklin_1_NEC-2276-03"] } }, diff --git a/common/constants/cr_constants/cr-greenbush.json b/common/constants/cr_constants/cr-greenbush.json index 2a5ddd80e..ae93bd104 100644 --- a/common/constants/cr_constants/cr-greenbush.json +++ b/common/constants/cr_constants/cr-greenbush.json @@ -102,7 +102,7 @@ "branches": null, "order": 10, "stops": { - "0": ["CR-Greenbush_0_NEC-2287", "CR-Greenbush_0_NEC-2287-13"], + "0": ["CR-Greenbush_0_NEC-2287-13", "CR-Greenbush_0_NEC-2287"], "1": [] } } diff --git a/common/constants/cr_constants/cr-haverhill.json b/common/constants/cr_constants/cr-haverhill.json index e19548dca..b8937b24c 100644 --- a/common/constants/cr_constants/cr-haverhill.json +++ b/common/constants/cr_constants/cr-haverhill.json @@ -153,10 +153,12 @@ "order": 15, "stops": { "0": [ - "CR-Haverhill_0_BNT-0000-03", "CR-Haverhill_0_BNT-0000-05", "CR-Haverhill_0_BNT-0000-01", - "CR-Haverhill_0_BNT-0000" + "CR-Haverhill_0_BNT-0000-02", + "CR-Haverhill_0_BNT-0000", + "CR-Haverhill_0_BNT-0000-04", + "CR-Haverhill_0_BNT-0000-03" ], "1": [] } diff --git a/common/constants/cr_constants/cr-kingston.json b/common/constants/cr_constants/cr-kingston.json index e33eacfb2..d0dd0f6a7 100644 --- a/common/constants/cr_constants/cr-kingston.json +++ b/common/constants/cr_constants/cr-kingston.json @@ -102,7 +102,7 @@ "branches": null, "order": 10, "stops": { - "0": ["CR-Kingston_0_NEC-2287"], + "0": ["CR-Kingston_0_NEC-2287-12", "CR-Kingston_0_NEC-2287"], "1": [] } } diff --git a/common/constants/cr_constants/cr-lowell.json b/common/constants/cr_constants/cr-lowell.json index 0da4052e8..d2cd2f5f3 100644 --- a/common/constants/cr_constants/cr-lowell.json +++ b/common/constants/cr_constants/cr-lowell.json @@ -72,7 +72,13 @@ "branches": null, "order": 7, "stops": { - "0": ["CR-Lowell_0_BNT-0000-09", "CR-Lowell_0_BNT-0000", "CR-Lowell_0_BNT-0000-10"], + "0": [ + "CR-Lowell_0_BNT-0000-09", + "CR-Lowell_0_BNT-0000", + "CR-Lowell_0_BNT-0000-06", + "CR-Lowell_0_BNT-0000-10", + "CR-Lowell_0_BNT-0000-08" + ], "1": [] } } diff --git a/common/constants/cr_constants/cr-needham.json b/common/constants/cr_constants/cr-needham.json index 50431a67e..2e267123a 100644 --- a/common/constants/cr_constants/cr-needham.json +++ b/common/constants/cr_constants/cr-needham.json @@ -102,7 +102,7 @@ "branches": null, "order": 10, "stops": { - "0": ["CR-Needham_0_NEC-2265-01", "CR-Needham_0_NEC-2265-03"], + "0": ["CR-Needham_0_NEC-2265-03", "CR-Needham_0_NEC-2265-01"], "1": ["CR-Needham_1_NEC-2265-03"] } }, @@ -112,7 +112,7 @@ "branches": null, "order": 11, "stops": { - "0": ["CR-Needham_0_NEC-2276-03", "CR-Needham_0_NEC-2276-01"], + "0": ["CR-Needham_0_NEC-2276-01", "CR-Needham_0_NEC-2276-03"], "1": ["CR-Needham_1_NEC-2276-03"] } }, diff --git a/common/constants/cr_constants/cr-providence.json b/common/constants/cr_constants/cr-providence.json index 6b076c7ba..71545d8d0 100644 --- a/common/constants/cr_constants/cr-providence.json +++ b/common/constants/cr_constants/cr-providence.json @@ -102,7 +102,7 @@ "branches": null, "order": 10, "stops": { - "0": ["CR-Providence_0_SB-0150-04", "CR-Providence_0_NEC-2139-01"], + "0": ["CR-Providence_0_NEC-2139-01", "CR-Providence_0_SB-0150-04"], "1": ["CR-Providence_1_NEC-2139-02", "CR-Providence_1_SB-0150-06"] } }, @@ -132,7 +132,7 @@ "branches": null, "order": 13, "stops": { - "0": ["CR-Providence_0_NEC-2265-03", "CR-Providence_0_NEC-2265-01"], + "0": ["CR-Providence_0_NEC-2265-01", "CR-Providence_0_NEC-2265-03"], "1": ["CR-Providence_1_NEC-2265-02"] } }, @@ -142,7 +142,7 @@ "branches": null, "order": 14, "stops": { - "0": ["CR-Providence_0_NEC-2276-03", "CR-Providence_0_NEC-2276-01"], + "0": ["CR-Providence_0_NEC-2276-01", "CR-Providence_0_NEC-2276-03"], "1": ["CR-Providence_1_NEC-2276-02"] } }, @@ -154,8 +154,8 @@ "stops": { "0": [ "CR-Providence_0_NEC-2287-03", - "CR-Providence_0_NEC-2287", - "CR-Providence_0_NEC-2287-05" + "CR-Providence_0_NEC-2287-05", + "CR-Providence_0_NEC-2287" ], "1": [] } diff --git a/common/constants/cr_constants/cr-worcester.json b/common/constants/cr_constants/cr-worcester.json index 1b11cd78b..1ffc9e8ec 100644 --- a/common/constants/cr_constants/cr-worcester.json +++ b/common/constants/cr_constants/cr-worcester.json @@ -63,7 +63,7 @@ "order": 6, "stops": { "0": ["CR-Worcester_0_WML-0214-02", "CR-Worcester_0_WML-0214-01"], - "1": ["CR-Worcester_1_WML-0214-01", "CR-Worcester_1_WML-0214-02"] + "1": ["CR-Worcester_1_WML-0214-02", "CR-Worcester_1_WML-0214-01"] } }, { @@ -73,7 +73,7 @@ "order": 7, "stops": { "0": ["CR-Worcester_0_WML-0199-01", "CR-Worcester_0_WML-0199-02"], - "1": ["CR-Worcester_1_WML-0199-02", "CR-Worcester_1_WML-0199-01"] + "1": ["CR-Worcester_1_WML-0199-01", "CR-Worcester_1_WML-0199-02"] } }, { @@ -82,7 +82,7 @@ "branches": null, "order": 8, "stops": { - "0": ["CR-Worcester_0_WML-0177-02", "CR-Worcester_0_WML-0177-01"], + "0": ["CR-Worcester_0_WML-0177-01", "CR-Worcester_0_WML-0177-02"], "1": ["CR-Worcester_1_WML-0177-02", "CR-Worcester_1_WML-0177-01"] } }, @@ -93,7 +93,7 @@ "order": 9, "stops": { "0": ["CR-Worcester_0_WML-0147-02", "CR-Worcester_0_WML-0147-01"], - "1": ["CR-Worcester_1_WML-0147-01", "CR-Worcester_1_WML-0147-02"] + "1": ["CR-Worcester_1_WML-0147-02", "CR-Worcester_1_WML-0147-01"] } }, { @@ -102,7 +102,7 @@ "branches": null, "order": 10, "stops": { - "0": ["CR-Worcester_0_WML-0135-02", "CR-Worcester_0_WML-0135-01"], + "0": ["CR-Worcester_0_WML-0135-01", "CR-Worcester_0_WML-0135-02"], "1": ["CR-Worcester_1_WML-0135-02", "CR-Worcester_1_WML-0135-01"] } }, @@ -112,7 +112,7 @@ "branches": null, "order": 11, "stops": { - "0": ["CR-Worcester_0_WML-0125-01", "CR-Worcester_0_WML-0125-02"], + "0": ["CR-Worcester_0_WML-0125-02", "CR-Worcester_0_WML-0125-01"], "1": ["CR-Worcester_1_WML-0125-02", "CR-Worcester_1_WML-0125-01"] } }, @@ -152,7 +152,7 @@ "branches": null, "order": 15, "stops": { - "0": ["CR-Worcester_0_WML-0035-02", "CR-Worcester_0_WML-0035-01"], + "0": ["CR-Worcester_0_WML-0035-01", "CR-Worcester_0_WML-0035-02"], "1": ["CR-Worcester_1_WML-0035-02", "CR-Worcester_1_WML-0035-01"] } }, @@ -183,9 +183,9 @@ "order": 18, "stops": { "0": [ + "CR-Worcester_0_NEC-2287", "CR-Worcester_0_NEC-2287-01", - "CR-Worcester_0_NEC-2287-02", - "CR-Worcester_0_NEC-2287" + "CR-Worcester_0_NEC-2287-02" ], "1": [] } diff --git a/server/scripts/generate_line_file.py b/server/scripts/generate_line_file.py index 7d794e5f6..212206038 100644 --- a/server/scripts/generate_line_file.py +++ b/server/scripts/generate_line_file.py @@ -5,10 +5,24 @@ import botocore MBTA_V3_API_KEY = os.environ.get("MBTA_V3_API_KEY", "") - -LINE_KEY = "CR-Providence" BUCKET = "tm-mbta-performance" +ROUTES_CR = [ + "CR-Fairmount", + "CR-Fitchburg", + "CR-Worcester", + "CR-Franklin", + "CR-Greenbush", + "CR-Haverhill", + "CR-Kingston", + "CR-Lowell", + "CR-Middleborough", + "CR-Needham", + "CR-Newburyport", + "CR-Providence", + "CR-Foxboro", +] + def get_line_stops(): s3 = boto3.client("s3", config=botocore.client.Config(max_pool_connections=15)) @@ -54,31 +68,31 @@ def is_inbound_or_outbound(stop_id: str): return "1" -r_f = requests.get("https://api-v3.mbta.com/stops?filter%5Broute%5D={}".format(LINE_KEY)) -stops = r_f.json() - -stop_layout = get_line_stops() - -stops_formatted = [ - { - "stop_name": stop["attributes"]["name"], - "station": stop["id"], - "branches": None, - "order": index + 1, - "stops": stop_layout[stop["id"]], +for LINE_KEY in ROUTES_CR: + r_f = requests.get("https://api-v3.mbta.com/stops?filter%5Broute%5D={}".format(LINE_KEY)) + stops = r_f.json() + + stop_layout = get_line_stops() + + stops_formatted = [ + { + "stop_name": stop["attributes"]["name"], + "station": stop["id"], + "branches": None, + "order": index + 1, + "stops": stop_layout[stop["id"]], + } + for index, stop in enumerate(stops["data"]) + ] + + output = { + LINE_KEY: { + "type": "commuter-rail", + "direction": {"0": "outbound", "1": "inbound"}, + "stations": stops_formatted, + } } - for index, stop in enumerate(stops["data"]) -] - -output = { - LINE_KEY: { - "type": "commuter-rail", - "direction": {"0": "outbound", "1": "inbound"}, - "stations": stops_formatted, - } -} - -out_json = json.dumps(output, indent=2) -with open("../common/constants/cr_constants/{}.json".format(LINE_KEY.lower()), "w") as f: - f.write(out_json) + out_json = json.dumps(output, indent=2) + with open("../common/constants/cr_constants/{}.json".format(LINE_KEY.lower()), "w") as f: + f.write(out_json) From 4f3f3370e3b4fd3e2c2274904d70b0e1e7b21330 Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Wed, 27 Dec 2023 11:31:22 -0500 Subject: [PATCH 23/53] Adding more stop ids --- common/constants/cr_constants/cr-fitchburg.json | 4 ++-- common/constants/cr_constants/cr-franklin.json | 2 +- common/constants/cr_constants/cr-haverhill.json | 8 ++++---- common/constants/cr_constants/cr-kingston.json | 2 +- common/constants/cr_constants/cr-lowell.json | 9 +++++---- .../constants/cr_constants/cr-middleborough.json | 2 +- common/constants/cr_constants/cr-worcester.json | 16 ++++++++-------- 7 files changed, 22 insertions(+), 21 deletions(-) diff --git a/common/constants/cr_constants/cr-fitchburg.json b/common/constants/cr_constants/cr-fitchburg.json index 765fc902e..7e1bb2716 100644 --- a/common/constants/cr_constants/cr-fitchburg.json +++ b/common/constants/cr_constants/cr-fitchburg.json @@ -173,9 +173,9 @@ "order": 17, "stops": { "0": [ - "CR-Fitchburg_0_BNT-0000-10", - "CR-Fitchburg_0_BNT-0000-09", "CR-Fitchburg_0_BNT-0000-08", + "CR-Fitchburg_0_BNT-0000-09", + "CR-Fitchburg_0_BNT-0000-10", "CR-Fitchburg_0_BNT-0000" ], "1": [] diff --git a/common/constants/cr_constants/cr-franklin.json b/common/constants/cr_constants/cr-franklin.json index 9ea176f21..be3f2733f 100644 --- a/common/constants/cr_constants/cr-franklin.json +++ b/common/constants/cr_constants/cr-franklin.json @@ -123,7 +123,7 @@ "order": 12, "stops": { "0": ["CR-Franklin_0_FB-0095-05", "CR-Franklin_0_FB-0095-04"], - "1": ["CR-Franklin_1_FB-0095-05", "CR-Franklin_1_FB-0095-04"] + "1": ["CR-Franklin_1_FB-0095-04", "CR-Franklin_1_FB-0095-05"] } }, { diff --git a/common/constants/cr_constants/cr-haverhill.json b/common/constants/cr_constants/cr-haverhill.json index b8937b24c..0c653c34e 100644 --- a/common/constants/cr_constants/cr-haverhill.json +++ b/common/constants/cr_constants/cr-haverhill.json @@ -153,12 +153,12 @@ "order": 15, "stops": { "0": [ - "CR-Haverhill_0_BNT-0000-05", - "CR-Haverhill_0_BNT-0000-01", - "CR-Haverhill_0_BNT-0000-02", "CR-Haverhill_0_BNT-0000", + "CR-Haverhill_0_BNT-0000-02", + "CR-Haverhill_0_BNT-0000-03", + "CR-Haverhill_0_BNT-0000-05", "CR-Haverhill_0_BNT-0000-04", - "CR-Haverhill_0_BNT-0000-03" + "CR-Haverhill_0_BNT-0000-01" ], "1": [] } diff --git a/common/constants/cr_constants/cr-kingston.json b/common/constants/cr_constants/cr-kingston.json index d0dd0f6a7..0fdfb6b5b 100644 --- a/common/constants/cr_constants/cr-kingston.json +++ b/common/constants/cr_constants/cr-kingston.json @@ -102,7 +102,7 @@ "branches": null, "order": 10, "stops": { - "0": ["CR-Kingston_0_NEC-2287-12", "CR-Kingston_0_NEC-2287"], + "0": ["CR-Kingston_0_NEC-2287", "CR-Kingston_0_NEC-2287-12"], "1": [] } } diff --git a/common/constants/cr_constants/cr-lowell.json b/common/constants/cr_constants/cr-lowell.json index d2cd2f5f3..a58b0b875 100644 --- a/common/constants/cr_constants/cr-lowell.json +++ b/common/constants/cr_constants/cr-lowell.json @@ -73,11 +73,12 @@ "order": 7, "stops": { "0": [ - "CR-Lowell_0_BNT-0000-09", - "CR-Lowell_0_BNT-0000", - "CR-Lowell_0_BNT-0000-06", "CR-Lowell_0_BNT-0000-10", - "CR-Lowell_0_BNT-0000-08" + "CR-Lowell_0_BNT-0000-07", + "CR-Lowell_0_BNT-0000", + "CR-Lowell_0_BNT-0000-09", + "CR-Lowell_0_BNT-0000-08", + "CR-Lowell_0_BNT-0000-06" ], "1": [] } diff --git a/common/constants/cr_constants/cr-middleborough.json b/common/constants/cr_constants/cr-middleborough.json index 1d74b5335..078e266b7 100644 --- a/common/constants/cr_constants/cr-middleborough.json +++ b/common/constants/cr_constants/cr-middleborough.json @@ -102,7 +102,7 @@ "branches": null, "order": 10, "stops": { - "0": ["CR-Middleborough_0_NEC-2287", "CR-Middleborough_0_NEC-2287-13"], + "0": ["CR-Middleborough_0_NEC-2287-13", "CR-Middleborough_0_NEC-2287"], "1": [] } } diff --git a/common/constants/cr_constants/cr-worcester.json b/common/constants/cr_constants/cr-worcester.json index 1ffc9e8ec..e6e4bdc91 100644 --- a/common/constants/cr_constants/cr-worcester.json +++ b/common/constants/cr_constants/cr-worcester.json @@ -63,7 +63,7 @@ "order": 6, "stops": { "0": ["CR-Worcester_0_WML-0214-02", "CR-Worcester_0_WML-0214-01"], - "1": ["CR-Worcester_1_WML-0214-02", "CR-Worcester_1_WML-0214-01"] + "1": ["CR-Worcester_1_WML-0214-01", "CR-Worcester_1_WML-0214-02"] } }, { @@ -82,7 +82,7 @@ "branches": null, "order": 8, "stops": { - "0": ["CR-Worcester_0_WML-0177-01", "CR-Worcester_0_WML-0177-02"], + "0": ["CR-Worcester_0_WML-0177-02", "CR-Worcester_0_WML-0177-01"], "1": ["CR-Worcester_1_WML-0177-02", "CR-Worcester_1_WML-0177-01"] } }, @@ -92,8 +92,8 @@ "branches": null, "order": 9, "stops": { - "0": ["CR-Worcester_0_WML-0147-02", "CR-Worcester_0_WML-0147-01"], - "1": ["CR-Worcester_1_WML-0147-02", "CR-Worcester_1_WML-0147-01"] + "0": ["CR-Worcester_0_WML-0147-01", "CR-Worcester_0_WML-0147-02"], + "1": ["CR-Worcester_1_WML-0147-01", "CR-Worcester_1_WML-0147-02"] } }, { @@ -103,7 +103,7 @@ "order": 10, "stops": { "0": ["CR-Worcester_0_WML-0135-01", "CR-Worcester_0_WML-0135-02"], - "1": ["CR-Worcester_1_WML-0135-02", "CR-Worcester_1_WML-0135-01"] + "1": ["CR-Worcester_1_WML-0135-01", "CR-Worcester_1_WML-0135-02"] } }, { @@ -112,8 +112,8 @@ "branches": null, "order": 11, "stops": { - "0": ["CR-Worcester_0_WML-0125-02", "CR-Worcester_0_WML-0125-01"], - "1": ["CR-Worcester_1_WML-0125-02", "CR-Worcester_1_WML-0125-01"] + "0": ["CR-Worcester_0_WML-0125-01", "CR-Worcester_0_WML-0125-02"], + "1": ["CR-Worcester_1_WML-0125-01", "CR-Worcester_1_WML-0125-02"] } }, { @@ -152,7 +152,7 @@ "branches": null, "order": 15, "stops": { - "0": ["CR-Worcester_0_WML-0035-01", "CR-Worcester_0_WML-0035-02"], + "0": ["CR-Worcester_0_WML-0035-02", "CR-Worcester_0_WML-0035-01"], "1": ["CR-Worcester_1_WML-0035-02", "CR-Worcester_1_WML-0035-01"] } }, From 6a42b6d5d68d27fc7d59ce8d6858ecd8b0121559 Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Sun, 7 Jan 2024 22:14:37 -0500 Subject: [PATCH 24/53] Fixing bus typing --- common/constants/baselines.ts | 5 ++--- common/types/lines.ts | 5 +++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/common/constants/baselines.ts b/common/constants/baselines.ts index d3ec215d6..e4603319b 100644 --- a/common/constants/baselines.ts +++ b/common/constants/baselines.ts @@ -1,4 +1,4 @@ -import type { BusRoute, CommuterRailRoute, Line } from '../types/lines'; +import type { BusRouteId, CommuterRailRoute, Line } from '../types/lines'; // These are manually chosen based off the peak *monthly* scheduled service. Selecting highest value " export const PEAK_SCHEDULED_SERVICE = { @@ -22,9 +22,8 @@ export const PEAK_SPEED = { export const PEAK_RIDERSHIP: { [key in | Exclude - | Exclude + | BusRouteId | CommuterRailRoute - | '114116117' | 'DEFAULT']: number; } = { 'line-red': 213703, diff --git a/common/types/lines.ts b/common/types/lines.ts index 631e616b1..af9156717 100644 --- a/common/types/lines.ts +++ b/common/types/lines.ts @@ -28,6 +28,11 @@ export type BusRoute = | '114/116/117' | '220/221/222'; +export type BusRouteId = + | Exclude + | '114116117' + | '220221222'; + /** TODO: Expand list to all lines */ export type CommuterRailRoute = | 'CR-Fitchburg' From 7e4505fce2c5010c606f0bec4f4d2564bc53911e Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Tue, 9 Jan 2024 13:55:21 -0500 Subject: [PATCH 25/53] Remove foxboro for now --- common/constants/baselines.ts | 1 - common/constants/cr_constants/cr-foxboro.json | 91 ----------------- server/scripts/generate_line_file.py | 98 ------------------- server/scripts/generate_line_files.py | 1 - 4 files changed, 191 deletions(-) delete mode 100644 common/constants/cr_constants/cr-foxboro.json delete mode 100644 server/scripts/generate_line_file.py diff --git a/common/constants/baselines.ts b/common/constants/baselines.ts index 9ac7d2191..2d862cc04 100644 --- a/common/constants/baselines.ts +++ b/common/constants/baselines.ts @@ -59,7 +59,6 @@ export const PEAK_RIDERSHIP: { 'CR-Greenbush': 0, 'CR-Haverhill': 0, 'CR-Lowell': 0, - 'CR-Foxboro': 0, 'CR-Worcester': 0, 'CR-Fairmount': 0, 'CR-Kingston': 0, diff --git a/common/constants/cr_constants/cr-foxboro.json b/common/constants/cr_constants/cr-foxboro.json deleted file mode 100644 index d26884a79..000000000 --- a/common/constants/cr_constants/cr-foxboro.json +++ /dev/null @@ -1,91 +0,0 @@ -{ - "CR-Foxboro": { - "type": "commuter-rail", - "direction": { - "0": "outbound", - "1": "inbound" - }, - "stations": [ - { - "stop_name": "Providence", - "station": "place-NEC-1851", - "branches": null, - "order": 1, - "stops": { - "0": [], - "1": [] - } - }, - { - "stop_name": "Pawtucket/Central Falls", - "station": "place-NEC-1891", - "branches": null, - "order": 2, - "stops": { - "0": [], - "1": [] - } - }, - { - "stop_name": "Attleboro", - "station": "place-NEC-1969", - "branches": null, - "order": 3, - "stops": { - "0": [], - "1": [] - } - }, - { - "stop_name": "Mansfield", - "station": "place-NEC-2040", - "branches": null, - "order": 4, - "stops": { - "0": [], - "1": [] - } - }, - { - "stop_name": "South Station", - "station": "place-sstat", - "branches": null, - "order": 5, - "stops": { - "0": [], - "1": [] - } - }, - { - "stop_name": "Back Bay", - "station": "place-bbsta", - "branches": null, - "order": 6, - "stops": { - "0": [], - "1": [] - } - }, - { - "stop_name": "Dedham Corporate Center", - "station": "place-FB-0118", - "branches": null, - "order": 7, - "stops": { - "0": [], - "1": [] - } - }, - { - "stop_name": "Foxboro", - "station": "place-FS-0049", - "branches": null, - "order": 8, - "stops": { - "0": [], - "1": [] - } - } - ] - } -} diff --git a/server/scripts/generate_line_file.py b/server/scripts/generate_line_file.py deleted file mode 100644 index 212206038..000000000 --- a/server/scripts/generate_line_file.py +++ /dev/null @@ -1,98 +0,0 @@ -import json -import os -import requests -import boto3 -import botocore - -MBTA_V3_API_KEY = os.environ.get("MBTA_V3_API_KEY", "") -BUCKET = "tm-mbta-performance" - -ROUTES_CR = [ - "CR-Fairmount", - "CR-Fitchburg", - "CR-Worcester", - "CR-Franklin", - "CR-Greenbush", - "CR-Haverhill", - "CR-Kingston", - "CR-Lowell", - "CR-Middleborough", - "CR-Needham", - "CR-Newburyport", - "CR-Providence", - "CR-Foxboro", -] - - -def get_line_stops(): - s3 = boto3.client("s3", config=botocore.client.Config(max_pool_connections=15)) - - objects = s3.list_objects_v2(Bucket=BUCKET, Prefix="Events-live/daily-cr-data/{}".format(LINE_KEY)) - - stop_names = set() - - for obj in objects["Contents"]: - stop_names.add(obj["Key"].split("/")[2]) - - stop_ids = [] - - stop_prefix_len = len(LINE_KEY) + 3 - for stop in stop_names: - stop_ids.append({"id": stop[stop_prefix_len:], "name": stop}) - - parent_children_map = {} - - for stop in stop_ids: - r_f = requests.get( - "https://api-v3.mbta.com/stops/{}?include=parent_station&api_key={}".format(stop["id"], MBTA_V3_API_KEY) - ) - stop_details = r_f.json() - - parent_id = stop_details["data"]["relationships"]["parent_station"]["data"]["id"] - - if parent_id not in parent_children_map: - if is_inbound_or_outbound(stop["name"]) == "0": - parent_children_map[parent_id] = {"0": [stop["name"]], "1": []} - else: - parent_children_map[parent_id] = {"0": [], "1": [stop["name"]]} - else: - parent_children_map[parent_id][is_inbound_or_outbound(stop["name"])].append(stop["name"]) - - return parent_children_map - - -def is_inbound_or_outbound(stop_id: str): - if "_0_" in stop_id: - return "0" - elif "_1_" in stop_id: - return "1" - - -for LINE_KEY in ROUTES_CR: - r_f = requests.get("https://api-v3.mbta.com/stops?filter%5Broute%5D={}".format(LINE_KEY)) - stops = r_f.json() - - stop_layout = get_line_stops() - - stops_formatted = [ - { - "stop_name": stop["attributes"]["name"], - "station": stop["id"], - "branches": None, - "order": index + 1, - "stops": stop_layout[stop["id"]], - } - for index, stop in enumerate(stops["data"]) - ] - - output = { - LINE_KEY: { - "type": "commuter-rail", - "direction": {"0": "outbound", "1": "inbound"}, - "stations": stops_formatted, - } - } - - out_json = json.dumps(output, indent=2) - with open("../common/constants/cr_constants/{}.json".format(LINE_KEY.lower()), "w") as f: - f.write(out_json) diff --git a/server/scripts/generate_line_files.py b/server/scripts/generate_line_files.py index ee8bf5669..c3dc7733f 100644 --- a/server/scripts/generate_line_files.py +++ b/server/scripts/generate_line_files.py @@ -20,7 +20,6 @@ "CR-Needham", "CR-Newburyport", "CR-Providence", - "CR-Foxboro", ] From 8db9c4624f8a364d1b8dcae6c04a6dff7edf2d43 Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Thu, 11 Jan 2024 14:03:10 -0500 Subject: [PATCH 26/53] Fix widget title import --- modules/tripexplorer/CommuterRailTripGraphs.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/tripexplorer/CommuterRailTripGraphs.tsx b/modules/tripexplorer/CommuterRailTripGraphs.tsx index 54da8a8e1..75d1b56f6 100644 --- a/modules/tripexplorer/CommuterRailTripGraphs.tsx +++ b/modules/tripexplorer/CommuterRailTripGraphs.tsx @@ -5,13 +5,13 @@ import type { AggregateAPIOptions, SingleDayAPIOptions } from '../../common/type import { WidgetDiv } from '../../common/components/widgets/WidgetDiv'; import { AggregateChartWrapper } from '../../common/components/charts/AggregateChartWrapper'; import { ButtonGroup } from '../../common/components/general/ButtonGroup'; -import { WidgetTitle } from '../dashboard/WidgetTitle'; import { getLocationDetails } from '../../common/utils/stations'; import type { Line } from '../../common/types/lines'; import { TravelTimesAggregateWrapper } from '../traveltimes/TravelTimesAggregateWrapper'; import { HeadwaysAggregateWrapper } from '../headways/HeadwaysAggregateWrapper'; import { TravelTimesSingleWrapper } from '../traveltimes/TravelTimesSingleWrapper'; import { HeadwaysSingleWrapper } from '../headways/HeadwaysSingleWrapper'; +import { WidgetTitle } from '../../common/components/widgets'; interface CommuterRailTripGraphsProps { fromStation: Station; From 3b102e1c9c791cfc1b27606ba1a59eae83c51f33 Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Tue, 16 Jan 2024 21:56:28 -0500 Subject: [PATCH 27/53] Updating CR line files --- .../constants/cr_constants/cr-fairmount.json | 6 +- .../constants/cr_constants/cr-fitchburg.json | 12 +- .../constants/cr_constants/cr-franklin.json | 11 +- .../constants/cr_constants/cr-greenbush.json | 7 +- .../constants/cr_constants/cr-haverhill.json | 9 +- .../constants/cr_constants/cr-kingston.json | 8 +- common/constants/cr_constants/cr-lowell.json | 10 +- .../cr_constants/cr-middleborough.json | 7 +- common/constants/cr_constants/cr-needham.json | 13 +- .../cr_constants/cr-newburyport.json | 203 ++++++++++++++++++ .../constants/cr_constants/cr-providence.json | 8 +- .../constants/cr_constants/cr-worcester.json | 21 +- server/scripts/generate_line_files.py | 79 ++++--- 13 files changed, 338 insertions(+), 56 deletions(-) create mode 100644 common/constants/cr_constants/cr-newburyport.json diff --git a/common/constants/cr_constants/cr-fairmount.json b/common/constants/cr_constants/cr-fairmount.json index c9e45f1c8..130aec312 100644 --- a/common/constants/cr_constants/cr-fairmount.json +++ b/common/constants/cr_constants/cr-fairmount.json @@ -93,9 +93,11 @@ "order": 9, "stops": { "0": [ - "CR-Fairmount_0_NEC-2287-10", + "CR-Fairmount_0_NEC-2287-09", + "CR-Fairmount_0_NEC-2287-07", "CR-Fairmount_0_NEC-2287", - "CR-Fairmount_0_NEC-2287-09" + "CR-Fairmount_0_NEC-2287-11", + "CR-Fairmount_0_NEC-2287-10" ], "1": [] } diff --git a/common/constants/cr_constants/cr-fitchburg.json b/common/constants/cr_constants/cr-fitchburg.json index 7e1bb2716..a8a998cad 100644 --- a/common/constants/cr_constants/cr-fitchburg.json +++ b/common/constants/cr_constants/cr-fitchburg.json @@ -173,10 +173,16 @@ "order": 17, "stops": { "0": [ - "CR-Fitchburg_0_BNT-0000-08", - "CR-Fitchburg_0_BNT-0000-09", + "CR-Fitchburg_0_BNT-0000-06", "CR-Fitchburg_0_BNT-0000-10", - "CR-Fitchburg_0_BNT-0000" + "CR-Fitchburg_0_BNT-0000", + "CR-Fitchburg_0_BNT-0000-02", + "CR-Fitchburg_0_BNT-0000-05", + "CR-Fitchburg_0_BNT-0000-07", + "CR-Fitchburg_0_BNT-0000-01", + "CR-Fitchburg_0_BNT-0000-09", + "CR-Fitchburg_0_BNT-0000-08", + "CR-Fitchburg_0_BNT-0000-04" ], "1": [] } diff --git a/common/constants/cr_constants/cr-franklin.json b/common/constants/cr_constants/cr-franklin.json index be3f2733f..345e0297b 100644 --- a/common/constants/cr_constants/cr-franklin.json +++ b/common/constants/cr_constants/cr-franklin.json @@ -142,7 +142,7 @@ "branches": null, "order": 14, "stops": { - "0": ["CR-Franklin_0_NEC-2265-01", "CR-Franklin_0_NEC-2265-03"], + "0": ["CR-Franklin_0_NEC-2265-03", "CR-Franklin_0_NEC-2265-01"], "1": ["CR-Franklin_1_NEC-2265-03"] } }, @@ -162,7 +162,14 @@ "branches": null, "order": 16, "stops": { - "0": ["CR-Franklin_0_NEC-2287"], + "0": [ + "CR-Franklin_0_NEC-2287-11", + "CR-Franklin_0_NEC-2287", + "CR-Franklin_0_NEC-2287-04", + "CR-Franklin_0_NEC-2287-05", + "CR-Franklin_0_NEC-2287-03", + "CR-Franklin_0_NEC-2287-07" + ], "1": [] } }, diff --git a/common/constants/cr_constants/cr-greenbush.json b/common/constants/cr_constants/cr-greenbush.json index ae93bd104..ef34b5f26 100644 --- a/common/constants/cr_constants/cr-greenbush.json +++ b/common/constants/cr_constants/cr-greenbush.json @@ -102,7 +102,12 @@ "branches": null, "order": 10, "stops": { - "0": ["CR-Greenbush_0_NEC-2287-13", "CR-Greenbush_0_NEC-2287"], + "0": [ + "CR-Greenbush_0_NEC-2287-11", + "CR-Greenbush_0_NEC-2287", + "CR-Greenbush_0_NEC-2287-13", + "CR-Greenbush_0_NEC-2287-12" + ], "1": [] } } diff --git a/common/constants/cr_constants/cr-haverhill.json b/common/constants/cr_constants/cr-haverhill.json index 0c653c34e..2c5cae1d6 100644 --- a/common/constants/cr_constants/cr-haverhill.json +++ b/common/constants/cr_constants/cr-haverhill.json @@ -153,11 +153,16 @@ "order": 15, "stops": { "0": [ + "CR-Haverhill_0_BNT-0000-10", "CR-Haverhill_0_BNT-0000", + "CR-Haverhill_0_BNT-0000-08", + "CR-Haverhill_0_BNT-0000-04", + "CR-Haverhill_0_BNT-0000-06", + "CR-Haverhill_0_BNT-0000-09", + "CR-Haverhill_0_BNT-0000-05", "CR-Haverhill_0_BNT-0000-02", "CR-Haverhill_0_BNT-0000-03", - "CR-Haverhill_0_BNT-0000-05", - "CR-Haverhill_0_BNT-0000-04", + "CR-Haverhill_0_BNT-0000-07", "CR-Haverhill_0_BNT-0000-01" ], "1": [] diff --git a/common/constants/cr_constants/cr-kingston.json b/common/constants/cr_constants/cr-kingston.json index 0fdfb6b5b..9d246ef07 100644 --- a/common/constants/cr_constants/cr-kingston.json +++ b/common/constants/cr_constants/cr-kingston.json @@ -102,7 +102,13 @@ "branches": null, "order": 10, "stops": { - "0": ["CR-Kingston_0_NEC-2287", "CR-Kingston_0_NEC-2287-12"], + "0": [ + "CR-Kingston_0_NEC-2287-12", + "CR-Kingston_0_NEC-2287-13", + "CR-Kingston_0_NEC-2287-11", + "CR-Kingston_0_NEC-2287", + "CR-Kingston_0_NEC-2287-09" + ], "1": [] } } diff --git a/common/constants/cr_constants/cr-lowell.json b/common/constants/cr_constants/cr-lowell.json index a58b0b875..5fe5dede6 100644 --- a/common/constants/cr_constants/cr-lowell.json +++ b/common/constants/cr_constants/cr-lowell.json @@ -73,12 +73,16 @@ "order": 7, "stops": { "0": [ - "CR-Lowell_0_BNT-0000-10", "CR-Lowell_0_BNT-0000-07", - "CR-Lowell_0_BNT-0000", + "CR-Lowell_0_BNT-0000-03", + "CR-Lowell_0_BNT-0000-06", "CR-Lowell_0_BNT-0000-09", + "CR-Lowell_0_BNT-0000-05", + "CR-Lowell_0_BNT-0000-10", + "CR-Lowell_0_BNT-0000-04", + "CR-Lowell_0_BNT-0000-02", "CR-Lowell_0_BNT-0000-08", - "CR-Lowell_0_BNT-0000-06" + "CR-Lowell_0_BNT-0000" ], "1": [] } diff --git a/common/constants/cr_constants/cr-middleborough.json b/common/constants/cr_constants/cr-middleborough.json index 078e266b7..9d2d52874 100644 --- a/common/constants/cr_constants/cr-middleborough.json +++ b/common/constants/cr_constants/cr-middleborough.json @@ -102,7 +102,12 @@ "branches": null, "order": 10, "stops": { - "0": ["CR-Middleborough_0_NEC-2287-13", "CR-Middleborough_0_NEC-2287"], + "0": [ + "CR-Middleborough_0_NEC-2287-13", + "CR-Middleborough_0_NEC-2287-12", + "CR-Middleborough_0_NEC-2287-11", + "CR-Middleborough_0_NEC-2287" + ], "1": [] } } diff --git a/common/constants/cr_constants/cr-needham.json b/common/constants/cr_constants/cr-needham.json index 2e267123a..9ede644da 100644 --- a/common/constants/cr_constants/cr-needham.json +++ b/common/constants/cr_constants/cr-needham.json @@ -92,7 +92,7 @@ "branches": null, "order": 9, "stops": { - "0": ["CR-Needham_0_NEC-2237-03", "CR-Needham_0_NEC-2237-05"], + "0": ["CR-Needham_0_NEC-2237-05", "CR-Needham_0_NEC-2237-03"], "1": ["CR-Needham_1_NEC-2237-05"] } }, @@ -102,7 +102,7 @@ "branches": null, "order": 10, "stops": { - "0": ["CR-Needham_0_NEC-2265-03", "CR-Needham_0_NEC-2265-01"], + "0": ["CR-Needham_0_NEC-2265-01", "CR-Needham_0_NEC-2265-03"], "1": ["CR-Needham_1_NEC-2265-03"] } }, @@ -112,7 +112,7 @@ "branches": null, "order": 11, "stops": { - "0": ["CR-Needham_0_NEC-2276-01", "CR-Needham_0_NEC-2276-03"], + "0": ["CR-Needham_0_NEC-2276-03", "CR-Needham_0_NEC-2276-01"], "1": ["CR-Needham_1_NEC-2276-03"] } }, @@ -122,7 +122,12 @@ "branches": null, "order": 12, "stops": { - "0": ["CR-Needham_0_NEC-2287-04", "CR-Needham_0_NEC-2287"], + "0": [ + "CR-Needham_0_NEC-2287-04", + "CR-Needham_0_NEC-2287-03", + "CR-Needham_0_NEC-2287-06", + "CR-Needham_0_NEC-2287" + ], "1": [] } } diff --git a/common/constants/cr_constants/cr-newburyport.json b/common/constants/cr_constants/cr-newburyport.json new file mode 100644 index 000000000..9a845d5e6 --- /dev/null +++ b/common/constants/cr_constants/cr-newburyport.json @@ -0,0 +1,203 @@ +{ + "CR-Newburyport": { + "type": "commuter-rail", + "direction": { + "0": "outbound", + "1": "inbound" + }, + "stations": [ + { + "stop_name": "Rockport", + "station": "place-GB-0353", + "branches": null, + "order": 1, + "stops": { + "0": [], + "1": ["CR-Newburyport_1_GB-0353-S"] + } + }, + { + "stop_name": "Gloucester", + "station": "place-GB-0316", + "branches": null, + "order": 2, + "stops": { + "0": ["CR-Newburyport_0_GB-0316-S"], + "1": ["CR-Newburyport_1_GB-0316-S"] + } + }, + { + "stop_name": "West Gloucester", + "station": "place-GB-0296", + "branches": null, + "order": 3, + "stops": { + "0": ["CR-Newburyport_0_GB-0296-01"], + "1": ["CR-Newburyport_1_GB-0296-02"] + } + }, + { + "stop_name": "Manchester", + "station": "place-GB-0254", + "branches": null, + "order": 4, + "stops": { + "0": ["CR-Newburyport_0_GB-0254-01"], + "1": ["CR-Newburyport_1_GB-0254-02"] + } + }, + { + "stop_name": "Beverly Farms", + "station": "place-GB-0229", + "branches": null, + "order": 5, + "stops": { + "0": ["CR-Newburyport_0_GB-0229-01"], + "1": ["CR-Newburyport_1_GB-0229-02"] + } + }, + { + "stop_name": "Montserrat", + "station": "place-GB-0198", + "branches": null, + "order": 6, + "stops": { + "0": ["CR-Newburyport_0_GB-0198-01"], + "1": ["CR-Newburyport_1_GB-0198-02"] + } + }, + { + "stop_name": "Newburyport", + "station": "place-ER-0362", + "branches": null, + "order": 7, + "stops": { + "0": [], + "1": ["CR-Newburyport_1_ER-0362-01"] + } + }, + { + "stop_name": "Rowley", + "station": "place-ER-0312", + "branches": null, + "order": 8, + "stops": { + "0": ["CR-Newburyport_0_ER-0312-S"], + "1": ["CR-Newburyport_1_ER-0312-S"] + } + }, + { + "stop_name": "Ipswich", + "station": "place-ER-0276", + "branches": null, + "order": 9, + "stops": { + "0": ["CR-Newburyport_0_ER-0276-S"], + "1": ["CR-Newburyport_1_ER-0276-S"] + } + }, + { + "stop_name": "Hamilton/Wenham", + "station": "place-ER-0227", + "branches": null, + "order": 10, + "stops": { + "0": ["CR-Newburyport_0_ER-0227-S"], + "1": ["CR-Newburyport_1_ER-0227-S"] + } + }, + { + "stop_name": "North Beverly", + "station": "place-ER-0208", + "branches": null, + "order": 11, + "stops": { + "0": ["CR-Newburyport_0_ER-0208-01"], + "1": ["CR-Newburyport_1_ER-0208-02"] + } + }, + { + "stop_name": "Beverly", + "station": "place-ER-0183", + "branches": null, + "order": 12, + "stops": { + "0": ["CR-Newburyport_0_ER-0183-01"], + "1": ["CR-Newburyport_1_ER-0183-02"] + } + }, + { + "stop_name": "Salem", + "station": "place-ER-0168", + "branches": null, + "order": 13, + "stops": { + "0": ["CR-Newburyport_0_ER-0168-S"], + "1": ["CR-Newburyport_1_ER-0168-S"] + } + }, + { + "stop_name": "Swampscott", + "station": "place-ER-0128", + "branches": null, + "order": 14, + "stops": { + "0": ["CR-Newburyport_0_ER-0128-01"], + "1": ["CR-Newburyport_1_ER-0128-02"] + } + }, + { + "stop_name": "Lynn Interim", + "station": "place-ER-0117", + "branches": null, + "order": 15, + "stops": { + "0": ["CR-Newburyport_0_ER-0117-01"], + "1": ["CR-Newburyport_1_ER-0117-02"] + } + }, + { + "stop_name": "River Works", + "station": "place-ER-0099", + "branches": null, + "order": 16, + "stops": { + "0": ["CR-Newburyport_0_ER-0099-01"], + "1": ["CR-Newburyport_1_ER-0099-02"] + } + }, + { + "stop_name": "Chelsea", + "station": "place-chels", + "branches": null, + "order": 17, + "stops": { + "0": ["CR-Newburyport_0_ER-0042-01"], + "1": ["CR-Newburyport_1_ER-0042-02"] + } + }, + { + "stop_name": "North Station", + "station": "place-north", + "branches": null, + "order": 18, + "stops": { + "0": [ + "CR-Newburyport_0_BNT-0000-08", + "CR-Newburyport_0_BNT-0000-03", + "CR-Newburyport_0_BNT-0000-02", + "CR-Newburyport_0_BNT-0000-07", + "CR-Newburyport_0_BNT-0000-05", + "CR-Newburyport_0_BNT-0000-04", + "CR-Newburyport_0_BNT-0000", + "CR-Newburyport_0_BNT-0000-06", + "CR-Newburyport_0_BNT-0000-01", + "CR-Newburyport_0_BNT-0000-10", + "CR-Newburyport_0_BNT-0000-09" + ], + "1": [] + } + } + ] + } +} diff --git a/common/constants/cr_constants/cr-providence.json b/common/constants/cr_constants/cr-providence.json index 71545d8d0..87cd10e46 100644 --- a/common/constants/cr_constants/cr-providence.json +++ b/common/constants/cr_constants/cr-providence.json @@ -132,7 +132,7 @@ "branches": null, "order": 13, "stops": { - "0": ["CR-Providence_0_NEC-2265-01", "CR-Providence_0_NEC-2265-03"], + "0": ["CR-Providence_0_NEC-2265-03", "CR-Providence_0_NEC-2265-01"], "1": ["CR-Providence_1_NEC-2265-02"] } }, @@ -153,9 +153,13 @@ "order": 15, "stops": { "0": [ + "CR-Providence_0_NEC-2287", "CR-Providence_0_NEC-2287-03", + "CR-Providence_0_NEC-2287-06", "CR-Providence_0_NEC-2287-05", - "CR-Providence_0_NEC-2287" + "CR-Providence_0_NEC-2287-08", + "CR-Providence_0_NEC-2287-07", + "CR-Providence_0_NEC-2287-04" ], "1": [] } diff --git a/common/constants/cr_constants/cr-worcester.json b/common/constants/cr_constants/cr-worcester.json index e6e4bdc91..1ebf314d9 100644 --- a/common/constants/cr_constants/cr-worcester.json +++ b/common/constants/cr_constants/cr-worcester.json @@ -12,7 +12,7 @@ "branches": null, "order": 1, "stops": { - "0": [], + "0": ["CR-Worcester_0_WML-0442-CS"], "1": ["CR-Worcester_1_WML-0442-CS"] } }, @@ -23,7 +23,7 @@ "order": 2, "stops": { "0": ["CR-Worcester_0_WML-0364-01"], - "1": ["CR-Worcester_1_WML-0364-02"] + "1": [] } }, { @@ -33,7 +33,7 @@ "order": 3, "stops": { "0": ["CR-Worcester_0_WML-0340-01"], - "1": ["CR-Worcester_1_WML-0340-02"] + "1": [] } }, { @@ -43,7 +43,7 @@ "order": 4, "stops": { "0": ["CR-Worcester_0_WML-0274-01"], - "1": ["CR-Worcester_1_WML-0274-02"] + "1": [] } }, { @@ -72,8 +72,8 @@ "branches": null, "order": 7, "stops": { - "0": ["CR-Worcester_0_WML-0199-01", "CR-Worcester_0_WML-0199-02"], - "1": ["CR-Worcester_1_WML-0199-01", "CR-Worcester_1_WML-0199-02"] + "0": ["CR-Worcester_0_WML-0199-02", "CR-Worcester_0_WML-0199-01"], + "1": ["CR-Worcester_1_WML-0199-02", "CR-Worcester_1_WML-0199-01"] } }, { @@ -102,7 +102,7 @@ "branches": null, "order": 10, "stops": { - "0": ["CR-Worcester_0_WML-0135-01", "CR-Worcester_0_WML-0135-02"], + "0": ["CR-Worcester_0_WML-0135-02", "CR-Worcester_0_WML-0135-01"], "1": ["CR-Worcester_1_WML-0135-01", "CR-Worcester_1_WML-0135-02"] } }, @@ -112,7 +112,7 @@ "branches": null, "order": 11, "stops": { - "0": ["CR-Worcester_0_WML-0125-01", "CR-Worcester_0_WML-0125-02"], + "0": ["CR-Worcester_0_WML-0125-02", "CR-Worcester_0_WML-0125-01"], "1": ["CR-Worcester_1_WML-0125-01", "CR-Worcester_1_WML-0125-02"] } }, @@ -183,9 +183,10 @@ "order": 18, "stops": { "0": [ - "CR-Worcester_0_NEC-2287", + "CR-Worcester_0_NEC-2287-02", + "CR-Worcester_0_NEC-2287-04", "CR-Worcester_0_NEC-2287-01", - "CR-Worcester_0_NEC-2287-02" + "CR-Worcester_0_NEC-2287" ], "1": [] } diff --git a/server/scripts/generate_line_files.py b/server/scripts/generate_line_files.py index c3dc7733f..f47c0636b 100644 --- a/server/scripts/generate_line_files.py +++ b/server/scripts/generate_line_files.py @@ -28,43 +28,46 @@ def get_line_stops(): objects = s3.list_objects_v2(Bucket=BUCKET, Prefix="Events-live/daily-cr-data/{}".format(LINE_KEY)) - stop_ids = set() + stop_names = set() for obj in objects["Contents"]: - stop_ids.add(parse_s3_cr_uri(obj)[2]) + stop_names.add(obj["Key"].split("/")[2]) + + stop_ids = [] + + stop_prefix_len = len(LINE_KEY) + 3 + for stop in stop_names: + stop_ids.append({"id": stop[stop_prefix_len:], "name": stop}) parent_children_map = {} for stop in stop_ids: + _, direction, stop_id = parse_stop_name(stop["name"]) + r_f = requests.get( - "https://api-v3.mbta.com/stops/{}?include=parent_station&api_key={}".format(stop["id"], MBTA_V3_API_KEY) + "https://api-v3.mbta.com/stops/{}?include=parent_station&api_key={}".format(stop_id, MBTA_V3_API_KEY) ) stop_details = r_f.json() parent_id = stop_details["data"]["relationships"]["parent_station"]["data"]["id"] if parent_id not in parent_children_map: - if stop["direction"] == "0": - parent_children_map[parent_id] = {"0": [stop["stop_id"]], "1": []} + if direction == "0": + parent_children_map[parent_id] = {"0": [stop["name"]], "1": []} else: - parent_children_map[parent_id] = {"0": [], "1": [stop["stop_id"]]} + parent_children_map[parent_id] = {"0": [], "1": [stop["name"]]} else: - parent_children_map[parent_id][stop["direction"]].append(stop["stop_id"]) + parent_children_map[parent_id][direction].append(stop["name"]) return parent_children_map -def parse_s3_cr_uri(uri: str): +def parse_stop_name(stop_name: str): """ - Parse a CR s3 URI beginning with Events-live + Parse a CR stop id into its components """ - _, _, stop_name, year, month, day, _ = uri["Key"].split("/") line, direction, stop_id = stop_name.split("_") - return {"line": line, "direction": direction, "stop_id": stop_id, "year": year, "month": month, "day": day} - - -def cr_stop_info_to_s3_prefix(line, direction, stop_id): - return "{}_{}_{}".format(line, direction, stop_id) + return line, direction, stop_id for LINE_KEY in ROUTES_CR: @@ -73,16 +76,42 @@ def cr_stop_info_to_s3_prefix(line, direction, stop_id): stop_layout = get_line_stops() - stops_formatted = [ - { - "stop_name": stop["attributes"]["name"], - "station": stop["id"], - "branches": None, - "order": index + 1, - "stops": stop_layout[stop["id"]], - } - for index, stop in enumerate(stops["data"]) - ] + stops_formatted = [] + + for index, stop in enumerate(stops["data"]): + try: + stops_formatted.append( + { + "stop_name": stop["attributes"]["name"], + "station": stop["id"], + "branches": None, + "order": index + 1, + "stops": stop_layout[stop["id"]], + } + ) + except KeyError: + c_f = requests.get( + "https://api-v3.mbta.com/stops/{}?include=child_stops&api_key={}".format(stop["id"], MBTA_V3_API_KEY) + ) + stop_details = c_f.json() + + child_stops = [ + child_stop["id"] for child_stop in stop_details["data"]["relationships"]["child_stops"]["data"] + ] + stops_map = { + "0": [f"{LINE_KEY}_0_{stop}" for stop in child_stops], + "1": [f"{LINE_KEY}_1_{stop}" for stop in child_stops], + } + + stops_formatted.append( + { + "stop_name": stop["attributes"]["name"], + "station": stop["id"], + "branches": None, + "order": index + 1, + "stops": stops_map, + } + ) output = { LINE_KEY: { From 35c5410b9244fa2ccf0496733eb56c2ebef73cb5 Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Sun, 21 Jan 2024 14:40:53 -0500 Subject: [PATCH 28/53] Hide stations we don't have stops for --- common/utils/stations.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/common/utils/stations.ts b/common/utils/stations.ts index 6b08f16ac..87c9b0bee 100644 --- a/common/utils/stations.ts +++ b/common/utils/stations.ts @@ -13,13 +13,21 @@ export const optionsForField = ( crRoute?: CommuterRailRoute ) => { if (type === 'from') { - return optionsStation(line, busRoute, crRoute); + return optionsStation(line, busRoute, crRoute)?.filter((entry) => { + if (entry.stops[0].length === 0) { + return false; + } + return true; + }); } if (type === 'to') { return optionsStation(line, busRoute, crRoute)?.filter((entry) => { if (fromStation && fromStation.branches && entry.branches) { return entry.branches.some((entryBranch) => fromStation.branches?.includes(entryBranch)); } + if (entry.stops[1].length === 0) { + return false; + } return true; }); } From 3101977a7597bc15dfd060c93132c6ab488cb380 Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Sun, 21 Jan 2024 15:08:06 -0500 Subject: [PATCH 29/53] Nevermind --- common/utils/stations.ts | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/common/utils/stations.ts b/common/utils/stations.ts index 87c9b0bee..6b08f16ac 100644 --- a/common/utils/stations.ts +++ b/common/utils/stations.ts @@ -13,21 +13,13 @@ export const optionsForField = ( crRoute?: CommuterRailRoute ) => { if (type === 'from') { - return optionsStation(line, busRoute, crRoute)?.filter((entry) => { - if (entry.stops[0].length === 0) { - return false; - } - return true; - }); + return optionsStation(line, busRoute, crRoute); } if (type === 'to') { return optionsStation(line, busRoute, crRoute)?.filter((entry) => { if (fromStation && fromStation.branches && entry.branches) { return entry.branches.some((entryBranch) => fromStation.branches?.includes(entryBranch)); } - if (entry.stops[1].length === 0) { - return false; - } return true; }); } From c27a83efac92a77774a625ed925494be2e51f2eb Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Sun, 21 Jan 2024 15:29:45 -0500 Subject: [PATCH 30/53] Populate with newer stops --- .../constants/cr_constants/cr-fairmount.json | 8 ++--- .../constants/cr_constants/cr-fitchburg.json | 14 ++++----- .../constants/cr_constants/cr-franklin.json | 16 +++++----- .../constants/cr_constants/cr-greenbush.json | 6 ++-- .../constants/cr_constants/cr-haverhill.json | 12 ++++---- .../constants/cr_constants/cr-kingston.json | 8 ++--- common/constants/cr_constants/cr-lowell.json | 14 ++++----- .../cr_constants/cr-middleborough.json | 6 ++-- common/constants/cr_constants/cr-needham.json | 8 ++--- .../cr_constants/cr-newburyport.json | 14 ++++----- .../constants/cr_constants/cr-providence.json | 12 ++++---- .../constants/cr_constants/cr-worcester.json | 30 +++++++++---------- server/scripts/generate_line_files.py | 20 +++++++++++-- 13 files changed, 92 insertions(+), 76 deletions(-) diff --git a/common/constants/cr_constants/cr-fairmount.json b/common/constants/cr_constants/cr-fairmount.json index 130aec312..38197e336 100644 --- a/common/constants/cr_constants/cr-fairmount.json +++ b/common/constants/cr_constants/cr-fairmount.json @@ -93,11 +93,11 @@ "order": 9, "stops": { "0": [ - "CR-Fairmount_0_NEC-2287-09", - "CR-Fairmount_0_NEC-2287-07", - "CR-Fairmount_0_NEC-2287", "CR-Fairmount_0_NEC-2287-11", - "CR-Fairmount_0_NEC-2287-10" + "CR-Fairmount_0_NEC-2287-10", + "CR-Fairmount_0_NEC-2287", + "CR-Fairmount_0_NEC-2287-09", + "CR-Fairmount_0_NEC-2287-07" ], "1": [] } diff --git a/common/constants/cr_constants/cr-fitchburg.json b/common/constants/cr_constants/cr-fitchburg.json index a8a998cad..2c6688d40 100644 --- a/common/constants/cr_constants/cr-fitchburg.json +++ b/common/constants/cr_constants/cr-fitchburg.json @@ -12,7 +12,7 @@ "branches": null, "order": 1, "stops": { - "0": [], + "0": ["CR-Fitchburg_0_FR-3338-CS"], "1": ["CR-Fitchburg_1_FR-3338-CS"] } }, @@ -173,16 +173,16 @@ "order": 17, "stops": { "0": [ - "CR-Fitchburg_0_BNT-0000-06", - "CR-Fitchburg_0_BNT-0000-10", + "CR-Fitchburg_0_BNT-0000-01", "CR-Fitchburg_0_BNT-0000", - "CR-Fitchburg_0_BNT-0000-02", "CR-Fitchburg_0_BNT-0000-05", + "CR-Fitchburg_0_BNT-0000-04", + "CR-Fitchburg_0_BNT-0000-10", + "CR-Fitchburg_0_BNT-0000-08", + "CR-Fitchburg_0_BNT-0000-06", "CR-Fitchburg_0_BNT-0000-07", - "CR-Fitchburg_0_BNT-0000-01", "CR-Fitchburg_0_BNT-0000-09", - "CR-Fitchburg_0_BNT-0000-08", - "CR-Fitchburg_0_BNT-0000-04" + "CR-Fitchburg_0_BNT-0000-02" ], "1": [] } diff --git a/common/constants/cr_constants/cr-franklin.json b/common/constants/cr_constants/cr-franklin.json index 345e0297b..5be3ef344 100644 --- a/common/constants/cr_constants/cr-franklin.json +++ b/common/constants/cr_constants/cr-franklin.json @@ -12,7 +12,7 @@ "branches": null, "order": 1, "stops": { - "0": [], + "0": ["CR-Franklin_0_FB-0303-S"], "1": ["CR-Franklin_1_FB-0303-S"] } }, @@ -42,7 +42,7 @@ "branches": null, "order": 4, "stops": { - "0": [], + "0": ["CR-Franklin_0_FS-0049-S"], "1": ["CR-Franklin_1_FS-0049-S"] } }, @@ -122,7 +122,7 @@ "branches": null, "order": 12, "stops": { - "0": ["CR-Franklin_0_FB-0095-05", "CR-Franklin_0_FB-0095-04"], + "0": ["CR-Franklin_0_FB-0095-04", "CR-Franklin_0_FB-0095-05"], "1": ["CR-Franklin_1_FB-0095-04", "CR-Franklin_1_FB-0095-05"] } }, @@ -142,7 +142,7 @@ "branches": null, "order": 14, "stops": { - "0": ["CR-Franklin_0_NEC-2265-03", "CR-Franklin_0_NEC-2265-01"], + "0": ["CR-Franklin_0_NEC-2265-01", "CR-Franklin_0_NEC-2265-03"], "1": ["CR-Franklin_1_NEC-2265-03"] } }, @@ -163,12 +163,12 @@ "order": 16, "stops": { "0": [ - "CR-Franklin_0_NEC-2287-11", + "CR-Franklin_0_NEC-2287-03", "CR-Franklin_0_NEC-2287", - "CR-Franklin_0_NEC-2287-04", + "CR-Franklin_0_NEC-2287-11", "CR-Franklin_0_NEC-2287-05", - "CR-Franklin_0_NEC-2287-03", - "CR-Franklin_0_NEC-2287-07" + "CR-Franklin_0_NEC-2287-07", + "CR-Franklin_0_NEC-2287-04" ], "1": [] } diff --git a/common/constants/cr_constants/cr-greenbush.json b/common/constants/cr_constants/cr-greenbush.json index ef34b5f26..524839682 100644 --- a/common/constants/cr_constants/cr-greenbush.json +++ b/common/constants/cr_constants/cr-greenbush.json @@ -103,10 +103,10 @@ "order": 10, "stops": { "0": [ - "CR-Greenbush_0_NEC-2287-11", - "CR-Greenbush_0_NEC-2287", + "CR-Greenbush_0_NEC-2287-12", "CR-Greenbush_0_NEC-2287-13", - "CR-Greenbush_0_NEC-2287-12" + "CR-Greenbush_0_NEC-2287", + "CR-Greenbush_0_NEC-2287-11" ], "1": [] } diff --git a/common/constants/cr_constants/cr-haverhill.json b/common/constants/cr_constants/cr-haverhill.json index 2c5cae1d6..10b741755 100644 --- a/common/constants/cr_constants/cr-haverhill.json +++ b/common/constants/cr_constants/cr-haverhill.json @@ -153,17 +153,17 @@ "order": 15, "stops": { "0": [ - "CR-Haverhill_0_BNT-0000-10", "CR-Haverhill_0_BNT-0000", - "CR-Haverhill_0_BNT-0000-08", + "CR-Haverhill_0_BNT-0000-02", + "CR-Haverhill_0_BNT-0000-05", + "CR-Haverhill_0_BNT-0000-01", "CR-Haverhill_0_BNT-0000-04", - "CR-Haverhill_0_BNT-0000-06", + "CR-Haverhill_0_BNT-0000-10", "CR-Haverhill_0_BNT-0000-09", - "CR-Haverhill_0_BNT-0000-05", - "CR-Haverhill_0_BNT-0000-02", "CR-Haverhill_0_BNT-0000-03", "CR-Haverhill_0_BNT-0000-07", - "CR-Haverhill_0_BNT-0000-01" + "CR-Haverhill_0_BNT-0000-06", + "CR-Haverhill_0_BNT-0000-08" ], "1": [] } diff --git a/common/constants/cr_constants/cr-kingston.json b/common/constants/cr_constants/cr-kingston.json index 9d246ef07..45e0ebb63 100644 --- a/common/constants/cr_constants/cr-kingston.json +++ b/common/constants/cr_constants/cr-kingston.json @@ -103,11 +103,11 @@ "order": 10, "stops": { "0": [ - "CR-Kingston_0_NEC-2287-12", - "CR-Kingston_0_NEC-2287-13", - "CR-Kingston_0_NEC-2287-11", "CR-Kingston_0_NEC-2287", - "CR-Kingston_0_NEC-2287-09" + "CR-Kingston_0_NEC-2287-11", + "CR-Kingston_0_NEC-2287-13", + "CR-Kingston_0_NEC-2287-09", + "CR-Kingston_0_NEC-2287-12" ], "1": [] } diff --git a/common/constants/cr_constants/cr-lowell.json b/common/constants/cr_constants/cr-lowell.json index 5fe5dede6..7b642ed7e 100644 --- a/common/constants/cr_constants/cr-lowell.json +++ b/common/constants/cr_constants/cr-lowell.json @@ -73,16 +73,16 @@ "order": 7, "stops": { "0": [ - "CR-Lowell_0_BNT-0000-07", - "CR-Lowell_0_BNT-0000-03", - "CR-Lowell_0_BNT-0000-06", + "CR-Lowell_0_BNT-0000-02", "CR-Lowell_0_BNT-0000-09", - "CR-Lowell_0_BNT-0000-05", - "CR-Lowell_0_BNT-0000-10", + "CR-Lowell_0_BNT-0000-06", + "CR-Lowell_0_BNT-0000-07", "CR-Lowell_0_BNT-0000-04", - "CR-Lowell_0_BNT-0000-02", "CR-Lowell_0_BNT-0000-08", - "CR-Lowell_0_BNT-0000" + "CR-Lowell_0_BNT-0000", + "CR-Lowell_0_BNT-0000-10", + "CR-Lowell_0_BNT-0000-05", + "CR-Lowell_0_BNT-0000-03" ], "1": [] } diff --git a/common/constants/cr_constants/cr-middleborough.json b/common/constants/cr_constants/cr-middleborough.json index 9d2d52874..242aa7d95 100644 --- a/common/constants/cr_constants/cr-middleborough.json +++ b/common/constants/cr_constants/cr-middleborough.json @@ -103,10 +103,10 @@ "order": 10, "stops": { "0": [ - "CR-Middleborough_0_NEC-2287-13", - "CR-Middleborough_0_NEC-2287-12", + "CR-Middleborough_0_NEC-2287", "CR-Middleborough_0_NEC-2287-11", - "CR-Middleborough_0_NEC-2287" + "CR-Middleborough_0_NEC-2287-13", + "CR-Middleborough_0_NEC-2287-12" ], "1": [] } diff --git a/common/constants/cr_constants/cr-needham.json b/common/constants/cr_constants/cr-needham.json index 9ede644da..ad928cd40 100644 --- a/common/constants/cr_constants/cr-needham.json +++ b/common/constants/cr_constants/cr-needham.json @@ -102,7 +102,7 @@ "branches": null, "order": 10, "stops": { - "0": ["CR-Needham_0_NEC-2265-01", "CR-Needham_0_NEC-2265-03"], + "0": ["CR-Needham_0_NEC-2265-03", "CR-Needham_0_NEC-2265-01"], "1": ["CR-Needham_1_NEC-2265-03"] } }, @@ -123,10 +123,10 @@ "order": 12, "stops": { "0": [ - "CR-Needham_0_NEC-2287-04", - "CR-Needham_0_NEC-2287-03", "CR-Needham_0_NEC-2287-06", - "CR-Needham_0_NEC-2287" + "CR-Needham_0_NEC-2287-03", + "CR-Needham_0_NEC-2287", + "CR-Needham_0_NEC-2287-04" ], "1": [] } diff --git a/common/constants/cr_constants/cr-newburyport.json b/common/constants/cr_constants/cr-newburyport.json index 9a845d5e6..39c879db0 100644 --- a/common/constants/cr_constants/cr-newburyport.json +++ b/common/constants/cr_constants/cr-newburyport.json @@ -12,7 +12,7 @@ "branches": null, "order": 1, "stops": { - "0": [], + "0": ["CR-Newburyport_0_GB-0353-S"], "1": ["CR-Newburyport_1_GB-0353-S"] } }, @@ -183,17 +183,17 @@ "order": 18, "stops": { "0": [ - "CR-Newburyport_0_BNT-0000-08", + "CR-Newburyport_0_BNT-0000-10", + "CR-Newburyport_0_BNT-0000-06", + "CR-Newburyport_0_BNT-0000-09", "CR-Newburyport_0_BNT-0000-03", - "CR-Newburyport_0_BNT-0000-02", "CR-Newburyport_0_BNT-0000-07", - "CR-Newburyport_0_BNT-0000-05", "CR-Newburyport_0_BNT-0000-04", "CR-Newburyport_0_BNT-0000", - "CR-Newburyport_0_BNT-0000-06", "CR-Newburyport_0_BNT-0000-01", - "CR-Newburyport_0_BNT-0000-10", - "CR-Newburyport_0_BNT-0000-09" + "CR-Newburyport_0_BNT-0000-08", + "CR-Newburyport_0_BNT-0000-05", + "CR-Newburyport_0_BNT-0000-02" ], "1": [] } diff --git a/common/constants/cr_constants/cr-providence.json b/common/constants/cr_constants/cr-providence.json index 87cd10e46..3f63ad195 100644 --- a/common/constants/cr_constants/cr-providence.json +++ b/common/constants/cr_constants/cr-providence.json @@ -132,7 +132,7 @@ "branches": null, "order": 13, "stops": { - "0": ["CR-Providence_0_NEC-2265-03", "CR-Providence_0_NEC-2265-01"], + "0": ["CR-Providence_0_NEC-2265-01", "CR-Providence_0_NEC-2265-03"], "1": ["CR-Providence_1_NEC-2265-02"] } }, @@ -142,8 +142,8 @@ "branches": null, "order": 14, "stops": { - "0": ["CR-Providence_0_NEC-2276-01", "CR-Providence_0_NEC-2276-03"], - "1": ["CR-Providence_1_NEC-2276-02"] + "0": ["CR-Providence_0_NEC-2276-03", "CR-Providence_0_NEC-2276-01"], + "1": ["CR-Providence_1_NEC-2276-02", "CR-Providence_1_NEC-2276-03"] } }, { @@ -153,11 +153,11 @@ "order": 15, "stops": { "0": [ - "CR-Providence_0_NEC-2287", - "CR-Providence_0_NEC-2287-03", - "CR-Providence_0_NEC-2287-06", "CR-Providence_0_NEC-2287-05", "CR-Providence_0_NEC-2287-08", + "CR-Providence_0_NEC-2287-03", + "CR-Providence_0_NEC-2287", + "CR-Providence_0_NEC-2287-06", "CR-Providence_0_NEC-2287-07", "CR-Providence_0_NEC-2287-04" ], diff --git a/common/constants/cr_constants/cr-worcester.json b/common/constants/cr_constants/cr-worcester.json index 1ebf314d9..7705ef80d 100644 --- a/common/constants/cr_constants/cr-worcester.json +++ b/common/constants/cr_constants/cr-worcester.json @@ -23,7 +23,7 @@ "order": 2, "stops": { "0": ["CR-Worcester_0_WML-0364-01"], - "1": [] + "1": ["CR-Worcester_1_WML-0364-02"] } }, { @@ -33,7 +33,7 @@ "order": 3, "stops": { "0": ["CR-Worcester_0_WML-0340-01"], - "1": [] + "1": ["CR-Worcester_1_WML-0340-02"] } }, { @@ -43,7 +43,7 @@ "order": 4, "stops": { "0": ["CR-Worcester_0_WML-0274-01"], - "1": [] + "1": ["CR-Worcester_1_WML-0274-02"] } }, { @@ -62,7 +62,7 @@ "branches": null, "order": 6, "stops": { - "0": ["CR-Worcester_0_WML-0214-02", "CR-Worcester_0_WML-0214-01"], + "0": ["CR-Worcester_0_WML-0214-01", "CR-Worcester_0_WML-0214-02"], "1": ["CR-Worcester_1_WML-0214-01", "CR-Worcester_1_WML-0214-02"] } }, @@ -73,7 +73,7 @@ "order": 7, "stops": { "0": ["CR-Worcester_0_WML-0199-02", "CR-Worcester_0_WML-0199-01"], - "1": ["CR-Worcester_1_WML-0199-02", "CR-Worcester_1_WML-0199-01"] + "1": ["CR-Worcester_1_WML-0199-01", "CR-Worcester_1_WML-0199-02"] } }, { @@ -82,8 +82,8 @@ "branches": null, "order": 8, "stops": { - "0": ["CR-Worcester_0_WML-0177-02", "CR-Worcester_0_WML-0177-01"], - "1": ["CR-Worcester_1_WML-0177-02", "CR-Worcester_1_WML-0177-01"] + "0": ["CR-Worcester_0_WML-0177-01", "CR-Worcester_0_WML-0177-02"], + "1": ["CR-Worcester_1_WML-0177-01", "CR-Worcester_1_WML-0177-02"] } }, { @@ -92,7 +92,7 @@ "branches": null, "order": 9, "stops": { - "0": ["CR-Worcester_0_WML-0147-01", "CR-Worcester_0_WML-0147-02"], + "0": ["CR-Worcester_0_WML-0147-02", "CR-Worcester_0_WML-0147-01"], "1": ["CR-Worcester_1_WML-0147-01", "CR-Worcester_1_WML-0147-02"] } }, @@ -102,8 +102,8 @@ "branches": null, "order": 10, "stops": { - "0": ["CR-Worcester_0_WML-0135-02", "CR-Worcester_0_WML-0135-01"], - "1": ["CR-Worcester_1_WML-0135-01", "CR-Worcester_1_WML-0135-02"] + "0": ["CR-Worcester_0_WML-0135-01", "CR-Worcester_0_WML-0135-02"], + "1": ["CR-Worcester_1_WML-0135-02", "CR-Worcester_1_WML-0135-01"] } }, { @@ -112,7 +112,7 @@ "branches": null, "order": 11, "stops": { - "0": ["CR-Worcester_0_WML-0125-02", "CR-Worcester_0_WML-0125-01"], + "0": ["CR-Worcester_0_WML-0125-01", "CR-Worcester_0_WML-0125-02"], "1": ["CR-Worcester_1_WML-0125-01", "CR-Worcester_1_WML-0125-02"] } }, @@ -153,7 +153,7 @@ "order": 15, "stops": { "0": ["CR-Worcester_0_WML-0035-02", "CR-Worcester_0_WML-0035-01"], - "1": ["CR-Worcester_1_WML-0035-02", "CR-Worcester_1_WML-0035-01"] + "1": ["CR-Worcester_1_WML-0035-01", "CR-Worcester_1_WML-0035-02"] } }, { @@ -183,10 +183,10 @@ "order": 18, "stops": { "0": [ - "CR-Worcester_0_NEC-2287-02", - "CR-Worcester_0_NEC-2287-04", + "CR-Worcester_0_NEC-2287", "CR-Worcester_0_NEC-2287-01", - "CR-Worcester_0_NEC-2287" + "CR-Worcester_0_NEC-2287-02", + "CR-Worcester_0_NEC-2287-04" ], "1": [] } diff --git a/server/scripts/generate_line_files.py b/server/scripts/generate_line_files.py index f47c0636b..28bc52412 100644 --- a/server/scripts/generate_line_files.py +++ b/server/scripts/generate_line_files.py @@ -23,14 +23,30 @@ ] +def get_all_s3_objects(s3, **base_kwargs): + continuation_token = None + while True: + list_kwargs = dict(MaxKeys=1000, **base_kwargs) + if continuation_token: + list_kwargs["ContinuationToken"] = continuation_token + response = s3.list_objects_v2(**list_kwargs) + yield from response.get("Contents", []) + if not response.get("IsTruncated"): # At the end of the list? + break + continuation_token = response.get("NextContinuationToken") + + def get_line_stops(): s3 = boto3.client("s3", config=botocore.client.Config(max_pool_connections=15)) - objects = s3.list_objects_v2(Bucket=BUCKET, Prefix="Events-live/daily-cr-data/{}".format(LINE_KEY)) + objects = [] + + for file in get_all_s3_objects(s3, Bucket=BUCKET, Prefix="Events-live/daily-cr-data/{}".format(LINE_KEY)): + objects.append(file) stop_names = set() - for obj in objects["Contents"]: + for obj in objects: stop_names.add(obj["Key"].split("/")[2]) stop_ids = [] From 631a5f07108f4a08da544625f2f9d2506d3dbe61 Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Sun, 4 Feb 2024 14:21:55 -0500 Subject: [PATCH 31/53] Fixing CR data calls --- server/chalicelib/s3.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/server/chalicelib/s3.py b/server/chalicelib/s3.py index 081504e09..8f092a3f7 100644 --- a/server/chalicelib/s3.py +++ b/server/chalicelib/s3.py @@ -64,7 +64,7 @@ def download_one_event_file(date, stop_id: str, use_live_data=False): if ex.response["Error"]["Code"] == "NoSuchKey": # raise Exception(f"Data not available on S3 for key {key} ") from None print(f"WARNING: No data available on S3 for key: {key}") - if not use_live_data and is_bus(stop_id): + if not use_live_data: return download_one_event_file(date, stop_id, use_live_data=True) return [] else: @@ -83,6 +83,8 @@ def download_one_event_file(date, stop_id: str, use_live_data=False): @parallel.make_parallel def parallel_download_events(datestop): (date, stop) = datestop + if is_cr(stop): + return download_one_event_file(date, stop, use_live_data=True) return download_one_event_file(date, stop) From 8fb44d10c3ccb2ed73ac086c773c3f20c9a0dbd4 Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Sun, 10 Mar 2024 18:47:37 -0400 Subject: [PATCH 32/53] Fixing 120+ minute headways for CR --- server/chalicelib/s3_historical.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/server/chalicelib/s3_historical.py b/server/chalicelib/s3_historical.py index 55dcf8bf6..ed522360b 100644 --- a/server/chalicelib/s3_historical.py +++ b/server/chalicelib/s3_historical.py @@ -78,8 +78,7 @@ def headways(stop_ids: list, start_date: str | date, end_date: str | date): headway_time_sec = delta.total_seconds() # Throw out any headways > 120 min - # TODO: We can't do this anymore for CR data - if headway_time_sec > 120 * 60: + if headway_time_sec > 120 * 60 and not s3.is_cr(this["route_id"]): continue benchmark_headway = this.get("scheduled_headway") From 634b98362893c40e3e65ca4f28fb3f56b833a895 Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Sun, 10 Mar 2024 20:03:11 -0400 Subject: [PATCH 33/53] Updating commuter rail stations and notices --- .../components/notices/GobbleDataNotice.tsx | 6 +- common/components/notices/SameDayNotice.tsx | 3 +- common/constants/colors.ts | 8 +- .../constants/cr_constants/cr-fairmount.json | 12 +-- .../constants/cr_constants/cr-fitchburg.json | 14 ++-- .../constants/cr_constants/cr-franklin.json | 32 +++++--- .../constants/cr_constants/cr-greenbush.json | 6 +- .../constants/cr_constants/cr-haverhill.json | 60 +++++++++------ .../constants/cr_constants/cr-kingston.json | 12 +-- common/constants/cr_constants/cr-lowell.json | 18 +++-- .../cr_constants/cr-middleborough.json | 6 +- common/constants/cr_constants/cr-needham.json | 14 ++-- .../cr_constants/cr-newburyport.json | 50 ++++++++---- .../constants/cr_constants/cr-providence.json | 21 ++--- .../constants/cr_constants/cr-worcester.json | 77 ++++++++++++++----- common/styles/general.ts | 2 +- server/scripts/generate_line_files.py | 20 ++--- 17 files changed, 237 insertions(+), 124 deletions(-) diff --git a/common/components/notices/GobbleDataNotice.tsx b/common/components/notices/GobbleDataNotice.tsx index 374cc5a2f..3a43e3ff1 100644 --- a/common/components/notices/GobbleDataNotice.tsx +++ b/common/components/notices/GobbleDataNotice.tsx @@ -21,8 +21,10 @@ export const GobbleDataNotice: React.FC = () => { const isEndDateAfterBusMaxDay = endDate !== undefined && dayjs(endDate).isAfter(BUS_MAX_DAY); if ( - (line === 'line-bus' || linePath === 'bus') && - (isStartDateAfterBusMaxDay || isEndDateAfterBusMaxDay) + ((line === 'line-bus' || linePath === 'bus') && + (isStartDateAfterBusMaxDay || isEndDateAfterBusMaxDay)) || + line === 'line-commuter-rail' || + linePath === 'commuter-rail' ) { return (
diff --git a/common/components/notices/SameDayNotice.tsx b/common/components/notices/SameDayNotice.tsx index 076f09147..3945b97e4 100644 --- a/common/components/notices/SameDayNotice.tsx +++ b/common/components/notices/SameDayNotice.tsx @@ -6,11 +6,12 @@ import { TODAY_STRING } from '../../constants/dates'; export const SameDayNotice: React.FC = () => { const { + line, query: { date, endDate }, } = useDelimitatedRoute(); const isToday = date === TODAY_STRING || endDate === TODAY_STRING; - if (isToday) { + if (isToday && line !== 'line-commuter-rail') { return (
diff --git a/common/constants/colors.ts b/common/constants/colors.ts index 4fa0018a5..0ef0eff52 100644 --- a/common/constants/colors.ts +++ b/common/constants/colors.ts @@ -1,3 +1,4 @@ +import type { Line } from '../types/lines'; import { hexWithAlpha } from '../utils/general'; export const COLORS = { @@ -43,7 +44,7 @@ export const CHART_COLORS = { BLOCKS_SOLID: '#d2d2d2', }; -export const LINE_COLORS = { +export const LINE_COLORS: { [key in Line | 'default']: string } = { 'line-red': COLORS.mbta.red, 'line-orange': COLORS.mbta.orange, 'line-blue': COLORS.mbta.blue, @@ -53,11 +54,14 @@ export const LINE_COLORS = { default: '#303030', }; -export const LINE_COLORS_LEVELS = { +export const LINE_COLORS_LEVELS: { + [key in Line | 'default']: { [num in number]: string } | string; +} = { 'line-red': { 0: '#D13434', 1: '#d64949', 2: '#da5e5e', 3: '#df7272' }, 'line-orange': { 0: '#ed8b00', 1: '#ff9907', 2: '#ffa321', 3: '#ffae3b' }, 'line-blue': { 0: '#003da5', 1: '#0046bf', 2: '#0050d8', 3: '#0059f2' }, 'line-green': { 0: '#00834d', 1: '#009d5c', 2: '#00b66b', 3: '#00d07a' }, 'line-bus': { 0: '#ffc72c', 1: '#ffce46', 2: '#ffd55f', 3: '#ffdb79' }, + 'line-commuter-rail': { 0: '#80276c', 1: '#8f2f7e', 2: '#9e3790', 3: '#ad41a2' }, default: '#303030', }; diff --git a/common/constants/cr_constants/cr-fairmount.json b/common/constants/cr_constants/cr-fairmount.json index 38197e336..b5d1994e2 100644 --- a/common/constants/cr_constants/cr-fairmount.json +++ b/common/constants/cr_constants/cr-fairmount.json @@ -14,7 +14,8 @@ "stops": { "0": [], "1": ["CR-Fairmount_1_FB-0095-04"] - } + }, + "terminus": true }, { "stop_name": "Fairmount", @@ -93,14 +94,15 @@ "order": 9, "stops": { "0": [ + "CR-Fairmount_0_NEC-2287-09", "CR-Fairmount_0_NEC-2287-11", "CR-Fairmount_0_NEC-2287-10", - "CR-Fairmount_0_NEC-2287", - "CR-Fairmount_0_NEC-2287-09", - "CR-Fairmount_0_NEC-2287-07" + "CR-Fairmount_0_NEC-2287-07", + "CR-Fairmount_0_NEC-2287" ], "1": [] - } + }, + "terminus": true } ] } diff --git a/common/constants/cr_constants/cr-fitchburg.json b/common/constants/cr_constants/cr-fitchburg.json index 2c6688d40..efb4f59ab 100644 --- a/common/constants/cr_constants/cr-fitchburg.json +++ b/common/constants/cr_constants/cr-fitchburg.json @@ -14,7 +14,8 @@ "stops": { "0": ["CR-Fitchburg_0_FR-3338-CS"], "1": ["CR-Fitchburg_1_FR-3338-CS"] - } + }, + "terminus": true }, { "stop_name": "Fitchburg", @@ -175,17 +176,18 @@ "0": [ "CR-Fitchburg_0_BNT-0000-01", "CR-Fitchburg_0_BNT-0000", - "CR-Fitchburg_0_BNT-0000-05", "CR-Fitchburg_0_BNT-0000-04", + "CR-Fitchburg_0_BNT-0000-02", "CR-Fitchburg_0_BNT-0000-10", - "CR-Fitchburg_0_BNT-0000-08", - "CR-Fitchburg_0_BNT-0000-06", + "CR-Fitchburg_0_BNT-0000-05", "CR-Fitchburg_0_BNT-0000-07", "CR-Fitchburg_0_BNT-0000-09", - "CR-Fitchburg_0_BNT-0000-02" + "CR-Fitchburg_0_BNT-0000-06", + "CR-Fitchburg_0_BNT-0000-08" ], "1": [] - } + }, + "terminus": true } ] } diff --git a/common/constants/cr_constants/cr-franklin.json b/common/constants/cr_constants/cr-franklin.json index 5be3ef344..69801f3fe 100644 --- a/common/constants/cr_constants/cr-franklin.json +++ b/common/constants/cr_constants/cr-franklin.json @@ -14,7 +14,8 @@ "stops": { "0": ["CR-Franklin_0_FB-0303-S"], "1": ["CR-Franklin_1_FB-0303-S"] - } + }, + "terminus": true }, { "stop_name": "Franklin", @@ -122,8 +123,8 @@ "branches": null, "order": 12, "stops": { - "0": ["CR-Franklin_0_FB-0095-04", "CR-Franklin_0_FB-0095-05"], - "1": ["CR-Franklin_1_FB-0095-04", "CR-Franklin_1_FB-0095-05"] + "0": ["CR-Franklin_0_FB-0095-05", "CR-Franklin_0_FB-0095-04"], + "1": ["CR-Franklin_1_FB-0095-05", "CR-Franklin_1_FB-0095-04"] } }, { @@ -142,8 +143,12 @@ "branches": null, "order": 14, "stops": { - "0": ["CR-Franklin_0_NEC-2265-01", "CR-Franklin_0_NEC-2265-03"], - "1": ["CR-Franklin_1_NEC-2265-03"] + "0": ["CR-Franklin_0_NEC-2265-03", "CR-Franklin_0_NEC-2265-01"], + "1": [ + "CR-Franklin_1_NEC-2265-03", + "CR-Franklin_1_NEC-2265-01", + "CR-Franklin_1_NEC-2265-02" + ] } }, { @@ -153,7 +158,11 @@ "order": 15, "stops": { "0": ["CR-Franklin_0_NEC-2276-01", "CR-Franklin_0_NEC-2276-03"], - "1": ["CR-Franklin_1_NEC-2276-03"] + "1": [ + "CR-Franklin_1_NEC-2276-02", + "CR-Franklin_1_NEC-2276-01", + "CR-Franklin_1_NEC-2276-03" + ] } }, { @@ -164,14 +173,17 @@ "stops": { "0": [ "CR-Franklin_0_NEC-2287-03", + "CR-Franklin_0_NEC-2287-04", + "CR-Franklin_0_NEC-2287-08", + "CR-Franklin_0_NEC-2287-07", + "CR-Franklin_0_NEC-2287-10", "CR-Franklin_0_NEC-2287", "CR-Franklin_0_NEC-2287-11", - "CR-Franklin_0_NEC-2287-05", - "CR-Franklin_0_NEC-2287-07", - "CR-Franklin_0_NEC-2287-04" + "CR-Franklin_0_NEC-2287-05" ], "1": [] - } + }, + "terminus": true }, { "stop_name": "Hyde Park", diff --git a/common/constants/cr_constants/cr-greenbush.json b/common/constants/cr_constants/cr-greenbush.json index 524839682..07a61f1e6 100644 --- a/common/constants/cr_constants/cr-greenbush.json +++ b/common/constants/cr_constants/cr-greenbush.json @@ -14,7 +14,8 @@ "stops": { "0": [], "1": ["CR-Greenbush_1_GRB-0276-S"] - } + }, + "terminus": true }, { "stop_name": "North Scituate", @@ -109,7 +110,8 @@ "CR-Greenbush_0_NEC-2287-11" ], "1": [] - } + }, + "terminus": true } ] } diff --git a/common/constants/cr_constants/cr-haverhill.json b/common/constants/cr_constants/cr-haverhill.json index 10b741755..357701a10 100644 --- a/common/constants/cr_constants/cr-haverhill.json +++ b/common/constants/cr_constants/cr-haverhill.json @@ -14,7 +14,8 @@ "stops": { "0": [], "1": ["CR-Haverhill_1_WR-0329-02"] - } + }, + "terminus": true }, { "stop_name": "Bradford", @@ -57,30 +58,40 @@ } }, { - "stop_name": "North Wilmington", - "station": "place-WR-0163", + "stop_name": "Reading", + "station": "place-WR-0120", "branches": null, "order": 6, "stops": { - "0": ["CR-Haverhill_0_WR-0163-S"], - "1": ["CR-Haverhill_1_WR-0163-S"] + "0": ["CR-Haverhill_0_WR-0120-S"], + "1": ["CR-Haverhill_1_WR-0120-S"] } }, { - "stop_name": "Reading", - "station": "place-WR-0120", + "stop_name": "Anderson/Woburn", + "station": "place-NHRML-0127", "branches": null, "order": 7, "stops": { - "0": ["CR-Haverhill_0_WR-0120-S"], - "1": ["CR-Haverhill_1_WR-0120-S"] + "0": ["CR-Haverhill_0_NHRML-0127-01"], + "1": ["CR-Haverhill_1_NHRML-0127-02"] + } + }, + { + "stop_name": "North Wilmington", + "station": "place-WR-0163", + "branches": null, + "order": 8, + "stops": { + "0": ["CR-Haverhill_0_WR-0163-S"], + "1": ["CR-Haverhill_1_WR-0163-S"] } }, { "stop_name": "Wakefield", "station": "place-WR-0099", "branches": null, - "order": 8, + "order": 9, "stops": { "0": ["CR-Haverhill_0_WR-0099-01"], "1": ["CR-Haverhill_1_WR-0099-02"] @@ -90,7 +101,7 @@ "stop_name": "Greenwood", "station": "place-WR-0085", "branches": null, - "order": 9, + "order": 10, "stops": { "0": ["CR-Haverhill_0_WR-0085-01"], "1": ["CR-Haverhill_1_WR-0085-02"] @@ -100,7 +111,7 @@ "stop_name": "Melrose Highlands", "station": "place-WR-0075", "branches": null, - "order": 10, + "order": 11, "stops": { "0": ["CR-Haverhill_0_WR-0075-01"], "1": ["CR-Haverhill_1_WR-0075-02"] @@ -110,7 +121,7 @@ "stop_name": "Melrose/Cedar Park", "station": "place-WR-0067", "branches": null, - "order": 11, + "order": 12, "stops": { "0": ["CR-Haverhill_0_WR-0067-01"], "1": ["CR-Haverhill_1_WR-0067-02"] @@ -120,7 +131,7 @@ "stop_name": "Wyoming Hill", "station": "place-WR-0062", "branches": null, - "order": 12, + "order": 13, "stops": { "0": ["CR-Haverhill_0_WR-0062-01"], "1": ["CR-Haverhill_1_WR-0062-02"] @@ -130,7 +141,7 @@ "stop_name": "Oak Grove", "station": "place-ogmnl", "branches": null, - "order": 13, + "order": 14, "stops": { "0": ["CR-Haverhill_0_WR-0053-S"], "1": ["CR-Haverhill_1_WR-0053-S"] @@ -140,7 +151,7 @@ "stop_name": "Malden Center", "station": "place-mlmnl", "branches": null, - "order": 14, + "order": 15, "stops": { "0": ["CR-Haverhill_0_WR-0045-S"], "1": ["CR-Haverhill_1_WR-0045-S"] @@ -150,23 +161,24 @@ "stop_name": "North Station", "station": "place-north", "branches": null, - "order": 15, + "order": 16, "stops": { "0": [ + "CR-Haverhill_0_BNT-0000-09", + "CR-Haverhill_0_BNT-0000-03", "CR-Haverhill_0_BNT-0000", "CR-Haverhill_0_BNT-0000-02", - "CR-Haverhill_0_BNT-0000-05", + "CR-Haverhill_0_BNT-0000-07", + "CR-Haverhill_0_BNT-0000-10", "CR-Haverhill_0_BNT-0000-01", "CR-Haverhill_0_BNT-0000-04", - "CR-Haverhill_0_BNT-0000-10", - "CR-Haverhill_0_BNT-0000-09", - "CR-Haverhill_0_BNT-0000-03", - "CR-Haverhill_0_BNT-0000-07", "CR-Haverhill_0_BNT-0000-06", - "CR-Haverhill_0_BNT-0000-08" + "CR-Haverhill_0_BNT-0000-08", + "CR-Haverhill_0_BNT-0000-05" ], "1": [] - } + }, + "terminus": true } ] } diff --git a/common/constants/cr_constants/cr-kingston.json b/common/constants/cr_constants/cr-kingston.json index 45e0ebb63..762555152 100644 --- a/common/constants/cr_constants/cr-kingston.json +++ b/common/constants/cr_constants/cr-kingston.json @@ -14,7 +14,8 @@ "stops": { "0": [], "1": ["CR-Kingston_1_KB-0351-S"] - } + }, + "terminus": true }, { "stop_name": "Halifax", @@ -103,14 +104,15 @@ "order": 10, "stops": { "0": [ + "CR-Kingston_0_NEC-2287-09", + "CR-Kingston_0_NEC-2287-12", "CR-Kingston_0_NEC-2287", "CR-Kingston_0_NEC-2287-11", - "CR-Kingston_0_NEC-2287-13", - "CR-Kingston_0_NEC-2287-09", - "CR-Kingston_0_NEC-2287-12" + "CR-Kingston_0_NEC-2287-13" ], "1": [] - } + }, + "terminus": true } ] } diff --git a/common/constants/cr_constants/cr-lowell.json b/common/constants/cr_constants/cr-lowell.json index 7b642ed7e..356d42e0c 100644 --- a/common/constants/cr_constants/cr-lowell.json +++ b/common/constants/cr_constants/cr-lowell.json @@ -14,7 +14,8 @@ "stops": { "0": [], "1": ["CR-Lowell_1_NHRML-0254-04"] - } + }, + "terminus": true }, { "stop_name": "North Billerica", @@ -73,19 +74,20 @@ "order": 7, "stops": { "0": [ - "CR-Lowell_0_BNT-0000-02", - "CR-Lowell_0_BNT-0000-09", + "CR-Lowell_0_BNT-0000-08", "CR-Lowell_0_BNT-0000-06", - "CR-Lowell_0_BNT-0000-07", "CR-Lowell_0_BNT-0000-04", - "CR-Lowell_0_BNT-0000-08", - "CR-Lowell_0_BNT-0000", + "CR-Lowell_0_BNT-0000-07", + "CR-Lowell_0_BNT-0000-02", "CR-Lowell_0_BNT-0000-10", + "CR-Lowell_0_BNT-0000", + "CR-Lowell_0_BNT-0000-03", "CR-Lowell_0_BNT-0000-05", - "CR-Lowell_0_BNT-0000-03" + "CR-Lowell_0_BNT-0000-09" ], "1": [] - } + }, + "terminus": true } ] } diff --git a/common/constants/cr_constants/cr-middleborough.json b/common/constants/cr_constants/cr-middleborough.json index 242aa7d95..b0a815c95 100644 --- a/common/constants/cr_constants/cr-middleborough.json +++ b/common/constants/cr_constants/cr-middleborough.json @@ -14,7 +14,8 @@ "stops": { "0": [], "1": ["CR-Middleborough_1_MM-0356-S"] - } + }, + "terminus": true }, { "stop_name": "Bridgewater", @@ -109,7 +110,8 @@ "CR-Middleborough_0_NEC-2287-12" ], "1": [] - } + }, + "terminus": true } ] } diff --git a/common/constants/cr_constants/cr-needham.json b/common/constants/cr_constants/cr-needham.json index ad928cd40..7c5d54f3b 100644 --- a/common/constants/cr_constants/cr-needham.json +++ b/common/constants/cr_constants/cr-needham.json @@ -14,7 +14,8 @@ "stops": { "0": [], "1": ["CR-Needham_1_NB-0137-S"] - } + }, + "terminus": true }, { "stop_name": "Needham Center", @@ -102,8 +103,8 @@ "branches": null, "order": 10, "stops": { - "0": ["CR-Needham_0_NEC-2265-03", "CR-Needham_0_NEC-2265-01"], - "1": ["CR-Needham_1_NEC-2265-03"] + "0": ["CR-Needham_0_NEC-2265-01", "CR-Needham_0_NEC-2265-03"], + "1": ["CR-Needham_1_NEC-2265-03", "CR-Needham_1_NEC-2265-02"] } }, { @@ -113,7 +114,7 @@ "order": 11, "stops": { "0": ["CR-Needham_0_NEC-2276-03", "CR-Needham_0_NEC-2276-01"], - "1": ["CR-Needham_1_NEC-2276-03"] + "1": ["CR-Needham_1_NEC-2276-02", "CR-Needham_1_NEC-2276-03"] } }, { @@ -124,8 +125,11 @@ "stops": { "0": [ "CR-Needham_0_NEC-2287-06", - "CR-Needham_0_NEC-2287-03", "CR-Needham_0_NEC-2287", + "CR-Needham_0_NEC-2287-02", + "CR-Needham_0_NEC-2287-08", + "CR-Needham_0_NEC-2287-01", + "CR-Needham_0_NEC-2287-03", "CR-Needham_0_NEC-2287-04" ], "1": [] diff --git a/common/constants/cr_constants/cr-newburyport.json b/common/constants/cr_constants/cr-newburyport.json index 39c879db0..fd8f260e0 100644 --- a/common/constants/cr_constants/cr-newburyport.json +++ b/common/constants/cr_constants/cr-newburyport.json @@ -14,7 +14,8 @@ "stops": { "0": ["CR-Newburyport_0_GB-0353-S"], "1": ["CR-Newburyport_1_GB-0353-S"] - } + }, + "terminus": true }, { "stop_name": "Gloucester", @@ -146,11 +147,31 @@ "1": ["CR-Newburyport_1_ER-0128-02"] } }, + { + "stop_name": "Lynn", + "station": "place-ER-0115", + "branches": null, + "order": 15, + "stops": { + "0": [ + "CR-Newburyport_0_14748", + "CR-Newburyport_0_ER-0115", + "CR-Newburyport_0_ER-0115-01", + "CR-Newburyport_0_ER-0115-02" + ], + "1": [ + "CR-Newburyport_1_14748", + "CR-Newburyport_1_ER-0115", + "CR-Newburyport_1_ER-0115-01", + "CR-Newburyport_1_ER-0115-02" + ] + } + }, { "stop_name": "Lynn Interim", "station": "place-ER-0117", "branches": null, - "order": 15, + "order": 16, "stops": { "0": ["CR-Newburyport_0_ER-0117-01"], "1": ["CR-Newburyport_1_ER-0117-02"] @@ -160,7 +181,7 @@ "stop_name": "River Works", "station": "place-ER-0099", "branches": null, - "order": 16, + "order": 17, "stops": { "0": ["CR-Newburyport_0_ER-0099-01"], "1": ["CR-Newburyport_1_ER-0099-02"] @@ -170,7 +191,7 @@ "stop_name": "Chelsea", "station": "place-chels", "branches": null, - "order": 17, + "order": 18, "stops": { "0": ["CR-Newburyport_0_ER-0042-01"], "1": ["CR-Newburyport_1_ER-0042-02"] @@ -180,23 +201,24 @@ "stop_name": "North Station", "station": "place-north", "branches": null, - "order": 18, + "order": 19, "stops": { "0": [ - "CR-Newburyport_0_BNT-0000-10", - "CR-Newburyport_0_BNT-0000-06", - "CR-Newburyport_0_BNT-0000-09", "CR-Newburyport_0_BNT-0000-03", - "CR-Newburyport_0_BNT-0000-07", - "CR-Newburyport_0_BNT-0000-04", - "CR-Newburyport_0_BNT-0000", + "CR-Newburyport_0_BNT-0000-02", "CR-Newburyport_0_BNT-0000-01", - "CR-Newburyport_0_BNT-0000-08", + "CR-Newburyport_0_BNT-0000-04", + "CR-Newburyport_0_BNT-0000-07", + "CR-Newburyport_0_BNT-0000-10", "CR-Newburyport_0_BNT-0000-05", - "CR-Newburyport_0_BNT-0000-02" + "CR-Newburyport_0_BNT-0000-06", + "CR-Newburyport_0_BNT-0000", + "CR-Newburyport_0_BNT-0000-09", + "CR-Newburyport_0_BNT-0000-08" ], "1": [] - } + }, + "terminus": true } ] } diff --git a/common/constants/cr_constants/cr-providence.json b/common/constants/cr_constants/cr-providence.json index 3f63ad195..2540dffea 100644 --- a/common/constants/cr_constants/cr-providence.json +++ b/common/constants/cr_constants/cr-providence.json @@ -14,7 +14,8 @@ "stops": { "0": [], "1": ["CR-Providence_1_NEC-1659-03"] - } + }, + "terminus": true }, { "stop_name": "TF Green Airport", @@ -102,8 +103,8 @@ "branches": null, "order": 10, "stops": { - "0": ["CR-Providence_0_NEC-2139-01", "CR-Providence_0_SB-0150-04"], - "1": ["CR-Providence_1_NEC-2139-02", "CR-Providence_1_SB-0150-06"] + "0": ["CR-Providence_0_SB-0150-04", "CR-Providence_0_NEC-2139-01"], + "1": ["CR-Providence_1_SB-0150-06", "CR-Providence_1_NEC-2139-02"] } }, { @@ -132,8 +133,8 @@ "branches": null, "order": 13, "stops": { - "0": ["CR-Providence_0_NEC-2265-01", "CR-Providence_0_NEC-2265-03"], - "1": ["CR-Providence_1_NEC-2265-02"] + "0": ["CR-Providence_0_NEC-2265-03", "CR-Providence_0_NEC-2265-01"], + "1": ["CR-Providence_1_NEC-2265-02", "CR-Providence_1_NEC-2265-03"] } }, { @@ -154,15 +155,17 @@ "stops": { "0": [ "CR-Providence_0_NEC-2287-05", + "CR-Providence_0_NEC-2287-09", + "CR-Providence_0_NEC-2287-07", "CR-Providence_0_NEC-2287-08", - "CR-Providence_0_NEC-2287-03", + "CR-Providence_0_NEC-2287-04", "CR-Providence_0_NEC-2287", "CR-Providence_0_NEC-2287-06", - "CR-Providence_0_NEC-2287-07", - "CR-Providence_0_NEC-2287-04" + "CR-Providence_0_NEC-2287-03" ], "1": [] - } + }, + "terminus": true } ] } diff --git a/common/constants/cr_constants/cr-worcester.json b/common/constants/cr_constants/cr-worcester.json index 7705ef80d..7e9ff0759 100644 --- a/common/constants/cr_constants/cr-worcester.json +++ b/common/constants/cr_constants/cr-worcester.json @@ -14,7 +14,8 @@ "stops": { "0": ["CR-Worcester_0_WML-0442-CS"], "1": ["CR-Worcester_1_WML-0442-CS"] - } + }, + "terminus": true }, { "stop_name": "Grafton", @@ -73,7 +74,7 @@ "order": 7, "stops": { "0": ["CR-Worcester_0_WML-0199-02", "CR-Worcester_0_WML-0199-01"], - "1": ["CR-Worcester_1_WML-0199-01", "CR-Worcester_1_WML-0199-02"] + "1": ["CR-Worcester_1_WML-0199-02", "CR-Worcester_1_WML-0199-01"] } }, { @@ -102,17 +103,51 @@ "branches": null, "order": 10, "stops": { - "0": ["CR-Worcester_0_WML-0135-01", "CR-Worcester_0_WML-0135-02"], - "1": ["CR-Worcester_1_WML-0135-02", "CR-Worcester_1_WML-0135-01"] + "0": ["CR-Worcester_0_WML-0135-02", "CR-Worcester_0_WML-0135-01"], + "1": ["CR-Worcester_1_WML-0135-01", "CR-Worcester_1_WML-0135-02"] + } + }, + { + "stop_name": "Riverside", + "station": "place-river", + "branches": null, + "order": 11, + "stops": { + "0": [ + "CR-Worcester_0_38155", + "CR-Worcester_0_70160", + "CR-Worcester_0_70161", + "CR-Worcester_0_door-river-estairs", + "CR-Worcester_0_door-river-ramp", + "CR-Worcester_0_door-river-wstairs", + "CR-Worcester_0_node-river-estairs-lobby", + "CR-Worcester_0_node-river-farepaid", + "CR-Worcester_0_node-river-fareunpaid", + "CR-Worcester_0_node-river-ramp-lobby", + "CR-Worcester_0_node-river-wstairs-lobby" + ], + "1": [ + "CR-Worcester_1_38155", + "CR-Worcester_1_70160", + "CR-Worcester_1_70161", + "CR-Worcester_1_door-river-estairs", + "CR-Worcester_1_door-river-ramp", + "CR-Worcester_1_door-river-wstairs", + "CR-Worcester_1_node-river-estairs-lobby", + "CR-Worcester_1_node-river-farepaid", + "CR-Worcester_1_node-river-fareunpaid", + "CR-Worcester_1_node-river-ramp-lobby", + "CR-Worcester_1_node-river-wstairs-lobby" + ] } }, { "stop_name": "Wellesley Farms", "station": "place-WML-0125", "branches": null, - "order": 11, + "order": 12, "stops": { - "0": ["CR-Worcester_0_WML-0125-01", "CR-Worcester_0_WML-0125-02"], + "0": ["CR-Worcester_0_WML-0125-02", "CR-Worcester_0_WML-0125-01"], "1": ["CR-Worcester_1_WML-0125-01", "CR-Worcester_1_WML-0125-02"] } }, @@ -120,7 +155,7 @@ "stop_name": "Auburndale", "station": "place-WML-0102", "branches": null, - "order": 12, + "order": 13, "stops": { "0": ["CR-Worcester_0_WML-0102-02"], "1": ["CR-Worcester_1_WML-0102-02"] @@ -130,7 +165,7 @@ "stop_name": "West Newton", "station": "place-WML-0091", "branches": null, - "order": 13, + "order": 14, "stops": { "0": ["CR-Worcester_0_WML-0091-02"], "1": ["CR-Worcester_1_WML-0091-02"] @@ -140,7 +175,7 @@ "stop_name": "Newtonville", "station": "place-WML-0081", "branches": null, - "order": 14, + "order": 15, "stops": { "0": ["CR-Worcester_0_WML-0081-02"], "1": ["CR-Worcester_1_WML-0081-02"] @@ -150,17 +185,17 @@ "stop_name": "Boston Landing", "station": "place-WML-0035", "branches": null, - "order": 15, + "order": 16, "stops": { - "0": ["CR-Worcester_0_WML-0035-02", "CR-Worcester_0_WML-0035-01"], - "1": ["CR-Worcester_1_WML-0035-01", "CR-Worcester_1_WML-0035-02"] + "0": ["CR-Worcester_0_WML-0035-01", "CR-Worcester_0_WML-0035-02"], + "1": ["CR-Worcester_1_WML-0035-02", "CR-Worcester_1_WML-0035-01"] } }, { "stop_name": "Lansdowne", "station": "place-WML-0025", "branches": null, - "order": 16, + "order": 17, "stops": { "0": ["CR-Worcester_0_WML-0025-07"], "1": ["CR-Worcester_1_WML-0025-05"] @@ -170,26 +205,30 @@ "stop_name": "Back Bay", "station": "place-bbsta", "branches": null, - "order": 17, + "order": 18, "stops": { "0": ["CR-Worcester_0_WML-0012-07"], - "1": ["CR-Worcester_1_WML-0012-05"] + "1": ["CR-Worcester_1_WML-0012-07", "CR-Worcester_1_WML-0012-05"] } }, { "stop_name": "South Station", "station": "place-sstat", "branches": null, - "order": 18, + "order": 19, "stops": { "0": [ + "CR-Worcester_0_NEC-2287-03", + "CR-Worcester_0_NEC-2287-04", + "CR-Worcester_0_NEC-2287-05", "CR-Worcester_0_NEC-2287", - "CR-Worcester_0_NEC-2287-01", "CR-Worcester_0_NEC-2287-02", - "CR-Worcester_0_NEC-2287-04" + "CR-Worcester_0_NEC-2287-10", + "CR-Worcester_0_NEC-2287-01" ], "1": [] - } + }, + "terminus": true } ] } diff --git a/common/styles/general.ts b/common/styles/general.ts index 3543b78da..37b763b6f 100644 --- a/common/styles/general.ts +++ b/common/styles/general.ts @@ -10,7 +10,7 @@ export const lineColorBackground: DefaultStyleMap = { DEFAULT: `bg-stone-800`, }; -export const lineColorLightBorder = { +export const lineColorLightBorder: DefaultStyleMap = { 'line-red': `border-mbta-lightRed`, 'line-orange': `border-mbta-lightOrange`, 'line-green': `border-mbta-lightGreen`, diff --git a/server/scripts/generate_line_files.py b/server/scripts/generate_line_files.py index 89c4e1859..a85e67c93 100644 --- a/server/scripts/generate_line_files.py +++ b/server/scripts/generate_line_files.py @@ -105,15 +105,17 @@ def parse_stop_name(stop_name: str): for index, stop in enumerate(stops["data"]): try: - stops_formatted.append( - { - "stop_name": stop["attributes"]["name"], - "station": stop["id"], - "branches": None, - "order": index + 1, - "stops": stop_layout[stop["id"]], - } - ) + station_json = { + "stop_name": stop["attributes"]["name"], + "station": stop["id"], + "branches": None, + "order": index + 1, + "stops": stop_layout[stop["id"]], + } + if index == 0 or index == len(stops["data"]) - 1: + station_json["terminus"] = True + + stops_formatted.append(station_json) except KeyError: c_f = requests.get( "https://api-v3.mbta.com/stops/{}?include=child_stops&api_key={}".format(stop["id"], MBTA_V3_API_KEY) From 7ce77b4b3c26ccc3fb86362e146784fe5bfb1f35 Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Thu, 16 May 2024 22:03:56 -0400 Subject: [PATCH 34/53] Fixing data fetching issues for cr --- common/components/notices/BetaDataNotice.tsx | 69 ++++++++++++++++++++ modules/tripexplorer/TripExplorer.tsx | 2 + server/chalicelib/parallel.py | 8 ++- server/chalicelib/s3.py | 9 +-- 4 files changed, 82 insertions(+), 6 deletions(-) create mode 100644 common/components/notices/BetaDataNotice.tsx diff --git a/common/components/notices/BetaDataNotice.tsx b/common/components/notices/BetaDataNotice.tsx new file mode 100644 index 000000000..01a30bd57 --- /dev/null +++ b/common/components/notices/BetaDataNotice.tsx @@ -0,0 +1,69 @@ +import React from 'react'; +import dayjs from 'dayjs'; +import Link from 'next/link'; +import classNames from 'classnames'; +import { ExclamationTriangleIcon } from '@heroicons/react/20/solid'; +import { useDelimitatedRoute } from '../../utils/router'; +import { BUS_MAX_DAY } from '../../constants/dates'; +import { lineColorTextHover } from '../../styles/general'; + +export const BetaDataNotice: React.FC = () => { + const { + line, + linePath, + query: { date, startDate, endDate }, + } = useDelimitatedRoute(); + + const isStartDateAfterBusMaxDay = + (startDate !== undefined && dayjs(startDate).isAfter(BUS_MAX_DAY)) || + (date !== undefined && dayjs(date).isAfter(BUS_MAX_DAY)); + const isEndDateAfterBusMaxDay = endDate !== undefined && dayjs(endDate).isAfter(BUS_MAX_DAY); + + if ( + (line === 'line-commuter-rail' || linePath === 'commuter-rail') && + (isStartDateAfterBusMaxDay || isEndDateAfterBusMaxDay) + ) { + return ( +
+
+
+
+
+

+ Real-time Commuter Rail data is in beta +

+
+

+ TransitMatters collects this data using the{' '} + + MBTA's V3 API + + . Unlike data from other sources, it is not cleaned or filtered before display. + Please expect reduced accuracy. +

+

+ Technical details of our data collection are available in our{' '} + + GitHub repository + + . +

+
+
+
+
+ ); + } + return null; +}; diff --git a/modules/tripexplorer/TripExplorer.tsx b/modules/tripexplorer/TripExplorer.tsx index bf3546e1a..98022af89 100644 --- a/modules/tripexplorer/TripExplorer.tsx +++ b/modules/tripexplorer/TripExplorer.tsx @@ -11,6 +11,7 @@ import { useDelimitatedRoute } from '../../common/utils/router'; import { getParentStationForStopId } from '../../common/utils/stations'; import { BusDataNotice } from '../../common/components/notices/BusDataNotice'; import { GobbleDataNotice } from '../../common/components/notices/GobbleDataNotice'; +import { BetaDataNotice } from '../../common/components/notices/BetaDataNotice'; import { useAlertStore } from './AlertStore'; import { TripGraphs } from './TripGraphs'; @@ -37,6 +38,7 @@ export const TripExplorer = () => { return ( + {alertsForModal?.length ? : null}
diff --git a/server/chalicelib/parallel.py b/server/chalicelib/parallel.py index 692a676b0..5bbbfbe18 100644 --- a/server/chalicelib/parallel.py +++ b/server/chalicelib/parallel.py @@ -2,6 +2,7 @@ from datetime import date import pandas as pd +from chalicelib import s3 from chalicelib import date_utils @@ -27,7 +28,7 @@ def date_range(start: str, end: str): return pd.date_range(start, end) -def s3_date_range(start: date, end: date): +def s3_date_range(start: date, end: date, stops: list[str]): """ Generates a date range, meant for s3 data For all dates that we have monthly datasets for, return 1 date of the month @@ -39,10 +40,13 @@ def s3_date_range(start: date, end: date): date_range = pd.date_range(start, month_end, freq="1D", inclusive="both") + # are any of the stops CR, if so use daily data only + cr_data = any([s3.is_cr(stop) for stop in stops]) + # This is kinda funky, but is stil simpler than other approaches # pandas won't generate a monthly date_range that includes Jan and Feb for Jan31-Feb1 e.g. # So we generate a daily date_range and then resample it down (summing 0s as a no-op in the process) so it aligns. - if date_utils.get_max_monthly_data_date() > start: + if date_utils.get_max_monthly_data_date() > start and not cr_data: dates = pd.date_range(start, month_end, freq="1D", inclusive="both") series = pd.Series(0, index=dates) date_range = series.resample("1M").sum().index diff --git a/server/chalicelib/s3.py b/server/chalicelib/s3.py index 8482d1156..07f6fb9dd 100644 --- a/server/chalicelib/s3.py +++ b/server/chalicelib/s3.py @@ -56,8 +56,11 @@ def download_one_event_file(date: pd.Timestamp, stop_id: str, use_gobble=False): """As advertised: single event file from s3""" year, month, day = date.year, date.month, date.day + if is_cr(stop_id): + folder = get_gobble_folder(stop_id) + key = f"Events-live/{folder}/{stop_id}/Year={year}/Month={month}/Day={day}/events.csv.gz" # if current date is newer than the max monthly data date, use LAMP - if date.date() > date_utils.get_max_monthly_data_date(): + elif date.date() > date_utils.get_max_monthly_data_date(): # if we've asked to use gobble data or bus data, check gobble if use_gobble or is_bus(stop_id): folder = get_gobble_folder(stop_id) @@ -96,13 +99,11 @@ def download_one_event_file(date: pd.Timestamp, stop_id: str, use_gobble=False): @parallel.make_parallel def parallel_download_events(datestop: itertools.product): (date, stop) = datestop - if is_cr(stop): - return download_one_event_file(date, stop, use_live_data=True) return download_one_event_file(date, stop) def download_events(start_date: date, end_date: date, stops: list): - datestops = itertools.product(parallel.s3_date_range(start_date, end_date), stops) + datestops = itertools.product(parallel.s3_date_range(start_date, end_date, stops), stops) result = parallel_download_events(datestops) result = filter( lambda row: start_date.strftime("%Y-%m-%d") <= row["service_date"] <= end_date.strftime("%Y-%m-%d"), result From d837b4c537faba5edd3313ccddb64a53a4afecf8 Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Thu, 16 May 2024 22:23:03 -0400 Subject: [PATCH 35/53] Remove unused --- server/chalicelib/data_funcs.py | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/server/chalicelib/data_funcs.py b/server/chalicelib/data_funcs.py index 0dd56b7f3..84e912aa8 100644 --- a/server/chalicelib/data_funcs.py +++ b/server/chalicelib/data_funcs.py @@ -62,28 +62,6 @@ def use_S3(date, bus=False): return archival or bus -def partition_S3_dates(start_date: str | date, end_date: str | date, bus=False, cr=False): - """ - Partitions dates by what data source they should be fetched from. - S3 is used for archival data and for bus data. API is used for recent (within 90 days) subway data. - TODO: Add Gobble data to this partitioning. - """ - CUTOFF = datetime.date.today() - datetime.timedelta(days=90) - - s3_dates = None - api_dates = None - - if end_date < CUTOFF or bus or cr: - s3_dates = (start_date, end_date) - elif CUTOFF <= start_date: - api_dates = (start_date, end_date) - else: - s3_dates = (start_date, CUTOFF - datetime.timedelta(days=1)) - api_dates = (CUTOFF, end_date) - - return (s3_dates, api_dates) - - def headways(start_date: date, stops, end_date: date | None = None): if end_date is None: return s3_historical.headways(stops, start_date, start_date) From 5ed457506e77d085f2ff6515245946ca26c637b3 Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Thu, 18 Jul 2024 21:52:33 -0400 Subject: [PATCH 36/53] Adding commuter rail ridership to dashboard --- .../components/nav/CommuterRailDropdown.tsx | 8 ++++--- common/components/nav/MenuDropdown.tsx | 21 ++++++++++++------- common/components/notices/BetaDataNotice.tsx | 9 ++++---- .../components/notices/GobbleDataNotice.tsx | 6 ++++-- common/components/notices/SameDayNotice.tsx | 9 ++------ common/constants/baselines.ts | 20 ++++++++++++++++-- common/constants/colors.ts | 19 ++++++++++------- common/constants/dashboardTabs.ts | 11 ++++++---- common/constants/dates.ts | 13 +++++++++++- common/constants/pages.ts | 2 +- common/constants/stations.ts | 4 +++- common/layouts/DashboardLayout.tsx | 9 ++++++-- common/state/dateStore.ts | 2 +- common/state/defaults/dateDefaults.ts | 18 +++++++++++++++- common/styles/general.ts | 2 +- common/types/lines.ts | 6 ++++++ common/types/router.ts | 2 +- common/utils/ridership.ts | 10 +++++++-- common/utils/router.tsx | 5 ++++- modules/dashboard/DesktopHeader.tsx | 11 ++++++++-- modules/landing/LineButton.tsx | 2 +- modules/navigation/SideNavigation.tsx | 2 ++ modules/ridership/RidershipDetails.tsx | 7 ++++--- modules/ridership/RidershipGraph.tsx | 5 +++-- modules/ridership/RidershipGraphWrapper.tsx | 6 ++++-- modules/ridership/RidershipWidget.tsx | 3 ++- modules/ridership/utils/utils.ts | 7 ++++--- pages/[line]/index.tsx | 4 ++-- pages/[line]/ridership.tsx | 4 ++-- 29 files changed, 160 insertions(+), 67 deletions(-) diff --git a/common/components/nav/CommuterRailDropdown.tsx b/common/components/nav/CommuterRailDropdown.tsx index 522d0c1bf..a1cdf9607 100644 --- a/common/components/nav/CommuterRailDropdown.tsx +++ b/common/components/nav/CommuterRailDropdown.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { SidebarTabs } from '../../../modules/navigation/SidebarTabs'; -import { TRIP_PAGES, COMMUTER_RAIL_OVERVIEW } from '../../constants/pages'; +import { COMMUTER_RAIL_OVERVIEW } from '../../constants/pages'; import { CommuterRailRouteSelection } from './CommuterRailRouteSelection'; interface CommuterRailDropdownProps { @@ -18,8 +18,10 @@ export const CommuterRailDropdown: React.FC = ({ clos role={'navigation'} > -
- + + {/* TODO: Once we have reliable travel data for CR */} + {/*
*/} + {/* */}
); diff --git a/common/components/nav/MenuDropdown.tsx b/common/components/nav/MenuDropdown.tsx index db3919182..412cafa67 100644 --- a/common/components/nav/MenuDropdown.tsx +++ b/common/components/nav/MenuDropdown.tsx @@ -4,7 +4,7 @@ import classNames from 'classnames'; import Link from 'next/link'; import React, { useEffect, useState } from 'react'; import { LINE_OBJECTS } from '../../constants/lines'; -import { BUS_DEFAULTS } from '../../state/defaults/dateDefaults'; +import { BUS_DEFAULTS, COMMUTER_RAIL_DEFAULTS } from '../../state/defaults/dateDefaults'; import { lineColorBackground } from '../../styles/general'; import type { Line } from '../../types/lines'; import type { Route } from '../../types/router'; @@ -38,15 +38,20 @@ export const MenuDropdown: React.FC = ({ line, route, childre } }, [line]); + const href = React.useMemo(() => { + switch (line) { + case 'line-bus': + return `/bus/trips/single?busRoute=1&date=${BUS_DEFAULTS.singleTripConfig.date}`; + case 'line-commuter-rail': + return `/commuter-rail/ridership?crRoute=CR-Lowell&startDate=${COMMUTER_RAIL_DEFAULTS.lineConfig.startDate}&endDate=${COMMUTER_RAIL_DEFAULTS.lineConfig.endDate}`; + default: + return getLineSelectionItemHref(line, route); + } + }, [line, route]); + return (
- +
{ const isEndDateAfterBusMaxDay = endDate !== undefined && dayjs(endDate).isAfter(BUS_MAX_DAY); if ( - (line === 'line-bus' || linePath === 'bus') && + (line === 'line-commuter-rail' || linePath === 'commuter-rail') && (isStartDateAfterBusMaxDay || isEndDateAfterBusMaxDay) ) { return ( @@ -30,7 +30,9 @@ export const BetaDataNotice: React.FC = () => {
-

Real-time bus data is in beta

+

+ Real-time Commuter Rail data is in beta +

TransitMatters collects this data using the{' '} @@ -46,8 +48,7 @@ export const BetaDataNotice: React.FC = () => { Please expect reduced accuracy.

- We favor official performance data from the MBTA when it's available. Technical - details of our data collection are available in our{' '} + Technical details of our data collection are available in our{' '} { const isEndDateAfterBusMaxDay = endDate !== undefined && dayjs(endDate).isAfter(BUS_MAX_DAY); if ( - (line === 'line-bus' || linePath === 'bus') && - (isStartDateAfterBusMaxDay || isEndDateAfterBusMaxDay) + ((line === 'line-bus' || linePath === 'bus') && + (isStartDateAfterBusMaxDay || isEndDateAfterBusMaxDay)) || + line === 'line-commuter-rail' || + linePath === 'commuter-rail' ) { return (

diff --git a/common/components/notices/SameDayNotice.tsx b/common/components/notices/SameDayNotice.tsx index 96959ba79..258fe8232 100644 --- a/common/components/notices/SameDayNotice.tsx +++ b/common/components/notices/SameDayNotice.tsx @@ -6,21 +6,16 @@ import { TODAY_STRING } from '../../constants/dates'; export const SameDayNotice: React.FC = () => { const { - line, query: { date, endDate }, } = useDelimitatedRoute(); const isToday = date === TODAY_STRING || endDate === TODAY_STRING; - if (isToday && line !== 'line-bus') { + if (isToday) { return (
-

- Due to data not being cleaned yet, today's data may not be fully accurate and may look - messy. -

-

Data is cleaned up overnight and should be more accurate tomorrow.

+

Data from today may not be complete. Data comes in with a delay of up to two hours

); diff --git a/common/constants/baselines.ts b/common/constants/baselines.ts index 1eed84ff2..ad85e11b3 100644 --- a/common/constants/baselines.ts +++ b/common/constants/baselines.ts @@ -1,4 +1,4 @@ -import type { BusRouteId, Line } from '../types/lines'; +import type { BusRouteId, CommuterRailRoute, Line } from '../types/lines'; // These are manually chosen based off the peak *monthly* scheduled service. Selecting highest value " export const PEAK_SCHEDULED_SERVICE = { @@ -20,7 +20,11 @@ export const PEAK_SPEED = { // These are manually chosen based off the peak value. Need to be updated when all data is generated. export const PEAK_RIDERSHIP: { - [key in Exclude | BusRouteId | 'DEFAULT']: number; + [key in + | Exclude + | BusRouteId + | CommuterRailRoute + | 'DEFAULT']: number; } = { 'line-red': 213703, 'line-orange': 169578, @@ -58,6 +62,18 @@ export const PEAK_RIDERSHIP: { '111': 11258, '114116117': 12867, '220221222': 3370, + 'CR-Fitchburg': 9302, + 'CR-Franklin': 11671, + 'CR-Greenbush': 6114, + 'CR-Haverhill': 7112, + 'CR-Lowell': 10925, + 'CR-Worcester': 18637, + 'CR-Fairmount': 2652, + 'CR-Kingston': 6089, + 'CR-Middleborough': 6863, + 'CR-Needham': 6690, + 'CR-Newburyport': 14972, + 'CR-Providence': 25728, DEFAULT: 520580, }; diff --git a/common/constants/colors.ts b/common/constants/colors.ts index af92c7083..d6178a649 100644 --- a/common/constants/colors.ts +++ b/common/constants/colors.ts @@ -1,3 +1,4 @@ +import type { Line } from '../types/lines'; import { hexWithAlpha } from '../utils/general'; export const COLORS = { @@ -44,20 +45,24 @@ export const CHART_COLORS = { BLOCKS_SOLID: '#d2d2d2', }; -export const LINE_COLORS = { - 'line-red': '#D13434', - 'line-orange': '#ed8b00', - 'line-blue': '#003da5', - 'line-green': '#00834d', - 'line-bus': '#ffc72c', +export const LINE_COLORS: { [key in Line | 'default']: string } = { + 'line-red': COLORS.mbta.red, + 'line-orange': COLORS.mbta.orange, + 'line-blue': COLORS.mbta.blue, + 'line-green': COLORS.mbta.green, + 'line-bus': COLORS.mbta.bus, + 'line-commuter-rail': COLORS.mbta.commuterRail, default: '#303030', }; -export const LINE_COLORS_LEVELS = { +export const LINE_COLORS_LEVELS: { + [key in Line | 'default']: { [num in number]: string } | string; +} = { 'line-red': { 0: '#D13434', 1: '#d64949', 2: '#da5e5e', 3: '#df7272' }, 'line-orange': { 0: '#ed8b00', 1: '#ff9907', 2: '#ffa321', 3: '#ffae3b' }, 'line-blue': { 0: '#003da5', 1: '#0046bf', 2: '#0050d8', 3: '#0059f2' }, 'line-green': { 0: '#00834d', 1: '#009d5c', 2: '#00b66b', 3: '#00d07a' }, 'line-bus': { 0: '#ffc72c', 1: '#ffce46', 2: '#ffd55f', 3: '#ffdb79' }, + 'line-commuter-rail': { 0: '#80276c', 1: '#8f2f7e', 2: '#9e3790', 3: '#ad41a2' }, default: '#303030', }; diff --git a/common/constants/dashboardTabs.ts b/common/constants/dashboardTabs.ts index 8e4084340..bbfd46a21 100644 --- a/common/constants/dashboardTabs.ts +++ b/common/constants/dashboardTabs.ts @@ -1,7 +1,5 @@ -import { BUS_DEFAULTS } from '../state/defaults/dateDefaults'; -import type { QueryParams } from '../types/router'; - -export type Tab = 'Subway' | 'Bus' | 'System'; +import { BUS_DEFAULTS, COMMUTER_RAIL_DEFAULTS } from '../state/defaults/dateDefaults'; +import type { QueryParams, Tab } from '../types/router'; export const DASHBOARD_TABS: { [key in Tab]: { name: Tab; path: string; disabled?: boolean; query?: QueryParams }; @@ -13,4 +11,9 @@ export const DASHBOARD_TABS: { path: '/bus/trips/single', query: { busRoute: '1', date: BUS_DEFAULTS.singleTripConfig.date }, }, + 'Commuter Rail': { + name: 'Commuter Rail', + path: '/commuter-rail', + query: { crRoute: 'CR-Lowell', date: COMMUTER_RAIL_DEFAULTS.singleTripConfig.date }, + }, }; diff --git a/common/constants/dates.ts b/common/constants/dates.ts index 441c994f1..14a8c43d6 100644 --- a/common/constants/dates.ts +++ b/common/constants/dates.ts @@ -8,7 +8,7 @@ import type { DateSelectionDefaultOptions, SingleDateParams, } from '../components/inputs/DateSelection/types/DateSelectionTypes'; -import type { Tab } from './dashboardTabs'; +import type { Tab } from '../types/router'; dayjs.extend(utc); dayjs.extend(timezone); @@ -40,6 +40,7 @@ export const BUS_MAX_DAY = dayjs(BUS_MAX_DATE); export const BUS_MAX_DATE_MINUS_ONE_WEEK = dayjs(BUS_MAX_DATE) .subtract(7, 'days') .format(DATE_FORMAT); +export const COMMUTER_RAIL_MIN_DATE = '2022-06-22'; export const getESTDayjs = (date: string) => { return dayjs(date).tz(est); @@ -72,6 +73,14 @@ export const FLAT_PICKER_OPTIONS: { altFormat: 'M j, Y', dateFormat: 'Y-m-d', }, + 'Commuter Rail': { + enableTime: false, + minDate: COMMUTER_RAIL_MIN_DATE, + maxDate: TODAY_STRING, + altInput: true, + altFormat: 'M j, Y', + dateFormat: 'Y-m-d', + }, }; const SINGLE_RAPID_PRESETS: { @@ -143,6 +152,7 @@ export const SINGLE_PRESETS: { Subway: SINGLE_RAPID_PRESETS, Bus: SINGLE_RAPID_PRESETS, System: SINGLE_RAPID_PRESETS, + 'Commuter Rail': SINGLE_RAPID_PRESETS, }; const RANGE_RAPID_PRESETS: { @@ -265,6 +275,7 @@ export const RANGE_PRESETS: { Subway: RANGE_RAPID_PRESETS, Bus: RANGE_RAPID_PRESETS, System: RANGE_RAPID_PRESETS, + 'Commuter Rail': RANGE_RAPID_PRESETS, }; export type DatePresetKey = diff --git a/common/constants/pages.ts b/common/constants/pages.ts index 69f7c7950..27e473ca3 100644 --- a/common/constants/pages.ts +++ b/common/constants/pages.ts @@ -141,7 +141,7 @@ export const ALL_PAGES: PageMap = { key: 'ridership', path: '/ridership', name: 'Ridership', - lines: ['line-red', 'line-blue', 'line-green', 'line-orange', 'line-bus'], + lines: ['line-red', 'line-blue', 'line-green', 'line-orange', 'line-bus', 'line-commuter-rail'], icon: faUsers, dateStoreSection: 'line', }, diff --git a/common/constants/stations.ts b/common/constants/stations.ts index 3593d4847..2e8ad80e8 100644 --- a/common/constants/stations.ts +++ b/common/constants/stations.ts @@ -1,5 +1,5 @@ /* eslint-disable import/max-dependencies */ -import type { LineShort } from '../types/lines'; +import { COMMUTER_RAIL_ROUTES, type LineShort } from '../types/lines'; import type { LineMap } from '../types/stations'; import stations_json from './stations.json'; import bus_1 from './bus_constants/1.json'; @@ -82,5 +82,7 @@ export const getBusRoutes = (): string[] => { }; export const getCommuterRailRoutes = (): string[] => { + return COMMUTER_RAIL_ROUTES; + // TODO: use this once we are on trips return Object.keys(commuterRailStations); }; diff --git a/common/layouts/DashboardLayout.tsx b/common/layouts/DashboardLayout.tsx index 1826f6508..98ab4194b 100644 --- a/common/layouts/DashboardLayout.tsx +++ b/common/layouts/DashboardLayout.tsx @@ -14,7 +14,7 @@ interface DashboardLayoutProps { export const DashboardLayout: React.FC = ({ children }) => { const isMobile = !useBreakpoint('md'); const { line, page, query, tab } = useDelimitatedRoute(); - const { busRoute } = query; + const { busRoute, crRoute } = query; const dateStoreSection = page ? ALL_PAGES[page]?.dateStoreSection : undefined; const showControlParams = dateStoreSection && (line || tab === 'System') && dateStoreSection !== 'today'; @@ -30,7 +30,12 @@ export const DashboardLayout: React.FC = ({ children }) =>
{isMobile && showControlParams && ( - + )}
); diff --git a/common/state/dateStore.ts b/common/state/dateStore.ts index 3ced87efe..5154dbf00 100644 --- a/common/state/dateStore.ts +++ b/common/state/dateStore.ts @@ -1,6 +1,6 @@ import { create } from 'zustand'; import { OVERVIEW_OPTIONS, TODAY_STRING } from '../constants/dates'; -import type { Tab } from '../constants/dashboardTabs'; +import type { Tab } from '../types/router'; import type { LineSectionParams, MultiTripsSectionParams, diff --git a/common/state/defaults/dateDefaults.ts b/common/state/defaults/dateDefaults.ts index d018a02e8..1551ae7a6 100644 --- a/common/state/defaults/dateDefaults.ts +++ b/common/state/defaults/dateDefaults.ts @@ -1,4 +1,4 @@ -import type { Tab } from '../../constants/dashboardTabs'; +import type { Tab } from '../../types/router'; import type { DateStoreSection } from '../../constants/pages'; import type { DateStoreConfiguration } from '../types/dateStoreTypes'; import { @@ -7,6 +7,7 @@ import { TODAY_STRING, YESTERDAY_STRING, TODAY_SERVICE_STARTED, + COMMUTER_RAIL_MIN_DATE, } from '../../constants/dates'; import type { WithOptional } from '../../types/general'; @@ -34,6 +35,20 @@ export const BUS_DEFAULTS: WithOptional = { + lineConfig: { startDate: OVERVIEW_OPTIONS.year.startDate, endDate: TODAY_STRING }, + multiTripConfig: { + startDate: COMMUTER_RAIL_MIN_DATE, + endDate: TODAY_STRING, + }, + singleTripConfig: { + date: TODAY_SERVICE_STARTED ? TODAY_STRING : YESTERDAY_STRING, + }, +}; + const SYSTEM_DEFAULTS: Partial = { systemConfig: { startDate: OVERVIEW_OPTIONS.year.startDate, endDate: TODAY_STRING }, }; @@ -42,6 +57,7 @@ const TAB_DATE_MAP: { [key in Tab]: Partial } = { Subway: SUBWAY_DEFAULTS, Bus: BUS_DEFAULTS, System: SYSTEM_DEFAULTS, + 'Commuter Rail': COMMUTER_RAIL_DEFAULTS, }; export const getDefaultDates = (dateStoreSection: DateStoreSection, tab: Tab) => { diff --git a/common/styles/general.ts b/common/styles/general.ts index 3543b78da..37b763b6f 100644 --- a/common/styles/general.ts +++ b/common/styles/general.ts @@ -10,7 +10,7 @@ export const lineColorBackground: DefaultStyleMap = { DEFAULT: `bg-stone-800`, }; -export const lineColorLightBorder = { +export const lineColorLightBorder: DefaultStyleMap = { 'line-red': `border-mbta-lightRed`, 'line-orange': `border-mbta-lightOrange`, 'line-green': `border-mbta-lightGreen`, diff --git a/common/types/lines.ts b/common/types/lines.ts index 2ac419093..900be6c23 100644 --- a/common/types/lines.ts +++ b/common/types/lines.ts @@ -174,3 +174,9 @@ export const BUS_PATH = { line: 'bus', }, }; + +export const COMMUTER_RAIL_PATH = { + params: { + line: 'commuter-rail', + }, +}; diff --git a/common/types/router.ts b/common/types/router.ts index d76fbe78e..c9c59b19b 100644 --- a/common/types/router.ts +++ b/common/types/router.ts @@ -28,4 +28,4 @@ export type QueryParams = { export type QueryTypeOptions = 'single' | 'range'; -export type Tab = 'Bus' | 'Subway' | 'System'; +export type Tab = 'Bus' | 'Subway' | 'Commuter Rail' | 'System'; diff --git a/common/utils/ridership.ts b/common/utils/ridership.ts index 29726be8a..881167e83 100644 --- a/common/utils/ridership.ts +++ b/common/utils/ridership.ts @@ -1,7 +1,11 @@ -import type { BusRoute, Line } from '../types/lines'; +import type { BusRoute, CommuterRailRoute, Line } from '../types/lines'; import { RIDERSHIP_KEYS } from '../types/lines'; -export const getRidershipLineId = (line: Line | undefined, busRoute: BusRoute | undefined) => { +export const getRidershipLineId = ( + line: Line | undefined, + busRoute: BusRoute | undefined, + crRoute: CommuterRailRoute | undefined +) => { if (line === 'line-bus' && busRoute) { switch (busRoute) { case '34': @@ -11,6 +15,8 @@ export const getRidershipLineId = (line: Line | undefined, busRoute: BusRoute | default: return `line-${busRoute.replaceAll('/', '')}`; } + } else if (line === 'line-commuter-rail' && crRoute) { + return `line-${crRoute.substring(3)}`; } else { return RIDERSHIP_KEYS[line ?? '']; } diff --git a/common/utils/router.tsx b/common/utils/router.tsx index 92c5286e8..42c1f2a0e 100644 --- a/common/utils/router.tsx +++ b/common/utils/router.tsx @@ -16,12 +16,13 @@ import { useDateStore } from '../state/dateStore'; import type { DateStore } from '../state/dateStore'; import { LINE_COLORS } from '../constants/colors'; -const linePathToKeyMap: Record = { +const linePathToKeyMap: Record = { red: 'line-red', orange: 'line-orange', green: 'line-green', blue: 'line-blue', bus: 'line-bus', + 'commuter-rail': 'line-commuter-rail', }; const getParams = (params: ParsedUrlQuery | QueryParams) => { @@ -60,6 +61,8 @@ const getTab = (path: LinePath) => { return 'Subway'; } else if (path === 'bus') { return 'Bus'; + } else if (path === 'commuter-rail') { + return 'Commuter Rail'; } else { return 'System'; } diff --git a/modules/dashboard/DesktopHeader.tsx b/modules/dashboard/DesktopHeader.tsx index 8bed60e2a..0335f033c 100644 --- a/modules/dashboard/DesktopHeader.tsx +++ b/modules/dashboard/DesktopHeader.tsx @@ -5,12 +5,13 @@ import { useDelimitatedRoute } from '../../common/utils/router'; import { ALL_PAGES } from '../../common/constants/pages'; import { ControlPanel } from '../../common/components/controls/ControlPanel'; import { lineColorBackground } from '../../common/styles/general'; +import { COMMUTER_RAIL_LINE_NAMES } from '../../common/types/lines'; export const DesktopHeader: React.FC = () => { const { line, page, - query: { busRoute }, + query: { busRoute, crRoute }, tab, } = useDelimitatedRoute(); const dateStoreSection = page ? ALL_PAGES[page]?.dateStoreSection : undefined; @@ -20,6 +21,7 @@ export const DesktopHeader: React.FC = () => { const getLineName = () => { if (busRoute) return `Route ${busRoute}`; + if (crRoute) return COMMUTER_RAIL_LINE_NAMES[crRoute]; if (line) return LINE_OBJECTS[line]?.name; if (tab === 'System') return 'System'; }; @@ -40,7 +42,12 @@ export const DesktopHeader: React.FC = () => {
{showControls && ( - + )}
); diff --git a/modules/landing/LineButton.tsx b/modules/landing/LineButton.tsx index c66f49b1e..24914fcfb 100644 --- a/modules/landing/LineButton.tsx +++ b/modules/landing/LineButton.tsx @@ -34,7 +34,7 @@ export const LineButton: React.FC = ({ children, line }) => {

{LINE_OBJECTS[line].name}

- {line === 'line-bus' &&

(Beta)

} + {line === 'line-commuter-rail' &&

(Beta)

}
); diff --git a/modules/navigation/SideNavigation.tsx b/modules/navigation/SideNavigation.tsx index 541bfe1a3..205b4dd39 100644 --- a/modules/navigation/SideNavigation.tsx +++ b/modules/navigation/SideNavigation.tsx @@ -6,6 +6,7 @@ import classNames from 'classnames'; import { SubwaySection } from '../../common/components/nav/SubwaySection'; import { BusSection } from '../../common/components/nav/BusSection'; import { useDelimitatedRoute } from '../../common/utils/router'; +import { CommuterRailSection } from '../../common/components/nav/CommuterRailSection'; interface SideNavigationProps { close?: () => void; @@ -58,6 +59,7 @@ export const SideNavigation: React.FC = ({ close }) => {
+ ); diff --git a/modules/ridership/RidershipDetails.tsx b/modules/ridership/RidershipDetails.tsx index 3fbe3bd2f..2e9b2468d 100644 --- a/modules/ridership/RidershipDetails.tsx +++ b/modules/ridership/RidershipDetails.tsx @@ -14,10 +14,10 @@ import { RidershipGraphWrapper } from './RidershipGraphWrapper'; export function RidershipDetails() { const { line, - query: { startDate, endDate, busRoute }, + query: { startDate, endDate, busRoute, crRoute }, } = useDelimitatedRoute(); const config = SPEED_RANGE_PARAM_MAP.week; - const lineId = getRidershipLineId(line, busRoute); + const lineId = getRidershipLineId(line, busRoute, crRoute); const enabled = Boolean(startDate && endDate && lineId); const ridership = useRidershipData( @@ -28,7 +28,7 @@ export function RidershipDetails() { }, enabled ); - const ridershipDataReady = !ridership.isError && startDate && endDate && line; + const ridershipDataReady = !ridership.isError && startDate && endDate && line && lineId; return ( @@ -44,6 +44,7 @@ export function RidershipDetails() { endDate={endDate} line={line} busRoute={busRoute} + crRoute={crRoute} /> ) : (
diff --git a/modules/ridership/RidershipGraph.tsx b/modules/ridership/RidershipGraph.tsx index 4e39c317a..129cf0415 100644 --- a/modules/ridership/RidershipGraph.tsx +++ b/modules/ridership/RidershipGraph.tsx @@ -37,16 +37,17 @@ export const RidershipGraph: React.FC = ({ const { line, linePath, - query: { busRoute }, + query: { busRoute, crRoute }, } = useDelimitatedRoute(); const { tooltipFormat, unit, callbacks } = config; const isMobile = !useBreakpoint('md'); const ref = useRef(); const chart = useMemo(() => { - const routeIndex = busRoute ? busRoute.replaceAll('/', '') : line; + const routeIndex = busRoute ? busRoute.replaceAll('/', '') : crRoute ?? line; const labels = data.map((point) => point.date); const lineColor = LINE_COLORS[line ?? 'default']; + return ( diff --git a/modules/ridership/RidershipGraphWrapper.tsx b/modules/ridership/RidershipGraphWrapper.tsx index 08c74b613..92ea4199d 100644 --- a/modules/ridership/RidershipGraphWrapper.tsx +++ b/modules/ridership/RidershipGraphWrapper.tsx @@ -5,7 +5,7 @@ import { WidgetCarousel } from '../../common/components/general/WidgetCarousel'; import { PercentageWidgetValue, RidersWidgetValue } from '../../common/types/basicWidgets'; import { WidgetForCarousel } from '../../common/components/widgets/internal/WidgetForCarousel'; import { CarouselGraphDiv } from '../../common/components/charts/CarouselGraphDiv'; -import type { BusRoute, Line } from '../../common/types/lines'; +import type { BusRoute, CommuterRailRoute, Line } from '../../common/types/lines'; import { NoDataNotice } from '../../common/components/notices/NoDataNotice'; import { getRidershipWidgetValues } from './utils/utils'; import { RidershipGraph } from './RidershipGraph'; @@ -14,6 +14,7 @@ interface RidershipGraphWrapperProps { data: RidershipCount[]; line?: Line; busRoute?: BusRoute | undefined; + crRoute?: CommuterRailRoute | undefined; config: ParamsType; startDate: string; endDate: string; @@ -23,12 +24,13 @@ export const RidershipGraphWrapper: React.FC = ({ data, line, busRoute, + crRoute, config, startDate, endDate, }) => { if (!data.some((datapoint) => datapoint.count !== null)) return ; - const { average, percentage, peak } = getRidershipWidgetValues(data, line, busRoute); + const { average, percentage, peak } = getRidershipWidgetValues(data, line, busRoute, crRoute); return ( diff --git a/modules/ridership/RidershipWidget.tsx b/modules/ridership/RidershipWidget.tsx index 1a5cce7ed..75f933712 100644 --- a/modules/ridership/RidershipWidget.tsx +++ b/modules/ridership/RidershipWidget.tsx @@ -15,7 +15,7 @@ export const RidershipWidget: React.FC = () => { const { startDate } = OVERVIEW_OPTIONS[query.view ?? 'year']; const endDate = TODAY_STRING; const config = getSpeedGraphConfig(dayjs(startDate), dayjs(endDate)); - const lineId = getRidershipLineId(line, query.busRoute); + const lineId = getRidershipLineId(line, query.busRoute, query.crRoute); const ridership = useRidershipData({ line_id: lineId, start_date: startDate, @@ -30,6 +30,7 @@ export const RidershipWidget: React.FC = () => { { - const routeIndex = busRoute ? busRoute.replaceAll('/', '') : line; + const routeIndex = crRoute ?? (busRoute ? busRoute.replaceAll('/', '') : line); const average = ridership.reduce((sum, current) => sum + current.count, 0) / ridership.length; const peak = ridership.reduce( (max, datapoint) => (datapoint.count > max.count ? datapoint : max), diff --git a/pages/[line]/index.tsx b/pages/[line]/index.tsx index 64662be5e..3d9fe451d 100644 --- a/pages/[line]/index.tsx +++ b/pages/[line]/index.tsx @@ -1,4 +1,4 @@ -import { ALL_LINE_PATHS, BUS_PATH } from '../../common/types/lines'; +import { ALL_LINE_PATHS, BUS_PATH, COMMUTER_RAIL_PATH } from '../../common/types/lines'; import { Overview } from '../../modules/dashboard/Overview'; export async function getStaticProps() { @@ -7,7 +7,7 @@ export async function getStaticProps() { export async function getStaticPaths() { return { - paths: [...ALL_LINE_PATHS, BUS_PATH], + paths: [...ALL_LINE_PATHS, BUS_PATH, COMMUTER_RAIL_PATH], fallback: false, }; } diff --git a/pages/[line]/ridership.tsx b/pages/[line]/ridership.tsx index 11009ff1f..ec86bb369 100644 --- a/pages/[line]/ridership.tsx +++ b/pages/[line]/ridership.tsx @@ -1,4 +1,4 @@ -import { ALL_LINE_PATHS, BUS_PATH } from '../../common/types/lines'; +import { ALL_LINE_PATHS, BUS_PATH, COMMUTER_RAIL_PATH } from '../../common/types/lines'; import { RidershipDetails } from '../../modules/ridership/RidershipDetails'; export async function getStaticProps() { @@ -7,7 +7,7 @@ export async function getStaticProps() { export async function getStaticPaths() { return { - paths: [...ALL_LINE_PATHS, BUS_PATH], + paths: [...ALL_LINE_PATHS, BUS_PATH, COMMUTER_RAIL_PATH], fallback: false, }; } From 0272985e8170f6467afd57113fae7cd41cd3965a Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Thu, 18 Jul 2024 21:58:50 -0400 Subject: [PATCH 37/53] Fixing props --- common/layouts/DashboardLayout.tsx | 7 +------ modules/dashboard/DesktopHeader.tsx | 7 +------ 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/common/layouts/DashboardLayout.tsx b/common/layouts/DashboardLayout.tsx index 98ab4194b..c2fb30d5d 100644 --- a/common/layouts/DashboardLayout.tsx +++ b/common/layouts/DashboardLayout.tsx @@ -30,12 +30,7 @@ export const DashboardLayout: React.FC = ({ children }) =>
{isMobile && showControlParams && ( - + )} ); diff --git a/modules/dashboard/DesktopHeader.tsx b/modules/dashboard/DesktopHeader.tsx index 0335f033c..649a59af2 100644 --- a/modules/dashboard/DesktopHeader.tsx +++ b/modules/dashboard/DesktopHeader.tsx @@ -42,12 +42,7 @@ export const DesktopHeader: React.FC = () => { {showControls && ( - + )} ); From 6af58db15ed5de6e06fb85a3cb7510fc3ac45d09 Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Thu, 18 Jul 2024 22:18:01 -0400 Subject: [PATCH 38/53] Adding commuter rail landing button --- modules/landing/LineButton.tsx | 10 ++++++---- modules/landing/LineSelectionLanding.tsx | 8 +++++++- modules/landing/charts/OverallRidershipChart.tsx | 1 + modules/slowzones/SlowZonesWidget.tsx | 3 ++- 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/modules/landing/LineButton.tsx b/modules/landing/LineButton.tsx index 24914fcfb..8985a1449 100644 --- a/modules/landing/LineButton.tsx +++ b/modules/landing/LineButton.tsx @@ -4,7 +4,7 @@ import classNames from 'classnames'; import type { Line } from '../../common/types/lines'; import { lineColorBackground, lineColorBorder } from '../../common/styles/general'; import { LINE_OBJECTS } from '../../common/constants/lines'; -import { BUS_DEFAULTS } from '../../common/state/defaults/dateDefaults'; +import { BUS_DEFAULTS, COMMUTER_RAIL_DEFAULTS } from '../../common/state/defaults/dateDefaults'; interface LineButtonProps { children: React.ReactNode; @@ -17,9 +17,11 @@ export const LineButton: React.FC = ({ children, line }) => { return ( diff --git a/modules/landing/LineSelectionLanding.tsx b/modules/landing/LineSelectionLanding.tsx index 99929ac97..1f39ecb53 100644 --- a/modules/landing/LineSelectionLanding.tsx +++ b/modules/landing/LineSelectionLanding.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { faBus, faTrainSubway, faTrainTram } from '@fortawesome/free-solid-svg-icons'; +import { faBus, faTrain, faTrainSubway, faTrainTram } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import classNames from 'classnames'; import { LineButton } from './LineButton'; @@ -40,6 +40,12 @@ export const LineSelectionLanding: React.FC = () => { className={classNames('h-16 w-16 lg:h-20 lg:w-20', 'text-white')} /> + + + ); diff --git a/modules/landing/charts/OverallRidershipChart.tsx b/modules/landing/charts/OverallRidershipChart.tsx index 97ddcff20..609e4ed76 100644 --- a/modules/landing/charts/OverallRidershipChart.tsx +++ b/modules/landing/charts/OverallRidershipChart.tsx @@ -12,6 +12,7 @@ interface OverallRidershipChartProps { export const OverallRidershipChart: React.FC = ({ ridershipData }) => { const labels = Object.values(ridershipData)[0].map((point) => point.date); const datasets = convertToRidershipDataset(ridershipData); + return ( diff --git a/modules/slowzones/SlowZonesWidget.tsx b/modules/slowzones/SlowZonesWidget.tsx index 8fc2da855..4184aac77 100644 --- a/modules/slowzones/SlowZonesWidget.tsx +++ b/modules/slowzones/SlowZonesWidget.tsx @@ -23,9 +23,10 @@ export const SlowZonesWidget: React.FC = () => { const totalSlowTimeReady = !delayTotals.isError && delayTotals.data && startDateUTC && endDateUTC && lineShort && line; - if (line === 'line-bus' || line === 'line-green') { + if (line === 'line-bus' || line === 'line-green' || line === 'line-commuter-rail') { return null; } + return ( <> From c23d10f78c11f3c8f01c3e61f141056a3add2295 Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Thu, 18 Jul 2024 22:43:32 -0400 Subject: [PATCH 39/53] Fixing commuter rail links --- common/components/nav/CommuterRailDropdown.tsx | 8 +++----- modules/landing/LineButton.tsx | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/common/components/nav/CommuterRailDropdown.tsx b/common/components/nav/CommuterRailDropdown.tsx index a1cdf9607..ff1e14003 100644 --- a/common/components/nav/CommuterRailDropdown.tsx +++ b/common/components/nav/CommuterRailDropdown.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { SidebarTabs } from '../../../modules/navigation/SidebarTabs'; -import { COMMUTER_RAIL_OVERVIEW } from '../../constants/pages'; +import { COMMUTER_RAIL_OVERVIEW, TRIP_PAGES } from '../../constants/pages'; import { CommuterRailRouteSelection } from './CommuterRailRouteSelection'; interface CommuterRailDropdownProps { @@ -18,10 +18,8 @@ export const CommuterRailDropdown: React.FC = ({ clos role={'navigation'} > - - {/* TODO: Once we have reliable travel data for CR */} - {/*
*/} - {/* */} +
+ ); diff --git a/modules/landing/LineButton.tsx b/modules/landing/LineButton.tsx index 8985a1449..4439b66ab 100644 --- a/modules/landing/LineButton.tsx +++ b/modules/landing/LineButton.tsx @@ -18,7 +18,7 @@ export const LineButton: React.FC = ({ children, line }) => { Date: Thu, 18 Jul 2024 22:59:44 -0400 Subject: [PATCH 40/53] Fix linting issues --- common/state/defaults/dateDefaults.ts | 1 - server/scripts/generate_line_files.py | 13 ------------- 2 files changed, 14 deletions(-) diff --git a/common/state/defaults/dateDefaults.ts b/common/state/defaults/dateDefaults.ts index 97abe3da7..fe5a3d03e 100644 --- a/common/state/defaults/dateDefaults.ts +++ b/common/state/defaults/dateDefaults.ts @@ -1,4 +1,3 @@ -import type { Tab } from '../../types/router'; import type { DateStoreSection } from '../../constants/pages'; import type { DateStoreConfiguration } from '../types/dateStoreTypes'; import { diff --git a/server/scripts/generate_line_files.py b/server/scripts/generate_line_files.py index a85e67c93..cb7209334 100644 --- a/server/scripts/generate_line_files.py +++ b/server/scripts/generate_line_files.py @@ -32,19 +32,6 @@ ] -def get_all_s3_objects(s3, **base_kwargs): - continuation_token = None - while True: - list_kwargs = dict(MaxKeys=1000, **base_kwargs) - if continuation_token: - list_kwargs["ContinuationToken"] = continuation_token - response = s3.list_objects_v2(**list_kwargs) - yield from response.get("Contents", []) - if not response.get("IsTruncated"): # At the end of the list? - break - continuation_token = response.get("NextContinuationToken") - - def get_line_stops(): s3 = boto3.client("s3", config=botocore.client.Config(max_pool_connections=15)) From 8b17144619ffc2e01d538755c182bc1246dc0642 Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Wed, 31 Jul 2024 21:52:04 -0400 Subject: [PATCH 41/53] Adding log retention policy --- server/.chalice/config.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/server/.chalice/config.json b/server/.chalice/config.json index c86619971..ee06ec21c 100644 --- a/server/.chalice/config.json +++ b/server/.chalice/config.json @@ -11,6 +11,7 @@ "api_gateway_stage": "production", "autogen_policy": false, "iam_policy_file": "policy.json", + "log_retention_in_days": 7, "environment_variables": { "DD_LAMBDA_HANDLER": "app.app", "DD_SERVICE": "t-performance-dash", @@ -33,6 +34,7 @@ "api_gateway_stage": "beta", "autogen_policy": false, "iam_policy_file": "policy.json", + "log_retention_in_days": 3, "environment_variables": { "DD_LAMBDA_HANDLER": "app.app", "DD_SERVICE": "t-performance-dash", From 3742ac3875715480a2c9d4b044bd43eaed0e82f0 Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Wed, 31 Jul 2024 22:04:29 -0400 Subject: [PATCH 42/53] Oops we'd need to delete the stack --- server/.chalice/config.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/server/.chalice/config.json b/server/.chalice/config.json index ee06ec21c..52caebdef 100644 --- a/server/.chalice/config.json +++ b/server/.chalice/config.json @@ -1,6 +1,6 @@ { "version": "2.0", - "app_name": "data-dashboard-v4", + "app_name": "data-dashboard", "api_gateway_endpoint_type": "REGIONAL", "minimum_compression_size": 1000, "lambda_timeout": 30, @@ -11,7 +11,6 @@ "api_gateway_stage": "production", "autogen_policy": false, "iam_policy_file": "policy.json", - "log_retention_in_days": 7, "environment_variables": { "DD_LAMBDA_HANDLER": "app.app", "DD_SERVICE": "t-performance-dash", From 385f905c0a414d03a8269fff5e4ad746fecc8b35 Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Wed, 31 Jul 2024 22:09:21 -0400 Subject: [PATCH 43/53] Okay nevermind --- server/.chalice/config.json | 1 - 1 file changed, 1 deletion(-) diff --git a/server/.chalice/config.json b/server/.chalice/config.json index 52caebdef..aa66375aa 100644 --- a/server/.chalice/config.json +++ b/server/.chalice/config.json @@ -33,7 +33,6 @@ "api_gateway_stage": "beta", "autogen_policy": false, "iam_policy_file": "policy.json", - "log_retention_in_days": 3, "environment_variables": { "DD_LAMBDA_HANDLER": "app.app", "DD_SERVICE": "t-performance-dash", From 0f015a44b8be6abbfc01cadd41b8ddbfa615f3e6 Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Sat, 18 Jan 2025 16:52:26 -0500 Subject: [PATCH 44/53] Update lines with current data --- .../constants/cr_constants/cr-fairmount.json | 22 ++- .../constants/cr_constants/cr-fitchburg.json | 62 ++++--- .../constants/cr_constants/cr-franklin.json | 41 ++--- .../constants/cr_constants/cr-greenbush.json | 8 +- .../constants/cr_constants/cr-haverhill.json | 90 +++++----- .../constants/cr_constants/cr-kingston.json | 11 +- common/constants/cr_constants/cr-lowell.json | 39 +++-- .../cr_constants/cr-middleborough.json | 13 +- common/constants/cr_constants/cr-needham.json | 22 ++- .../cr_constants/cr-newburyport.json | 162 +++++++++++++++--- .../constants/cr_constants/cr-providence.json | 80 ++++++--- .../constants/cr_constants/cr-worcester.json | 85 +++------ server/scripts/generate_line_files.py | 2 +- 13 files changed, 389 insertions(+), 248 deletions(-) diff --git a/common/constants/cr_constants/cr-fairmount.json b/common/constants/cr_constants/cr-fairmount.json index b5d1994e2..443022d75 100644 --- a/common/constants/cr_constants/cr-fairmount.json +++ b/common/constants/cr_constants/cr-fairmount.json @@ -23,7 +23,7 @@ "branches": null, "order": 2, "stops": { - "0": ["CR-Fairmount_0_DB-2205-01"], + "0": ["CR-Fairmount_0_DB-2205-01", "CR-Fairmount_0_DB-2205-02"], "1": ["CR-Fairmount_1_DB-2205-02"] } }, @@ -33,7 +33,7 @@ "branches": null, "order": 3, "stops": { - "0": ["CR-Fairmount_0_DB-2222-01"], + "0": ["CR-Fairmount_0_DB-2222-02", "CR-Fairmount_0_DB-2222-01"], "1": ["CR-Fairmount_1_DB-2222-02"] } }, @@ -43,7 +43,7 @@ "branches": null, "order": 4, "stops": { - "0": ["CR-Fairmount_0_DB-2230-01"], + "0": ["CR-Fairmount_0_DB-2230-01", "CR-Fairmount_0_DB-2230-02"], "1": ["CR-Fairmount_1_DB-2230-02"] } }, @@ -53,7 +53,7 @@ "branches": null, "order": 5, "stops": { - "0": ["CR-Fairmount_0_DB-2240-01"], + "0": ["CR-Fairmount_0_DB-2240-01", "CR-Fairmount_0_DB-2240-02"], "1": ["CR-Fairmount_1_DB-2240-02"] } }, @@ -73,7 +73,7 @@ "branches": null, "order": 7, "stops": { - "0": ["CR-Fairmount_0_DB-2258-01"], + "0": ["CR-Fairmount_0_DB-2258-01", "CR-Fairmount_0_DB-2258-02"], "1": ["CR-Fairmount_1_DB-2258-02"] } }, @@ -83,7 +83,7 @@ "branches": null, "order": 8, "stops": { - "0": ["CR-Fairmount_0_DB-2265-01"], + "0": ["CR-Fairmount_0_DB-2265-02", "CR-Fairmount_0_DB-2265-01"], "1": ["CR-Fairmount_1_DB-2265-02"] } }, @@ -94,11 +94,15 @@ "order": 9, "stops": { "0": [ - "CR-Fairmount_0_NEC-2287-09", + "CR-Fairmount_0_NEC-2287-07", + "CR-Fairmount_0_NEC-2287", "CR-Fairmount_0_NEC-2287-11", + "CR-Fairmount_0_NEC-2287-08", + "CR-Fairmount_0_NEC-2287-13", + "CR-Fairmount_0_NEC-2287-09", + "CR-Fairmount_0_NEC-2287-01", "CR-Fairmount_0_NEC-2287-10", - "CR-Fairmount_0_NEC-2287-07", - "CR-Fairmount_0_NEC-2287" + "CR-Fairmount_0_NEC-2287-12" ], "1": [] }, diff --git a/common/constants/cr_constants/cr-fitchburg.json b/common/constants/cr_constants/cr-fitchburg.json index efb4f59ab..0a727d727 100644 --- a/common/constants/cr_constants/cr-fitchburg.json +++ b/common/constants/cr_constants/cr-fitchburg.json @@ -12,7 +12,7 @@ "branches": null, "order": 1, "stops": { - "0": ["CR-Fitchburg_0_FR-3338-CS"], + "0": [], "1": ["CR-Fitchburg_1_FR-3338-CS"] }, "terminus": true @@ -63,7 +63,7 @@ "branches": null, "order": 6, "stops": { - "0": ["CR-Fitchburg_0_FR-0301-01"], + "0": ["CR-Fitchburg_0_FR-0301-02", "CR-Fitchburg_0_FR-0301-01"], "1": ["CR-Fitchburg_1_FR-0301-02"] } }, @@ -73,7 +73,7 @@ "branches": null, "order": 7, "stops": { - "0": ["CR-Fitchburg_0_FR-0253-01"], + "0": ["CR-Fitchburg_0_FR-0253-01", "CR-Fitchburg_0_FR-0253-02"], "1": ["CR-Fitchburg_1_FR-0253-02"] } }, @@ -83,7 +83,7 @@ "branches": null, "order": 8, "stops": { - "0": ["CR-Fitchburg_0_FR-0219-01"], + "0": ["CR-Fitchburg_0_FR-0219-02", "CR-Fitchburg_0_FR-0219-01"], "1": ["CR-Fitchburg_1_FR-0219-02"] } }, @@ -93,7 +93,7 @@ "branches": null, "order": 9, "stops": { - "0": ["CR-Fitchburg_0_FR-0201-01"], + "0": ["CR-Fitchburg_0_FR-0201-02", "CR-Fitchburg_0_FR-0201-01"], "1": ["CR-Fitchburg_1_FR-0201-02"] } }, @@ -103,17 +103,27 @@ "branches": null, "order": 10, "stops": { - "0": ["CR-Fitchburg_0_FR-0167-01"], + "0": ["CR-Fitchburg_0_FR-0167-01", "CR-Fitchburg_0_FR-0167-02"], "1": ["CR-Fitchburg_1_FR-0167-02"] } }, + { + "stop_name": "Silver Hill", + "station": "place-FR-0147", + "branches": null, + "order": 11, + "stops": { + "0": ["CR-Fitchburg_0_FR-0147-01"], + "1": ["CR-Fitchburg_1_FR-0147-02"] + } + }, { "stop_name": "Kendal Green", "station": "place-FR-0132", "branches": null, - "order": 11, + "order": 12, "stops": { - "0": ["CR-Fitchburg_0_FR-0132-01"], + "0": ["CR-Fitchburg_0_FR-0132-01", "CR-Fitchburg_0_FR-0132-02"], "1": ["CR-Fitchburg_1_FR-0132-02"] } }, @@ -121,9 +131,9 @@ "stop_name": "Brandeis/Roberts", "station": "place-FR-0115", "branches": null, - "order": 12, + "order": 13, "stops": { - "0": ["CR-Fitchburg_0_FR-0115-01"], + "0": ["CR-Fitchburg_0_FR-0115-02", "CR-Fitchburg_0_FR-0115-01"], "1": ["CR-Fitchburg_1_FR-0115-02"] } }, @@ -131,9 +141,9 @@ "stop_name": "Waltham", "station": "place-FR-0098", "branches": null, - "order": 13, + "order": 14, "stops": { - "0": ["CR-Fitchburg_0_FR-0098-01"], + "0": ["CR-Fitchburg_0_FR-0098-S", "CR-Fitchburg_0_FR-0098-01"], "1": ["CR-Fitchburg_1_FR-0098-S"] } }, @@ -141,9 +151,9 @@ "stop_name": "Waverley", "station": "place-FR-0074", "branches": null, - "order": 14, + "order": 15, "stops": { - "0": ["CR-Fitchburg_0_FR-0074-01"], + "0": ["CR-Fitchburg_0_FR-0074-01", "CR-Fitchburg_0_FR-0074-02"], "1": ["CR-Fitchburg_1_FR-0074-02"] } }, @@ -151,9 +161,9 @@ "stop_name": "Belmont", "station": "place-FR-0064", "branches": null, - "order": 15, + "order": 16, "stops": { - "0": ["CR-Fitchburg_0_FR-0064-01"], + "0": ["CR-Fitchburg_0_FR-0064-01", "CR-Fitchburg_0_FR-0064-02"], "1": ["CR-Fitchburg_1_FR-0064-02"] } }, @@ -161,9 +171,9 @@ "stop_name": "Porter", "station": "place-portr", "branches": null, - "order": 16, + "order": 17, "stops": { - "0": ["CR-Fitchburg_0_FR-0034-01"], + "0": ["CR-Fitchburg_0_FR-0034-02", "CR-Fitchburg_0_FR-0034-01"], "1": ["CR-Fitchburg_1_FR-0034-02"] } }, @@ -171,19 +181,19 @@ "stop_name": "North Station", "station": "place-north", "branches": null, - "order": 17, + "order": 18, "stops": { "0": [ + "CR-Fitchburg_0_BNT-0000-05", + "CR-Fitchburg_0_BNT-0000-06", + "CR-Fitchburg_0_BNT-0000-07", + "CR-Fitchburg_0_BNT-0000-04", "CR-Fitchburg_0_BNT-0000-01", + "CR-Fitchburg_0_BNT-0000-10", "CR-Fitchburg_0_BNT-0000", - "CR-Fitchburg_0_BNT-0000-04", + "CR-Fitchburg_0_BNT-0000-08", "CR-Fitchburg_0_BNT-0000-02", - "CR-Fitchburg_0_BNT-0000-10", - "CR-Fitchburg_0_BNT-0000-05", - "CR-Fitchburg_0_BNT-0000-07", - "CR-Fitchburg_0_BNT-0000-09", - "CR-Fitchburg_0_BNT-0000-06", - "CR-Fitchburg_0_BNT-0000-08" + "CR-Fitchburg_0_BNT-0000-09" ], "1": [] }, diff --git a/common/constants/cr_constants/cr-franklin.json b/common/constants/cr_constants/cr-franklin.json index 69801f3fe..a1bcc12a7 100644 --- a/common/constants/cr_constants/cr-franklin.json +++ b/common/constants/cr_constants/cr-franklin.json @@ -12,7 +12,7 @@ "branches": null, "order": 1, "stops": { - "0": ["CR-Franklin_0_FB-0303-S"], + "0": [], "1": ["CR-Franklin_1_FB-0303-S"] }, "terminus": true @@ -43,7 +43,7 @@ "branches": null, "order": 4, "stops": { - "0": ["CR-Franklin_0_FS-0049-S"], + "0": [], "1": ["CR-Franklin_1_FS-0049-S"] } }, @@ -124,7 +124,7 @@ "order": 12, "stops": { "0": ["CR-Franklin_0_FB-0095-05", "CR-Franklin_0_FB-0095-04"], - "1": ["CR-Franklin_1_FB-0095-05", "CR-Franklin_1_FB-0095-04"] + "1": ["CR-Franklin_1_NEC-2192-02", "CR-Franklin_1_FB-0095-04", "CR-Franklin_1_FB-0095-05"] } }, { @@ -145,9 +145,9 @@ "stops": { "0": ["CR-Franklin_0_NEC-2265-03", "CR-Franklin_0_NEC-2265-01"], "1": [ + "CR-Franklin_1_NEC-2265-02", "CR-Franklin_1_NEC-2265-03", - "CR-Franklin_1_NEC-2265-01", - "CR-Franklin_1_NEC-2265-02" + "CR-Franklin_1_NEC-2265-01" ] } }, @@ -157,11 +157,15 @@ "branches": null, "order": 15, "stops": { - "0": ["CR-Franklin_0_NEC-2276-01", "CR-Franklin_0_NEC-2276-03"], + "0": [ + "CR-Franklin_0_WML-0012-07", + "CR-Franklin_0_NEC-2276-03", + "CR-Franklin_0_NEC-2276-01" + ], "1": [ "CR-Franklin_1_NEC-2276-02", - "CR-Franklin_1_NEC-2276-01", - "CR-Franklin_1_NEC-2276-03" + "CR-Franklin_1_NEC-2276-03", + "CR-Franklin_1_NEC-2276-01" ] } }, @@ -172,28 +176,21 @@ "order": 16, "stops": { "0": [ - "CR-Franklin_0_NEC-2287-03", + "CR-Franklin_0_NEC-2287-10", "CR-Franklin_0_NEC-2287-04", "CR-Franklin_0_NEC-2287-08", - "CR-Franklin_0_NEC-2287-07", - "CR-Franklin_0_NEC-2287-10", "CR-Franklin_0_NEC-2287", "CR-Franklin_0_NEC-2287-11", - "CR-Franklin_0_NEC-2287-05" + "CR-Franklin_0_NEC-2287-03", + "CR-Franklin_0_NEC-2287-02", + "CR-Franklin_0_NEC-2287-07", + "CR-Franklin_0_NEC-2287-05", + "CR-Franklin_0_NEC-2287-06", + "CR-Franklin_0_NEC-2287-09" ], "1": [] }, "terminus": true - }, - { - "stop_name": "Hyde Park", - "station": "place-NEC-2203", - "branches": null, - "order": 17, - "stops": { - "0": ["CR-Franklin_0_NEC-2203-03"], - "1": [] - } } ] } diff --git a/common/constants/cr_constants/cr-greenbush.json b/common/constants/cr_constants/cr-greenbush.json index 07a61f1e6..c76d69691 100644 --- a/common/constants/cr_constants/cr-greenbush.json +++ b/common/constants/cr_constants/cr-greenbush.json @@ -104,10 +104,12 @@ "order": 10, "stops": { "0": [ - "CR-Greenbush_0_NEC-2287-12", - "CR-Greenbush_0_NEC-2287-13", + "CR-Greenbush_0_NEC-2287-10", "CR-Greenbush_0_NEC-2287", - "CR-Greenbush_0_NEC-2287-11" + "CR-Greenbush_0_NEC-2287-11", + "CR-Greenbush_0_NEC-2287-09", + "CR-Greenbush_0_NEC-2287-12", + "CR-Greenbush_0_NEC-2287-13" ], "1": [] }, diff --git a/common/constants/cr_constants/cr-haverhill.json b/common/constants/cr_constants/cr-haverhill.json index 357701a10..0bfcc6272 100644 --- a/common/constants/cr_constants/cr-haverhill.json +++ b/common/constants/cr_constants/cr-haverhill.json @@ -7,31 +7,21 @@ }, "stations": [ { - "stop_name": "Haverhill", - "station": "place-WR-0329", + "stop_name": "Bradford", + "station": "place-WR-0325", "branches": null, "order": 1, "stops": { - "0": [], - "1": ["CR-Haverhill_1_WR-0329-02"] + "0": ["CR-Haverhill_0_WR-0325-01", "CR-Haverhill_0_WR-0325-02"], + "1": ["CR-Haverhill_1_WR-0325-02", "CR-Haverhill_1_WR-0325-01"] }, "terminus": true }, - { - "stop_name": "Bradford", - "station": "place-WR-0325", - "branches": null, - "order": 2, - "stops": { - "0": ["CR-Haverhill_0_WR-0325-01"], - "1": ["CR-Haverhill_1_WR-0325-02"] - } - }, { "stop_name": "Lawrence", "station": "place-WR-0264", "branches": null, - "order": 3, + "order": 2, "stops": { "0": ["CR-Haverhill_0_WR-0264-02"], "1": ["CR-Haverhill_1_WR-0264-02"] @@ -41,7 +31,7 @@ "stop_name": "Andover", "station": "place-WR-0228", "branches": null, - "order": 4, + "order": 3, "stops": { "0": ["CR-Haverhill_0_WR-0228-02"], "1": ["CR-Haverhill_1_WR-0228-02"] @@ -51,12 +41,22 @@ "stop_name": "Ballardvale", "station": "place-WR-0205", "branches": null, - "order": 5, + "order": 4, "stops": { "0": ["CR-Haverhill_0_WR-0205-02"], "1": ["CR-Haverhill_1_WR-0205-02"] } }, + { + "stop_name": "North Wilmington", + "station": "place-WR-0163", + "branches": null, + "order": 5, + "stops": { + "0": ["CR-Haverhill_0_WR-0163-S"], + "1": ["CR-Haverhill_1_WR-0163-S"] + } + }, { "stop_name": "Reading", "station": "place-WR-0120", @@ -77,43 +77,33 @@ "1": ["CR-Haverhill_1_NHRML-0127-02"] } }, - { - "stop_name": "North Wilmington", - "station": "place-WR-0163", - "branches": null, - "order": 8, - "stops": { - "0": ["CR-Haverhill_0_WR-0163-S"], - "1": ["CR-Haverhill_1_WR-0163-S"] - } - }, { "stop_name": "Wakefield", "station": "place-WR-0099", "branches": null, - "order": 9, + "order": 8, "stops": { - "0": ["CR-Haverhill_0_WR-0099-01"], - "1": ["CR-Haverhill_1_WR-0099-02"] + "0": ["CR-Haverhill_0_WR-0099-01", "CR-Haverhill_0_WR-0099-02"], + "1": ["CR-Haverhill_1_WR-0099-02", "CR-Haverhill_1_WR-0099-01"] } }, { "stop_name": "Greenwood", "station": "place-WR-0085", "branches": null, - "order": 10, + "order": 9, "stops": { - "0": ["CR-Haverhill_0_WR-0085-01"], - "1": ["CR-Haverhill_1_WR-0085-02"] + "0": ["CR-Haverhill_0_WR-0085-01", "CR-Haverhill_0_WR-0085-02"], + "1": ["CR-Haverhill_1_WR-0085-02", "CR-Haverhill_1_WR-0085-01"] } }, { "stop_name": "Melrose Highlands", "station": "place-WR-0075", "branches": null, - "order": 11, + "order": 10, "stops": { - "0": ["CR-Haverhill_0_WR-0075-01"], + "0": ["CR-Haverhill_0_WR-0075-02", "CR-Haverhill_0_WR-0075-01"], "1": ["CR-Haverhill_1_WR-0075-02"] } }, @@ -121,9 +111,9 @@ "stop_name": "Melrose/Cedar Park", "station": "place-WR-0067", "branches": null, - "order": 12, + "order": 11, "stops": { - "0": ["CR-Haverhill_0_WR-0067-01"], + "0": ["CR-Haverhill_0_WR-0067-01", "CR-Haverhill_0_WR-0067-02"], "1": ["CR-Haverhill_1_WR-0067-02"] } }, @@ -131,9 +121,9 @@ "stop_name": "Wyoming Hill", "station": "place-WR-0062", "branches": null, - "order": 13, + "order": 12, "stops": { - "0": ["CR-Haverhill_0_WR-0062-01"], + "0": ["CR-Haverhill_0_WR-0062-01", "CR-Haverhill_0_WR-0062-02"], "1": ["CR-Haverhill_1_WR-0062-02"] } }, @@ -141,7 +131,7 @@ "stop_name": "Oak Grove", "station": "place-ogmnl", "branches": null, - "order": 14, + "order": 13, "stops": { "0": ["CR-Haverhill_0_WR-0053-S"], "1": ["CR-Haverhill_1_WR-0053-S"] @@ -151,7 +141,7 @@ "stop_name": "Malden Center", "station": "place-mlmnl", "branches": null, - "order": 15, + "order": 14, "stops": { "0": ["CR-Haverhill_0_WR-0045-S"], "1": ["CR-Haverhill_1_WR-0045-S"] @@ -161,20 +151,20 @@ "stop_name": "North Station", "station": "place-north", "branches": null, - "order": 16, + "order": 15, "stops": { "0": [ - "CR-Haverhill_0_BNT-0000-09", - "CR-Haverhill_0_BNT-0000-03", - "CR-Haverhill_0_BNT-0000", - "CR-Haverhill_0_BNT-0000-02", - "CR-Haverhill_0_BNT-0000-07", "CR-Haverhill_0_BNT-0000-10", - "CR-Haverhill_0_BNT-0000-01", + "CR-Haverhill_0_BNT-0000-05", "CR-Haverhill_0_BNT-0000-04", + "CR-Haverhill_0_BNT-0000-07", + "CR-Haverhill_0_BNT-0000", + "CR-Haverhill_0_BNT-0000-03", + "CR-Haverhill_0_BNT-0000-09", + "CR-Haverhill_0_BNT-0000-02", "CR-Haverhill_0_BNT-0000-06", - "CR-Haverhill_0_BNT-0000-08", - "CR-Haverhill_0_BNT-0000-05" + "CR-Haverhill_0_BNT-0000-01", + "CR-Haverhill_0_BNT-0000-08" ], "1": [] }, diff --git a/common/constants/cr_constants/cr-kingston.json b/common/constants/cr_constants/cr-kingston.json index 762555152..e4e071d51 100644 --- a/common/constants/cr_constants/cr-kingston.json +++ b/common/constants/cr_constants/cr-kingston.json @@ -24,7 +24,7 @@ "order": 2, "stops": { "0": ["CR-Kingston_0_PB-0281-S"], - "1": ["CR-Kingston_1_PB-0281-S"] + "1": ["CR-Kingston_1_PB-0281-CS", "CR-Kingston_1_PB-0281-S"] } }, { @@ -104,11 +104,14 @@ "order": 10, "stops": { "0": [ - "CR-Kingston_0_NEC-2287-09", + "CR-Kingston_0_NEC-2287-13", "CR-Kingston_0_NEC-2287-12", - "CR-Kingston_0_NEC-2287", + "CR-Kingston_0_NEC-2287-05", + "CR-Kingston_0_NEC-2287-09", "CR-Kingston_0_NEC-2287-11", - "CR-Kingston_0_NEC-2287-13" + "CR-Kingston_0_NEC-2287-07", + "CR-Kingston_0_NEC-2287-10", + "CR-Kingston_0_NEC-2287" ], "1": [] }, diff --git a/common/constants/cr_constants/cr-lowell.json b/common/constants/cr_constants/cr-lowell.json index 356d42e0c..165422e7a 100644 --- a/common/constants/cr_constants/cr-lowell.json +++ b/common/constants/cr_constants/cr-lowell.json @@ -23,7 +23,7 @@ "branches": null, "order": 2, "stops": { - "0": ["CR-Lowell_0_NHRML-0218-01"], + "0": ["CR-Lowell_0_NHRML-0218-02", "CR-Lowell_0_NHRML-0218-01"], "1": ["CR-Lowell_1_NHRML-0218-02"] } }, @@ -33,7 +33,7 @@ "branches": null, "order": 3, "stops": { - "0": ["CR-Lowell_0_NHRML-0152-01"], + "0": ["CR-Lowell_0_NHRML-0152-02", "CR-Lowell_0_NHRML-0152-01"], "1": ["CR-Lowell_1_NHRML-0152-02"] } }, @@ -43,17 +43,27 @@ "branches": null, "order": 4, "stops": { - "0": ["CR-Lowell_0_NHRML-0127-01"], + "0": ["CR-Lowell_0_NHRML-0127-02", "CR-Lowell_0_NHRML-0127-01"], "1": ["CR-Lowell_1_NHRML-0127-02"] } }, + { + "stop_name": "Winchester Center", + "station": "place-NHRML-0078", + "branches": null, + "order": 5, + "stops": { + "0": ["CR-Lowell_0_NHRML-0078-02", "CR-Lowell_0_NHRML-0078-01"], + "1": ["CR-Lowell_1_NHRML-0078-02"] + } + }, { "stop_name": "Wedgemere", "station": "place-NHRML-0073", "branches": null, - "order": 5, + "order": 6, "stops": { - "0": ["CR-Lowell_0_NHRML-0073-01"], + "0": ["CR-Lowell_0_NHRML-0073-02", "CR-Lowell_0_NHRML-0073-01"], "1": ["CR-Lowell_1_NHRML-0073-02"] } }, @@ -61,9 +71,9 @@ "stop_name": "West Medford", "station": "place-NHRML-0055", "branches": null, - "order": 6, + "order": 7, "stops": { - "0": ["CR-Lowell_0_NHRML-0055-01"], + "0": ["CR-Lowell_0_NHRML-0055-01", "CR-Lowell_0_NHRML-0055-02"], "1": ["CR-Lowell_1_NHRML-0055-02"] } }, @@ -71,19 +81,20 @@ "stop_name": "North Station", "station": "place-north", "branches": null, - "order": 7, + "order": 8, "stops": { "0": [ + "CR-Lowell_0_BNT-0000-05", "CR-Lowell_0_BNT-0000-08", - "CR-Lowell_0_BNT-0000-06", "CR-Lowell_0_BNT-0000-04", - "CR-Lowell_0_BNT-0000-07", - "CR-Lowell_0_BNT-0000-02", - "CR-Lowell_0_BNT-0000-10", "CR-Lowell_0_BNT-0000", "CR-Lowell_0_BNT-0000-03", - "CR-Lowell_0_BNT-0000-05", - "CR-Lowell_0_BNT-0000-09" + "CR-Lowell_0_BNT-0000-07", + "CR-Lowell_0_BNT-0000-10", + "CR-Lowell_0_BNT-0000-09", + "CR-Lowell_0_BNT-0000-06", + "CR-Lowell_0_BNT-0000-01", + "CR-Lowell_0_BNT-0000-02" ], "1": [] }, diff --git a/common/constants/cr_constants/cr-middleborough.json b/common/constants/cr_constants/cr-middleborough.json index b0a815c95..736034ff7 100644 --- a/common/constants/cr_constants/cr-middleborough.json +++ b/common/constants/cr_constants/cr-middleborough.json @@ -44,7 +44,7 @@ "order": 4, "stops": { "0": ["CR-Middleborough_0_MM-0200-S"], - "1": ["CR-Middleborough_1_MM-0200-CS"] + "1": ["CR-Middleborough_1_MM-0200-S", "CR-Middleborough_1_MM-0200-CS"] } }, { @@ -54,7 +54,7 @@ "order": 5, "stops": { "0": ["CR-Middleborough_0_MM-0186-S"], - "1": ["CR-Middleborough_1_MM-0186-CS"] + "1": ["CR-Middleborough_1_MM-0186-CS", "CR-Middleborough_1_MM-0186-S"] } }, { @@ -104,10 +104,13 @@ "order": 10, "stops": { "0": [ - "CR-Middleborough_0_NEC-2287", - "CR-Middleborough_0_NEC-2287-11", "CR-Middleborough_0_NEC-2287-13", - "CR-Middleborough_0_NEC-2287-12" + "CR-Middleborough_0_NEC-2287-12", + "CR-Middleborough_0_NEC-2287-11", + "CR-Middleborough_0_NEC-2287-10", + "CR-Middleborough_0_NEC-2287-08", + "CR-Middleborough_0_NEC-2287", + "CR-Middleborough_0_NEC-2287-09" ], "1": [] }, diff --git a/common/constants/cr_constants/cr-needham.json b/common/constants/cr_constants/cr-needham.json index 7c5d54f3b..8e93310bc 100644 --- a/common/constants/cr_constants/cr-needham.json +++ b/common/constants/cr_constants/cr-needham.json @@ -93,7 +93,7 @@ "branches": null, "order": 9, "stops": { - "0": ["CR-Needham_0_NEC-2237-05", "CR-Needham_0_NEC-2237-03"], + "0": ["CR-Needham_0_NEC-2237-03", "CR-Needham_0_NEC-2237-05"], "1": ["CR-Needham_1_NEC-2237-05"] } }, @@ -103,8 +103,8 @@ "branches": null, "order": 10, "stops": { - "0": ["CR-Needham_0_NEC-2265-01", "CR-Needham_0_NEC-2265-03"], - "1": ["CR-Needham_1_NEC-2265-03", "CR-Needham_1_NEC-2265-02"] + "0": ["CR-Needham_0_NEC-2265-03", "CR-Needham_0_NEC-2265-01"], + "1": ["CR-Needham_1_NEC-2265-02", "CR-Needham_1_NEC-2265-03"] } }, { @@ -124,16 +124,22 @@ "order": 12, "stops": { "0": [ + "CR-Needham_0_NEC-2287-10", + "CR-Needham_0_NEC-2287-05", "CR-Needham_0_NEC-2287-06", - "CR-Needham_0_NEC-2287", - "CR-Needham_0_NEC-2287-02", + "CR-Needham_0_NEC-2287-07", "CR-Needham_0_NEC-2287-08", + "CR-Needham_0_NEC-2287", "CR-Needham_0_NEC-2287-01", - "CR-Needham_0_NEC-2287-03", - "CR-Needham_0_NEC-2287-04" + "CR-Needham_0_NEC-2287-04", + "CR-Needham_0_NEC-2287-02", + "CR-Needham_0_NEC-2287-12", + "CR-Needham_0_NEC-2287-13", + "CR-Needham_0_NEC-2287-03" ], "1": [] - } + }, + "terminus": true } ] } diff --git a/common/constants/cr_constants/cr-newburyport.json b/common/constants/cr_constants/cr-newburyport.json index fd8f260e0..2b6210d02 100644 --- a/common/constants/cr_constants/cr-newburyport.json +++ b/common/constants/cr_constants/cr-newburyport.json @@ -12,7 +12,7 @@ "branches": null, "order": 1, "stops": { - "0": ["CR-Newburyport_0_GB-0353-S"], + "0": [], "1": ["CR-Newburyport_1_GB-0353-S"] }, "terminus": true @@ -33,7 +33,7 @@ "branches": null, "order": 3, "stops": { - "0": ["CR-Newburyport_0_GB-0296-01"], + "0": ["CR-Newburyport_0_GB-0296-01", "CR-Newburyport_0_GB-0296-02"], "1": ["CR-Newburyport_1_GB-0296-02"] } }, @@ -43,7 +43,7 @@ "branches": null, "order": 4, "stops": { - "0": ["CR-Newburyport_0_GB-0254-01"], + "0": ["CR-Newburyport_0_GB-0254-01", "CR-Newburyport_0_GB-0254-02"], "1": ["CR-Newburyport_1_GB-0254-02"] } }, @@ -53,7 +53,7 @@ "branches": null, "order": 5, "stops": { - "0": ["CR-Newburyport_0_GB-0229-01"], + "0": ["CR-Newburyport_0_GB-0229-01", "CR-Newburyport_0_GB-0229-02"], "1": ["CR-Newburyport_1_GB-0229-02"] } }, @@ -63,7 +63,7 @@ "branches": null, "order": 6, "stops": { - "0": ["CR-Newburyport_0_GB-0198-01"], + "0": ["CR-Newburyport_0_GB-0198-02", "CR-Newburyport_0_GB-0198-01"], "1": ["CR-Newburyport_1_GB-0198-02"] } }, @@ -113,7 +113,7 @@ "branches": null, "order": 11, "stops": { - "0": ["CR-Newburyport_0_ER-0208-01"], + "0": ["CR-Newburyport_0_ER-0208-02", "CR-Newburyport_0_ER-0208-01"], "1": ["CR-Newburyport_1_ER-0208-02"] } }, @@ -123,7 +123,7 @@ "branches": null, "order": 12, "stops": { - "0": ["CR-Newburyport_0_ER-0183-01"], + "0": ["CR-Newburyport_0_ER-0183-02", "CR-Newburyport_0_ER-0183-01"], "1": ["CR-Newburyport_1_ER-0183-02"] } }, @@ -143,7 +143,7 @@ "branches": null, "order": 14, "stops": { - "0": ["CR-Newburyport_0_ER-0128-01"], + "0": ["CR-Newburyport_0_ER-0128-01", "CR-Newburyport_0_ER-0128-02"], "1": ["CR-Newburyport_1_ER-0128-02"] } }, @@ -167,13 +167,129 @@ ] } }, + { + "stop_name": "Wonderland", + "station": "place-wondl", + "branches": null, + "order": 16, + "stops": { + "0": [ + "CR-Newburyport_0_15796", + "CR-Newburyport_0_15797", + "CR-Newburyport_0_15798", + "CR-Newburyport_0_15799", + "CR-Newburyport_0_15800", + "CR-Newburyport_0_70059", + "CR-Newburyport_0_70060", + "CR-Newburyport_0_door-wondl-nshore", + "CR-Newburyport_0_door-wondl-ocean", + "CR-Newburyport_0_door-wondl-oceann", + "CR-Newburyport_0_door-wondl-oceannele", + "CR-Newburyport_0_door-wondl-revere", + "CR-Newburyport_0_node-701-bridge", + "CR-Newburyport_0_node-701-lobby", + "CR-Newburyport_0_node-701-plaza", + "CR-Newburyport_0_node-702-bridge", + "CR-Newburyport_0_node-702-lobby", + "CR-Newburyport_0_node-702-plaza", + "CR-Newburyport_0_node-703-bridge", + "CR-Newburyport_0_node-703-lobby", + "CR-Newburyport_0_node-703-plaza", + "CR-Newburyport_0_node-708-lobby", + "CR-Newburyport_0_node-709-plaza", + "CR-Newburyport_0_node-709-street", + "CR-Newburyport_0_node-710-platform", + "CR-Newburyport_0_node-710-plaza", + "CR-Newburyport_0_node-711-plaza", + "CR-Newburyport_0_node-wondl-busramp-busway", + "CR-Newburyport_0_node-wondl-busstairs-busway", + "CR-Newburyport_0_node-wondl-buswaydoor", + "CR-Newburyport_0_node-wondl-eplazacenter", + "CR-Newburyport_0_node-wondl-farepaid", + "CR-Newburyport_0_node-wondl-fareunpaid", + "CR-Newburyport_0_node-wondl-footbridgeib", + "CR-Newburyport_0_node-wondl-footbridgeob", + "CR-Newburyport_0_node-wondl-ibfootbridgestairs-lobby", + "CR-Newburyport_0_node-wondl-ibplazaentrance", + "CR-Newburyport_0_node-wondl-ibplazastairs-bridge", + "CR-Newburyport_0_node-wondl-ibplazastairs-lobby", + "CR-Newburyport_0_node-wondl-ibplazastairs-plaza", + "CR-Newburyport_0_node-wondl-lobbycenter", + "CR-Newburyport_0_node-wondl-nshoreplazastairs-plaza", + "CR-Newburyport_0_node-wondl-nshoreplazastairs-street", + "CR-Newburyport_0_node-wondl-nshorestairs-bottom", + "CR-Newburyport_0_node-wondl-obplatstairs-platform", + "CR-Newburyport_0_node-wondl-obplazaentrance", + "CR-Newburyport_0_node-wondl-obplazastairs-street", + "CR-Newburyport_0_node-wondl-oceanaveingress", + "CR-Newburyport_0_node-wondl-oceanramp-bottom", + "CR-Newburyport_0_node-wondl-oceanstairs-plaza", + "CR-Newburyport_0_node-wondl-plazacenter", + "CR-Newburyport_0_node-wondl-revereramp-top" + ], + "1": [ + "CR-Newburyport_1_15796", + "CR-Newburyport_1_15797", + "CR-Newburyport_1_15798", + "CR-Newburyport_1_15799", + "CR-Newburyport_1_15800", + "CR-Newburyport_1_70059", + "CR-Newburyport_1_70060", + "CR-Newburyport_1_door-wondl-nshore", + "CR-Newburyport_1_door-wondl-ocean", + "CR-Newburyport_1_door-wondl-oceann", + "CR-Newburyport_1_door-wondl-oceannele", + "CR-Newburyport_1_door-wondl-revere", + "CR-Newburyport_1_node-701-bridge", + "CR-Newburyport_1_node-701-lobby", + "CR-Newburyport_1_node-701-plaza", + "CR-Newburyport_1_node-702-bridge", + "CR-Newburyport_1_node-702-lobby", + "CR-Newburyport_1_node-702-plaza", + "CR-Newburyport_1_node-703-bridge", + "CR-Newburyport_1_node-703-lobby", + "CR-Newburyport_1_node-703-plaza", + "CR-Newburyport_1_node-708-lobby", + "CR-Newburyport_1_node-709-plaza", + "CR-Newburyport_1_node-709-street", + "CR-Newburyport_1_node-710-platform", + "CR-Newburyport_1_node-710-plaza", + "CR-Newburyport_1_node-711-plaza", + "CR-Newburyport_1_node-wondl-busramp-busway", + "CR-Newburyport_1_node-wondl-busstairs-busway", + "CR-Newburyport_1_node-wondl-buswaydoor", + "CR-Newburyport_1_node-wondl-eplazacenter", + "CR-Newburyport_1_node-wondl-farepaid", + "CR-Newburyport_1_node-wondl-fareunpaid", + "CR-Newburyport_1_node-wondl-footbridgeib", + "CR-Newburyport_1_node-wondl-footbridgeob", + "CR-Newburyport_1_node-wondl-ibfootbridgestairs-lobby", + "CR-Newburyport_1_node-wondl-ibplazaentrance", + "CR-Newburyport_1_node-wondl-ibplazastairs-bridge", + "CR-Newburyport_1_node-wondl-ibplazastairs-lobby", + "CR-Newburyport_1_node-wondl-ibplazastairs-plaza", + "CR-Newburyport_1_node-wondl-lobbycenter", + "CR-Newburyport_1_node-wondl-nshoreplazastairs-plaza", + "CR-Newburyport_1_node-wondl-nshoreplazastairs-street", + "CR-Newburyport_1_node-wondl-nshorestairs-bottom", + "CR-Newburyport_1_node-wondl-obplatstairs-platform", + "CR-Newburyport_1_node-wondl-obplazaentrance", + "CR-Newburyport_1_node-wondl-obplazastairs-street", + "CR-Newburyport_1_node-wondl-oceanaveingress", + "CR-Newburyport_1_node-wondl-oceanramp-bottom", + "CR-Newburyport_1_node-wondl-oceanstairs-plaza", + "CR-Newburyport_1_node-wondl-plazacenter", + "CR-Newburyport_1_node-wondl-revereramp-top" + ] + } + }, { "stop_name": "Lynn Interim", "station": "place-ER-0117", "branches": null, - "order": 16, + "order": 17, "stops": { - "0": ["CR-Newburyport_0_ER-0117-01"], + "0": ["CR-Newburyport_0_ER-0117-02", "CR-Newburyport_0_ER-0117-01"], "1": ["CR-Newburyport_1_ER-0117-02"] } }, @@ -181,9 +297,9 @@ "stop_name": "River Works", "station": "place-ER-0099", "branches": null, - "order": 17, + "order": 18, "stops": { - "0": ["CR-Newburyport_0_ER-0099-01"], + "0": ["CR-Newburyport_0_ER-0099-02", "CR-Newburyport_0_ER-0099-01"], "1": ["CR-Newburyport_1_ER-0099-02"] } }, @@ -191,9 +307,9 @@ "stop_name": "Chelsea", "station": "place-chels", "branches": null, - "order": 18, + "order": 19, "stops": { - "0": ["CR-Newburyport_0_ER-0042-01"], + "0": ["CR-Newburyport_0_ER-0042-01", "CR-Newburyport_0_ER-0042-02"], "1": ["CR-Newburyport_1_ER-0042-02"] } }, @@ -201,20 +317,20 @@ "stop_name": "North Station", "station": "place-north", "branches": null, - "order": 19, + "order": 20, "stops": { "0": [ - "CR-Newburyport_0_BNT-0000-03", - "CR-Newburyport_0_BNT-0000-02", - "CR-Newburyport_0_BNT-0000-01", "CR-Newburyport_0_BNT-0000-04", - "CR-Newburyport_0_BNT-0000-07", - "CR-Newburyport_0_BNT-0000-10", - "CR-Newburyport_0_BNT-0000-05", "CR-Newburyport_0_BNT-0000-06", - "CR-Newburyport_0_BNT-0000", + "CR-Newburyport_0_BNT-0000-02", + "CR-Newburyport_0_BNT-0000-07", "CR-Newburyport_0_BNT-0000-09", - "CR-Newburyport_0_BNT-0000-08" + "CR-Newburyport_0_BNT-0000-01", + "CR-Newburyport_0_BNT-0000-08", + "CR-Newburyport_0_BNT-0000", + "CR-Newburyport_0_BNT-0000-10", + "CR-Newburyport_0_BNT-0000-03", + "CR-Newburyport_0_BNT-0000-05" ], "1": [] }, diff --git a/common/constants/cr_constants/cr-providence.json b/common/constants/cr_constants/cr-providence.json index 2540dffea..5ff5eadb3 100644 --- a/common/constants/cr_constants/cr-providence.json +++ b/common/constants/cr_constants/cr-providence.json @@ -43,17 +43,27 @@ "branches": null, "order": 4, "stops": { - "0": ["CR-Providence_0_NEC-1891-01"], - "1": ["CR-Providence_1_NEC-1891-02"] + "0": ["CR-Providence_0_NEC-1891-02", "CR-Providence_0_NEC-1891-01"], + "1": ["CR-Providence_1_NEC-1891-02", "CR-Providence_1_NEC-1891-01"] + } + }, + { + "stop_name": "South Attleboro", + "station": "place-NEC-1919", + "branches": null, + "order": 5, + "stops": { + "0": ["CR-Providence_0_NEC-1919-01"], + "1": ["CR-Providence_1_NEC-1919-01"] } }, { "stop_name": "Attleboro", "station": "place-NEC-1969", "branches": null, - "order": 5, + "order": 6, "stops": { - "0": ["CR-Providence_0_NEC-1969-03"], + "0": ["CR-Providence_0_NEC-1969-03", "CR-Providence_0_NEC-1969-04"], "1": ["CR-Providence_1_NEC-1969-04"] } }, @@ -61,7 +71,7 @@ "stop_name": "Mansfield", "station": "place-NEC-2040", "branches": null, - "order": 6, + "order": 7, "stops": { "0": ["CR-Providence_0_NEC-2040-01"], "1": ["CR-Providence_1_NEC-2040-02"] @@ -71,9 +81,9 @@ "stop_name": "Sharon", "station": "place-NEC-2108", "branches": null, - "order": 7, + "order": 8, "stops": { - "0": ["CR-Providence_0_NEC-2108-01"], + "0": ["CR-Providence_0_NEC-2108-01", "CR-Providence_0_NEC-2108-02"], "1": ["CR-Providence_1_NEC-2108-02"] } }, @@ -81,7 +91,7 @@ "stop_name": "Stoughton", "station": "place-SB-0189", "branches": null, - "order": 8, + "order": 9, "stops": { "0": [], "1": ["CR-Providence_1_SB-0189-S"] @@ -91,7 +101,7 @@ "stop_name": "Canton Center", "station": "place-SB-0156", "branches": null, - "order": 9, + "order": 10, "stops": { "0": ["CR-Providence_0_SB-0156-S"], "1": ["CR-Providence_1_SB-0156-S"] @@ -101,9 +111,13 @@ "stop_name": "Canton Junction", "station": "place-NEC-2139", "branches": null, - "order": 10, + "order": 11, "stops": { - "0": ["CR-Providence_0_SB-0150-04", "CR-Providence_0_NEC-2139-01"], + "0": [ + "CR-Providence_0_NEC-2139-02", + "CR-Providence_0_NEC-2139-01", + "CR-Providence_0_SB-0150-04" + ], "1": ["CR-Providence_1_SB-0150-06", "CR-Providence_1_NEC-2139-02"] } }, @@ -111,17 +125,27 @@ "stop_name": "Route 128", "station": "place-NEC-2173", "branches": null, - "order": 11, + "order": 12, "stops": { - "0": ["CR-Providence_0_NEC-2173-01"], - "1": ["CR-Providence_1_NEC-2173-02"] + "0": ["CR-Providence_0_NEC-2173-01", "CR-Providence_0_NEC-2173-02"], + "1": ["CR-Providence_1_NEC-2173-01", "CR-Providence_1_NEC-2173-02"] + } + }, + { + "stop_name": "Readville", + "station": "place-DB-0095", + "branches": null, + "order": 13, + "stops": { + "0": ["CR-Providence_0_NEC-2192-03"], + "1": ["CR-Providence_1_NEC-2192-03", "CR-Providence_1_NEC-2192-02"] } }, { "stop_name": "Hyde Park", "station": "place-NEC-2203", "branches": null, - "order": 12, + "order": 14, "stops": { "0": ["CR-Providence_0_NEC-2203-03"], "1": ["CR-Providence_1_NEC-2203-02"] @@ -131,9 +155,9 @@ "stop_name": "Ruggles", "station": "place-rugg", "branches": null, - "order": 13, + "order": 15, "stops": { - "0": ["CR-Providence_0_NEC-2265-03", "CR-Providence_0_NEC-2265-01"], + "0": ["CR-Providence_0_NEC-2265-01", "CR-Providence_0_NEC-2265-03"], "1": ["CR-Providence_1_NEC-2265-02", "CR-Providence_1_NEC-2265-03"] } }, @@ -141,27 +165,31 @@ "stop_name": "Back Bay", "station": "place-bbsta", "branches": null, - "order": 14, + "order": 16, "stops": { - "0": ["CR-Providence_0_NEC-2276-03", "CR-Providence_0_NEC-2276-01"], - "1": ["CR-Providence_1_NEC-2276-02", "CR-Providence_1_NEC-2276-03"] + "0": ["CR-Providence_0_NEC-2276-01", "CR-Providence_0_NEC-2276-03"], + "1": ["CR-Providence_1_NEC-2276-03", "CR-Providence_1_NEC-2276-02"] } }, { "stop_name": "South Station", "station": "place-sstat", "branches": null, - "order": 15, + "order": 17, "stops": { "0": [ - "CR-Providence_0_NEC-2287-05", - "CR-Providence_0_NEC-2287-09", - "CR-Providence_0_NEC-2287-07", + "CR-Providence_0_NEC-2287-03", "CR-Providence_0_NEC-2287-08", + "CR-Providence_0_NEC-2287-07", + "CR-Providence_0_NEC-2287-06", "CR-Providence_0_NEC-2287-04", + "CR-Providence_0_NEC-2287-05", + "CR-Providence_0_NEC-2287-11", + "CR-Providence_0_NEC-2287-09", + "CR-Providence_0_NEC-2287-12", + "CR-Providence_0_NEC-2287-02", "CR-Providence_0_NEC-2287", - "CR-Providence_0_NEC-2287-06", - "CR-Providence_0_NEC-2287-03" + "CR-Providence_0_NEC-2287-10" ], "1": [] }, diff --git a/common/constants/cr_constants/cr-worcester.json b/common/constants/cr_constants/cr-worcester.json index 7e9ff0759..7b69d5d27 100644 --- a/common/constants/cr_constants/cr-worcester.json +++ b/common/constants/cr_constants/cr-worcester.json @@ -12,7 +12,7 @@ "branches": null, "order": 1, "stops": { - "0": ["CR-Worcester_0_WML-0442-CS"], + "0": [], "1": ["CR-Worcester_1_WML-0442-CS"] }, "terminus": true @@ -23,7 +23,7 @@ "branches": null, "order": 2, "stops": { - "0": ["CR-Worcester_0_WML-0364-01"], + "0": ["CR-Worcester_0_WML-0364-01", "CR-Worcester_0_WML-0364-02"], "1": ["CR-Worcester_1_WML-0364-02"] } }, @@ -33,7 +33,7 @@ "branches": null, "order": 3, "stops": { - "0": ["CR-Worcester_0_WML-0340-01"], + "0": ["CR-Worcester_0_WML-0340-01", "CR-Worcester_0_WML-0340-02"], "1": ["CR-Worcester_1_WML-0340-02"] } }, @@ -43,7 +43,7 @@ "branches": null, "order": 4, "stops": { - "0": ["CR-Worcester_0_WML-0274-01"], + "0": ["CR-Worcester_0_WML-0274-02", "CR-Worcester_0_WML-0274-01"], "1": ["CR-Worcester_1_WML-0274-02"] } }, @@ -53,7 +53,7 @@ "branches": null, "order": 5, "stops": { - "0": ["CR-Worcester_0_WML-0252-01"], + "0": ["CR-Worcester_0_WML-0252-01", "CR-Worcester_0_WML-0252-02"], "1": ["CR-Worcester_1_WML-0252-02"] } }, @@ -64,7 +64,7 @@ "order": 6, "stops": { "0": ["CR-Worcester_0_WML-0214-01", "CR-Worcester_0_WML-0214-02"], - "1": ["CR-Worcester_1_WML-0214-01", "CR-Worcester_1_WML-0214-02"] + "1": ["CR-Worcester_1_WML-0214-02", "CR-Worcester_1_WML-0214-01"] } }, { @@ -107,47 +107,13 @@ "1": ["CR-Worcester_1_WML-0135-01", "CR-Worcester_1_WML-0135-02"] } }, - { - "stop_name": "Riverside", - "station": "place-river", - "branches": null, - "order": 11, - "stops": { - "0": [ - "CR-Worcester_0_38155", - "CR-Worcester_0_70160", - "CR-Worcester_0_70161", - "CR-Worcester_0_door-river-estairs", - "CR-Worcester_0_door-river-ramp", - "CR-Worcester_0_door-river-wstairs", - "CR-Worcester_0_node-river-estairs-lobby", - "CR-Worcester_0_node-river-farepaid", - "CR-Worcester_0_node-river-fareunpaid", - "CR-Worcester_0_node-river-ramp-lobby", - "CR-Worcester_0_node-river-wstairs-lobby" - ], - "1": [ - "CR-Worcester_1_38155", - "CR-Worcester_1_70160", - "CR-Worcester_1_70161", - "CR-Worcester_1_door-river-estairs", - "CR-Worcester_1_door-river-ramp", - "CR-Worcester_1_door-river-wstairs", - "CR-Worcester_1_node-river-estairs-lobby", - "CR-Worcester_1_node-river-farepaid", - "CR-Worcester_1_node-river-fareunpaid", - "CR-Worcester_1_node-river-ramp-lobby", - "CR-Worcester_1_node-river-wstairs-lobby" - ] - } - }, { "stop_name": "Wellesley Farms", "station": "place-WML-0125", "branches": null, - "order": 12, + "order": 11, "stops": { - "0": ["CR-Worcester_0_WML-0125-02", "CR-Worcester_0_WML-0125-01"], + "0": ["CR-Worcester_0_WML-0125-01", "CR-Worcester_0_WML-0125-02"], "1": ["CR-Worcester_1_WML-0125-01", "CR-Worcester_1_WML-0125-02"] } }, @@ -155,7 +121,7 @@ "stop_name": "Auburndale", "station": "place-WML-0102", "branches": null, - "order": 13, + "order": 12, "stops": { "0": ["CR-Worcester_0_WML-0102-02"], "1": ["CR-Worcester_1_WML-0102-02"] @@ -165,7 +131,7 @@ "stop_name": "West Newton", "station": "place-WML-0091", "branches": null, - "order": 14, + "order": 13, "stops": { "0": ["CR-Worcester_0_WML-0091-02"], "1": ["CR-Worcester_1_WML-0091-02"] @@ -175,7 +141,7 @@ "stop_name": "Newtonville", "station": "place-WML-0081", "branches": null, - "order": 15, + "order": 14, "stops": { "0": ["CR-Worcester_0_WML-0081-02"], "1": ["CR-Worcester_1_WML-0081-02"] @@ -185,9 +151,9 @@ "stop_name": "Boston Landing", "station": "place-WML-0035", "branches": null, - "order": 16, + "order": 15, "stops": { - "0": ["CR-Worcester_0_WML-0035-01", "CR-Worcester_0_WML-0035-02"], + "0": ["CR-Worcester_0_WML-0035-02", "CR-Worcester_0_WML-0035-01"], "1": ["CR-Worcester_1_WML-0035-02", "CR-Worcester_1_WML-0035-01"] } }, @@ -195,36 +161,41 @@ "stop_name": "Lansdowne", "station": "place-WML-0025", "branches": null, - "order": 17, + "order": 16, "stops": { "0": ["CR-Worcester_0_WML-0025-07"], - "1": ["CR-Worcester_1_WML-0025-05"] + "1": ["CR-Worcester_1_WML-0025-05", "CR-Worcester_1_WML-0025-07"] } }, { "stop_name": "Back Bay", "station": "place-bbsta", "branches": null, - "order": 18, + "order": 17, "stops": { - "0": ["CR-Worcester_0_WML-0012-07"], - "1": ["CR-Worcester_1_WML-0012-07", "CR-Worcester_1_WML-0012-05"] + "0": ["CR-Worcester_0_WML-0012-07", "CR-Worcester_0_WML-0012-05"], + "1": ["CR-Worcester_1_WML-0012-05", "CR-Worcester_1_WML-0012-07"] } }, { "stop_name": "South Station", "station": "place-sstat", "branches": null, - "order": 19, + "order": 18, "stops": { "0": [ "CR-Worcester_0_NEC-2287-03", - "CR-Worcester_0_NEC-2287-04", - "CR-Worcester_0_NEC-2287-05", - "CR-Worcester_0_NEC-2287", + "CR-Worcester_0_NEC-2287-12", "CR-Worcester_0_NEC-2287-02", + "CR-Worcester_0_NEC-2287", + "CR-Worcester_0_NEC-2287-11", + "CR-Worcester_0_NEC-2287-06", + "CR-Worcester_0_NEC-2287-07", + "CR-Worcester_0_NEC-2287-05", + "CR-Worcester_0_NEC-2287-04", + "CR-Worcester_0_NEC-2287-01", "CR-Worcester_0_NEC-2287-10", - "CR-Worcester_0_NEC-2287-01" + "CR-Worcester_0_NEC-2287-09" ], "1": [] }, diff --git a/server/scripts/generate_line_files.py b/server/scripts/generate_line_files.py index cb7209334..4b7f3c3c7 100644 --- a/server/scripts/generate_line_files.py +++ b/server/scripts/generate_line_files.py @@ -83,7 +83,7 @@ def parse_stop_name(stop_name: str): for LINE_KEY in ROUTES_CR: - r_f = requests.get("https://api-v3.mbta.com/stops?filter%5Broute%5D={}".format(LINE_KEY)) + r_f = requests.get("https://api-v3.mbta.com/stops?filter%5Broute%5D={}&filter%5Bdirection_id%5D=1".format(LINE_KEY)) stops = r_f.json() stop_layout = get_line_stops() From 7dc121d9952ff1a0586a90f19eb03ff2bc50b283 Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Mon, 20 Jan 2025 19:13:04 -0500 Subject: [PATCH 45/53] Add in newburyport line --- common/components/inputs/StationSelector.tsx | 8 +++++--- common/components/widgets/StationSelectorWidget.tsx | 1 + common/constants/stations.ts | 2 ++ modules/tripexplorer/TripExplorer.tsx | 2 ++ 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/common/components/inputs/StationSelector.tsx b/common/components/inputs/StationSelector.tsx index b5fc7a477..0167a172c 100644 --- a/common/components/inputs/StationSelector.tsx +++ b/common/components/inputs/StationSelector.tsx @@ -5,7 +5,7 @@ import { faBicycle, faChevronDown, faWheelchair } from '@fortawesome/free-solid- import classNames from 'classnames'; import type { Station } from '../../types/stations'; import { useDelimitatedRoute } from '../../utils/router'; -import { optionsForField } from '../../utils/stations'; +import { optionsForField, stopIdsForStations } from '../../utils/stations'; import { buttonHighlightFocus, lineColorBackground, @@ -77,8 +77,10 @@ export const StationSelector: React.FC = ({ key={stationIndex} disabled={ type === 'from' - ? station.station === toStation.station - : station.station === fromStation.station + ? station.station === toStation.station || + stopIdsForStations(station, toStation).fromStopIds?.length === 0 + : station.station === fromStation.station || + stopIdsForStations(fromStation, station).toStopIds?.length === 0 } className={({ active, selected, disabled }) => classNames( diff --git a/common/components/widgets/StationSelectorWidget.tsx b/common/components/widgets/StationSelectorWidget.tsx index 87e7799cb..6410b1058 100644 --- a/common/components/widgets/StationSelectorWidget.tsx +++ b/common/components/widgets/StationSelectorWidget.tsx @@ -35,6 +35,7 @@ export const StationSelectorWidget: React.FC = ({ const stations = optionsStation(lineShort, busRoute, crRoute); const toStation = to ? getParentStationForStopId(to) : stations?.[stations.length - 2]; const fromStation = from ? getParentStationForStopId(from) : stations?.[1]; + React.useEffect(() => { const { fromStopIds, toStopIds } = stopIdsForStations(fromStation, toStation); updateQueryParams({ from: fromStopIds?.[0], to: toStopIds?.[0] }); diff --git a/common/constants/stations.ts b/common/constants/stations.ts index f6d19ae9d..3b718a145 100644 --- a/common/constants/stations.ts +++ b/common/constants/stations.ts @@ -74,6 +74,7 @@ import cr_greenbush from './cr_constants/cr-greenbush.json'; import cr_fairmount from './cr_constants/cr-fairmount.json'; import cr_kingston from './cr_constants/cr-kingston.json'; import cr_middleborough from './cr_constants/cr-middleborough.json'; +import cr_newburyport from './cr_constants/cr-newburyport.json'; import cr_needham from './cr_constants/cr-needham.json'; import cr_providence from './cr_constants/cr-providence.json'; @@ -155,6 +156,7 @@ export const crStations: { [key: string]: LineMap } = { ...cr_fairmount, ...cr_kingston, ...cr_middleborough, + ...cr_newburyport, ...cr_needham, ...cr_providence, }; diff --git a/modules/tripexplorer/TripExplorer.tsx b/modules/tripexplorer/TripExplorer.tsx index e5c0071bc..0463e128d 100644 --- a/modules/tripexplorer/TripExplorer.tsx +++ b/modules/tripexplorer/TripExplorer.tsx @@ -36,6 +36,7 @@ export const TripExplorer = () => { if (!(fromStation && toStation)) { return null; } + return ( @@ -53,4 +54,5 @@ export const TripExplorer = () => { ); }; + TripExplorer.Layout = Layout.Dashboard; From e4da0ef93eb9d52535cace7e27a9e9bbfc4df98e Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Mon, 20 Jan 2025 19:15:03 -0500 Subject: [PATCH 46/53] Beta notice in all commuter rail --- common/components/notices/BetaDataNotice.tsx | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/common/components/notices/BetaDataNotice.tsx b/common/components/notices/BetaDataNotice.tsx index 01a30bd57..1f97c8793 100644 --- a/common/components/notices/BetaDataNotice.tsx +++ b/common/components/notices/BetaDataNotice.tsx @@ -1,28 +1,14 @@ import React from 'react'; -import dayjs from 'dayjs'; import Link from 'next/link'; import classNames from 'classnames'; import { ExclamationTriangleIcon } from '@heroicons/react/20/solid'; import { useDelimitatedRoute } from '../../utils/router'; -import { BUS_MAX_DAY } from '../../constants/dates'; import { lineColorTextHover } from '../../styles/general'; export const BetaDataNotice: React.FC = () => { - const { - line, - linePath, - query: { date, startDate, endDate }, - } = useDelimitatedRoute(); + const { line, linePath } = useDelimitatedRoute(); - const isStartDateAfterBusMaxDay = - (startDate !== undefined && dayjs(startDate).isAfter(BUS_MAX_DAY)) || - (date !== undefined && dayjs(date).isAfter(BUS_MAX_DAY)); - const isEndDateAfterBusMaxDay = endDate !== undefined && dayjs(endDate).isAfter(BUS_MAX_DAY); - - if ( - (line === 'line-commuter-rail' || linePath === 'commuter-rail') && - (isStartDateAfterBusMaxDay || isEndDateAfterBusMaxDay) - ) { + if (line === 'line-commuter-rail' || linePath === 'commuter-rail') { return (
From ed90f934c7cdc34094c57654a6921b1bd6d3278a Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Sun, 16 Feb 2025 14:05:52 -0700 Subject: [PATCH 47/53] Update modules/tripexplorer/CommuterRailTripGraphs.tsx Co-authored-by: transitmatters-datadog[bot] <127633113+transitmatters-datadog[bot]@users.noreply.github.com> --- modules/tripexplorer/CommuterRailTripGraphs.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/tripexplorer/CommuterRailTripGraphs.tsx b/modules/tripexplorer/CommuterRailTripGraphs.tsx index 75d1b56f6..6688454c8 100644 --- a/modules/tripexplorer/CommuterRailTripGraphs.tsx +++ b/modules/tripexplorer/CommuterRailTripGraphs.tsx @@ -81,7 +81,7 @@ export const CommuterRailTripGraphs: React.FC = ({ fromStation={fromStation} type={'traveltimes'} timeUnit={'by_time'} - peakTime={peakTime === 'weekday' ? true : false} + peakTime={peakTime === 'weekday'} />
Date: Sat, 1 Mar 2025 16:39:31 -0500 Subject: [PATCH 48/53] Clean up date selection and remaining small bugs --- .../inputs/DateSelection/DatePickers.tsx | 6 ++-- common/components/nav/MenuDropdown.tsx | 2 +- common/constants/dashboardTabs.ts | 2 +- common/constants/dates.ts | 24 ++++++++++++-- common/state/defaults/dateDefaults.ts | 3 +- common/utils/middleware.ts | 32 ++++++++++++++----- common/utils/router.tsx | 5 ++- modules/landing/LineButton.tsx | 2 +- 8 files changed, 56 insertions(+), 20 deletions(-) diff --git a/common/components/inputs/DateSelection/DatePickers.tsx b/common/components/inputs/DateSelection/DatePickers.tsx index 9dcbd2ec8..fbf05d87e 100644 --- a/common/components/inputs/DateSelection/DatePickers.tsx +++ b/common/components/inputs/DateSelection/DatePickers.tsx @@ -7,7 +7,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import Flatpickr from 'react-flatpickr'; import 'flatpickr/dist/themes/light.css'; import { useDelimitatedRoute, useUpdateQuery } from '../../../utils/router'; -import { FLAT_PICKER_OPTIONS, TODAY_STRING, RANGE_PRESETS } from '../../../constants/dates'; +import { TODAY_STRING, RANGE_PRESETS, getDatePickerOptions } from '../../../constants/dates'; import { buttonHighlightFocus } from '../../../styles/general'; import type { Line } from '../../../types/lines'; import { ALL_PAGES } from '../../../constants/pages'; @@ -108,7 +108,7 @@ export const DatePickers: React.FC = ({ range, setRange, type, value={startDate ?? date} key={'start'} placeholder={'mm/dd/yyyy'} - options={FLAT_PICKER_OPTIONS[tab]} + options={getDatePickerOptions(tab, page)} onChange={(dates, currentDateString) => { if (isSingleDate) { handleDateChange(currentDateString); @@ -135,7 +135,7 @@ export const DatePickers: React.FC = ({ range, setRange, type, value={endDate} key={'end'} placeholder={'mm/dd/yyyy'} - options={FLAT_PICKER_OPTIONS[tab]} + options={getDatePickerOptions(tab, page)} onChange={(dates, currentDateString) => { handleEndDateChange(currentDateString); }} diff --git a/common/components/nav/MenuDropdown.tsx b/common/components/nav/MenuDropdown.tsx index 11e14a640..971694f1e 100644 --- a/common/components/nav/MenuDropdown.tsx +++ b/common/components/nav/MenuDropdown.tsx @@ -44,7 +44,7 @@ export const MenuDropdown: React.FC = ({ line, route, childre case 'line-bus': return `/bus/trips/single?busRoute=1&date=${BUS_DEFAULTS.singleTripConfig.date}`; case 'line-commuter-rail': - return `/commuter-rail/trips/single?crRoute=CR-Lowell&date=${COMMUTER_RAIL_DEFAULTS.singleTripConfig.date}`; + return `/commuter-rail/trips/single?crRoute=CR-Fairmount&date=${COMMUTER_RAIL_DEFAULTS.singleTripConfig.date}`; default: return getLineSelectionItemHref(line, route); } diff --git a/common/constants/dashboardTabs.ts b/common/constants/dashboardTabs.ts index bbfd46a21..938f03876 100644 --- a/common/constants/dashboardTabs.ts +++ b/common/constants/dashboardTabs.ts @@ -14,6 +14,6 @@ export const DASHBOARD_TABS: { 'Commuter Rail': { name: 'Commuter Rail', path: '/commuter-rail', - query: { crRoute: 'CR-Lowell', date: COMMUTER_RAIL_DEFAULTS.singleTripConfig.date }, + query: { crRoute: 'CR-Fairmount', date: COMMUTER_RAIL_DEFAULTS.singleTripConfig.date }, }, }; diff --git a/common/constants/dates.ts b/common/constants/dates.ts index eff7c5d66..ed32b12b8 100644 --- a/common/constants/dates.ts +++ b/common/constants/dates.ts @@ -9,6 +9,7 @@ import type { SingleDateParams, } from '../components/inputs/DateSelection/types/DateSelectionTypes'; import type { Tab } from '../types/router'; +import type { Page } from './pages'; dayjs.extend(utc); dayjs.extend(timezone); @@ -40,13 +41,30 @@ export const BUS_MAX_DAY = dayjs(BUS_MAX_DATE); export const BUS_MAX_DATE_MINUS_ONE_WEEK = dayjs(BUS_MAX_DATE) .subtract(7, 'days') .format(DATE_FORMAT); -export const COMMUTER_RAIL_MIN_DATE = '2022-06-22'; + +// Commuter Rail earliest Ridership date +export const COMMUTER_RAIL_RIDERSHIP_MIN_DATE = '2022-06-22'; +export const COMMUTER_RAIL_DATA_MIN_DATE = '2024-01-01'; export const getESTDayjs = (date: string) => { return dayjs(date).tz(est); }; -export const FLAT_PICKER_OPTIONS: { +export const getDatePickerOptions = (tab: Tab, page?: Page) => { + if (tab === 'Commuter Rail') { + if (page === 'ridership') { + return { + ...FLAT_PICKER_OPTIONS[tab], + minDate: COMMUTER_RAIL_RIDERSHIP_MIN_DATE, + maxDate: TODAY_STRING, + }; + } + } + + return FLAT_PICKER_OPTIONS[tab]; +}; + +const FLAT_PICKER_OPTIONS: { [key in Tab]: DateTimePickerProps['options']; } = { Subway: { @@ -75,7 +93,7 @@ export const FLAT_PICKER_OPTIONS: { }, 'Commuter Rail': { enableTime: false, - minDate: COMMUTER_RAIL_MIN_DATE, + minDate: COMMUTER_RAIL_DATA_MIN_DATE, maxDate: TODAY_STRING, altInput: true, altFormat: 'M j, Y', diff --git a/common/state/defaults/dateDefaults.ts b/common/state/defaults/dateDefaults.ts index 1551ae7a6..568ab90fe 100644 --- a/common/state/defaults/dateDefaults.ts +++ b/common/state/defaults/dateDefaults.ts @@ -7,7 +7,6 @@ import { TODAY_STRING, YESTERDAY_STRING, TODAY_SERVICE_STARTED, - COMMUTER_RAIL_MIN_DATE, } from '../../constants/dates'; import type { WithOptional } from '../../types/general'; @@ -41,7 +40,7 @@ export const COMMUTER_RAIL_DEFAULTS: WithOptional< > = { lineConfig: { startDate: OVERVIEW_OPTIONS.year.startDate, endDate: TODAY_STRING }, multiTripConfig: { - startDate: COMMUTER_RAIL_MIN_DATE, + startDate: ONE_WEEK_AGO_STRING, endDate: TODAY_STRING, }, singleTripConfig: { diff --git a/common/utils/middleware.ts b/common/utils/middleware.ts index 41f17532c..b1767759a 100644 --- a/common/utils/middleware.ts +++ b/common/utils/middleware.ts @@ -1,16 +1,25 @@ import type { ReadonlyURLSearchParams } from 'next/navigation'; import { useSearchParams } from 'next/navigation'; import { useRouter } from 'next/router'; -import { RAIL_LINES, type BusRoute, type LinePath, BUS_ROUTES } from '../types/lines'; +import { + type CommuterRailRoute, + type BusRoute, + type LinePath, + COMMUTER_RAIL_ROUTES, + BUS_ROUTES, + RAIL_LINES, +} from '../types/lines'; import { TODAY_STRING } from '../constants/dates'; -const getBusOrLine = ( +const getLineOrRoute = ( lineString: string | BusRoute -): { type: 'rail' | 'bus'; value: LinePath | BusRoute } | undefined => { +): { type: 'rail' | 'bus' | 'cr'; value: LinePath | BusRoute | CommuterRailRoute } | undefined => { if (RAIL_LINES.includes(lineString.toLowerCase())) return { type: 'rail', value: lineString.toLowerCase() as LinePath }; if (BUS_ROUTES.includes(lineString.toString() as BusRoute)) return { type: 'bus', value: lineString as BusRoute }; + if (COMMUTER_RAIL_ROUTES.includes(lineString.toString() as CommuterRailRoute)) + return { type: 'cr', value: lineString as CommuterRailRoute }; }; export const configToQueryParams = (search: ReadonlyURLSearchParams | URLSearchParams) => { @@ -21,8 +30,8 @@ export const configToQueryParams = (search: ReadonlyURLSearchParams | URLSearchP : search.get('config')?.split(','); if (!configArr || configArr.length !== 5) return; - const busOrLine = getBusOrLine(configArr[0]); - if (!busOrLine) return; + const lineOrRoute = getLineOrRoute(configArr[0]); + if (!lineOrRoute) return; const query = { from: configArr[1] || undefined, @@ -42,13 +51,20 @@ export const configToQueryParams = (search: ReadonlyURLSearchParams | URLSearchP string, string, ][]; - if (busOrLine.type === 'bus') queryArr.push(['busRoute', busOrLine.value]); + if (lineOrRoute.type === 'bus') queryArr.push(['busRoute', lineOrRoute.value]); + if (lineOrRoute.type === 'cr') queryArr.push(['crRoute', lineOrRoute.value]); const newQueryParams = new URLSearchParams(queryArr); - if (busOrLine.type === 'rail') + if (lineOrRoute.type === 'rail') return { - line: busOrLine.value, + line: lineOrRoute.value, + queryParams: newQueryParams, + tripSection: singleOrMulti, + }; + if (lineOrRoute.type === 'cr') + return { + line: 'commuter-rail', queryParams: newQueryParams, tripSection: singleOrMulti, }; diff --git a/common/utils/router.tsx b/common/utils/router.tsx index f1bba8fc6..b3fb69295 100644 --- a/common/utils/router.tsx +++ b/common/utils/router.tsx @@ -159,8 +159,11 @@ export const getLineSelectionItemHref = (newLine: Line, route: Route): string => } delete query.from; delete query.to; + // Get queryParams but exclude busRoute and crRoute const queryParams = query - ? new URLSearchParams(Object.entries(query).filter(([key]) => key !== 'busRoute')) + ? new URLSearchParams( + Object.entries(query).filter(([key]) => key !== 'busRoute' && key !== 'crRoute') + ) : new URLSearchParams(); href += currentPath ? `${currentPath}` : ''; const queryString = queryParams.toString(); diff --git a/modules/landing/LineButton.tsx b/modules/landing/LineButton.tsx index 4439b66ab..38490fb6c 100644 --- a/modules/landing/LineButton.tsx +++ b/modules/landing/LineButton.tsx @@ -18,7 +18,7 @@ export const LineButton: React.FC = ({ children, line }) => { Date: Sat, 1 Mar 2025 17:35:29 -0500 Subject: [PATCH 49/53] Version bump and improve legend --- .vscode/settings.json | 3 ++- common/components/charts/Legend.tsx | 32 ++++++++++++++++++++++------- package.json | 4 ++-- 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 33f77f6d9..b385ddc34 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -12,5 +12,6 @@ "python.formatting.provider": "black", "[python]": { "editor.defaultFormatter": "ms-python.black-formatter" - } + }, + "cSpell.words": ["MBTA"] } diff --git a/common/components/charts/Legend.tsx b/common/components/charts/Legend.tsx index cf66bf823..5d282bdca 100644 --- a/common/components/charts/Legend.tsx +++ b/common/components/charts/Legend.tsx @@ -2,12 +2,14 @@ import { faChevronDown, faChevronUp } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Disclosure } from '@headlessui/react'; import React from 'react'; +import { useDelimitatedRoute } from '../../utils/router'; interface LegendProps { showUnderRatio?: boolean; } -export const LegendSingleDay: React.FC = ({ showUnderRatio = false }) => { +export const LegendSingleDay: React.FC = ({ showUnderRatio }) => { + const { line } = useDelimitatedRoute(); return ( {({ open }) => ( @@ -18,12 +20,28 @@ export const LegendSingleDay: React.FC = ({ showUnderRatio = false
- - + +
+ +
+ +
+ {line === 'line-commuter-rail' && ( +

+ Due to how we collect data for Commuter Rail, we may occasionally miss trips or + stops. This can lead to inaccuracies in headways numbers and gaps in travel time + data. Confirm data you see here with official MBTA sources when possible. +

+ )} +
)} diff --git a/package.json b/package.json index e1ef48df2..ca86d7b5d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "t-performance-dash", - "version": "4.1.2", + "version": "4.2.0", "private": true, "homepage": ".", "scripts": { @@ -133,4 +133,4 @@ "@storybook/react-docgen-typescript-plugin": "1.0.6--canary.9.0c3f3b7.0" }, "proxy": "http://localhost:5000" -} \ No newline at end of file +} From 73b8ad191aa0c4fbb55224fa2d4bb05bf5883a76 Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Sat, 1 Mar 2025 17:46:43 -0500 Subject: [PATCH 50/53] Format Y axis --- common/components/charts/AggregateLineChart.tsx | 5 +++++ common/components/charts/SingleDayLineChart.tsx | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/common/components/charts/AggregateLineChart.tsx b/common/components/charts/AggregateLineChart.tsx index 6af32ad82..4094d5fe9 100644 --- a/common/components/charts/AggregateLineChart.tsx +++ b/common/components/charts/AggregateLineChart.tsx @@ -106,6 +106,11 @@ export const AggregateLineChart: React.FC = ({ }, ticks: { precision: 1, + callback: (value) => { + return yUnit === 'Minutes' && typeof value === 'number' + ? getFormattedTimeString(value, 'minutes') + : value.toLocaleString(); + }, }, suggestedMin: suggestedYMin, suggestedMax: suggestedYMax, diff --git a/common/components/charts/SingleDayLineChart.tsx b/common/components/charts/SingleDayLineChart.tsx index 34eb2966c..285814045 100644 --- a/common/components/charts/SingleDayLineChart.tsx +++ b/common/components/charts/SingleDayLineChart.tsx @@ -195,6 +195,11 @@ export const SingleDayLineChart: React.FC = ({ display: true, ticks: { color: COLORS.design.subtitleGrey, + callback: (value) => { + return units === 'Minutes' && typeof value === 'number' + ? getFormattedTimeString(value, 'minutes') + : value.toLocaleString(); + }, }, title: { display: true, From 340b542052c61699d56a190fe9ba10ffdc49cd74 Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Sat, 1 Mar 2025 17:51:24 -0500 Subject: [PATCH 51/53] Update lockfile --- package-lock.json | 260 ++++++++++++++++++++++++---------------------- 1 file changed, 137 insertions(+), 123 deletions(-) diff --git a/package-lock.json b/package-lock.json index a1d3abecc..02465b9b0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "t-performance-dash", - "version": "4.1.2", + "version": "4.2.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "t-performance-dash", - "version": "4.1.2", + "version": "4.2.0", "hasInstallScript": true, "dependencies": { "@fortawesome/fontawesome-svg-core": "^6.7.2", @@ -1776,9 +1776,9 @@ "license": "MIT" }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz", - "integrity": "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.0.tgz", + "integrity": "sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ==", "cpu": [ "ppc64" ], @@ -1793,9 +1793,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.2.tgz", - "integrity": "sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.0.tgz", + "integrity": "sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g==", "cpu": [ "arm" ], @@ -1810,9 +1810,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.2.tgz", - "integrity": "sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.0.tgz", + "integrity": "sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g==", "cpu": [ "arm64" ], @@ -1827,9 +1827,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.2.tgz", - "integrity": "sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.0.tgz", + "integrity": "sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg==", "cpu": [ "x64" ], @@ -1844,9 +1844,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.2.tgz", - "integrity": "sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.0.tgz", + "integrity": "sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw==", "cpu": [ "arm64" ], @@ -1861,9 +1861,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.2.tgz", - "integrity": "sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.0.tgz", + "integrity": "sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg==", "cpu": [ "x64" ], @@ -1878,9 +1878,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.2.tgz", - "integrity": "sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.0.tgz", + "integrity": "sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w==", "cpu": [ "arm64" ], @@ -1895,9 +1895,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.2.tgz", - "integrity": "sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.0.tgz", + "integrity": "sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A==", "cpu": [ "x64" ], @@ -1912,9 +1912,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.2.tgz", - "integrity": "sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.0.tgz", + "integrity": "sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg==", "cpu": [ "arm" ], @@ -1929,9 +1929,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.2.tgz", - "integrity": "sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.0.tgz", + "integrity": "sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg==", "cpu": [ "arm64" ], @@ -1946,9 +1946,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.2.tgz", - "integrity": "sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.0.tgz", + "integrity": "sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg==", "cpu": [ "ia32" ], @@ -1963,9 +1963,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.2.tgz", - "integrity": "sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.0.tgz", + "integrity": "sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw==", "cpu": [ "loong64" ], @@ -1980,9 +1980,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.2.tgz", - "integrity": "sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.0.tgz", + "integrity": "sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ==", "cpu": [ "mips64el" ], @@ -1997,9 +1997,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.2.tgz", - "integrity": "sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.0.tgz", + "integrity": "sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw==", "cpu": [ "ppc64" ], @@ -2014,9 +2014,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.2.tgz", - "integrity": "sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.0.tgz", + "integrity": "sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA==", "cpu": [ "riscv64" ], @@ -2031,9 +2031,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.2.tgz", - "integrity": "sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.0.tgz", + "integrity": "sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA==", "cpu": [ "s390x" ], @@ -2048,9 +2048,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.2.tgz", - "integrity": "sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.0.tgz", + "integrity": "sha512-9yl91rHw/cpwMCNytUDxwj2XjFpxML0y9HAOH9pNVQDpQrBxHy01Dx+vaMu0N1CKa/RzBD2hB4u//nfc+Sd3Cw==", "cpu": [ "x64" ], @@ -2065,9 +2065,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.24.2.tgz", - "integrity": "sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.0.tgz", + "integrity": "sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw==", "cpu": [ "arm64" ], @@ -2082,9 +2082,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.2.tgz", - "integrity": "sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.0.tgz", + "integrity": "sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA==", "cpu": [ "x64" ], @@ -2099,9 +2099,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.2.tgz", - "integrity": "sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.0.tgz", + "integrity": "sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw==", "cpu": [ "arm64" ], @@ -2116,9 +2116,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.2.tgz", - "integrity": "sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.0.tgz", + "integrity": "sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg==", "cpu": [ "x64" ], @@ -2133,9 +2133,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.2.tgz", - "integrity": "sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.0.tgz", + "integrity": "sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg==", "cpu": [ "x64" ], @@ -2150,9 +2150,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.2.tgz", - "integrity": "sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.0.tgz", + "integrity": "sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw==", "cpu": [ "arm64" ], @@ -2167,9 +2167,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.2.tgz", - "integrity": "sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.0.tgz", + "integrity": "sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA==", "cpu": [ "ia32" ], @@ -2184,9 +2184,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.2.tgz", - "integrity": "sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.0.tgz", + "integrity": "sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ==", "cpu": [ "x64" ], @@ -3769,16 +3769,16 @@ } }, "node_modules/@storybook/core": { - "version": "8.5.1", - "resolved": "https://registry.npmjs.org/@storybook/core/-/core-8.5.1.tgz", - "integrity": "sha512-4zxjclENpZYuNY1fZJE4a7hd8Ho/SiOSN2B57fsIi1qCpKax3JU3J59ZcAWT0iidy5qgM2qMcWbrl0Bl/tWamA==", + "version": "8.6.3", + "resolved": "https://registry.npmjs.org/@storybook/core/-/core-8.6.3.tgz", + "integrity": "sha512-0iMTfmo3UFCa1hFJLtThnRIppkIpGPyTL3MElhORP1t5l9lCUq5am0ymbi/TeCbsJPjE86FjeO0NinokL9iQiw==", "dev": true, "license": "MIT", "dependencies": { - "@storybook/csf": "0.1.12", + "@storybook/theming": "8.6.3", "better-opn": "^3.0.2", "browser-assert": "^1.2.1", - "esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0", + "esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0 || ^0.25.0", "esbuild-register": "^3.5.0", "jsdoc-type-pratt-parser": "^4.0.0", "process": "^0.11.10", @@ -3817,10 +3817,24 @@ "storybook": "^8.5.1" } }, + "node_modules/@storybook/core/node_modules/@storybook/theming": { + "version": "8.6.3", + "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-8.6.3.tgz", + "integrity": "sha512-sDcWnnko73KOCIc9stQyec9KvTmGOuMswqeKtWh0ha/wsgYB6G2/2j1xOheFmWKPitOsbwgvqtjCP7bRE68uIA==", + "dev": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0" + } + }, "node_modules/@storybook/core/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", "dev": true, "license": "ISC", "bin": { @@ -8647,9 +8661,9 @@ } }, "node_modules/esbuild": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.2.tgz", - "integrity": "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.0.tgz", + "integrity": "sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -8660,31 +8674,31 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.24.2", - "@esbuild/android-arm": "0.24.2", - "@esbuild/android-arm64": "0.24.2", - "@esbuild/android-x64": "0.24.2", - "@esbuild/darwin-arm64": "0.24.2", - "@esbuild/darwin-x64": "0.24.2", - "@esbuild/freebsd-arm64": "0.24.2", - "@esbuild/freebsd-x64": "0.24.2", - "@esbuild/linux-arm": "0.24.2", - "@esbuild/linux-arm64": "0.24.2", - "@esbuild/linux-ia32": "0.24.2", - "@esbuild/linux-loong64": "0.24.2", - "@esbuild/linux-mips64el": "0.24.2", - "@esbuild/linux-ppc64": "0.24.2", - "@esbuild/linux-riscv64": "0.24.2", - "@esbuild/linux-s390x": "0.24.2", - "@esbuild/linux-x64": "0.24.2", - "@esbuild/netbsd-arm64": "0.24.2", - "@esbuild/netbsd-x64": "0.24.2", - "@esbuild/openbsd-arm64": "0.24.2", - "@esbuild/openbsd-x64": "0.24.2", - "@esbuild/sunos-x64": "0.24.2", - "@esbuild/win32-arm64": "0.24.2", - "@esbuild/win32-ia32": "0.24.2", - "@esbuild/win32-x64": "0.24.2" + "@esbuild/aix-ppc64": "0.25.0", + "@esbuild/android-arm": "0.25.0", + "@esbuild/android-arm64": "0.25.0", + "@esbuild/android-x64": "0.25.0", + "@esbuild/darwin-arm64": "0.25.0", + "@esbuild/darwin-x64": "0.25.0", + "@esbuild/freebsd-arm64": "0.25.0", + "@esbuild/freebsd-x64": "0.25.0", + "@esbuild/linux-arm": "0.25.0", + "@esbuild/linux-arm64": "0.25.0", + "@esbuild/linux-ia32": "0.25.0", + "@esbuild/linux-loong64": "0.25.0", + "@esbuild/linux-mips64el": "0.25.0", + "@esbuild/linux-ppc64": "0.25.0", + "@esbuild/linux-riscv64": "0.25.0", + "@esbuild/linux-s390x": "0.25.0", + "@esbuild/linux-x64": "0.25.0", + "@esbuild/netbsd-arm64": "0.25.0", + "@esbuild/netbsd-x64": "0.25.0", + "@esbuild/openbsd-arm64": "0.25.0", + "@esbuild/openbsd-x64": "0.25.0", + "@esbuild/sunos-x64": "0.25.0", + "@esbuild/win32-arm64": "0.25.0", + "@esbuild/win32-ia32": "0.25.0", + "@esbuild/win32-x64": "0.25.0" } }, "node_modules/esbuild-register": { @@ -14583,9 +14597,9 @@ } }, "node_modules/recast": { - "version": "0.23.9", - "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.9.tgz", - "integrity": "sha512-Hx/BGIbwj+Des3+xy5uAtAbdCyqK9y9wbBcDFDYanLS9JnMqf7OeF87HQwUimE87OEc72mr6tkKUKMBBL+hF9Q==", + "version": "0.23.10", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.10.tgz", + "integrity": "sha512-mbCmRMJUKCJ1h41V0cu2C26ULBURwuoZ34C9rChjcDaeJ/4Kv5al3O2HPwTs2m0wQ1vGhMY+tguhzU1aE8md1A==", "dev": true, "license": "MIT", "dependencies": { @@ -15811,13 +15825,13 @@ } }, "node_modules/storybook": { - "version": "8.5.1", - "resolved": "https://registry.npmjs.org/storybook/-/storybook-8.5.1.tgz", - "integrity": "sha512-HuaAFA97j2w4i/1EHKj6X4iDiVzPrXzQpmTEE1tLD1QXzqrQKKHse+Ggc8AGMuLTAzxA6xmrX9xibgMNWCgvRA==", + "version": "8.6.3", + "resolved": "https://registry.npmjs.org/storybook/-/storybook-8.6.3.tgz", + "integrity": "sha512-Vbmd8/FXp6X0AOMak6arcg3WdkHj+2AYJTNHbCPVHsCEbnREyRZIG+Eq5/Ffmy6byiz+4OAX5HwsHGSMR6Xmow==", "dev": true, "license": "MIT", "dependencies": { - "@storybook/core": "8.5.1" + "@storybook/core": "8.6.3" }, "bin": { "getstorybook": "bin/index.cjs", @@ -17698,9 +17712,9 @@ "license": "ISC" }, "node_modules/ws": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==", "dev": true, "license": "MIT", "engines": { From 2b0f5380fff1d5354a45751f65b2aa6652587cf1 Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Sat, 1 Mar 2025 20:54:16 -0500 Subject: [PATCH 52/53] Include commuter rail in description --- pages/_document.tsx | 2 +- public/manifest.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pages/_document.tsx b/pages/_document.tsx index 8caf19cc0..fcab24839 100644 --- a/pages/_document.tsx +++ b/pages/_document.tsx @@ -12,7 +12,7 @@ export default function Document() { diff --git a/public/manifest.json b/public/manifest.json index 6b2361614..ae34e8cec 100644 --- a/public/manifest.json +++ b/public/manifest.json @@ -1,7 +1,7 @@ { "short_name": "Data Dashboard", "name": "Transitmatters Data Dashboard", - "description": "Explore MBTA subway and bus performance data with the TransitMatters Data Dashboard.", + "description": "Explore MBTA subway, commuter rail and bus performance data with the TransitMatters Data Dashboard.", "icons": [ { "src": "favicon_128.png", From 4419c52c4c461d900b76ad8608b10d843b76665c Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Sat, 1 Mar 2025 20:56:34 -0500 Subject: [PATCH 53/53] Improve page warnings --- .../notices/CommuterRailDataNotice.tsx | 24 +++++++++++++++++++ modules/tripexplorer/TripExplorer.tsx | 2 ++ 2 files changed, 26 insertions(+) create mode 100644 common/components/notices/CommuterRailDataNotice.tsx diff --git a/common/components/notices/CommuterRailDataNotice.tsx b/common/components/notices/CommuterRailDataNotice.tsx new file mode 100644 index 000000000..25806377c --- /dev/null +++ b/common/components/notices/CommuterRailDataNotice.tsx @@ -0,0 +1,24 @@ +import React from 'react'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { faLocationCrosshairs } from '@fortawesome/free-solid-svg-icons'; +import { useDelimitatedRoute } from '../../utils/router'; + +export const CommuterRailDataNotice: React.FC = () => { + const { line, linePath } = useDelimitatedRoute(); + + if (line === 'line-commuter-rail' || linePath === 'commuter-rail') { + return ( +
+ +
+

+ Due to how we collect data for Commuter Rail, we may occasionally miss trips or stops. + This can lead to inaccuracies in headways numbers and gaps in travel time data. Confirm + data you see here with official MBTA sources when possible. +

+
+
+ ); + } + return null; +}; diff --git a/modules/tripexplorer/TripExplorer.tsx b/modules/tripexplorer/TripExplorer.tsx index 4c65ae882..71c158fa6 100644 --- a/modules/tripexplorer/TripExplorer.tsx +++ b/modules/tripexplorer/TripExplorer.tsx @@ -13,6 +13,7 @@ import { BusDataNotice } from '../../common/components/notices/BusDataNotice'; import { GobbleDataNotice } from '../../common/components/notices/GobbleDataNotice'; import { BetaDataNotice } from '../../common/components/notices/BetaDataNotice'; import { PokeySchleppieAwardBanner } from '../../common/components/notices/PokeySchleppieAwardBanner'; +import { CommuterRailDataNotice } from '../../common/components/notices/CommuterRailDataNotice'; import { useAlertStore } from './AlertStore'; import { TripGraphs } from './TripGraphs'; @@ -47,6 +48,7 @@ export const TripExplorer = () => {
+