@ak--47/dungeon-master 1.0.0 → 1.2.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 (104) 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 +92 -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} +12 -5
  8. package/dungeons/technical/experiments-schema.json +203 -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} +3 -3
  12. package/dungeons/technical/group-analytics-schema.json +241 -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} +2 -3
  20. package/dungeons/technical/sanity-schema.json +185 -0
  21. package/dungeons/{sanity.js → technical/sanity.js} +4 -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 +467 -0
  25. package/dungeons/{scd.js → technical/scd.js} +20 -10
  26. package/dungeons/technical/simple-schema.json +362 -0
  27. package/dungeons/{simple.js → technical/simple.js} +7 -7
  28. package/dungeons/technical/simplest-schema.json +724 -0
  29. package/dungeons/{simplest.js → technical/simplest.js} +7 -7
  30. package/dungeons/technical/text-generation-schema.json +1062 -0
  31. package/dungeons/{text-generation.js → technical/text-generation.js} +24 -11
  32. package/dungeons/vertical/community-schema.json +579 -0
  33. package/dungeons/vertical/community.js +794 -0
  34. package/dungeons/vertical/devtools-schema.json +601 -0
  35. package/dungeons/vertical/devtools.js +843 -0
  36. package/dungeons/vertical/ecommerce-schema.json +604 -0
  37. package/dungeons/{ecommerce.js → vertical/ecommerce.js} +43 -5
  38. package/dungeons/vertical/education-schema.json +5686 -0
  39. package/dungeons/{education.js → vertical/education.js} +70 -39
  40. package/dungeons/vertical/fintech-schema.json +630 -0
  41. package/dungeons/{fintech.js → vertical/fintech.js} +107 -56
  42. package/dungeons/vertical/fitness-schema.json +530 -0
  43. package/dungeons/vertical/fitness.js +808 -0
  44. package/dungeons/vertical/food-delivery-schema.json +36728 -0
  45. package/dungeons/{food.js → vertical/food-delivery.js} +67 -26
  46. package/dungeons/vertical/gaming-schema.json +438 -0
  47. package/dungeons/{gaming.js → vertical/gaming.js} +29 -16
  48. package/dungeons/vertical/healthcare-schema.json +549 -0
  49. package/dungeons/vertical/healthcare.js +775 -0
  50. package/dungeons/vertical/insurance-application-schema.json +485 -0
  51. package/dungeons/{insurance-application.js → vertical/insurance-application.js} +41 -31
  52. package/dungeons/vertical/logistics-schema.json +574 -0
  53. package/dungeons/vertical/logistics.js +799 -0
  54. package/dungeons/vertical/marketplace-schema.json +533 -0
  55. package/dungeons/vertical/marketplace.js +850 -0
  56. package/dungeons/vertical/media-schema.json +4749 -0
  57. package/dungeons/{media.js → vertical/media.js} +103 -19
  58. package/dungeons/vertical/rpg-schema.json +2491 -0
  59. package/dungeons/{rpg.js → vertical/rpg.js} +87 -60
  60. package/dungeons/vertical/sass-schema.json +3128 -0
  61. package/dungeons/{sass.js → vertical/sass.js} +65 -26
  62. package/dungeons/vertical/social-schema.json +620 -0
  63. package/dungeons/{social.js → vertical/social.js} +76 -17
  64. package/dungeons/vertical/travel-schema.json +580 -0
  65. package/dungeons/vertical/travel.js +742 -0
  66. package/index.js +20 -16
  67. package/lib/core/config-validator.js +286 -1
  68. package/lib/core/context.js +16 -5
  69. package/lib/core/storage.js +2 -0
  70. package/lib/generators/adspend.js +3 -3
  71. package/lib/generators/events.js +141 -14
  72. package/lib/generators/funnels.js +67 -7
  73. package/lib/generators/text.js +2 -2
  74. package/lib/orchestrators/user-loop.js +444 -22
  75. package/lib/templates/soup-presets.js +2 -2
  76. package/lib/utils/utils.js +4 -5
  77. package/package.json +4 -3
  78. package/scripts/dungeon-to-json.mjs +163 -0
  79. package/scripts/extract-dungeon-schema.mjs +343 -0
  80. package/scripts/json-to-dungeon.mjs +200 -0
  81. package/scripts/run-dungeon.mjs +76 -0
  82. package/scripts/run-many.mjs +118 -0
  83. package/scripts/verify-runner.mjs +42 -0
  84. package/types.d.ts +316 -1
  85. package/dungeons/array-of-object-lookup-schema.json +0 -327
  86. package/dungeons/ecommerce-schema.json +0 -462
  87. package/dungeons/education-schema.json +0 -2409
  88. package/dungeons/fintech-schema.json +0 -14034
  89. package/dungeons/foobar-schema.json +0 -403
  90. package/dungeons/food-delivery-schema.json +0 -192
  91. package/dungeons/food-delivery.js +0 -602
  92. package/dungeons/food-schema.json +0 -1152
  93. package/dungeons/gaming-schema.json +0 -1270
  94. package/dungeons/insurance-application-schema.json +0 -204
  95. package/dungeons/media-schema.json +0 -906
  96. package/dungeons/retention-cadence-schema.json +0 -78
  97. package/dungeons/rpg-schema.json +0 -4526
  98. package/dungeons/sanity-schema.json +0 -255
  99. package/dungeons/sass-schema.json +0 -1291
  100. package/dungeons/scd-schema.json +0 -919
  101. package/dungeons/simple-schema.json +0 -608
  102. package/dungeons/simplest-schema.json +0 -1418
  103. package/dungeons/social-schema.json +0 -1118
  104. 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-social";
@@ -10,7 +10,7 @@ const chance = u.initChance(SEED);
10
10
  const num_users = 5_000;
11
11
  const days = 100;
12
12
 
13
- /** @typedef {import("../types.js").Dungeon} Config */
13
+ /** @typedef {import("../../types").Dungeon} Config */
14
14
 
15
15
  /*
16
16
  * =====================================================================================
@@ -182,10 +182,23 @@ const config = {
182
182
  hasAdSpend: false,
183
183
  percentUsersBornInDataset: 50,
184
184
  hasAvatar: true,
185
- batchSize: 2_500_000,
186
185
  concurrency: 1,
187
186
  writeToDisk: false,
188
- scdProps: {},
187
+ scdProps: {
188
+ account_type: {
189
+ values: ["personal", "creator", "business", "verified"],
190
+ frequency: "month",
191
+ timing: "fuzzy",
192
+ max: 6
193
+ },
194
+ community_status: {
195
+ values: ["new", "growing", "established", "featured"],
196
+ frequency: "month",
197
+ timing: "fixed",
198
+ max: 6,
199
+ type: "community_id"
200
+ }
201
+ },
189
202
 
190
203
  funnels: [
191
204
  {
@@ -253,6 +266,7 @@ const config = {
253
266
  properties: {
254
267
  "signup_method": ["email", "google", "apple", "sso"],
255
268
  "referred_by": ["organic", "friend", "ad", "influencer"],
269
+ "toxic_user": [false],
256
270
  }
257
271
  },
258
272
  {
@@ -261,8 +275,13 @@ const config = {
261
275
  properties: {
262
276
  "post_type": ["text", "image", "video", "poll", "link"],
263
277
  "character_count": u.weighNumRange(1, 280),
264
- "has_media": u.pickAWinner([true, false], 0.4),
278
+ "has_media": [false, false, false, true, true],
265
279
  "hashtag_count": u.weighNumRange(0, 10, 0.5),
280
+ "weekend_surge": [false],
281
+ "weekend_duplicate": [false],
282
+ "monetized_creator": [false],
283
+ "follow_back_effect": [false],
284
+ "toxic_user": [false],
266
285
  }
267
286
  },
268
287
  {
@@ -272,6 +291,11 @@ const config = {
272
291
  "post_type": ["text", "image", "video", "poll", "link"],
273
292
  "view_duration_sec": u.weighNumRange(1, 120, 0.3, 5),
274
293
  "source": ["feed", "explore", "search", "profile", "notification"],
294
+ "engagement_bait": [false],
295
+ "trending_reengagement": [false],
296
+ "viral_cascade": [false],
297
+ "monetized_creator": [false],
298
+ "toxic_user": [false],
275
299
  }
276
300
  },
277
301
  {
@@ -279,6 +303,8 @@ const config = {
279
303
  weight: 18,
280
304
  properties: {
281
305
  "post_type": ["text", "image", "video", "poll", "link"],
306
+ "viral_cascade": [false],
307
+ "toxic_user": [false],
282
308
  }
283
309
  },
284
310
  {
@@ -286,6 +312,8 @@ const config = {
286
312
  weight: 6,
287
313
  properties: {
288
314
  "share_destination": ["repost", "dm", "external", "copy_link"],
315
+ "viral_cascade": [false],
316
+ "toxic_user": [false],
289
317
  }
290
318
  },
291
319
  {
@@ -293,7 +321,9 @@ const config = {
293
321
  weight: 10,
294
322
  properties: {
295
323
  "comment_length": u.weighNumRange(1, 500, 0.3, 20),
296
- "has_mention": u.pickAWinner([true, false, false]),
324
+ "has_mention": [true, false, false],
325
+ "follow_back_effect": [false],
326
+ "toxic_user": [false],
297
327
  }
298
328
  },
299
329
  {
@@ -301,6 +331,7 @@ const config = {
301
331
  weight: 8,
302
332
  properties: {
303
333
  "discovery_source": ["suggested", "search", "post", "profile", "mutual"],
334
+ "toxic_user": [false],
304
335
  }
305
336
  },
306
337
  {
@@ -308,6 +339,7 @@ const config = {
308
339
  weight: 2,
309
340
  properties: {
310
341
  "reason": ["content_quality", "too_frequent", "lost_interest", "offensive"],
342
+ "toxic_user": [false],
311
343
  }
312
344
  },
313
345
  {
@@ -316,7 +348,8 @@ const config = {
316
348
  properties: {
317
349
  "story_type": ["photo", "video", "text"],
318
350
  "view_duration_sec": u.weighNumRange(1, 30, 0.5, 5),
319
- "completed": u.pickAWinner([true, false], 0.6),
351
+ "completed": [false, false, true, true, true],
352
+ "toxic_user": [false],
320
353
  }
321
354
  },
322
355
  {
@@ -324,8 +357,12 @@ const config = {
324
357
  weight: 5,
325
358
  properties: {
326
359
  "story_type": ["photo", "video", "text"],
327
- "has_filter": u.pickAWinner([true, false], 0.5),
328
- "has_sticker": u.pickAWinner([true, false], 0.3),
360
+ "has_filter": [true, false],
361
+ "has_sticker": [false, false, true],
362
+ "weekend_surge": [false],
363
+ "weekend_duplicate": [false],
364
+ "monetized_creator": [false],
365
+ "toxic_user": [false],
329
366
  }
330
367
  },
331
368
  {
@@ -334,6 +371,7 @@ const config = {
334
371
  properties: {
335
372
  "search_type": ["users", "hashtags", "posts"],
336
373
  "results_count": u.weighNumRange(0, 50, 0.5, 10),
374
+ "toxic_user": [false],
337
375
  }
338
376
  },
339
377
  {
@@ -341,7 +379,8 @@ const config = {
341
379
  weight: 12,
342
380
  properties: {
343
381
  "notification_type": ["like", "follow", "comment", "mention", "trending"],
344
- "clicked": u.pickAWinner([true, false], 0.4),
382
+ "clicked": [false, false, false, true, true],
383
+ "toxic_user": [false],
345
384
  }
346
385
  },
347
386
  {
@@ -350,6 +389,7 @@ const config = {
350
389
  properties: {
351
390
  "message_type": ["text", "image", "voice", "link"],
352
391
  "conversation_length": u.weighNumRange(1, 100),
392
+ "toxic_user": [false],
353
393
  }
354
394
  },
355
395
  {
@@ -359,6 +399,7 @@ const config = {
359
399
  "ad_format": ["feed_native", "story", "banner", "video"],
360
400
  "ad_category": ["retail", "tech", "food", "finance", "entertainment"],
361
401
  "view_duration_sec": u.weighNumRange(1, 30, 0.3),
402
+ "toxic_user": [false],
362
403
  }
363
404
  },
364
405
  {
@@ -367,6 +408,7 @@ const config = {
367
408
  properties: {
368
409
  "ad_format": ["feed_native", "story", "banner", "video"],
369
410
  "ad_category": ["retail", "tech", "food", "finance", "entertainment"],
411
+ "toxic_user": [false],
370
412
  }
371
413
  },
372
414
  {
@@ -375,6 +417,7 @@ const config = {
375
417
  properties: {
376
418
  "report_type": ["spam", "harassment", "misinformation", "hate_speech", "other"],
377
419
  "content_type": ["post", "comment", "user", "dm"],
420
+ "toxic_user": [false],
378
421
  }
379
422
  },
380
423
  {
@@ -382,6 +425,7 @@ const config = {
382
425
  weight: 3,
383
426
  properties: {
384
427
  "field_updated": ["bio", "avatar", "display_name", "privacy_settings", "interests"],
428
+ "toxic_user": [false],
385
429
  }
386
430
  },
387
431
  {
@@ -389,7 +433,8 @@ const config = {
389
433
  weight: 2,
390
434
  properties: {
391
435
  "tier": ["basic", "premium", "vip"],
392
- "price_usd": u.pickAWinner([4.99, 9.99, 19.99]),
436
+ "price_usd": [4.99, 9.99, 19.99],
437
+ "toxic_user": [false],
393
438
  }
394
439
  },
395
440
  ],
@@ -403,7 +448,7 @@ const config = {
403
448
  "follower_count": u.weighNumRange(0, 10000, 0.2, 50),
404
449
  "following_count": u.weighNumRange(0, 5000, 0.3, 100),
405
450
  "bio_length": u.weighNumRange(0, 160),
406
- "verified": u.pickAWinner([true, false], 0.05),
451
+ "verified": [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true],
407
452
  "content_niche": ["lifestyle", "tech", "food", "fitness", "travel", "comedy", "news", "art"],
408
453
  },
409
454
 
@@ -416,7 +461,7 @@ const config = {
416
461
  "name": () => `${chance.word()} ${chance.pickone(["Hub", "Circle", "Squad", "Zone", "Space"])}`,
417
462
  "member_count": u.weighNumRange(50, 5000, 0.3, 200),
418
463
  "category": ["technology", "entertainment", "sports", "politics", "art", "science"],
419
- "is_moderated": u.pickAWinner([true, false], 0.7),
464
+ "is_moderated": [false, false, false, true, true, true, true, true, true, true],
420
465
  }
421
466
  },
422
467
 
@@ -536,8 +581,13 @@ const config = {
536
581
  const viralShares = chance.integer({ min: 10, max: 20 });
537
582
  const injected = [];
538
583
 
584
+ const viewTemplate = userEvents.find(e => e.event === "post viewed");
585
+ const likeTemplate = userEvents.find(e => e.event === "post liked");
586
+ const shareTemplate = userEvents.find(e => e.event === "post shared");
587
+
539
588
  for (let i = 0; i < viralViews; i++) {
540
589
  injected.push({
590
+ ...(viewTemplate || event),
541
591
  event: "post viewed",
542
592
  time: eventTime.add(chance.integer({ min: 1, max: 180 }), 'minutes').toISOString(),
543
593
  user_id: event.user_id,
@@ -545,10 +595,13 @@ const config = {
545
595
  source: chance.pickone(["feed", "explore", "search"]),
546
596
  view_duration_sec: chance.integer({ min: 5, max: 90 }),
547
597
  viral_cascade: true,
598
+ engagement_bait: false,
599
+ trending_reengagement: false,
548
600
  });
549
601
  }
550
602
  for (let i = 0; i < viralLikes; i++) {
551
603
  injected.push({
604
+ ...(likeTemplate || event),
552
605
  event: "post liked",
553
606
  time: eventTime.add(chance.integer({ min: 2, max: 240 }), 'minutes').toISOString(),
554
607
  user_id: event.user_id,
@@ -558,6 +611,7 @@ const config = {
558
611
  }
559
612
  for (let i = 0; i < viralShares; i++) {
560
613
  injected.push({
614
+ ...(shareTemplate || event),
561
615
  event: "post shared",
562
616
  time: eventTime.add(chance.integer({ min: 5, max: 300 }), 'minutes').toISOString(),
563
617
  user_id: event.user_id,
@@ -574,8 +628,9 @@ const config = {
574
628
  // Users with 5+ follows become prolific creators
575
629
  if (followReceivedCount >= 5 && event.event === "post created") {
576
630
  if (chance.bool({ likelihood: 50 })) {
631
+ const commentTemplate = userEvents.find(e => e.event === "comment posted");
577
632
  const duplicatePost = {
578
- event: "post created",
633
+ ...event,
579
634
  time: eventTime.add(chance.integer({ min: 30, max: 240 }), 'minutes').toISOString(),
580
635
  user_id: event.user_id,
581
636
  post_type: chance.pickone(["text", "image", "video"]),
@@ -585,6 +640,7 @@ const config = {
585
640
  follow_back_effect: true,
586
641
  };
587
642
  const extraComment = {
643
+ ...(commentTemplate || event),
588
644
  event: "comment posted",
589
645
  time: eventTime.add(chance.integer({ min: 10, max: 120 }), 'minutes').toISOString(),
590
646
  user_id: event.user_id,
@@ -602,7 +658,7 @@ const config = {
602
658
  // Triple frequency: add 2 extra posts for each existing one
603
659
  for (let i = 0; i < 2; i++) {
604
660
  const extraPost = {
605
- event: "post created",
661
+ ...event,
606
662
  time: eventTime.add(chance.integer({ min: 1, max: 12 }), 'hours').toISOString(),
607
663
  user_id: event.user_id,
608
664
  post_type: chance.pickone(["text", "image", "video", "link"]),
@@ -618,7 +674,7 @@ const config = {
618
674
  // Also triple story creation
619
675
  for (let i = 0; i < 2; i++) {
620
676
  const extraStory = {
621
- event: "story created",
677
+ ...event,
622
678
  time: eventTime.add(chance.integer({ min: 1, max: 8 }), 'hours').toISOString(),
623
679
  user_id: event.user_id,
624
680
  story_type: chance.pickone(["photo", "video", "text"]),
@@ -633,13 +689,16 @@ const config = {
633
689
  if (hasCreatorSubscription && event.event === "post viewed") {
634
690
  if (chance.bool({ likelihood: 25 })) {
635
691
  const analyticsView = {
636
- event: "post viewed",
692
+ ...event,
637
693
  time: eventTime.add(chance.integer({ min: 1, max: 30 }), 'minutes').toISOString(),
638
694
  user_id: event.user_id,
639
695
  post_type: event.post_type || "text",
640
696
  source: "profile",
641
697
  view_duration_sec: chance.integer({ min: 10, max: 60 }),
642
698
  monetized_creator: true,
699
+ engagement_bait: false,
700
+ trending_reengagement: false,
701
+ viral_cascade: false,
643
702
  };
644
703
  userEvents.splice(idx + 1, 0, analyticsView);
645
704
  }