// Worcester Line stop ID mappings (18 stops from South Station to Worcester)
export const WORCESTER_LINE_STOPS = {
"south-station": "place-sstat",
"back-bay": "place-bbsta",
lansdowne: "place-WML-0025",
"boston-landing": "place-WML-0035",
newtonville: "place-WML-0081",
"west-newton": "place-WML-0091",
auburndale: "place-WML-0102",
"wellesley-farms": "place-WML-0125",
"wellesley-hills": "place-WML-0135",
"wellesley-square": "place-WML-0147",
"natick-center": "place-WML-0177",
"west-natick": "place-WML-0199",
framingham: "place-WML-0214",
ashland: "place-WML-0252",
southborough: "place-WML-0274",
westborough: "place-WML-0340",
grafton: "place-WML-0364",
worcester: "place-WML-0442",
} as const;
export type StopSlug = keyof typeof WORCESTER_LINE_STOPS;
export const STOP_NAMES: Record<string, string> = {
"place-sstat": "South Station",
"place-bbsta": "Back Bay",
"place-WML-0025": "Lansdowne",
"place-WML-0035": "Boston Landing",
"place-WML-0081": "Newtonville",
"place-WML-0091": "West Newton",
"place-WML-0102": "Auburndale",
"place-WML-0125": "Wellesley Farms",
"place-WML-0135": "Wellesley Hills",
"place-WML-0147": "Wellesley Square",
"place-WML-0177": "Natick Center",
"place-WML-0199": "West Natick",
"place-WML-0214": "Framingham",
"place-WML-0252": "Ashland",
"place-WML-0274": "Southborough",
"place-WML-0340": "Westborough",
"place-WML-0364": "Grafton",
"place-WML-0442": "Worcester",
};
// List of all valid stop IDs for validation
const VALID_STOP_IDS = new Set<string>(Object.values(WORCESTER_LINE_STOPS));
/**
* Resolves a user-provided stop identifier to an MBTA stop ID.
* Accepts: slug ("south-station"), name ("South Station"), or ID ("place-sstat")
*/
export function resolveStopId(input: string): string | null {
// Check if it's already a valid stop ID
if (input.startsWith("place-") && VALID_STOP_IDS.has(input)) {
return input;
}
// Try slug lookup (normalize: lowercase, spaces to hyphens)
const normalized = input.toLowerCase().replace(/\s+/g, "-");
const bySlug = WORCESTER_LINE_STOPS[normalized as StopSlug];
if (bySlug) {
return bySlug;
}
// Try matching against stop names (case-insensitive)
const lowerInput = input.toLowerCase();
for (const [stopId, name] of Object.entries(STOP_NAMES)) {
if (name.toLowerCase() === lowerInput) {
return stopId;
}
}
return null;
}
/**
* Get a formatted list of all available stops for error messages
*/
export function getAvailableStopsText(): string {
return Object.values(STOP_NAMES).join(", ");
}