Lab
Lazy initialization
type Sheet = { id: number; species: string };
// The night's care-sheet export: still syncing when the desk opens.
let exportReady = false;
// The recipe: each word of a species name → the ids of its sheets.
function buildIndex(sheets: Sheet[]): Map<string, number[]> {
if (!exportReady) throw new Error('export still syncing');
const index = new Map<string, number[]>();
for (const sheet of sheets) {
for (const word of sheet.species.toLowerCase().split(' ')) {
index.set(word, [...(index.get(word) ?? []), sheet.id]);
}
}
return index;
}
// One center's care sheets. The lookup waits for the first lookup.
class CareSheets {
builds = 0;
private sheets: Sheet[];
private index: Map<string, number[]> | undefined;
constructor(sheets: Sheet[]) {
this.sheets = sheets;
}
browse(): Sheet[] {
return this.sheets;
}
lookup(word: string): number[] {
this.index ??= this.build();
return this.index.get(word) ?? [];
}
private build(): Map<string, number[]> {
this.builds++;
return buildIndex(this.sheets);
}
}
const center = new CareSheets([
{ id: 1, species: 'Red fox' },
{ id: 2, species: 'River otter' },
{ id: 3, species: 'Barn owl' },
{ id: 4, species: 'Hedgehog' },
]);
function attempt(word: string): string {
try {
return `${word}: [${center.lookup(word).join(', ')}]`;
} catch (error) {
return `${word}: ${(error as Error).message}`;
}
}
console.log(`opened: builds=${center.builds}`);
const browsed = center.browse();
console.log(`browse: ${browsed.length} sheets, builds=${center.builds}`);
const first = attempt('fox');
console.log(`${first}, builds=${center.builds}`);
exportReady = true; // the export finishes syncing
const second = attempt('fox');
console.log(`${second}, builds=${center.builds}`);
const third = attempt('owl');
console.log(`${third}, builds=${center.builds}`);
TODO
Visual to come