@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
 
6
6
  const SEED = "harness-fintech";
7
7
  dayjs.extend(utc);
@@ -221,7 +221,7 @@ const config = {
221
221
  weight: 1,
222
222
  isFirstEvent: true,
223
223
  properties: {
224
- "account_type": u.pickAWinner(["personal", "business", "personal"]),
224
+ "account_type": ["personal", "business", "personal"],
225
225
  "signup_channel": ["app", "web", "referral", "branch"],
226
226
  }
227
227
  },
@@ -231,6 +231,7 @@ const config = {
231
231
  properties: {
232
232
  "session_duration_sec": u.weighNumRange(10, 600, 0.3, 60),
233
233
  "pages_viewed": u.weighNumRange(1, 15, 0.5, 3),
234
+ "month_end_anxiety": [false],
234
235
  }
235
236
  },
236
237
  {
@@ -239,6 +240,7 @@ const config = {
239
240
  properties: {
240
241
  "account_balance": u.weighNumRange(0, 50000, 0.8, 2500),
241
242
  "account_type": ["checking", "savings", "investment"],
243
+ "month_end_check": [false],
242
244
  }
243
245
  },
244
246
  {
@@ -249,6 +251,8 @@ const config = {
249
251
  "amount": u.weighNumRange(1, 5000, 0.3, 50),
250
252
  "merchant_category": ["grocery", "restaurant", "gas", "retail", "online", "subscription", "utilities"],
251
253
  "payment_method": ["debit", "credit", "contactless", "online"],
254
+ "payday": [false],
255
+ "fraud_sequence": [false],
252
256
  }
253
257
  },
254
258
  {
@@ -258,6 +262,7 @@ const config = {
258
262
  "transfer_type": ["internal", "external", "p2p", "wire"],
259
263
  "amount": u.weighNumRange(10, 10000, 0.3, 200),
260
264
  "recipient_type": ["friend", "family", "business", "self"],
265
+ "post_payday_spending": [false],
261
266
  }
262
267
  },
263
268
  {
@@ -266,7 +271,9 @@ const config = {
266
271
  properties: {
267
272
  "bill_type": ["rent", "utilities", "phone", "insurance", "subscription", "loan_payment"],
268
273
  "amount": u.weighNumRange(20, 3000, 0.5, 150),
269
- "auto_pay": u.pickAWinner([true, false], 0.4),
274
+ "auto_pay": [false, false, false, true, true],
275
+ "missed_payment": [false],
276
+ "manual_payment": [false],
270
277
  }
271
278
  },
272
279
  {
@@ -292,6 +299,7 @@ const config = {
292
299
  "goal_type": ["emergency", "vacation", "car", "home", "education", "retirement"],
293
300
  "target_amount": u.weighNumRange(500, 50000, 0.3, 5000),
294
301
  "monthly_contribution": u.weighNumRange(25, 2000, 0.5, 200),
302
+ "budget_discipline": [false],
295
303
  }
296
304
  },
297
305
  {
@@ -300,7 +308,9 @@ const config = {
300
308
  properties: {
301
309
  "investment_type": ["stocks", "etf", "crypto", "bonds", "mutual_fund"],
302
310
  "amount": u.weighNumRange(10, 10000, 0.3, 250),
303
- "action": u.pickAWinner(["buy", "sell", "buy"]),
311
+ "action": ["buy", "sell", "buy"],
312
+ "premium_returns": [false],
313
+ "budget_discipline": [false],
304
314
  }
305
315
  },
306
316
  {
@@ -308,6 +318,7 @@ const config = {
308
318
  weight: 1,
309
319
  properties: {
310
320
  "reason": ["lost", "stolen", "suspicious_activity", "travel"],
321
+ "fraud_sequence": [false],
311
322
  }
312
323
  },
313
324
  {
@@ -316,6 +327,7 @@ const config = {
316
327
  properties: {
317
328
  "dispute_amount": u.weighNumRange(10, 2000, 0.5, 100),
318
329
  "reason": ["unauthorized", "duplicate", "not_received", "damaged", "wrong_amount"],
330
+ "fraud_sequence": [false],
319
331
  }
320
332
  },
321
333
  {
@@ -340,8 +352,8 @@ const config = {
340
352
  weight: 2,
341
353
  properties: {
342
354
  "old_tier": ["basic", "plus", "premium"],
343
- "new_tier": u.pickAWinner(["plus", "premium", "premium"]),
344
- "monthly_fee": u.pickAWinner([4.99, 9.99, 14.99]),
355
+ "new_tier": ["plus", "premium", "premium"],
356
+ "monthly_fee": [4.99, 9.99, 14.99],
345
357
  }
346
358
  },
347
359
  {
@@ -350,7 +362,8 @@ const config = {
350
362
  properties: {
351
363
  "channel": ["chat", "phone", "email", "in_app"],
352
364
  "issue_type": ["transaction", "account", "card", "transfer", "technical"],
353
- "resolved": u.pickAWinner([true, false], 0.8),
365
+ "resolved": [false, true, true, true, true],
366
+ "fraud_sequence": [false],
354
367
  }
355
368
  },
356
369
  {
@@ -358,7 +371,7 @@ const config = {
358
371
  weight: 10,
359
372
  properties: {
360
373
  "notification_type": ["transaction", "low_balance", "bill_due", "reward", "security", "promo"],
361
- "action_taken": u.pickAWinner([true, false], 0.6),
374
+ "action_taken": [false, false, true, true, true],
362
375
  }
363
376
  },
364
377
  {
@@ -367,13 +380,15 @@ const config = {
367
380
  properties: {
368
381
  "reward_type": ["cashback", "points", "discount", "partner_offer"],
369
382
  "value": u.weighNumRange(1, 100, 0.5, 10),
383
+ "premium_reward": [false],
370
384
  }
371
385
  }
372
386
  ],
373
387
 
374
388
  superProps: {
375
- account_tier: u.pickAWinner(["basic", "basic", "basic", "plus", "plus", "premium"]),
389
+ account_tier: ["basic", "basic", "basic", "plus", "plus", "premium"],
376
390
  platform: ["ios", "android", "web"],
391
+ low_balance_churn: [false],
377
392
  },
378
393
 
379
394
  userProps: {
@@ -381,7 +396,13 @@ const config = {
381
396
  "income_bracket": ["under_30k", "30k_50k", "50k_75k", "75k_100k", "100k_150k", "over_150k"],
382
397
  "account_age_months": u.weighNumRange(1, 60, 0.5, 12),
383
398
  "total_balance": u.weighNumRange(0, 100000, 0.3, 5000),
384
- "has_direct_deposit": u.pickAWinner([true, false], 0.6),
399
+ "has_direct_deposit": [false, false, true, true, true],
400
+ "account_segment": ["personal"],
401
+ "employee_count": [0],
402
+ "annual_revenue": [0],
403
+ "industry": [""],
404
+ "age_range": [""],
405
+ "life_stage": [""],
385
406
  },
386
407
 
387
408
  groupKeys: [
@@ -393,7 +414,7 @@ const config = {
393
414
  "household_size": u.weighNumRange(1, 6),
394
415
  "combined_income": u.weighNumRange(20000, 300000, 0.3, 75000),
395
416
  "financial_health_score": u.weighNumRange(1, 100, 1, 65),
396
- "primary_bank": u.pickAWinner(["NexBank_only", "multi_bank", "NexBank_only"]),
417
+ "primary_bank": ["NexBank_only", "multi_bank", "NexBank_only"],
397
418
  }
398
419
  },
399
420
 
@@ -568,48 +589,62 @@ const config = {
568
589
  const burstCount = chance.integer({ min: 3, max: 5 });
569
590
  const fraudEvents = [];
570
591
 
592
+ // Find template events for cloning
593
+ const txnTemplate = userEvents.find(e => e.event === "transaction completed");
594
+ const cardTemplate = userEvents.find(e => e.event === "card locked");
595
+ const disputeTemplate = userEvents.find(e => e.event === "dispute filed");
596
+ const supportTemplate = userEvents.find(e => e.event === "support contacted");
597
+
571
598
  for (let i = 0; i < burstCount; i++) {
599
+ if (txnTemplate) {
600
+ fraudEvents.push({
601
+ ...txnTemplate,
602
+ time: midTime.add(i * 10, "minutes").toISOString(),
603
+ user_id: distinctId,
604
+ transaction_type: "purchase",
605
+ amount: chance.integer({ min: 500, max: 3000 }),
606
+ merchant_category: chance.pickone(["online", "retail"]),
607
+ payment_method: "credit",
608
+ fraud_sequence: true,
609
+ });
610
+ }
611
+ }
612
+
613
+ // Card locked after the burst
614
+ if (cardTemplate) {
572
615
  fraudEvents.push({
573
- event: "transaction completed",
574
- time: midTime.add(i * 10, "minutes").toISOString(),
616
+ ...cardTemplate,
617
+ time: midTime.add(burstCount * 10 + 5, "minutes").toISOString(),
575
618
  user_id: distinctId,
576
- transaction_type: "purchase",
577
- amount: chance.integer({ min: 500, max: 3000 }),
578
- merchant_category: chance.pickone(["online", "retail"]),
579
- payment_method: "credit",
619
+ reason: "suspicious_activity",
580
620
  fraud_sequence: true,
581
621
  });
582
622
  }
583
623
 
584
- // Card locked after the burst
585
- fraudEvents.push({
586
- event: "card locked",
587
- time: midTime.add(burstCount * 10 + 5, "minutes").toISOString(),
588
- user_id: distinctId,
589
- reason: "suspicious_activity",
590
- fraud_sequence: true,
591
- });
592
-
593
624
  // Dispute filed shortly after
594
- fraudEvents.push({
595
- event: "dispute filed",
596
- time: midTime.add(burstCount * 10 + 30, "minutes").toISOString(),
597
- user_id: distinctId,
598
- dispute_amount: chance.integer({ min: 500, max: 3000 }),
599
- reason: "unauthorized",
600
- fraud_sequence: true,
601
- });
625
+ if (disputeTemplate) {
626
+ fraudEvents.push({
627
+ ...disputeTemplate,
628
+ time: midTime.add(burstCount * 10 + 30, "minutes").toISOString(),
629
+ user_id: distinctId,
630
+ dispute_amount: chance.integer({ min: 500, max: 3000 }),
631
+ reason: "unauthorized",
632
+ fraud_sequence: true,
633
+ });
634
+ }
602
635
 
603
636
  // Support contacted
604
- fraudEvents.push({
605
- event: "support contacted",
606
- time: midTime.add(burstCount * 10 + 45, "minutes").toISOString(),
607
- user_id: distinctId,
608
- channel: "phone",
609
- issue_type: "card",
610
- resolved: true,
611
- fraud_sequence: true,
612
- });
637
+ if (supportTemplate) {
638
+ fraudEvents.push({
639
+ ...supportTemplate,
640
+ time: midTime.add(burstCount * 10 + 45, "minutes").toISOString(),
641
+ user_id: distinctId,
642
+ channel: "phone",
643
+ issue_type: "card",
644
+ resolved: true,
645
+ fraud_sequence: true,
646
+ });
647
+ }
613
648
 
614
649
  // Splice all fraud events into the user's timeline
615
650
  userEvents.splice(midIdx + 1, 0, ...fraudEvents);
@@ -674,16 +709,19 @@ const config = {
674
709
 
675
710
  // Splice extra savings goal events (budget-conscious users set more goals)
676
711
  if (event.event === "budget created" && chance.bool({ likelihood: 50 })) {
677
- const extraGoal = {
678
- event: "savings goal set",
679
- time: eventTime.add(chance.integer({ min: 1, max: 7 }), "days").toISOString(),
680
- user_id: event.user_id,
681
- goal_type: chance.pickone(["emergency", "vacation", "car", "home"]),
682
- target_amount: chance.integer({ min: 1000, max: 20000 }),
683
- monthly_contribution: chance.integer({ min: 100, max: 800 }),
684
- budget_discipline: true,
685
- };
686
- userEvents.splice(idx + 1, 0, extraGoal);
712
+ const savingsTemplate = userEvents.find(e => e.event === "savings goal set");
713
+ if (savingsTemplate) {
714
+ const extraGoal = {
715
+ ...savingsTemplate,
716
+ time: eventTime.add(chance.integer({ min: 1, max: 7 }), "days").toISOString(),
717
+ user_id: event.user_id,
718
+ goal_type: chance.pickone(["emergency", "vacation", "car", "home"]),
719
+ target_amount: chance.integer({ min: 1000, max: 20000 }),
720
+ monthly_contribution: chance.integer({ min: 100, max: 800 }),
721
+ budget_discipline: true,
722
+ };
723
+ userEvents.splice(idx + 1, 0, extraGoal);
724
+ }
687
725
  }
688
726
  });
689
727
  }