loredata 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/LICENSE +9 -0
  2. package/README.md +119 -0
  3. package/data/breaking-bad/addresses.json +37 -0
  4. package/data/breaking-bad/characters.json +120 -0
  5. package/data/breaking-bad/domains.json +6 -0
  6. package/data/breaking-bad/meta.json +4 -0
  7. package/data/fast-and-furious/addresses.json +28 -0
  8. package/data/fast-and-furious/characters.json +115 -0
  9. package/data/fast-and-furious/domains.json +6 -0
  10. package/data/fast-and-furious/meta.json +4 -0
  11. package/data/friends/addresses.json +34 -0
  12. package/data/friends/characters.json +176 -0
  13. package/data/friends/domains.json +6 -0
  14. package/data/friends/meta.json +1 -0
  15. package/data/game-of-thrones/addresses.json +37 -0
  16. package/data/game-of-thrones/characters.json +270 -0
  17. package/data/game-of-thrones/domains.json +6 -0
  18. package/data/game-of-thrones/meta.json +4 -0
  19. package/data/harry-potter/addresses.json +37 -0
  20. package/data/harry-potter/characters.json +125 -0
  21. package/data/harry-potter/domains.json +6 -0
  22. package/data/harry-potter/meta.json +4 -0
  23. package/data/house-md/addresses.json +32 -0
  24. package/data/house-md/characters.json +213 -0
  25. package/data/house-md/domains.json +6 -0
  26. package/data/house-md/meta.json +1 -0
  27. package/data/lost/addresses.json +31 -0
  28. package/data/lost/characters.json +204 -0
  29. package/data/lost/domains.json +6 -0
  30. package/data/lost/meta.json +1 -0
  31. package/data/matrix/addresses.json +6 -0
  32. package/data/matrix/characters.json +194 -0
  33. package/data/matrix/domains.json +6 -0
  34. package/data/matrix/meta.json +1 -0
  35. package/data/peaky-blinders/addresses.json +26 -0
  36. package/data/peaky-blinders/characters.json +198 -0
  37. package/data/peaky-blinders/domains.json +6 -0
  38. package/data/peaky-blinders/meta.json +1 -0
  39. package/data/sherlock/addresses.json +31 -0
  40. package/data/sherlock/characters.json +184 -0
  41. package/data/sherlock/domains.json +6 -0
  42. package/data/sherlock/meta.json +1 -0
  43. package/data/the-office/addresses.json +30 -0
  44. package/data/the-office/characters.json +244 -0
  45. package/data/the-office/domains.json +6 -0
  46. package/data/the-office/meta.json +4 -0
  47. package/dist/browser.cjs +321 -0
  48. package/dist/browser.cjs.map +1 -0
  49. package/dist/browser.d.cts +11 -0
  50. package/dist/browser.d.ts +11 -0
  51. package/dist/browser.js +288 -0
  52. package/dist/browser.js.map +1 -0
  53. package/dist/cli/cli.cjs +390 -0
  54. package/dist/cli/cli.cjs.map +1 -0
  55. package/dist/cli/cli.d.cts +1 -0
  56. package/dist/cli/cli.d.ts +1 -0
  57. package/dist/cli/cli.js +388 -0
  58. package/dist/cli/cli.js.map +1 -0
  59. package/dist/index.cjs +356 -0
  60. package/dist/index.cjs.map +1 -0
  61. package/dist/index.d.cts +26 -0
  62. package/dist/index.d.ts +26 -0
  63. package/dist/index.js +323 -0
  64. package/dist/index.js.map +1 -0
  65. package/dist/universe-store-DJrm7bP7.d.cts +98 -0
  66. package/dist/universe-store-DJrm7bP7.d.ts +98 -0
  67. package/package.json +77 -0
@@ -0,0 +1,11 @@
1
+ import { U as UniverseData, P as Person } from './universe-store-DJrm7bP7.cjs';
2
+ export { A as Address, a as AddressData, C as CharacterData, b as CharacterEntry, c as CharacterQuery, D as DomainsData, d as UniverseInfo, e as UniverseStore } from './universe-store-DJrm7bP7.cjs';
3
+
4
+ declare function getAvailableIds(): string[];
5
+ declare function loadUniverse(id: string): Promise<UniverseData>;
6
+ declare function loadUniverses(ids: string[]): Promise<UniverseData[]>;
7
+ declare function loadAllUniverses(): Promise<UniverseData[]>;
8
+
9
+ declare function personFromData(universe: UniverseData, seed?: number): Person;
10
+
11
+ export { Person, UniverseData, getAvailableIds, loadAllUniverses, loadUniverse, loadUniverses, personFromData };
@@ -0,0 +1,11 @@
1
+ import { U as UniverseData, P as Person } from './universe-store-DJrm7bP7.js';
2
+ export { A as Address, a as AddressData, C as CharacterData, b as CharacterEntry, c as CharacterQuery, D as DomainsData, d as UniverseInfo, e as UniverseStore } from './universe-store-DJrm7bP7.js';
3
+
4
+ declare function getAvailableIds(): string[];
5
+ declare function loadUniverse(id: string): Promise<UniverseData>;
6
+ declare function loadUniverses(ids: string[]): Promise<UniverseData[]>;
7
+ declare function loadAllUniverses(): Promise<UniverseData[]>;
8
+
9
+ declare function personFromData(universe: UniverseData, seed?: number): Person;
10
+
11
+ export { Person, UniverseData, getAvailableIds, loadAllUniverses, loadUniverse, loadUniverses, personFromData };
@@ -0,0 +1,288 @@
1
+ // src/generators/random.ts
2
+ function createRng(seed) {
3
+ if (seed === void 0) {
4
+ return Math.random;
5
+ }
6
+ let s = seed;
7
+ return function rng() {
8
+ s += 1831565813;
9
+ let z = s;
10
+ z = Math.imul(z ^ z >>> 15, z | 1);
11
+ z ^= z + Math.imul(z ^ z >>> 7, z | 61);
12
+ return ((z ^ z >>> 14) >>> 0) / 4294967296;
13
+ };
14
+ }
15
+ function pickRandom(array, rng) {
16
+ const index = Math.floor(rng() * array.length);
17
+ return array[index];
18
+ }
19
+
20
+ // src/generators/email.ts
21
+ var EmailGenerator = class {
22
+ static generate(firstName, lastName, domains, rng) {
23
+ const domain = pickRandom(domains.emailDomains, rng);
24
+ const first = firstName.toLowerCase();
25
+ const last = lastName.toLowerCase();
26
+ return `${first}.${last}@${domain}`;
27
+ }
28
+ static generateFromUsername(username, domains, rng) {
29
+ const domain = pickRandom(domains.emailDomains, rng);
30
+ return `${username}@${domain}`;
31
+ }
32
+ };
33
+
34
+ // src/generators/phone.ts
35
+ var PhoneGenerator = class {
36
+ static generate(domains, rng) {
37
+ if (domains.phoneEasterEggs && domains.phoneEasterEggs.length > 0 && rng() < 0.2) {
38
+ return pickRandom(domains.phoneEasterEggs, rng);
39
+ }
40
+ const prefix = pickRandom(domains.phonePrefixes, rng);
41
+ const suffix = this.randomDigits(7, rng);
42
+ return `${prefix}-${suffix.slice(0, 3)}-${suffix.slice(3)}`;
43
+ }
44
+ static randomDigits(count, rng) {
45
+ let result = "";
46
+ for (let i = 0; i < count; i++) {
47
+ result += Math.floor(rng() * 10).toString();
48
+ }
49
+ return result;
50
+ }
51
+ };
52
+
53
+ // src/generators/password.ts
54
+ var PasswordGenerator = class {
55
+ static generate(domains, rng) {
56
+ if (domains.passwordEasterEggs && domains.passwordEasterEggs.length > 0 && rng() < 0.3) {
57
+ return pickRandom(domains.passwordEasterEggs, rng);
58
+ }
59
+ return this.randomPassword(12, rng);
60
+ }
61
+ static randomPassword(length, rng) {
62
+ const chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$";
63
+ let result = "";
64
+ for (let i = 0; i < length; i++) {
65
+ result += chars[Math.floor(rng() * chars.length)];
66
+ }
67
+ return result;
68
+ }
69
+ };
70
+
71
+ // src/engine/person-factory.ts
72
+ var PersonFactory = class {
73
+ static build(universe, seed) {
74
+ const rng = createRng(seed);
75
+ const character = pickRandom(universe.characters, rng);
76
+ return this.buildFromCharacter(character, universe, rng);
77
+ }
78
+ static buildByCharacterId(characterId, universe, seed) {
79
+ const character = universe.characters.find((c) => c.id === characterId);
80
+ if (!character) {
81
+ throw new Error(`Character "${characterId}" not found in universe "${universe.id}"`);
82
+ }
83
+ const rng = createRng(seed);
84
+ return this.buildFromCharacter(character, universe, rng);
85
+ }
86
+ static buildFromCharacter(character, universe, rng) {
87
+ const address = character.address ?? pickRandom(universe.addresses, rng);
88
+ const username = pickRandom(character.usernames, rng);
89
+ const domains = character.emailDomain ? { ...universe.domains, emailDomains: [character.emailDomain] } : universe.domains;
90
+ const email = EmailGenerator.generateFromUsername(username, domains, rng);
91
+ const phone = PhoneGenerator.generate(universe.domains, rng);
92
+ const password = PasswordGenerator.generate(universe.domains, rng);
93
+ const quote = pickRandom(character.quotes, rng);
94
+ const avatarName = encodeURIComponent(`${character.firstName} ${character.lastName}`);
95
+ const avatar = `https://ui-avatars.com/api/?name=${avatarName}&background=random`;
96
+ const person = {
97
+ id: crypto.randomUUID(),
98
+ characterId: character.id,
99
+ firstName: character.firstName,
100
+ lastName: character.lastName,
101
+ username,
102
+ email,
103
+ password,
104
+ phone,
105
+ address: {
106
+ street: address.street,
107
+ city: address.city,
108
+ state: address.state ?? "",
109
+ zip: address.zip ?? "",
110
+ country: address.country
111
+ },
112
+ profession: character.profession,
113
+ interests: character.interests,
114
+ quote,
115
+ universe: universe.id,
116
+ universeName: universe.name,
117
+ avatar
118
+ };
119
+ return person;
120
+ }
121
+ };
122
+
123
+ // src/engine/universe-store.ts
124
+ var UniverseStore = class {
125
+ universes;
126
+ characterIndex;
127
+ constructor(universes) {
128
+ this.universes = universes;
129
+ this.characterIndex = this.buildIndex(universes);
130
+ }
131
+ get index() {
132
+ return this.characterIndex;
133
+ }
134
+ getInterests(universeIds) {
135
+ const entries = universeIds && universeIds.length > 0 ? this.characterIndex.filter((e) => universeIds.includes(e.universeId)) : this.characterIndex;
136
+ const interestSet = /* @__PURE__ */ new Set();
137
+ for (const entry of entries) {
138
+ for (const interest of entry.interests) {
139
+ interestSet.add(interest);
140
+ }
141
+ }
142
+ const result = Array.from(interestSet).sort();
143
+ return result;
144
+ }
145
+ getUniverses() {
146
+ const result = this.universes.map((u) => ({
147
+ id: u.id,
148
+ name: u.name,
149
+ characterCount: u.characters.length
150
+ }));
151
+ return result;
152
+ }
153
+ findCharacters(query) {
154
+ let entries = this.characterIndex;
155
+ if (query.universes && query.universes.length > 0) {
156
+ entries = entries.filter((e) => query.universes.includes(e.universeId));
157
+ }
158
+ if (query.name && query.name.trim().length > 0) {
159
+ const needle = query.name.toLowerCase();
160
+ entries = entries.filter((e) => {
161
+ const fullName = `${e.firstName} ${e.lastName}`.toLowerCase();
162
+ return fullName.includes(needle);
163
+ });
164
+ }
165
+ if (query.interests && query.interests.length > 0) {
166
+ const mode = query.interestsMode ?? "or";
167
+ if (mode === "and") {
168
+ entries = entries.filter((e) => query.interests.every((interest) => e.interests.includes(interest)));
169
+ } else {
170
+ entries = entries.filter((e) => query.interests.some((interest) => e.interests.includes(interest)));
171
+ }
172
+ }
173
+ return entries;
174
+ }
175
+ personByCharacterId(characterId, seed) {
176
+ const entry = this.characterIndex.find((e) => e.characterId === characterId);
177
+ if (!entry) {
178
+ throw new Error(`Character "${characterId}" not found in store`);
179
+ }
180
+ const universe = this.universes.find((u) => u.id === entry.universeId);
181
+ if (!universe) {
182
+ throw new Error(`Universe "${entry.universeId}" not found in store`);
183
+ }
184
+ return PersonFactory.buildByCharacterId(characterId, universe, seed);
185
+ }
186
+ generatePersonas(query, count, seed) {
187
+ const matching = this.findCharacters(query);
188
+ if (matching.length === 0) {
189
+ return [];
190
+ }
191
+ const rng = createRng(seed);
192
+ const actualCount = Math.min(count, matching.length);
193
+ const shuffled = [...matching].sort(() => rng() - 0.5);
194
+ const selected = shuffled.slice(0, actualCount);
195
+ const personas = [];
196
+ for (let i = 0; i < selected.length; i++) {
197
+ const entry = selected[i];
198
+ const universe = this.universes.find((u) => u.id === entry.universeId);
199
+ const personSeed = seed !== void 0 ? seed + i : void 0;
200
+ personas.push(PersonFactory.buildByCharacterId(entry.characterId, universe, personSeed));
201
+ }
202
+ return personas;
203
+ }
204
+ buildIndex(universes) {
205
+ const index = [];
206
+ for (const universe of universes) {
207
+ for (const character of universe.characters) {
208
+ const entry = {
209
+ characterId: character.id,
210
+ universeId: universe.id,
211
+ universeName: universe.name,
212
+ firstName: character.firstName,
213
+ lastName: character.lastName,
214
+ interests: character.interests,
215
+ profession: character.profession
216
+ };
217
+ index.push(entry);
218
+ }
219
+ }
220
+ return index;
221
+ }
222
+ };
223
+
224
+ // src/universes/browser-loader.ts
225
+ var metaModules = import.meta.glob("../data/*/meta.json", { eager: false });
226
+ var characterModules = import.meta.glob("../data/*/characters.json", { eager: false });
227
+ var addressModules = import.meta.glob("../data/*/addresses.json", { eager: false });
228
+ var domainModules = import.meta.glob("../data/*/domains.json", { eager: false });
229
+ function extractId(path) {
230
+ const parts = path.split("/");
231
+ return parts[parts.length - 2];
232
+ }
233
+ function getAvailableIds() {
234
+ return Object.keys(metaModules).map(extractId);
235
+ }
236
+ async function loadUniverse(id) {
237
+ const metaPath = `../data/${id}/meta.json`;
238
+ const charactersPath = `../data/${id}/characters.json`;
239
+ const addressesPath = `../data/${id}/addresses.json`;
240
+ const domainsPath = `../data/${id}/domains.json`;
241
+ const metaLoader = metaModules[metaPath];
242
+ const charactersLoader = characterModules[charactersPath];
243
+ const addressesLoader = addressModules[addressesPath];
244
+ const domainsLoader = domainModules[domainsPath];
245
+ if (!metaLoader || !charactersLoader || !addressesLoader || !domainsLoader) {
246
+ throw new Error(`Universe "${id}" not found`);
247
+ }
248
+ const [metaModule, charactersModule, addressesModule, domainsModule] = await Promise.all([
249
+ metaLoader(),
250
+ charactersLoader(),
251
+ addressesLoader(),
252
+ domainsLoader()
253
+ ]);
254
+ const meta = metaModule.default;
255
+ const characters = charactersModule.default;
256
+ const addresses = addressesModule.default;
257
+ const domains = domainsModule.default;
258
+ const universeData = {
259
+ id: meta.id,
260
+ name: meta.name,
261
+ characters,
262
+ addresses,
263
+ domains
264
+ };
265
+ return universeData;
266
+ }
267
+ async function loadUniverses(ids) {
268
+ const result = await Promise.all(ids.map((id) => loadUniverse(id)));
269
+ return result;
270
+ }
271
+ async function loadAllUniverses() {
272
+ const ids = getAvailableIds();
273
+ return loadUniverses(ids);
274
+ }
275
+
276
+ // src/browser.ts
277
+ function personFromData(universe, seed) {
278
+ return PersonFactory.build(universe, seed);
279
+ }
280
+ export {
281
+ UniverseStore,
282
+ getAvailableIds,
283
+ loadAllUniverses,
284
+ loadUniverse,
285
+ loadUniverses,
286
+ personFromData
287
+ };
288
+ //# sourceMappingURL=browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/generators/random.ts","../src/generators/email.ts","../src/generators/phone.ts","../src/generators/password.ts","../src/engine/person-factory.ts","../src/engine/universe-store.ts","../src/universes/browser-loader.ts","../src/browser.ts"],"sourcesContent":["/**\n * Seeded pseudo-random number generator (mulberry32).\n * Returns a function that produces values in [0, 1).\n */\nexport function createRng(seed?: number): () => number {\n\tif (seed === undefined) {\n\t\treturn Math.random;\n\t}\n\n\tlet s = seed;\n\n\treturn function rng(): number {\n\t\ts += 0x6d2b79f5;\n\t\tlet z = s;\n\t\tz = Math.imul(z ^ (z >>> 15), z | 1);\n\t\tz ^= z + Math.imul(z ^ (z >>> 7), z | 61);\n\n\t\treturn ((z ^ (z >>> 14)) >>> 0) / 4294967296;\n\t};\n}\n\nexport function pickRandom<T>(array: T[], rng: () => number): T {\n\tconst index = Math.floor(rng() * array.length);\n\n\treturn array[index];\n}\n","import { pickRandom } from './random';\n\nimport type { DomainsData } from '@/types';\n\nexport class EmailGenerator {\n\tstatic generate(firstName: string, lastName: string, domains: DomainsData, rng: () => number): string {\n\t\tconst domain = pickRandom(domains.emailDomains, rng);\n\t\tconst first = firstName.toLowerCase();\n\t\tconst last = lastName.toLowerCase();\n\n\t\treturn `${first}.${last}@${domain}`;\n\t}\n\n\tstatic generateFromUsername(username: string, domains: DomainsData, rng: () => number): string {\n\t\tconst domain = pickRandom(domains.emailDomains, rng);\n\n\t\treturn `${username}@${domain}`;\n\t}\n}\n","import { pickRandom } from './random';\n\nimport type { DomainsData } from '@/types';\n\nexport class PhoneGenerator {\n\tstatic generate(domains: DomainsData, rng: () => number): string {\n\t\tif (domains.phoneEasterEggs && domains.phoneEasterEggs.length > 0 && rng() < 0.2) {\n\t\t\treturn pickRandom(domains.phoneEasterEggs, rng);\n\t\t}\n\n\t\tconst prefix = pickRandom(domains.phonePrefixes, rng);\n\t\tconst suffix = this.randomDigits(7, rng);\n\n\t\treturn `${prefix}-${suffix.slice(0, 3)}-${suffix.slice(3)}`;\n\t}\n\n\tprivate static randomDigits(count: number, rng: () => number): string {\n\t\tlet result = '';\n\n\t\tfor (let i = 0; i < count; i++) {\n\t\t\tresult += Math.floor(rng() * 10).toString();\n\t\t}\n\n\t\treturn result;\n\t}\n}\n","import { pickRandom } from './random';\n\nimport type { DomainsData } from '@/types';\n\nexport class PasswordGenerator {\n\tstatic generate(domains: DomainsData, rng: () => number): string {\n\t\tif (domains.passwordEasterEggs && domains.passwordEasterEggs.length > 0 && rng() < 0.3) {\n\t\t\treturn pickRandom(domains.passwordEasterEggs, rng);\n\t\t}\n\n\t\treturn this.randomPassword(12, rng);\n\t}\n\n\tprivate static randomPassword(length: number, rng: () => number): string {\n\t\tconst chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$';\n\t\tlet result = '';\n\n\t\tfor (let i = 0; i < length; i++) {\n\t\t\tresult += chars[Math.floor(rng() * chars.length)];\n\t\t}\n\n\t\treturn result;\n\t}\n}\n","import { createRng, pickRandom, EmailGenerator, PhoneGenerator, PasswordGenerator } from '@/generators';\n\nimport type { Person, UniverseData, CharacterData } from '@/types';\n\nexport class PersonFactory {\n\tstatic build(universe: UniverseData, seed?: number): Person {\n\t\tconst rng = createRng(seed);\n\n\t\tconst character = pickRandom(universe.characters, rng);\n\n\t\treturn this.buildFromCharacter(character, universe, rng);\n\t}\n\n\tstatic buildByCharacterId(characterId: string, universe: UniverseData, seed?: number): Person {\n\t\tconst character = universe.characters.find((c) => c.id === characterId);\n\n\t\tif (!character) {\n\t\t\tthrow new Error(`Character \"${characterId}\" not found in universe \"${universe.id}\"`);\n\t\t}\n\n\t\tconst rng = createRng(seed);\n\n\t\treturn this.buildFromCharacter(character, universe, rng);\n\t}\n\n\tprivate static buildFromCharacter(character: CharacterData, universe: UniverseData, rng: () => number): Person {\n\t\tconst address = character.address ?? pickRandom(universe.addresses, rng);\n\n\t\tconst username = pickRandom(character.usernames, rng);\n\n\t\tconst domains = character.emailDomain ? { ...universe.domains, emailDomains: [character.emailDomain] } : universe.domains;\n\n\t\tconst email = EmailGenerator.generateFromUsername(username, domains, rng);\n\t\tconst phone = PhoneGenerator.generate(universe.domains, rng);\n\t\tconst password = PasswordGenerator.generate(universe.domains, rng);\n\t\tconst quote = pickRandom(character.quotes, rng);\n\t\tconst avatarName = encodeURIComponent(`${character.firstName} ${character.lastName}`);\n\t\tconst avatar = `https://ui-avatars.com/api/?name=${avatarName}&background=random`;\n\n\t\tconst person: Person = {\n\t\t\tid: crypto.randomUUID(),\n\t\t\tcharacterId: character.id,\n\t\t\tfirstName: character.firstName,\n\t\t\tlastName: character.lastName,\n\t\t\tusername,\n\t\t\temail,\n\t\t\tpassword,\n\t\t\tphone,\n\t\t\taddress: {\n\t\t\t\tstreet: address.street,\n\t\t\t\tcity: address.city,\n\t\t\t\tstate: address.state ?? '',\n\t\t\t\tzip: address.zip ?? '',\n\t\t\t\tcountry: address.country\n\t\t\t},\n\t\t\tprofession: character.profession,\n\t\t\tinterests: character.interests,\n\t\t\tquote,\n\t\t\tuniverse: universe.id,\n\t\t\tuniverseName: universe.name,\n\t\t\tavatar\n\t\t};\n\n\t\treturn person;\n\t}\n}\n","import { createRng } from '@/generators';\n\nimport { PersonFactory } from './person-factory';\n\nimport type { UniverseData, Person, CharacterEntry, CharacterQuery } from '@/types';\n\nexport class UniverseStore {\n\tprivate universes: UniverseData[];\n\tprivate characterIndex: CharacterEntry[];\n\n\tconstructor(universes: UniverseData[]) {\n\t\tthis.universes = universes;\n\t\tthis.characterIndex = this.buildIndex(universes);\n\t}\n\n\tget index(): CharacterEntry[] {\n\t\treturn this.characterIndex;\n\t}\n\n\tgetInterests(universeIds?: string[]): string[] {\n\t\tconst entries =\n\t\t\tuniverseIds && universeIds.length > 0\n\t\t\t\t? this.characterIndex.filter((e) => universeIds.includes(e.universeId))\n\t\t\t\t: this.characterIndex;\n\n\t\tconst interestSet = new Set<string>();\n\n\t\tfor (const entry of entries) {\n\t\t\tfor (const interest of entry.interests) {\n\t\t\t\tinterestSet.add(interest);\n\t\t\t}\n\t\t}\n\n\t\tconst result = Array.from(interestSet).sort();\n\n\t\treturn result;\n\t}\n\n\tgetUniverses(): { id: string; name: string; characterCount: number }[] {\n\t\tconst result = this.universes.map((u) => ({\n\t\t\tid: u.id,\n\t\t\tname: u.name,\n\t\t\tcharacterCount: u.characters.length\n\t\t}));\n\n\t\treturn result;\n\t}\n\n\tfindCharacters(query: CharacterQuery): CharacterEntry[] {\n\t\tlet entries = this.characterIndex;\n\n\t\tif (query.universes && query.universes.length > 0) {\n\t\t\tentries = entries.filter((e) => query.universes!.includes(e.universeId));\n\t\t}\n\n\t\tif (query.name && query.name.trim().length > 0) {\n\t\t\tconst needle = query.name.toLowerCase();\n\n\t\t\tentries = entries.filter((e) => {\n\t\t\t\tconst fullName = `${e.firstName} ${e.lastName}`.toLowerCase();\n\n\t\t\t\treturn fullName.includes(needle);\n\t\t\t});\n\t\t}\n\n\t\tif (query.interests && query.interests.length > 0) {\n\t\t\tconst mode = query.interestsMode ?? 'or';\n\n\t\t\tif (mode === 'and') {\n\t\t\t\tentries = entries.filter((e) => query.interests!.every((interest) => e.interests.includes(interest)));\n\t\t\t} else {\n\t\t\t\tentries = entries.filter((e) => query.interests!.some((interest) => e.interests.includes(interest)));\n\t\t\t}\n\t\t}\n\n\t\treturn entries;\n\t}\n\n\tpersonByCharacterId(characterId: string, seed?: number): Person {\n\t\tconst entry = this.characterIndex.find((e) => e.characterId === characterId);\n\n\t\tif (!entry) {\n\t\t\tthrow new Error(`Character \"${characterId}\" not found in store`);\n\t\t}\n\n\t\tconst universe = this.universes.find((u) => u.id === entry.universeId);\n\n\t\tif (!universe) {\n\t\t\tthrow new Error(`Universe \"${entry.universeId}\" not found in store`);\n\t\t}\n\n\t\treturn PersonFactory.buildByCharacterId(characterId, universe, seed);\n\t}\n\n\tgeneratePersonas(query: CharacterQuery, count: number, seed?: number): Person[] {\n\t\tconst matching = this.findCharacters(query);\n\n\t\tif (matching.length === 0) {\n\t\t\treturn [];\n\t\t}\n\n\t\tconst rng = createRng(seed);\n\t\tconst actualCount = Math.min(count, matching.length);\n\n\t\tconst shuffled = [...matching].sort(() => rng() - 0.5);\n\t\tconst selected = shuffled.slice(0, actualCount);\n\t\tconst personas: Person[] = [];\n\n\t\tfor (let i = 0; i < selected.length; i++) {\n\t\t\tconst entry = selected[i];\n\t\t\tconst universe = this.universes.find((u) => u.id === entry.universeId)!;\n\t\t\tconst personSeed = seed !== undefined ? seed + i : undefined;\n\n\t\t\tpersonas.push(PersonFactory.buildByCharacterId(entry.characterId, universe, personSeed));\n\t\t}\n\n\t\treturn personas;\n\t}\n\n\tprivate buildIndex(universes: UniverseData[]): CharacterEntry[] {\n\t\tconst index: CharacterEntry[] = [];\n\n\t\tfor (const universe of universes) {\n\t\t\tfor (const character of universe.characters) {\n\t\t\t\tconst entry: CharacterEntry = {\n\t\t\t\t\tcharacterId: character.id,\n\t\t\t\t\tuniverseId: universe.id,\n\t\t\t\t\tuniverseName: universe.name,\n\t\t\t\t\tfirstName: character.firstName,\n\t\t\t\t\tlastName: character.lastName,\n\t\t\t\t\tinterests: character.interests,\n\t\t\t\t\tprofession: character.profession\n\t\t\t\t};\n\n\t\t\t\tindex.push(entry);\n\t\t\t}\n\t\t}\n\n\t\treturn index;\n\t}\n}\n","import type { UniverseData, CharacterData, AddressData, DomainsData } from '@/types';\n\ninterface MetaJson {\n\tid: string;\n\tname: string;\n}\n\nconst metaModules = import.meta.glob('../data/*/meta.json', { eager: false });\nconst characterModules = import.meta.glob('../data/*/characters.json', { eager: false });\nconst addressModules = import.meta.glob('../data/*/addresses.json', { eager: false });\nconst domainModules = import.meta.glob('../data/*/domains.json', { eager: false });\n\nfunction extractId(path: string): string {\n\tconst parts = path.split('/');\n\n\treturn parts[parts.length - 2];\n}\n\nexport function getAvailableIds(): string[] {\n\treturn Object.keys(metaModules).map(extractId);\n}\n\nexport async function loadUniverse(id: string): Promise<UniverseData> {\n\tconst metaPath = `../data/${id}/meta.json`;\n\tconst charactersPath = `../data/${id}/characters.json`;\n\tconst addressesPath = `../data/${id}/addresses.json`;\n\tconst domainsPath = `../data/${id}/domains.json`;\n\n\tconst metaLoader = metaModules[metaPath];\n\tconst charactersLoader = characterModules[charactersPath];\n\tconst addressesLoader = addressModules[addressesPath];\n\tconst domainsLoader = domainModules[domainsPath];\n\n\tif (!metaLoader || !charactersLoader || !addressesLoader || !domainsLoader) {\n\t\tthrow new Error(`Universe \"${id}\" not found`);\n\t}\n\n\tconst [metaModule, charactersModule, addressesModule, domainsModule] = await Promise.all([\n\t\tmetaLoader(),\n\t\tcharactersLoader(),\n\t\taddressesLoader(),\n\t\tdomainsLoader()\n\t]);\n\n\tconst meta = (metaModule as { default: MetaJson }).default;\n\tconst characters = (charactersModule as { default: CharacterData[] }).default;\n\tconst addresses = (addressesModule as { default: AddressData[] }).default;\n\tconst domains = (domainsModule as { default: DomainsData }).default;\n\n\tconst universeData: UniverseData = {\n\t\tid: meta.id,\n\t\tname: meta.name,\n\t\tcharacters,\n\t\taddresses,\n\t\tdomains\n\t};\n\n\treturn universeData;\n}\n\nexport async function loadUniverses(ids: string[]): Promise<UniverseData[]> {\n\tconst result = await Promise.all(ids.map((id) => loadUniverse(id)));\n\n\treturn result;\n}\n\nexport async function loadAllUniverses(): Promise<UniverseData[]> {\n\tconst ids = getAvailableIds();\n\n\treturn loadUniverses(ids);\n}\n","import { PersonFactory } from '@/engine/person-factory';\nimport { UniverseStore } from '@/engine/universe-store';\n\nimport type { Person, UniverseData } from '@/types';\n\nexport { UniverseStore };\nexport { loadUniverse, loadUniverses, loadAllUniverses, getAvailableIds } from '@/universes/browser-loader';\n\nexport function personFromData(universe: UniverseData, seed?: number): Person {\n\treturn PersonFactory.build(universe, seed);\n}\n\nexport type { Person, UniverseInfo } from '@/types';\nexport type { Address, UniverseData, CharacterData, AddressData, DomainsData } from '@/types';\nexport type { CharacterEntry, CharacterQuery } from '@/types';\n"],"mappings":"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","names":[]}