Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | 5x 434x 5x 513x 5x 513x 513x 5x 80x 80x 80x 80x 290x 5x 29x 29x 27x 27x 27x 15x 100x 15x 14x 181x 181x 14x 167x 14x 9x 9x 144x 513x 9x 9x 5x 5x | import { Building, BUILDINGS } from "../data/buildings";
const normalizeLocationText = (value: string): string =>
value
.toLowerCase()
.replaceAll(/[^a-z0-9]+/g, " ")
.trim();
const escapeRegExp = (value: string): string =>
value.replaceAll(/[.*+?^${}()|[\]\\]/g, String.raw`\$&`);
const containsAlias = (normalizedLocation: string, alias: string): boolean => {
const aliasPattern = new RegExp(String.raw`\b${escapeRegExp(alias)}\b`);
return aliasPattern.test(normalizedLocation);
};
const BUILDING_ALIAS_INDEX = BUILDINGS.map((building) => {
const normalizedName = normalizeLocationText(building.name);
const simplifiedName = normalizedName
.replaceAll(/\b(building|complex|annex|library|wing|center|centre)\b/g, " ")
.replaceAll(/\s+/g, " ")
.trim();
const aliases = new Set<string>([
normalizeLocationText(building.id),
normalizedName,
simplifiedName,
...building.aliases.map(normalizeLocationText),
]);
return {
building,
aliases: [...aliases].filter((alias) => alias.length >= 2),
};
});
export const findBuildingFromLocationText = (
locationText: string,
): Building | null => {
const trimmed = locationText.trim();
if (!trimmed) return null;
const upper = trimmed.toUpperCase();
const roomCodeMatch = /\b([A-Z]{1,3})[-\s]?[A-Z]?\d{2,4}[A-Z]?\b/.exec(upper);
if (roomCodeMatch?.[1]) {
const byRoomCode = BUILDINGS.find(
(building) => building.id.toUpperCase() === roomCodeMatch[1],
);
if (byRoomCode) return byRoomCode;
}
const byBuildingId = BUILDINGS.find((building) => {
const id = building.id.toUpperCase();
if (id.length === 1) {
return new RegExp(String.raw`\b${id}[-\s]?\d{2,4}[A-Z]?\b`).test(upper);
}
return new RegExp(String.raw`\b${id}(?=\b|[-\s])`).test(upper);
});
if (byBuildingId) return byBuildingId;
const normalizedLocation = normalizeLocationText(trimmed);
const aliasMatches = BUILDING_ALIAS_INDEX.flatMap(({ building, aliases }) =>
aliases
.filter((alias) => containsAlias(normalizedLocation, alias))
.map((alias) => ({ building, score: alias.length })),
);
if (aliasMatches.length === 0) return null;
aliasMatches.sort((a, b) => b.score - a.score);
return aliasMatches[0].building;
};
|