import { readFileSync, writeFileSync } from 'fs'; import { dirname, join } from 'path'; import { fileURLToPath } from 'url'; const __dirname = dirname(fileURLToPath(import.meta.url)); const root = join(__dirname, '..'); const snippetPath = join(root, 'scripts/_npc_name_arrays_snippet.sql'); const snippet = readFileSync(snippetPath, 'utf8'); const decl = snippet .split('\n') .filter((l) => l.includes('text[] :=')) .join('\n'); const n8 = [ [1, 'Maren Thistlewood'], [2, 'Finn Marlow'], [3, 'Asha Kentwell'], [4, 'Halric Morrow'], [5, 'Wynn Cartwright'], [6, 'Orin Aldgate'], [7, 'Osbert Waynwood'], [8, 'Liora Selwyn'], ]; const n926 = [ [9, 'npc.brandric_thacker.v1', 'Brandric Thacker'], [10, 'npc.conrad_pitwright.v1', 'Conrad Pitwright'], [11, 'npc.nessa_bramble.v1', 'Nessa Bramble'], [12, 'npc.torin_marshwick.v1', 'Torin Marshwick'], [13, 'npc.renulf_broadmere.v1', 'Renulf Broadmere'], [14, 'npc.kael_ironwright.v1', 'Kael Ironwright'], [15, 'npc.edmund_cinderwell.v1', 'Edmund Cinderwell'], [16, 'npc.aelith_northgate.v1', 'Aelith Northgate'], [17, 'npc.dorian_hawke.v1', 'Dorian Hawke'], [18, 'npc.mariel_starling.v1', 'Mariel Starling'], [19, 'npc.milo_ropewalk.v1', 'Milo Ropewalk'], [20, 'npc.lissa_harcourt.v1', 'Lissa Harcourt'], [21, 'npc.jasper_kindling.v1', 'Jasper Kindling'], [22, 'npc.kess_wiley.v1', 'Kess Wiley'], [23, 'npc.aldwin_relicton.v1', 'Aldwin Relicton'], [24, 'npc.torvik_grimstad.v1', 'Torvik Grimstad'], [25, 'npc.morna_fenwick.v1', 'Morna Fenwick'], [26, 'npc.morah_ellis.v1', 'Morah Ellis'], ]; const n27108 = [ [27, 'Sera Whitcomb'], [28, 'Bram Ashcombe'], [29, 'Nils Copperton'], [30, 'Mara Tinwell'], [31, 'Agnes Stillwater'], [32, 'Rodrick Cantrell'], [33, 'Wulfric Strand'], [34, 'Jada Boltwright'], [35, 'Alaric Motlow'], [36, 'Percival Pike'], [37, 'Eadric Ashenford'], [38, 'Yoric Scarn'], [39, 'Rillian Hereward'], [40, 'Tove Millerson'], [41, 'Gareth Grantham'], [42, 'Renulf Sackville'], [43, 'Bernard Lukin'], [44, 'Aldwin Grimston'], [45, 'Edmund Edgerton'], [46, 'Crispin Aylesford'], [47, 'Brunhild Flint'], [48, 'Oren Starward'], [49, 'Simon Spirewell'], [50, 'Hugh Comstock'], [51, 'Yves Portier'], [52, 'Cedric Brinewell'], [53, 'Osmund Salter'], [54, 'Rhys Reedman'], [55, 'Godfrey Middleton'], [56, 'Wystan Postlethwaite'], [57, 'Ivo Ironside'], [58, 'Roland Rivett'], [59, 'Lucan Forrest'], [60, 'Alaric Boghurst'], [61, 'Norbert Fenwick'], [62, 'Miles Myreham'], [63, 'Cuthbert Reed'], [64, 'Wendel Marsham'], [65, 'Sigurd Dunstan'], [66, 'Silas Siltwell'], [67, 'Peter Sanderson'], [68, 'Griselda Holt'], [69, 'Bartholomew Howe'], [70, 'Baldwin Bonewright'], [71, 'Cole Aldridge'], [72, 'Shadrach Morrow'], [73, 'Rowan Mistwell'], [74, 'Fergus Fogarty'], [75, 'Dewi Tarrant'], [76, 'Vespasian Vale'], [77, 'Hugo Holloway'], [78, 'Meredith Stowe'], [79, 'Roderick Rotherham'], [80, 'Beatrice Boghurst'], [81, 'Ashford Hale'], [82, 'Cyril Cinders'], [83, 'Emrys Emberly'], [84, 'Alicia Ashford'], [85, 'Thorne Hawthorn'], [86, 'Brian Briarton'], [87, 'Rowan Rootwell'], [88, 'Leofric Leaford'], [89, 'Galfrid Gales'], [90, 'Wynstan Windham'], [91, 'Gustav Merseburg'], [92, 'Blaise Brissot'], [93, 'Archibald Frostwick'], [94, 'Rhys Rimer'], [95, 'Horace Hoarwell'], [96, 'Isolde Ismay'], [97, 'Solomon Sunderland'], [98, 'Clifford Cliffeton'], [99, 'Craig Cragwell'], [100, 'Dustin Harwell'], [101, 'Marshall Fordham'], [102, 'Rivers Trent'], [103, 'Bridges Ballard'], [104, 'Sterling Brook'], [105, 'Sevrin Veilcourt'], [106, 'Sterling Starwell'], [107, 'Neville Nevett'], [108, 'Vera Veilhart'], ]; function esc(s) { return s.replace(/'/g, "''"); } function caseWhen(pairs, col) { return pairs.map(([id, v]) => ` WHEN ${id} THEN '${esc(v)}'`).join('\n'); } function caseWhen926() { const k = n926.map(([id, key]) => ` WHEN ${id} THEN '${esc(key)}'`).join('\n'); const n = n926.map(([id, , name]) => ` WHEN ${id} THEN '${esc(name)}'`).join('\n'); return { k, n }; } const c926 = caseWhen926(); const sql = `-- Medieval-style personal names for NPCs; generic elders/medics/stalls use per-id keys and pools (frontend/npcGeneratedNames.ts). DO $$ DECLARE ${decl} BEGIN UPDATE public.npcs SET name_key = 'npc.elder.byid.' || id::text || '.v1', name = elder_names[1 + ((id * 3) % 20)] WHERE name_key = 'npc.town_speaker_generic.v1'; UPDATE public.npcs SET name_key = 'npc.medic.byid.' || id::text || '.v1', name = medic_names[1 + ((id * 7) % 40)] WHERE name_key = 'npc.roadside_medic_generic.v1'; UPDATE public.npcs SET name_key = 'npc.stall.byid.' || id::text || '.v1', name = stall_names[1 + ((id * 13) % 112)] WHERE name_key = 'npc.stall_vendor_generic.v1'; END $$; UPDATE public.npcs SET name = v.n FROM (VALUES ('npc.capital.merchant_clerk.v1', 'Hugh Pennington'), ('npc.capital.armorer.v1', 'Raoul d''Aubigny'), ('npc.capital.smith.v1', 'Gilles Ferron'), ('npc.capital.jeweler.v1', 'Ysabel Tremaine'), ('npc.capital.bounty_agent_a.v1', 'Roderick Vaughn'), ('npc.capital.bounty_agent_b.v1', 'Matteo Fabbri'), ('npc.capital.elder.v1', 'Anselm Corwyn'), ('npc.capital.healer.v1', 'Clothilde Mercier'), ('npc.capital.second_armorer.v1', 'Bertrand Hale'), ('npc.capital.second_jeweler.v1', 'Eleonore Rivard') ) AS v(k, n) WHERE public.npcs.name_key = v.k; UPDATE public.npcs SET name = CASE id ${caseWhen(n8, 'name')} END WHERE id BETWEEN 1 AND 8; UPDATE public.npcs SET name_key = CASE id ${c926.k} END, name = CASE id ${c926.n} END WHERE id BETWEEN 9 AND 27; `; // Fix: WHERE id BETWEEN 9 AND 26 not 27 const sqlFixed = sql.replace('WHERE id BETWEEN 9 AND 27', 'WHERE id BETWEEN 9 AND 26'); const part27 = `UPDATE public.npcs SET name = CASE id ${caseWhen(n27108, 'name')} END WHERE id BETWEEN 27 AND 108; `; const out = sqlFixed + '\n' + part27; writeFileSync(join(root, 'backend/migrations/000034_npc_medieval_names.sql'), out); console.log('Wrote 000034_npc_medieval_names.sql');