wren/lost-property Public Public: anyone can read this; nobody can change it.

workbenchthis machine
Files d66e67826a76bd71f7b0790b198ae93f73fe1614
55 lines · 2.2 KB · ~630 tok Raw History
1
/**
2
 * The curatorial rules: pure functions, no I/O, no randomness. Everything a
3
 * plaque says about an object — its catalogue number, its vitrine, its
4
 * condition — is derived only from the object's id and the description its
5
 * loser gave, so the same item always reads the same way.
6
 */
7
8
export const VITRINES: readonly string[] = [
9
  "Outerwear and Umbrellas",
10
  "Keys and Fastenings",
11
  "Spectacles and Lenses",
12
  "Small Electronics",
13
  "Jewellery and Adornment",
14
  "Papers and Correspondence",
15
  "Children's Effects",
16
  "Miscellanea",
17
];
18
19
// Checked in order; the first match wins. Anything that matches nothing
20
// goes to Miscellanea, the last vitrine.
21
const KEYWORDS: readonly [RegExp, number][] = [
22
  [/\b(umbrellas?|coats?|jackets?|gloves?|scarves?|scarfs?|hats?|mittens?)\b/i, 0],
23
  [/\b(keys?|padlocks?|keyrings?|locks?)\b/i, 1],
24
  [/\b(glasses|spectacles|sunglasses|lenses?)\b/i, 2],
25
  [/\b(phones?|chargers?|laptops?|tablets?|earbuds?|headphones?|cameras?|cables?|airpods?)\b/i, 3],
26
  [/\b(rings?|necklaces?|bracelets?|earrings?|watches?|brooches?)\b/i, 4],
27
  [/\b(books?|letters?|notebooks?|diaries|diary|papers?|envelopes?|postcards?)\b/i, 5],
28
  [/\b(toys?|teddy|teddies|dolls?|dummies|dummy|pacifiers?)\b/i, 6],
29
];
30
31
export function vitrineOf(description: string): number {
32
  for (const [pattern, index] of KEYWORDS) if (pattern.test(description)) return index;
33
  return VITRINES.length - 1;
34
}
35
36
const CONDITIONS: readonly string[] = [
37
  "Wear consistent with ordinary use.",
38
  "Good condition; minor surface wear.",
39
  "Handled; edges softened with use.",
40
  "Condition at time of loss not recorded.",
41
  "As described by the finder; not further examined.",
42
  "Stable condition; no active deterioration noted.",
43
];
44
45
export function conditionOf(id: number): string {
46
  return CONDITIONS[id % CONDITIONS.length]!;
47
}
48
49
// A museum accession number: LP, the year it entered the collection, and
50
// its sequence within the collection — not within that year, since this
51
// museum is smaller than that distinction is worth.
52
export function catalogueNumber(id: number, createdAt: string): string {
53
  const year = createdAt.slice(0, 4);
54
  return `LP ${year}.${String(id).padStart(4, "0")}`;
55
}
↑↓ navigate ↵ open esc close
↑↓ navigate ↵ open esc close

Keyboard shortcuts