@ak--47/dungeon-master 1.0.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 (66) hide show
  1. package/README.md +518 -0
  2. package/dungeons/array-of-object-lookup-schema.json +327 -0
  3. package/dungeons/array-of-object-lookup.js +220 -0
  4. package/dungeons/ecommerce-schema.json +462 -0
  5. package/dungeons/ecommerce.js +447 -0
  6. package/dungeons/education-schema.json +2409 -0
  7. package/dungeons/education.js +768 -0
  8. package/dungeons/fintech-schema.json +14034 -0
  9. package/dungeons/fintech.js +696 -0
  10. package/dungeons/foobar-schema.json +403 -0
  11. package/dungeons/foobar.js +296 -0
  12. package/dungeons/food-delivery-schema.json +192 -0
  13. package/dungeons/food-delivery.js +602 -0
  14. package/dungeons/food-schema.json +1152 -0
  15. package/dungeons/food.js +754 -0
  16. package/dungeons/gaming-schema.json +1270 -0
  17. package/dungeons/gaming.js +508 -0
  18. package/dungeons/insurance-application-schema.json +204 -0
  19. package/dungeons/insurance-application.js +605 -0
  20. package/dungeons/media-schema.json +906 -0
  21. package/dungeons/media.js +790 -0
  22. package/dungeons/retention-cadence-schema.json +78 -0
  23. package/dungeons/retention-cadence.js +244 -0
  24. package/dungeons/rpg-schema.json +4526 -0
  25. package/dungeons/rpg.js +919 -0
  26. package/dungeons/sanity-schema.json +255 -0
  27. package/dungeons/sanity.js +152 -0
  28. package/dungeons/sass-schema.json +1291 -0
  29. package/dungeons/sass.js +795 -0
  30. package/dungeons/scd-schema.json +919 -0
  31. package/dungeons/scd.js +277 -0
  32. package/dungeons/simple-schema.json +608 -0
  33. package/dungeons/simple.js +285 -0
  34. package/dungeons/simplest-schema.json +1418 -0
  35. package/dungeons/simplest.js +392 -0
  36. package/dungeons/social-schema.json +1118 -0
  37. package/dungeons/social.js +686 -0
  38. package/dungeons/text-generation-schema.json +3096 -0
  39. package/dungeons/text-generation.js +812 -0
  40. package/index.js +567 -0
  41. package/lib/core/config-validator.js +395 -0
  42. package/lib/core/context.js +204 -0
  43. package/lib/core/dungeon-loader.js +337 -0
  44. package/lib/core/storage.js +379 -0
  45. package/lib/generators/adspend.js +132 -0
  46. package/lib/generators/events.js +271 -0
  47. package/lib/generators/funnels.js +407 -0
  48. package/lib/generators/mirror.js +167 -0
  49. package/lib/generators/product-lookup.js +262 -0
  50. package/lib/generators/product-names.js +195 -0
  51. package/lib/generators/profiles.js +93 -0
  52. package/lib/generators/scd.js +124 -0
  53. package/lib/generators/text.js +1192 -0
  54. package/lib/orchestrators/mixpanel-sender.js +266 -0
  55. package/lib/orchestrators/user-loop.js +335 -0
  56. package/lib/templates/abbreviated.d.ts +169 -0
  57. package/lib/templates/defaults.js +1405 -0
  58. package/lib/templates/phrases.js +2526 -0
  59. package/lib/templates/schema.d.ts +173 -0
  60. package/lib/templates/soup-presets.js +188 -0
  61. package/lib/utils/function-registry.js +302 -0
  62. package/lib/utils/json-evaluator.js +172 -0
  63. package/lib/utils/logger.js +34 -0
  64. package/lib/utils/utils.js +1490 -0
  65. package/package.json +89 -0
  66. package/types.d.ts +865 -0
@@ -0,0 +1,508 @@
1
+
2
+ import dayjs from "dayjs";
3
+ import utc from "dayjs/plugin/utc.js";
4
+ import "dotenv/config";
5
+ import * as u from "../lib/utils/utils.js";
6
+ import * as v from "ak-tools";
7
+
8
+ const SEED = "my-seed";
9
+ dayjs.extend(utc);
10
+ const chance = u.initChance(SEED);
11
+ const num_users = 12_000;
12
+ const days = 180;
13
+
14
+ /** @typedef {import("../types.d.ts").Dungeon} Config */
15
+
16
+ /*
17
+ * ═══════════════════════════════════════════════════════════════════════════════
18
+ * DATASET OVERVIEW
19
+ * ═══════════════════════════════════════════════════════════════════════════════
20
+ *
21
+ * QuestForge — A D&D-inspired action RPG where players create characters,
22
+ * join parties, embark on quests, fight bosses, and level up. Think Baldur's
23
+ * Gate meets a mobile RPG with in-game purchases and seasonal content.
24
+ *
25
+ * CORE USER LOOP:
26
+ * Players install the app, create a character (race + class + alignment),
27
+ * and join a party. They then cycle through quests — starting quests,
28
+ * engaging in gameplay (attacks, defenses, enemy defeats), completing quests
29
+ * for gold rewards, fighting bosses, and leveling up. In-game purchases
30
+ * (gold, gems, weapons, armor, boosts) monetize the experience.
31
+ *
32
+ * SCALE: 12,000 users, ~1.08M events, 180 days
33
+ *
34
+ * KEY DIMENSIONS:
35
+ * - Platform: Mobile, Xbox, Playstation, Switch, Web
36
+ * - Game mode: Single Player vs Multiplayer (biased toward Multiplayer)
37
+ * - Character: 9 races, 12 classes, 9 alignments, 13 backgrounds
38
+ * - Quests: 5 types, 4 difficulties, 5 locations
39
+ * - Experiment: fast leveling / tension economy / free trial with A/B/C/Control
40
+ *
41
+ * FUNNELS:
42
+ * 1. Onboarding: app install → character creation → join party (80% conversion)
43
+ * 2. Quest loop: start quest → gameplay summary → complete quest (99% conversion)
44
+ */
45
+
46
+ /*
47
+ * ═══════════════════════════════════════════════════════════════════════════════
48
+ * ANALYTICS HOOKS
49
+ * ═══════════════════════════════════════════════════════════════════════════════
50
+ *
51
+ * This dungeon has 3 deliberate patterns engineered via hooks:
52
+ *
53
+ * ───────────────────────────────────────────────────────────────────────────────
54
+ * 1. GOLD SCALING BY LEVEL (event hook)
55
+ * ───────────────────────────────────────────────────────────────────────────────
56
+ *
57
+ * PATTERN: On "complete quest" events, the quest reward (gold) is multiplied by
58
+ * (1 + level * 0.1), so a level-10 player earns 2x gold and a level-20 player
59
+ * earns 3x gold compared to level-1.
60
+ *
61
+ * HOW TO FIND IT IN MIXPANEL:
62
+ * - Report type: Insights
63
+ * - Event: "complete quest"
64
+ * - Measure: Average of "quest reward (gold)"
65
+ * - Breakdown: "level at end"
66
+ * - Expected: Linear increase — level 1 ≈ 55 gold, level 10 ≈ 110 gold,
67
+ * level 20 ≈ 165 gold. Clear positive correlation between level and reward.
68
+ *
69
+ * ───────────────────────────────────────────────────────────────────────────────
70
+ * 2. WHALE PURCHASES (event hook)
71
+ * ───────────────────────────────────────────────────────────────────────────────
72
+ *
73
+ * PATTERN: ~33% of users (determined by first character of user_id hash) are
74
+ * "whales" who spend 1.8x on in-game purchases and are tagged is_whale: true.
75
+ *
76
+ * HOW TO FIND IT IN MIXPANEL:
77
+ *
78
+ * Report 1: Whale vs Normal Purchase Amounts
79
+ * - Report type: Insights
80
+ * - Event: "in-game purchase"
81
+ * - Measure: Average of "purchase amount"
82
+ * - Breakdown: "is_whale"
83
+ * - Expected: is_whale=true shows ~1.8x higher avg purchase amount than
84
+ * is_whale=false (e.g., ~18 vs ~10)
85
+ *
86
+ * Report 2: Revenue Concentration
87
+ * - Report type: Insights
88
+ * - Event: "in-game purchase"
89
+ * - Measure: Sum of "purchase amount"
90
+ * - Breakdown: "is_whale"
91
+ * - Expected: ~33% of users (whales) contribute disproportionate total revenue
92
+ *
93
+ * ───────────────────────────────────────────────────────────────────────────────
94
+ * 3. ALIGNMENT ARCHETYPE (user hook)
95
+ * ───────────────────────────────────────────────────────────────────────────────
96
+ *
97
+ * PATTERN: User profiles are enriched with an "archetype" property based on
98
+ * alignment. Evil alignments → "villain", Good alignments → "hero", others → "neutral".
99
+ *
100
+ * HOW TO FIND IT IN MIXPANEL:
101
+ *
102
+ * Report 1: Archetype Distribution
103
+ * - Report type: Insights
104
+ * - Event: Any event (e.g., "complete quest")
105
+ * - Measure: Total unique users
106
+ * - Breakdown: User profile "archetype"
107
+ * - Expected: Three segments — "hero" (~22%), "villain" (~22%), "neutral" (~56%)
108
+ * matching the 2/9, 2/9, 5/9 alignment split
109
+ *
110
+ * Report 2: Archetype Behavior Comparison
111
+ * - Report type: Insights
112
+ * - Event: "fight boss"
113
+ * - Measure: Total events per user
114
+ * - Breakdown: User profile "archetype"
115
+ * - Expected: All three archetypes should show similar event volumes
116
+ * (archetype doesn't affect gameplay — just a profiling hook)
117
+ *
118
+ * ═══════════════════════════════════════════════════════════════════════════════
119
+ * EXPECTED METRICS SUMMARY
120
+ * ═══════════════════════════════════════════════════════════════════════════════
121
+ *
122
+ * Hook | Metric | Baseline | Hook Effect | Ratio
123
+ * ────────────────────────|─────────────────────────|──────────|──────────────|──────
124
+ * Gold Scaling | Avg gold at level 1 | ~55 | ~55 | 1.0x
125
+ * Gold Scaling | Avg gold at level 10 | ~55 | ~110 | 2.0x
126
+ * Gold Scaling | Avg gold at level 20 | ~55 | ~165 | 3.0x
127
+ * Whale Purchases | Avg purchase (whale) | ~10 | ~18 | 1.8x
128
+ * Whale Purchases | Revenue share (whale) | ~33% | >50% | disprop.
129
+ * Alignment Archetype | Hero users | — | ~22% | 2/9
130
+ * Alignment Archetype | Villain users | — | ~22% | 2/9
131
+ * Alignment Archetype | Neutral users | — | ~56% | 5/9
132
+ *
133
+ * ═══════════════════════════════════════════════════════════════════════════════
134
+ * ADVANCED ANALYSIS IDEAS
135
+ * ═══════════════════════════════════════════════════════════════════════════════
136
+ *
137
+ * 1. Gold Economy Analysis: Plot avg gold earned by level AND quest difficulty.
138
+ * Do Legendary quests at high levels create outsized gold rewards?
139
+ *
140
+ * 2. Whale Segmentation: Cross-reference is_whale with platform and game mode.
141
+ * Are whales concentrated on mobile? Do multiplayer whales spend more?
142
+ *
143
+ * 3. Archetype × Class Matrix: Do certain class/archetype combos correlate
144
+ * with higher boss fight rates or quest completion?
145
+ *
146
+ * 4. Experiment Impact: Compare "fast leveling" vs "tension economy" vs
147
+ * "free trial" on purchase amounts, level progression, and retention.
148
+ *
149
+ * 5. Quest Difficulty Funnel: How does quest difficulty affect completion
150
+ * rate, death count, and hint/boost usage? Is "Legendary" too hard?
151
+ *
152
+ * ═══════════════════════════════════════════════════════════════════════════════
153
+ */
154
+
155
+ /** @type {Config} */
156
+ const config = {
157
+ token: "",
158
+ seed: "i am gamer face",
159
+ numDays: days,
160
+ numEvents: num_users * 90,
161
+ numUsers: num_users,
162
+ hasAnonIds: false,
163
+ hasSessionIds: false,
164
+ format: "json",
165
+ alsoInferFunnels: true,
166
+ hasLocation: true,
167
+ hasAndroidDevices: false,
168
+ hasIOSDevices: false,
169
+ hasDesktopDevices: false,
170
+ hasBrowser: false,
171
+ hasCampaigns: false,
172
+ isAnonymous: false,
173
+ hasAdSpend: false,
174
+ percentUsersBornInDataset: 25,
175
+
176
+ hasAvatar: true,
177
+
178
+ batchSize: 2_500_000,
179
+ concurrency: 1,
180
+ writeToDisk: false,
181
+ funnels: [
182
+ {
183
+ "sequence": ["app install", "character creation", "join party"],
184
+ "isFirstFunnel": true,
185
+ "conversionRate": 0.8,
186
+ "timeToConvert": .25,
187
+ },
188
+ {
189
+ "sequence": ["start quest", "gameplay summary", "complete quest"],
190
+ conversionRate: 0.99,
191
+ timeToConvert: 1,
192
+ props: {
193
+ "quest type": [
194
+ "Rescue",
195
+ "Retrieve",
196
+ "Explore",
197
+ "Destroy",
198
+ "Investigate",
199
+ ],
200
+ "quest difficulty": [
201
+ "Easy",
202
+ "Medium",
203
+ "Hard",
204
+ "Legendary",
205
+ ],
206
+ "quest location": [
207
+ "Forest",
208
+ "Dungeon",
209
+ "Mountain",
210
+ "City",
211
+ "Desert",
212
+ ]
213
+ }
214
+ },
215
+ ],
216
+ events: [
217
+ { event: "app install", weight: 10, isFirstEvent: true },
218
+ {
219
+ event: "character creation",
220
+ weight: 2,
221
+ properties: {
222
+ mode: ["fast", "slow", "template"],
223
+ },
224
+ },
225
+ {
226
+ event: "join party",
227
+ weight: 8,
228
+ properties: {
229
+ "party size": u.weighNumRange(1, 6),
230
+ "party leader": [
231
+ "Bard",
232
+ "Cleric",
233
+ "Fighter",
234
+ "Rogue",
235
+ "Wizard",
236
+ "Paladin",
237
+ "Ranger",
238
+ "Sorcerer",
239
+ "Warlock",
240
+ ],
241
+ },
242
+ },
243
+ {
244
+ event: "start quest",
245
+ weight: 12,
246
+ properties: {
247
+ "quest type": [
248
+ "Rescue",
249
+ "Retrieve",
250
+ "Explore",
251
+ "Destroy",
252
+ "Investigate",
253
+ ],
254
+ "quest difficulty": [
255
+ "Easy",
256
+ "Medium",
257
+ "Hard",
258
+ "Legendary",
259
+ ],
260
+ "quest location": [
261
+ "Forest",
262
+ "Dungeon",
263
+ "Mountain",
264
+ "City",
265
+ "Desert",
266
+ ],
267
+ "party size": u.weighNumRange(1, 6),
268
+ "used hint": u.pickAWinner(["yes", "no"], 0.3),
269
+ "used boost": u.pickAWinner(["yes", "no"], 0.2),
270
+ "level at start": u.weighNumRange(1, 20),
271
+ },
272
+ },
273
+ {
274
+ event: "complete quest",
275
+ weight: 12,
276
+ properties: {
277
+ "completion time (mins)": u.weighNumRange(5, 120, 1, 30),
278
+ "quest reward (gold)": u.weighNumRange(10, 500, 1, 100),
279
+ "quest success": u.pickAWinner(["yes", "no"], 0.9),
280
+ "used hint": u.pickAWinner(["yes", "no"], 0.3),
281
+ "used boost": u.pickAWinner(["yes", "no"], 0.2),
282
+ "number of deaths": u.weighNumRange(0, 5, 1, 2),
283
+ "level at start": u.weighNumRange(1, 20),
284
+ "level at end": u.weighNumRange(1, 20),
285
+ },
286
+ },
287
+ {
288
+ "event": "gameplay summary",
289
+ "weight": 14,
290
+ "properties": {
291
+ "# enemies defeated": u.weighNumRange(0, 100),
292
+ "# respawns": u.weighNumRange(0, 10, 5),
293
+ "# attacks": u.weighNumRange(0, 100, 6, 12),
294
+ "# gold found": u.weighNumRange(0, 1000),
295
+ }
296
+ },
297
+ {
298
+ "event": "in-game purchase",
299
+ "weight": 2,
300
+ "properties": {
301
+ "purchase type": [
302
+ "Gold",
303
+ "Gems",
304
+ "Items: Weapons",
305
+ "Items: Armor",
306
+ "Items: Potions",
307
+ "Items: Scrolls",
308
+ "Boosts",
309
+ "Currency",
310
+ ],
311
+ "purchase amount": u.weighNumRange(1, 50, 1, 20),
312
+ }
313
+ },
314
+ {
315
+ event: "fight boss",
316
+ weight: 3,
317
+ properties: {
318
+ "boss type": [
319
+ "Dragon",
320
+ "Demon",
321
+ "Lich",
322
+ "Vampire",
323
+ "Beholder",
324
+ ],
325
+ "boss level": u.weighNumRange(10, 20),
326
+ "boss difficulty": [
327
+ "Hard",
328
+ "Legendary",
329
+ "Impossible",
330
+ ],
331
+ "fight duration (mins)": u.weighNumRange(1, 60),
332
+
333
+ },
334
+ },
335
+ {
336
+ event: "level up",
337
+ weight: 1,
338
+ properties: {
339
+ "new abilities": [
340
+ "Attack",
341
+ "Spell",
342
+ "Feat",
343
+ "Skill",
344
+ ],
345
+ },
346
+ },
347
+ {
348
+ event: "attack",
349
+ weight: 5,
350
+ properties: {
351
+ generic_prop: ["foo", "bar", "baz", "qux"],
352
+ }
353
+ },
354
+ {
355
+ event: "defend",
356
+ weight: 3,
357
+ properties: {
358
+ generic_prop: ["foo", "bar", "baz", "qux"],
359
+ }
360
+ },
361
+ ],
362
+ superProps: {
363
+ platform: [
364
+ "Mobile",
365
+ "Xbox",
366
+ "Playstation",
367
+ "Switch",
368
+ "Web"
369
+ ],
370
+ "game mode": u.pickAWinner([
371
+ "Single Player",
372
+ "Multiplayer",
373
+ ], 1),
374
+ language: [
375
+ "English",
376
+ "Spanish",
377
+ "French",
378
+ "German",
379
+ "Japanese",
380
+ "Korean",
381
+ "Chinese",
382
+ ],
383
+
384
+ },
385
+ scdProps: {
386
+ // "subscription MRR" : {
387
+ // "frequency": "week",
388
+ // "type": "number",
389
+ // values: u.weighNumRange(0, 250, 1, 200),
390
+ // timing: "fixed",
391
+ // max: 250,
392
+ // }
393
+ },
394
+ userProps: {
395
+ experiment: [
396
+ "fast leveling",
397
+ "tension economy",
398
+ "free trial",
399
+ ],
400
+ variant: ["A", "B", "C", "Control"],
401
+
402
+ race: [
403
+ "Human",
404
+ "Elf",
405
+ "Dwarf",
406
+ "Halfling",
407
+ "Dragonborn",
408
+ "Gnome",
409
+ "Half-Elf",
410
+ "Half-Orc",
411
+ "Tiefling",
412
+ ],
413
+ class: [
414
+ "Barbarian",
415
+ "Bard",
416
+ "Cleric",
417
+ "Druid",
418
+ "Fighter",
419
+ "Monk",
420
+ "Paladin",
421
+ "Ranger",
422
+ "Rogue",
423
+ "Sorcerer",
424
+ "Warlock",
425
+ "Wizard",
426
+ ],
427
+ alignment: [
428
+ "Lawful Good",
429
+ "Neutral Good",
430
+ "Chaotic Good",
431
+ "Lawful Neutral",
432
+ "True Neutral",
433
+ "Chaotic Neutral",
434
+ "Lawful Evil",
435
+ "Neutral Evil",
436
+ "Chaotic Evil",
437
+ ],
438
+ level: u.weighNumRange(1, 20),
439
+ background: [
440
+ "Acolyte",
441
+ "Charlatan",
442
+ "Criminal",
443
+ "Entertainer",
444
+ "Folk Hero",
445
+ "Guild Artisan",
446
+ "Hermit",
447
+ "Noble",
448
+ "Outlander",
449
+ "Sage",
450
+ "Sailor",
451
+ "Soldier",
452
+ "Urchin",
453
+ ],
454
+ "subscription MRR": u.weighNumRange(0, 250, 1, 200)
455
+ },
456
+ // HOOK: 3 patterns — gold scaling by level, whale purchases, alignment archetype
457
+ hook: function (record, type, meta) {
458
+
459
+ if (type === "event") {
460
+ // Pattern 1: Higher-level players earn more gold and defeat more enemies
461
+ if (record.event === "complete quest") {
462
+ const level = record["level at end"] || 1;
463
+ record["quest reward (gold)"] = Math.round((record["quest reward (gold)"] || 50) * (1 + level * 0.1));
464
+ }
465
+
466
+ // Pattern 2: In-game purchases are bigger for "free trial" experiment users
467
+ if (record.event === "in-game purchase") {
468
+ // We don't have profile here, so use a hash-based approach
469
+ const uid = record.user_id || record.distinct_id || "";
470
+ if (uid.charCodeAt(0) % 3 === 0) {
471
+ record["purchase amount"] = Math.round((record["purchase amount"] || 10) * 1.8);
472
+ record.is_whale = true;
473
+ }
474
+ }
475
+ }
476
+
477
+ if (type === "user") {
478
+ // Pattern 3: Chaotic Evil players get a "villain" tag; Lawful Good get "hero"
479
+ if (record.alignment === "Chaotic Evil" || record.alignment === "Neutral Evil") {
480
+ record.archetype = "villain";
481
+ } else if (record.alignment === "Lawful Good" || record.alignment === "Neutral Good") {
482
+ record.archetype = "hero";
483
+ } else {
484
+ record.archetype = "neutral";
485
+ }
486
+ }
487
+
488
+ if (type === "funnel-post") {
489
+
490
+ }
491
+
492
+ if (type === "funnel-pre") {
493
+
494
+ }
495
+
496
+ if (type === "scd") {
497
+
498
+ }
499
+
500
+ if (type === "everything") {
501
+
502
+ }
503
+
504
+ return record;
505
+ }
506
+ };
507
+
508
+ export default config;