Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions public/static_data.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,46 @@
"totalActive": 6,
"totalInactive": 4
},
"Worcester": {
"totalActive": 109,
"totalInactive": 19
},
"Fairmount": {
"totalActive": 109,
"totalInactive": 19
},
"Fitchburg": {
"totalActive": 109,
"totalInactive": 19
},
"Greenbush": {
"totalActive": 109,
"totalInactive": 19
},
"Haverhill": {
"totalActive": 109,
"totalInactive": 19
},
"Kingston": {
"totalActive": 109,
"totalInactive": 19
},
"Lowell": {
"totalActive": 109,
"totalInactive": 19
},
"Needham": {
"totalActive": 109,
"totalInactive": 19
},
"Providence": {
"totalActive": 109,
"totalInactive": 19
},
"Franklin": {
"totalActive": 109,
"totalInactive": 19
},
"Sources": {
"fleet_numbers": "http://roster.transithistory.org/"
},
Expand Down
13 changes: 13 additions & 0 deletions server/chalicelib/fleet.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
silver_is_new = lambda x: int(x) >= 1294 and int(x) <= 1299
blue_is_new = lambda _: False
mattapan_is_new = lambda x: False
cr_is_new = lambda x: False


def get_route_test_function_dict(route_ids, test_fn):
Expand All @@ -30,6 +31,18 @@ def get_route_test_function_dict(route_ids, test_fn):
**get_route_test_function_dict(SILVER_ROUTE_IDS, silver_is_new),
"Blue": blue_is_new,
"Mattapan": mattapan_is_new,
"CR-Worcester": cr_is_new,
"CR-Fairmount": cr_is_new,
"CR-Fitchburg": cr_is_new,
"CR-Greenbush": cr_is_new,
"CR-Haverhill": cr_is_new,
"CR-Kingston": cr_is_new,
"CR-Lowell": cr_is_new,
"CR-Needham": cr_is_new,
"CR-Franklin-A": cr_is_new,
"CR-Franklin-B": cr_is_new,
"CR-Providence-A": cr_is_new,
"CR-Providence-B": cr_is_new,
}


Expand Down
5 changes: 4 additions & 1 deletion server/chalicelib/mbta_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ async def trip_departure_predictions(trip_id: str, stop_id: str):
try:
prediction = await getV3("predictions", {"filter[trip]": trip_id, "filter[stop]": stop_id})

return {'departure_time': prediction[0]['departure_time']}
return {"departure_time": prediction[0]["departure_time"]}
except Exception as e:
print(f"Error getting predictions for trip: {e}")
return {"departure_time": "null"}
Expand Down Expand Up @@ -128,6 +128,8 @@ async def vehicle_data_for_routes(route_ids):

is_pride_car = any(carriage.get("label") == "3706" for carriage in vehicle["carriages"])

is_heritage_car = any([vehicle["label"] == "1030"])

vehicles_to_display.append(
{
"vehicleId": vehicle["id"],
Expand All @@ -144,6 +146,7 @@ async def vehicle_data_for_routes(route_ids):
"carriages": vehicle["carriages"],
"updatedAt": vehicle["updated_at"],
"isPrideCar": is_pride_car,
"isHeritageCar": is_heritage_car,
"speed": vehicle["speed"],
}
)
Expand Down
79 changes: 78 additions & 1 deletion server/chalicelib/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,32 @@
"70094",
]

CR_Franklin_A_STOP_IDS = ["place-FB-0303", "place-FB-0275", "place-FB-0230", "place-FB-0191"]
CR_Franklin_B_STOP_IDS = ["place-FS-0049"]

CR_Providence_A_STOP_IDS = ["place-SB-0156", "place-SB-0189"]
CR_Providence_B_STOP_IDS = [
"place-NEC-1659",
"place-NEC-1768",
"place-NEC-1851",
"place-NEC-1891",
"place-NEC-1919",
"place-NEC-1969",
"place-NEC-2040",
"place-NEC-2108",
]


# "normalizes" route id by aggregating "Red-A" and "Red-B" ids into "Red"
def normalize_custom_route_name(route_id):
return "Red" if route_id in ("Red-A", "Red-B") else route_id
if route_id in ("Red-A", "Red-B"):
return "Red"
if route_id in ("CR-Franklin-A", "CR-Franklin-B"):
return "CR-Franklin"
if route_id in ("CR-Providence-A", "CR-Providence-B"):
return "CR-Providence"
else:
return route_id


# takes a list of route ids
Expand Down Expand Up @@ -71,6 +93,36 @@ def derive_custom_route_name(vehicle):
except Exception:
pass

if default_route_id == "CR-Franklin":
# First try to figure it out by route pattern
try:
route_pattern_name = vehicle["trip"]["route_pattern"]["name"]
return "CR-Franklin-A" if "Forge Park/495" in route_pattern_name else "CR-Franklin-B"
except Exception:
pass
# Second try to figure it out by whether its stop status is on the Ashmont branch
try:
if vehicle["stop"]["id"] in CR_Franklin_A_STOP_IDS:
return "CR-Franklin-A"
return "CR-Franklin-B"
except Exception:
pass

if default_route_id == "CR-Providence":
# First try to figure it out by route pattern
try:
route_pattern_name = vehicle["trip"]["route_pattern"]["name"]
return "CR-Providence-A" if "Providence" in route_pattern_name else "CR-Providence-B"
except Exception:
pass
# Second try to figure it out by whether its stop status is on the Ashmont branch
try:
if vehicle["stop"]["id"] in CR_Providence_A_STOP_IDS:
return "CR-Providence-A"
return "CR-Providence-B"
except Exception:
pass

# If that all fails, RIP
return default_route_id

Expand All @@ -82,6 +134,17 @@ def derive_custom_direction_destinations(route, normalized_route_name, custom_ro
return ["Ashmont", "Alewife"]
else:
return ["Braintree", "Alewife"]
if normalized_route_name == "CR-Franklin":
if custom_route_name == "CR-Franklin-A":
return ["Forge Park/495", "South Station"]
else:
return ["Foxboro", "South Station"]

if normalized_route_name == "CR-Providence":
if custom_route_name == "CR-Providence-A":
return ["Wickford Junction", "South Station"]
else:
return ["Stoughton", "South Station"]
return route["direction_destinations"]


Expand All @@ -104,6 +167,20 @@ def stop_belongs_to_custom_route(stop_id, custom_route_name, normalized_route_na
"place-smmnl",
"place-asmnl",
)
if normalized_route_name != "CR-Franklin":
return True
if custom_route_name == "CR-Franklin-A":
return stop_id not in CR_Franklin_B_STOP_IDS
if custom_route_name == "CR-Franklin-B":
return stop_id not in CR_Franklin_A_STOP_IDS
if normalized_route_name != "CR-Providence":
return True
if normalized_route_name != "CR-Providence":
return True
if custom_route_name == "CR-Providence-A":
return stop_id not in CR_Providence_B_STOP_IDS
if custom_route_name == "CR-Providence-B":
return stop_id not in CR_Providence_A_STOP_IDS
return True


Expand Down
32 changes: 29 additions & 3 deletions src/components/App.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,29 @@
import { useEffect, useLayoutEffect } from 'react';
import Favicon from 'react-favicon';

import { greenLine, orangeLine, redLine, blueLine, mattapanLine } from '../lines';
import {
greenLine,
orangeLine,
redLine,
blueLine,
mattapanLine,
crworcesterLine,
crfairmountLine,
crfitchburgLine,
crkingstonLine,
crLowellLine,
crNeedhamLine,
crGreenbushLine,
crHaverillLine,
crFranklinLine,
crProvidenceLine,
} from '../lines';
import { useMbtaApi } from '../hooks/useMbtaApi';

import { Line } from './Line';
import { Header } from './Header';
import { Footer } from './Footer';
import { LineTabPicker } from './LineTabPicker';
import { SeparatedLineTabPicker } from './SeparatedLineTabPicker';
import { LineStats } from './LineStats/LineStats';
import { setCssVariable } from './util';

Expand All @@ -25,6 +41,16 @@ const lineByTabId: Record<LineName, TLine> = {
Red: redLine,
Blue: blueLine,
Mattapan: mattapanLine,
Worcester: crworcesterLine,
Fairmount: crfairmountLine,
Fitchburg: crfitchburgLine,
Kingston: crkingstonLine,
Lowell: crLowellLine,
Needham: crNeedhamLine,
Greenbush: crGreenbushLine,
Haverhill: crHaverillLine,
Franklin: crFranklinLine,
Providence: crProvidenceLine,
};

export const App: React.FC = () => {
Expand Down Expand Up @@ -80,7 +106,7 @@ export const App: React.FC = () => {
<div className={'selectors'}>
<CategoryTabPicker tabColor={selectedLine.color} />
{api.trainsByRoute && (
<LineTabPicker
<SeparatedLineTabPicker
lines={Object.values(lineByTabId)}
trainsByRoute={api.trainsByRoute}
/>
Expand Down
1 change: 1 addition & 0 deletions src/components/CategoryTabPicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const trainTypes: TrainCategory[] = [
{ key: 'new_vehicles', label: 'New' },
{ key: 'vehicles', label: 'All' },
{ key: 'pride', label: 'Pride' },
{ key: 'heritage', label: 'B&M' },
];

interface CategoryTabPickerProps {
Expand Down
1 change: 1 addition & 0 deletions src/components/Line.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const AGE_WORD_MAP = new Map<VehicleCategory, string>([
['old_vehicles', ' old '],
['vehicles', ' '],
['pride', ' pride '],
['heritage', ' heritage '],
]);

interface LineProps {
Expand Down
58 changes: 58 additions & 0 deletions src/components/SeparatedLineTabPicker.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { Line, Train } from '../types';
import { LineTabPicker } from './LineTabPicker';

interface SeparatedLineTabPickerProps {
lines: Line[];
trainsByRoute: { [key: string]: Train[] };
}

export const SeparatedLineTabPicker: React.FC<SeparatedLineTabPickerProps> = ({
lines,
trainsByRoute,
}) => {
// Separate subway lines from commuter rail lines
const subwayLines = lines.filter(
(line) =>
!line.name.startsWith('cr') &&
![
'Worcester',
'Fairmount',
'Fitchburg',
'Kingston',
'Lowell',
'Needham',
'Greenbush',
'Haverhill',
'Franklin',
'Providence',
].includes(line.name)
);

const commuterRailLines = lines.filter(
(line) =>
line.name.startsWith('cr') ||
[
'Worcester',
'Fairmount',
'Fitchburg',
'Kingston',
'Lowell',
'Needham',
'Greenbush',
'Haverhill',
'Franklin',
'Providence',
].includes(line.name)
);

return (
<div className="separated-line-tabs">
<div className="subway-tabs">
<LineTabPicker lines={subwayLines} trainsByRoute={trainsByRoute} />
</div>
<div className="commuter-rail-tabs">
<LineTabPicker lines={commuterRailLines} trainsByRoute={trainsByRoute} />
</div>
</div>
);
};
6 changes: 6 additions & 0 deletions src/hooks/useMbtaApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,19 @@ const filterPride = (trains: Train[]) => {
return trains.filter((train) => train.isPrideCar);
};

const filterHeritage = (trains: Train[]) => {
return trains.filter((train) => train.isHeritageCar);
};

const filterTrains = (trains: Train[], vehiclesAge: VehicleCategory) => {
if (vehiclesAge === 'new_vehicles') {
return filterNew(trains);
} else if (vehiclesAge === 'old_vehicles') {
return filterOld(trains);
} else if (vehiclesAge === 'pride') {
return filterPride(trains);
} else if (vehiclesAge == 'heritage') {
return filterHeritage(trains);
}
return trains;
};
Expand Down
Loading
Loading