Lab
Flyweight
type SeatSpec = { row: string; number: number; zone: string };
// The arena's zones: what a ticket costs and the colour the map draws.
const zones: Record<string, { price: number; color: string }> = {
floor: { price: 120, color: 'red' },
lower: { price: 85, color: 'blue' },
upper: { price: 40, color: 'green' },
};
// Everything the map draws for one seat's zone. Each seat makes its own.
type ZoneStyle = { zone: string; price: number; color: string; held: boolean };
type Seat = { row: string; number: number; style: ZoneStyle };
function zoneStyle(zone: string): ZoneStyle {
if (!Object.hasOwn(zones, zone)) throw new Error(`unknown zone: ${zone}`);
const { price, color } = zones[zone]!;
return { zone, price, color, held: false };
}
function buildSeatMap(specs: SeatSpec[]): Seat[] {
return specs.map((spec) => ({
row: spec.row,
number: spec.number,
style: zoneStyle(spec.zone),
}));
}
// Hold one seat for a customer at the box office.
function holdSeat(seats: Seat[], row: string, number: number): boolean {
const seat = seats.find((s) => s.row === row && s.number === number);
if (!seat || seat.style.held) return false;
seat.style.held = true;
return true;
}
function drawSeat(seat: Seat): string {
const { zone, price, color } = seat.style;
const held = seat.style.held ? ' held' : '';
return `${seat.row}${seat.number} ${zone} $${price} ${color}${held}`;
}