@ak--47/dungeon-master 1.0.0 → 1.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 (103) hide show
  1. package/README.md +7 -7
  2. package/dungeons/technical/ad-spend-schema.json +128 -0
  3. package/dungeons/technical/ad-spend.js +116 -0
  4. package/dungeons/technical/anonymous-users-schema.json +91 -0
  5. package/dungeons/technical/anonymous-users.js +102 -0
  6. package/dungeons/technical/array-of-object-lookup-schema.json +191 -0
  7. package/dungeons/{array-of-object-lookup.js → technical/array-of-object-lookup.js} +11 -4
  8. package/dungeons/technical/experiments-schema.json +197 -0
  9. package/dungeons/technical/experiments.js +168 -0
  10. package/dungeons/technical/foobar-schema.json +362 -0
  11. package/dungeons/{foobar.js → technical/foobar.js} +2 -2
  12. package/dungeons/technical/group-analytics-schema.json +149 -0
  13. package/dungeons/technical/group-analytics.js +151 -0
  14. package/dungeons/technical/mirror-strategies-schema.json +84 -0
  15. package/dungeons/technical/mirror-strategies.js +126 -0
  16. package/dungeons/technical/nested-objects-schema.json +145 -0
  17. package/dungeons/technical/nested-objects.js +207 -0
  18. package/dungeons/technical/retention-cadence-schema.json +37 -0
  19. package/dungeons/{retention-cadence.js → technical/retention-cadence.js} +1 -1
  20. package/dungeons/technical/sanity-schema.json +185 -0
  21. package/dungeons/{sanity.js → technical/sanity.js} +3 -2
  22. package/dungeons/technical/scale-test-schema.json +70 -0
  23. package/dungeons/technical/scale-test.js +90 -0
  24. package/dungeons/technical/scd-schema.json +270 -0
  25. package/dungeons/{scd.js → technical/scd.js} +19 -10
  26. package/dungeons/technical/simple-schema.json +278 -0
  27. package/dungeons/{simple.js → technical/simple.js} +6 -6
  28. package/dungeons/technical/simplest-schema.json +635 -0
  29. package/dungeons/{simplest.js → technical/simplest.js} +6 -6
  30. package/dungeons/technical/text-generation-schema.json +1059 -0
  31. package/dungeons/{text-generation.js → technical/text-generation.js} +23 -9
  32. package/dungeons/vertical/community-schema.json +557 -0
  33. package/dungeons/vertical/community.js +788 -0
  34. package/dungeons/vertical/devtools-schema.json +580 -0
  35. package/dungeons/vertical/devtools.js +837 -0
  36. package/dungeons/vertical/ecommerce-schema.json +586 -0
  37. package/dungeons/{ecommerce.js → vertical/ecommerce.js} +34 -3
  38. package/dungeons/vertical/education-schema.json +697 -0
  39. package/dungeons/{education.js → vertical/education.js} +54 -36
  40. package/dungeons/vertical/fintech-schema.json +563 -0
  41. package/dungeons/{fintech.js → vertical/fintech.js} +91 -53
  42. package/dungeons/vertical/fitness-schema.json +508 -0
  43. package/dungeons/vertical/fitness.js +802 -0
  44. package/dungeons/vertical/food-delivery-schema.json +678 -0
  45. package/dungeons/{food.js → vertical/food-delivery.js} +51 -23
  46. package/dungeons/vertical/gaming-schema.json +394 -0
  47. package/dungeons/{gaming.js → vertical/gaming.js} +9 -7
  48. package/dungeons/vertical/healthcare-schema.json +527 -0
  49. package/dungeons/vertical/healthcare.js +769 -0
  50. package/dungeons/vertical/insurance-application-schema.json +466 -0
  51. package/dungeons/{insurance-application.js → vertical/insurance-application.js} +33 -29
  52. package/dungeons/vertical/logistics-schema.json +552 -0
  53. package/dungeons/vertical/logistics.js +793 -0
  54. package/dungeons/vertical/marketplace-schema.json +511 -0
  55. package/dungeons/vertical/marketplace.js +844 -0
  56. package/dungeons/vertical/media-schema.json +787 -0
  57. package/dungeons/{media.js → vertical/media.js} +94 -16
  58. package/dungeons/vertical/rpg-schema.json +654 -0
  59. package/dungeons/{rpg.js → vertical/rpg.js} +78 -57
  60. package/dungeons/vertical/sass-schema.json +653 -0
  61. package/dungeons/{sass.js → vertical/sass.js} +49 -23
  62. package/dungeons/vertical/social-schema.json +552 -0
  63. package/dungeons/{social.js → vertical/social.js} +60 -14
  64. package/dungeons/vertical/travel-schema.json +558 -0
  65. package/dungeons/vertical/travel.js +736 -0
  66. package/index.js +19 -15
  67. package/lib/core/config-validator.js +286 -1
  68. package/lib/core/context.js +7 -5
  69. package/lib/generators/adspend.js +3 -3
  70. package/lib/generators/events.js +141 -14
  71. package/lib/generators/funnels.js +67 -7
  72. package/lib/generators/text.js +2 -2
  73. package/lib/orchestrators/user-loop.js +441 -22
  74. package/lib/templates/soup-presets.js +2 -2
  75. package/lib/utils/utils.js +4 -5
  76. package/package.json +4 -3
  77. package/scripts/dungeon-to-json.mjs +163 -0
  78. package/scripts/extract-dungeon-schema.mjs +297 -0
  79. package/scripts/json-to-dungeon.mjs +200 -0
  80. package/scripts/run-dungeon.mjs +76 -0
  81. package/scripts/run-many.mjs +118 -0
  82. package/scripts/verify-runner.mjs +42 -0
  83. package/types.d.ts +313 -1
  84. package/dungeons/array-of-object-lookup-schema.json +0 -327
  85. package/dungeons/ecommerce-schema.json +0 -462
  86. package/dungeons/education-schema.json +0 -2409
  87. package/dungeons/fintech-schema.json +0 -14034
  88. package/dungeons/foobar-schema.json +0 -403
  89. package/dungeons/food-delivery-schema.json +0 -192
  90. package/dungeons/food-delivery.js +0 -602
  91. package/dungeons/food-schema.json +0 -1152
  92. package/dungeons/gaming-schema.json +0 -1270
  93. package/dungeons/insurance-application-schema.json +0 -204
  94. package/dungeons/media-schema.json +0 -906
  95. package/dungeons/retention-cadence-schema.json +0 -78
  96. package/dungeons/rpg-schema.json +0 -4526
  97. package/dungeons/sanity-schema.json +0 -255
  98. package/dungeons/sass-schema.json +0 -1291
  99. package/dungeons/scd-schema.json +0 -919
  100. package/dungeons/simple-schema.json +0 -608
  101. package/dungeons/simplest-schema.json +0 -1418
  102. package/dungeons/social-schema.json +0 -1118
  103. package/dungeons/text-generation-schema.json +0 -3096
@@ -1,7 +1,7 @@
1
1
  import dayjs from "dayjs";
2
2
  import utc from "dayjs/plugin/utc.js";
3
3
  import "dotenv/config";
4
- import * as u from "../lib/utils/utils.js";
4
+ import * as u from "../../lib/utils/utils.js";
5
5
  import * as v from "ak-tools";
6
6
 
7
7
  const SEED = "harness-gaming";
@@ -211,7 +211,7 @@ const config = {
211
211
  timeToConvert: 2,
212
212
  weight: 4,
213
213
  props: {
214
- "dungeon_id": u.pickAWinner(dungeonIds),
214
+ "dungeon_id": dungeonIds,
215
215
  "difficulty": ["Easy", "Medium", "Hard", "Deadly"],
216
216
  }
217
217
  },
@@ -221,7 +221,7 @@ const config = {
221
221
  conversionRate: 55,
222
222
  timeToConvert: 3,
223
223
  weight: 3,
224
- props: { "quest_id": u.pickAWinner(questIds) },
224
+ props: { "quest_id": questIds },
225
225
  },
226
226
  {
227
227
  // Preparation before dungeon: inspect + search for strategic explorer hook
@@ -274,14 +274,14 @@ const config = {
274
274
  weight: 2,
275
275
  properties: {
276
276
  "completion_time_mins": u.weighNumRange(3, 25, 0.8, 10),
277
- "skipped": u.pickAWinner([true, false], 0.15),
277
+ "skipped": [false, false, false, false, false, false, true],
278
278
  }
279
279
  },
280
280
  {
281
281
  event: "quest accepted",
282
282
  weight: 15,
283
283
  properties: {
284
- "quest_id": u.pickAWinner(questIds),
284
+ "quest_id": questIds,
285
285
  "quest_type": [
286
286
  "Main Story",
287
287
  "Side Quest",
@@ -296,7 +296,7 @@ const config = {
296
296
  event: "quest objective completed",
297
297
  weight: 12,
298
298
  properties: {
299
- "quest_id": u.pickAWinner(questIds),
299
+ "quest_id": questIds,
300
300
  "objective_number": u.weighNumRange(1, 5),
301
301
  }
302
302
  },
@@ -304,16 +304,18 @@ const config = {
304
304
  event: "quest turned in",
305
305
  weight: 10,
306
306
  properties: {
307
- "quest_id": u.pickAWinner(questIds),
307
+ "quest_id": questIds,
308
308
  "reward_gold": u.weighNumRange(10, 500, 0.5, 100),
309
309
  "reward_xp": u.weighNumRange(50, 2000, 0.5, 500),
310
+ "compass_user": [false],
311
+ "subscriber_advantage": ["Free"],
310
312
  }
311
313
  },
312
314
  {
313
315
  event: "enter dungeon",
314
316
  weight: 18,
315
317
  properties: {
316
- "dungeon_id": u.pickAWinner(dungeonIds),
318
+ "dungeon_id": dungeonIds,
317
319
  "difficulty": ["Easy", "Medium", "Hard", "Deadly"],
318
320
  "party_size": u.weighNumRange(1, 5),
319
321
  }
@@ -322,9 +324,12 @@ const config = {
322
324
  event: "exit dungeon",
323
325
  weight: 14,
324
326
  properties: {
325
- "dungeon_id": u.pickAWinner(dungeonIds),
327
+ "dungeon_id": dungeonIds,
326
328
  "time_spent_mins": u.weighNumRange(5, 120, 0.6, 30),
327
329
  "completion_status": ["completed", "abandoned", "died"],
330
+ "strategic_explorer": [false],
331
+ "legendary_weapon_equipped": [false],
332
+ "subscriber_advantage": ["Free"],
328
333
  }
329
334
  },
330
335
  {
@@ -340,6 +345,10 @@ const config = {
340
345
  "Rare Artifact"
341
346
  ],
342
347
  "treasure_value": u.weighNumRange(5, 1000, 1.2, 50),
348
+ "legendary_drop": [false],
349
+ "strategic_explorer": [false],
350
+ "subscriber_advantage": ["Free"],
351
+ "elite_bonus": [false],
343
352
  }
344
353
  },
345
354
  {
@@ -354,7 +363,10 @@ const config = {
354
363
  "Friendly Fire"
355
364
  ],
356
365
  "player_level": u.weighNumRange(1, 50),
357
- "resurrection_used": u.pickAWinner([true, false], 0.25),
366
+ "resurrection_used": [false, false, false, true],
367
+ "cursed_week": [false],
368
+ "near_death_survival": [false],
369
+ "subscriber_advantage": ["Free"],
358
370
  }
359
371
  },
360
372
  {
@@ -369,7 +381,7 @@ const config = {
369
381
  event: "item purchased",
370
382
  weight: 11,
371
383
  properties: {
372
- "item_id": u.pickAWinner(itemIds),
384
+ "item_id": itemIds,
373
385
  "item_type": [
374
386
  "Weapon",
375
387
  "Armor",
@@ -386,7 +398,7 @@ const config = {
386
398
  event: "item sold",
387
399
  weight: 7,
388
400
  properties: {
389
- "item_id": u.pickAWinner(itemIds),
401
+ "item_id": itemIds,
390
402
  "item_type": [
391
403
  "Weapon",
392
404
  "Armor",
@@ -409,8 +421,9 @@ const config = {
409
421
  "Cosmetic Bundle",
410
422
  "Season Pass"
411
423
  ],
412
- "price_usd": u.pickAWinner([4.99, 9.99, 19.99, 49.99, 99.99]),
424
+ "price_usd": [4.99, 9.99, 19.99, 49.99, 99.99],
413
425
  "payment_method": ["Credit Card", "PayPal", "Apple Pay", "Google Pay"],
426
+ "lucky_charm_effect": [false],
414
427
  }
415
428
  },
416
429
  {
@@ -457,14 +470,14 @@ const config = {
457
470
  "Quest Location",
458
471
  "Town Square"
459
472
  ],
460
- "clue_found": u.pickAWinner([true, false], 0.6),
473
+ "clue_found": [false, false, true, true, true],
461
474
  }
462
475
  },
463
476
  {
464
477
  event: "use item",
465
478
  weight: 14,
466
479
  properties: {
467
- "item_id": u.pickAWinner(itemIds),
480
+ "item_id": itemIds,
468
481
  "item_type": [
469
482
  "Health Potion",
470
483
  "Mana Potion",
@@ -497,7 +510,11 @@ const config = {
497
510
  weight: 18,
498
511
  properties: {
499
512
  "outcome": ["Victory", "Defeat", "Fled"],
500
- "loot_gained": u.pickAWinner([true, false], 0.7),
513
+ "loot_gained": [false, false, false, true, true, true, true, true, true, true],
514
+ "legendary_weapon_equipped": [false],
515
+ "subscriber_advantage": ["Free"],
516
+ "near_death_survival": [false],
517
+ "guild_member_retained": [false],
501
518
  }
502
519
  }
503
520
  ],
@@ -516,7 +533,7 @@ const config = {
516
533
  "High",
517
534
  "Ultra"
518
535
  ],
519
- subscription_tier: u.pickAWinner(["Free", "Free", "Free", "Premium", "Elite"]),
536
+ subscription_tier: ["Free", "Free", "Free", "Premium", "Elite"],
520
537
  },
521
538
 
522
539
  scdProps: {},
@@ -585,18 +602,16 @@ const config = {
585
602
  if (EVENT_TIME.isAfter(CURSED_WEEK_START) && EVENT_TIME.isBefore(CURSED_WEEK_END)) {
586
603
  // 50% chance to inject a death event
587
604
  if (chance.bool({ likelihood: 30 })) {
588
- const deathEvent = {
589
- event: "player death",
590
- time: record.time,
591
- user_id: record.user_id,
592
- cause_of_death: "Curse",
593
- player_level: chance.integer({ min: 1, max: 50 }),
594
- resurrection_used: chance.bool({ likelihood: 80 }), // More res usage during curse
595
- cursed_week: true,
596
- };
597
- // Return death event instead sometimes
605
+ // Return death event instead sometimes (clone from current record for schema)
598
606
  if (chance.bool({ likelihood: 50 })) {
599
- return deathEvent;
607
+ return {
608
+ ...record,
609
+ event: "player death",
610
+ cause_of_death: "Curse",
611
+ player_level: chance.integer({ min: 1, max: 50 }),
612
+ resurrection_used: chance.bool({ likelihood: 80 }), // More res usage during curse
613
+ cursed_week: true,
614
+ };
600
615
  }
601
616
  }
602
617
  }
@@ -715,9 +730,8 @@ const config = {
715
730
  // Add extra quest completions for compass users
716
731
  if (chance.bool({ likelihood: 40 })) {
717
732
  const extraQuest = {
718
- event: "quest turned in",
733
+ ...event,
719
734
  time: eventTime.add(chance.integer({ min: 10, max: 120 }), 'minutes').toISOString(),
720
- user_id: event.user_id,
721
735
  quest_id: chance.pickone(questIds),
722
736
  reward_gold: chance.integer({ min: 100, max: 500 }),
723
737
  reward_xp: chance.integer({ min: 500, max: 2000 }),
@@ -742,20 +756,23 @@ const config = {
742
756
 
743
757
  // Add additional purchase events (higher LTV)
744
758
  if (event.event === "item purchased" && chance.bool({ likelihood: 35 })) {
745
- const extraPurchase = {
746
- event: "real money purchase",
747
- time: eventTime.add(chance.integer({ min: 1, max: 3 }), 'days').toISOString(),
748
- user_id: event.user_id,
749
- product: chance.pickone([
750
- "Premium Currency (5000)",
751
- "Legendary Weapon Chest",
752
- "Season Pass"
753
- ]),
754
- price_usd: chance.pickone([19.99, 49.99, 99.99]),
755
- payment_method: chance.pickone(["Credit Card", "PayPal"]),
756
- lucky_charm_effect: true,
757
- };
758
- userEvents.splice(idx + 1, 0, extraPurchase);
759
+ const purchaseTemplate = userEvents.find(e => e.event === "real money purchase");
760
+ if (purchaseTemplate) {
761
+ const extraPurchase = {
762
+ ...purchaseTemplate,
763
+ time: eventTime.add(chance.integer({ min: 1, max: 3 }), 'days').toISOString(),
764
+ user_id: event.user_id,
765
+ product: chance.pickone([
766
+ "Premium Currency (5000)",
767
+ "Legendary Weapon Chest",
768
+ "Season Pass"
769
+ ]),
770
+ price_usd: chance.pickone([19.99, 49.99, 99.99]),
771
+ payment_method: chance.pickone(["Credit Card", "PayPal"]),
772
+ lucky_charm_effect: true,
773
+ };
774
+ userEvents.splice(idx + 1, 0, extraPurchase);
775
+ }
759
776
  }
760
777
  }
761
778
 
@@ -863,17 +880,20 @@ const config = {
863
880
  // Elite users get bonus engagement events
864
881
  if (isElite && Math.random() * 100 < 15) {
865
882
  if (event.event === "quest turned in" || event.event === "exit dungeon") {
866
- const treasureTypes = ["Rare Artifact", "Gold", "Weapon", "Armor"];
867
- const bonusEvent = {
868
- event: "find treasure",
869
- time: eventTime.add(Math.floor(Math.random() * 26) + 5, 'minutes').toISOString(),
870
- user_id: event.user_id,
871
- treasure_type: treasureTypes[Math.floor(Math.random() * treasureTypes.length)],
872
- treasure_value: Math.floor(Math.random() * 601) + 200,
873
- subscriber_advantage: "Elite",
874
- elite_bonus: true,
875
- };
876
- userEvents.splice(idx + 1, 0, bonusEvent);
883
+ const treasureTemplate = userEvents.find(e => e.event === "find treasure");
884
+ if (treasureTemplate) {
885
+ const treasureTypes = ["Rare Artifact", "Gold", "Weapon", "Armor"];
886
+ const bonusEvent = {
887
+ ...treasureTemplate,
888
+ time: eventTime.add(Math.floor(Math.random() * 26) + 5, 'minutes').toISOString(),
889
+ user_id: event.user_id,
890
+ treasure_type: treasureTypes[Math.floor(Math.random() * treasureTypes.length)],
891
+ treasure_value: Math.floor(Math.random() * 601) + 200,
892
+ subscriber_advantage: "Elite",
893
+ elite_bonus: true,
894
+ };
895
+ userEvents.splice(idx + 1, 0, bonusEvent);
896
+ }
877
897
  }
878
898
  }
879
899
  }
@@ -898,9 +918,10 @@ const config = {
898
918
  } else if (joinedGuildEarly) {
899
919
  // Add extra engagement events for retained users
900
920
  const lastEvent = userEvents[userEvents.length - 1];
901
- if (lastEvent && chance.bool({ likelihood: 60 })) {
921
+ const combatTemplate = userEvents.find(e => e.event === "combat completed");
922
+ if (lastEvent && combatTemplate && chance.bool({ likelihood: 60 })) {
902
923
  const retentionEvent = {
903
- event: "combat completed",
924
+ ...combatTemplate,
904
925
  time: dayjs(lastEvent.time).add(chance.integer({ min: 1, max: 5 }), 'days').toISOString(),
905
926
  user_id: lastEvent.user_id,
906
927
  outcome: "Victory",