Lab
Bridge
// minutes: how long until the train leaves; below zero, it has already left.
type Departure = { destination: string; platform: number; minutes: number };
// Checker plumbing, you don't need to edit this: the cases build trains with it.
function train(destination: string, platform: number, minutes: number): Departure {
return { destination, platform, minutes };
}
// Today: one function per display, each with its own copy of the rules.
function boardNextTrains(departures: Departure[]): string {
const due = departures
.filter((d) => d.minutes >= 0)
.sort((a, b) => a.minutes - b.minutes)
.slice(0, 3);
const rows = due.map((d) => {
const when = d.minutes === 0 ? 'DUE' : `${d.minutes} MIN`;
return `${d.destination.toUpperCase()} P${d.platform} ${when}`;
});
return `NEXT TRAINS: ${rows.length ? rows.join(' | ') : '--'}`;
}
// Copied from the board's function for the announcer, then edited.
function announceNextTrains(departures: Departure[]): string {
const due = [...departures].sort((a, b) => a.minutes - b.minutes).slice(0, 3);
const rows = due.map((d) => {
const when = d.minutes === 0 ? 'now' : `in ${d.minutes} minutes`;
return `The ${d.destination} train leaves platform ${d.platform} ${when}`;
});
return rows.length ? `Next trains. ${rows.join('. ')}.` : 'Next trains. No trains are due.';
}
// What every display can show: one departure, and a screen around the rows.
interface Display {
departure(destination: string, platform: number, minutes: number): string;
screen(title: string, rows: string[]): string;
}
// The LED board: capitals, and DUE for a train leaving now.
class LedBoard implements Display {
departure(destination: string, platform: number, minutes: number): string {
return ''; // not written yet
}
screen(title: string, rows: string[]): string {
return ''; // not written yet
}
}
// The announcer: a sentence per train, read aloud.
class Announcer implements Display {
departure(destination: string, platform: number, minutes: number): string {
return ''; // not written yet
}
screen(title: string, rows: string[]): string {
return ''; // not written yet
}
}
// The split the station asked for, half done: NextTrains holds a display,
// but still calls the announcer's old function, whatever display it holds.
class NextTrains {
private readonly display: Display;
constructor(display: Display) {
this.display = display;
}
show(departures: Departure[]): string {
return announceNextTrains(departures);
}
}