@ak--47/dungeon-master 1.1.0 → 1.2.1

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 (72) hide show
  1. package/dungeons/technical/ad-spend-schema.json +2 -2
  2. package/dungeons/technical/ad-spend.js +16 -5
  3. package/dungeons/technical/anonymous-users-schema.json +4 -3
  4. package/dungeons/technical/anonymous-users.js +16 -6
  5. package/dungeons/technical/array-of-object-lookup-schema.json +1 -1
  6. package/dungeons/technical/array-of-object-lookup.js +22 -6
  7. package/dungeons/technical/experiments-schema.json +25 -19
  8. package/dungeons/technical/experiments.js +24 -6
  9. package/dungeons/technical/foobar.js +29 -13
  10. package/dungeons/technical/group-analytics-schema.json +92 -0
  11. package/dungeons/technical/group-analytics.js +16 -6
  12. package/dungeons/technical/mirror-strategies-schema.json +4 -4
  13. package/dungeons/technical/mirror-strategies.js +16 -6
  14. package/dungeons/technical/nested-objects.js +16 -5
  15. package/dungeons/technical/retention-cadence.js +14 -9
  16. package/dungeons/technical/sanity-schema.json +22 -22
  17. package/dungeons/technical/sanity.js +26 -6
  18. package/dungeons/technical/scale-test.js +16 -5
  19. package/dungeons/technical/scd-schema.json +230 -33
  20. package/dungeons/technical/scd.js +25 -5
  21. package/dungeons/technical/simple-schema.json +132 -48
  22. package/dungeons/technical/simple.js +21 -6
  23. package/dungeons/technical/simplest-schema.json +168 -79
  24. package/dungeons/technical/simplest.js +24 -7
  25. package/dungeons/technical/text-generation-schema.json +7 -4
  26. package/dungeons/technical/text-generation.js +23 -8
  27. package/dungeons/user/.gitkeep +0 -0
  28. package/dungeons/user/shalini.js +847 -0
  29. package/dungeons/vertical/community-schema.json +71 -49
  30. package/dungeons/vertical/community.js +57 -30
  31. package/dungeons/vertical/devtools-schema.json +69 -48
  32. package/dungeons/vertical/devtools.js +58 -31
  33. package/dungeons/vertical/ecommerce-schema.json +126 -108
  34. package/dungeons/vertical/ecommerce.js +32 -8
  35. package/dungeons/vertical/education-schema.json +5261 -272
  36. package/dungeons/vertical/education.js +45 -22
  37. package/dungeons/vertical/fintech-schema.json +165 -98
  38. package/dungeons/vertical/fintech.js +43 -11
  39. package/dungeons/vertical/fitness-schema.json +69 -47
  40. package/dungeons/vertical/fitness.js +56 -24
  41. package/dungeons/vertical/food-delivery-schema.json +36237 -187
  42. package/dungeons/vertical/food-delivery.js +67 -15
  43. package/dungeons/vertical/gaming-schema.json +104 -60
  44. package/dungeons/vertical/gaming.js +61 -16
  45. package/dungeons/vertical/healthcare-schema.json +70 -48
  46. package/dungeons/vertical/healthcare.js +77 -42
  47. package/dungeons/vertical/insurance-application-schema.json +66 -47
  48. package/dungeons/vertical/insurance-application.js +34 -10
  49. package/dungeons/vertical/logistics-schema.json +60 -38
  50. package/dungeons/vertical/logistics.js +77 -43
  51. package/dungeons/vertical/marketplace-schema.json +65 -43
  52. package/dungeons/vertical/marketplace.js +52 -21
  53. package/dungeons/vertical/media-schema.json +4085 -123
  54. package/dungeons/vertical/media.js +65 -18
  55. package/dungeons/vertical/rpg-schema.json +1984 -147
  56. package/dungeons/vertical/rpg.js +47 -11
  57. package/dungeons/vertical/sass-schema.json +2622 -147
  58. package/dungeons/vertical/sass.js +40 -10
  59. package/dungeons/vertical/social-schema.json +146 -78
  60. package/dungeons/vertical/social.js +39 -10
  61. package/dungeons/vertical/travel-schema.json +57 -35
  62. package/dungeons/vertical/travel.js +58 -21
  63. package/index.js +4 -1
  64. package/lib/core/config-validator.js +13 -2
  65. package/lib/core/context.js +9 -0
  66. package/lib/core/storage.js +2 -0
  67. package/lib/generators/events.js +3 -5
  68. package/lib/orchestrators/user-loop.js +24 -1
  69. package/lib/utils/utils.js +129 -9
  70. package/package.json +1 -1
  71. package/scripts/extract-dungeon-schema.mjs +64 -18
  72. package/types.d.ts +8 -3
@@ -392,6 +392,9 @@
392
392
  },
393
393
  {
394
394
  "event": "account deactivated",
395
+ "isChurnEvent": true,
396
+ "returnLikelihood": 0.15,
397
+ "isStrictEvent": true,
395
398
  "properties": {
396
399
  "reason": [
397
400
  "lost_motivation",
@@ -403,52 +406,6 @@
403
406
  }
404
407
  }
405
408
  ],
406
- "superProps": {
407
- "platform": [
408
- "ios",
409
- "android"
410
- ],
411
- "workout_type": [
412
- "strength",
413
- "cardio",
414
- "yoga",
415
- "hiit",
416
- "running",
417
- "cycling"
418
- ]
419
- },
420
- "userProps": {
421
- "fitness_level": [
422
- "beginner"
423
- ],
424
- "segment": [
425
- "casual"
426
- ],
427
- "streak_days": [
428
- 0
429
- ],
430
- "total_workouts": {
431
- "$range": [
432
- 0,
433
- 0
434
- ]
435
- },
436
- "preferred_workout": [
437
- "strength",
438
- "cardio",
439
- "yoga",
440
- "hiit",
441
- "running",
442
- "cycling"
443
- ],
444
- "goal": [
445
- "weight_loss",
446
- "muscle_gain",
447
- "endurance",
448
- "flexibility",
449
- "general_health"
450
- ]
451
- },
452
409
  "funnels": [
453
410
  {
454
411
  "sequence": [
@@ -457,6 +414,7 @@
457
414
  "workout planned",
458
415
  "workout completed"
459
416
  ],
417
+ "name": "Onboarding",
460
418
  "isFirstFunnel": true,
461
419
  "conversionRate": 45,
462
420
  "timeToConvert": 72,
@@ -468,6 +426,7 @@
468
426
  "workout completed",
469
427
  "progress checked"
470
428
  ],
429
+ "name": "Workout Loop",
471
430
  "conversionRate": 45,
472
431
  "timeToConvert": 48,
473
432
  "weight": 5
@@ -478,6 +437,7 @@
478
437
  "leaderboard viewed",
479
438
  "challenge joined"
480
439
  ],
440
+ "name": "Social Engagement",
481
441
  "conversionRate": 35,
482
442
  "timeToConvert": 96,
483
443
  "weight": 3
@@ -489,6 +449,7 @@
489
449
  "challenge completed",
490
450
  "achievement unlocked"
491
451
  ],
452
+ "name": "Challenge Completion",
492
453
  "conversionRate": 30,
493
454
  "timeToConvert": 336,
494
455
  "weight": 2
@@ -500,9 +461,70 @@
500
461
  "workout completed",
501
462
  "progress checked"
502
463
  ],
464
+ "name": "Coaching Path",
503
465
  "conversionRate": 50,
504
466
  "timeToConvert": 72,
505
467
  "weight": 2
506
468
  }
507
- ]
469
+ ],
470
+ "superProps": {
471
+ "Platform": [
472
+ "ios",
473
+ "android"
474
+ ],
475
+ "workout_type": [
476
+ "strength",
477
+ "cardio",
478
+ "yoga",
479
+ "hiit",
480
+ "running",
481
+ "cycling"
482
+ ]
483
+ },
484
+ "userProps": {
485
+ "fitness_level": [
486
+ "beginner"
487
+ ],
488
+ "segment": [
489
+ "casual"
490
+ ],
491
+ "streak_days": [
492
+ 0
493
+ ],
494
+ "total_workouts": {
495
+ "$range": [
496
+ 0,
497
+ 0
498
+ ]
499
+ },
500
+ "preferred_workout": [
501
+ "strength",
502
+ "cardio",
503
+ "yoga",
504
+ "hiit",
505
+ "running",
506
+ "cycling"
507
+ ],
508
+ "goal": [
509
+ "weight_loss",
510
+ "muscle_gain",
511
+ "endurance",
512
+ "flexibility",
513
+ "general_health"
514
+ ]
515
+ },
516
+ "scdProps": {
517
+ "fitness_level": {
518
+ "type": "user",
519
+ "frequency": "month",
520
+ "timing": "fuzzy",
521
+ "max": 8,
522
+ "values": [
523
+ "beginner",
524
+ "intermediate",
525
+ "advanced",
526
+ "elite"
527
+ ]
528
+ }
529
+ }
508
530
  }
@@ -1,15 +1,22 @@
1
+ // ── TWEAK THESE ──
2
+ const SEED = "dm4-fitness";
3
+ const num_days = 100;
4
+ const num_users = 5_000;
5
+ const avg_events_per_user = 120;
6
+ let token = "your-mixpanel-token";
7
+
8
+ // ── env overrides ──
9
+ if (process.env.MP_TOKEN) token = process.env.MP_TOKEN;
10
+
1
11
  import dayjs from "dayjs";
2
12
  import utc from "dayjs/plugin/utc.js";
3
13
  import "dotenv/config";
4
14
  import * as u from "../../lib/utils/utils.js";
5
15
 
6
- const SEED = "dm4-fitness";
7
16
  dayjs.extend(utc);
8
17
  const chance = u.initChance(SEED);
9
- const num_users = 5_000;
10
- const days = 100;
11
18
  const NOW = dayjs();
12
- const DATASET_START = NOW.subtract(days, "days");
19
+ const DATASET_START = NOW.subtract(num_days, "days");
13
20
 
14
21
  /** @typedef {import("../../types").Dungeon} Config */
15
22
 
@@ -219,12 +226,12 @@ const DATASET_START = NOW.subtract(days, "days");
219
226
  * consistency to build credibility with their clients.
220
227
  *
221
228
  * ───────────────────────────────────────────────────────────────
222
- * 8. ANNUAL SUBSCRIBER WORKOUT FUNNEL LIFT (funnel-pre hook)
229
+ * 8. ANNUAL SUBSCRIBER WORKOUT FUNNEL LIFT (everything hook)
223
230
  * ───────────────────────────────────────────────────────────────
224
231
  *
225
- * PATTERN: Users with subscription_tier "annual" or "family"
226
- * get 1.4x conversion rate through the Workout Loop funnel.
227
- * Annual commitment correlates with follow-through.
232
+ * PATTERN: Free/monthly-tier users lose ~30% of "progress checked"
233
+ * events (last step of the Workout Loop funnel), simulating lower
234
+ * follow-through. Annual/family subscribers retain all events.
228
235
  *
229
236
  * HOW TO FIND IT IN MIXPANEL:
230
237
  *
@@ -255,10 +262,10 @@ const DATASET_START = NOW.subtract(days, "days");
255
262
 
256
263
  /** @type {Config} */
257
264
  const config = {
258
- token: "",
265
+ token,
259
266
  seed: SEED,
260
- numDays: days,
261
- numEvents: num_users * 120,
267
+ numDays: num_days,
268
+ numEvents: num_users * avg_events_per_user,
262
269
  numUsers: num_users,
263
270
  hasAnonIds: false,
264
271
  hasSessionIds: true,
@@ -275,10 +282,16 @@ const config = {
275
282
  hasAdSpend: false,
276
283
  percentUsersBornInDataset: 35,
277
284
  hasAvatar: true,
278
- batchSize: 2_500_000,
279
285
  concurrency: 1,
280
286
  writeToDisk: false,
281
- scdProps: {},
287
+ scdProps: {
288
+ fitness_level: {
289
+ values: ["beginner", "intermediate", "advanced", "elite"],
290
+ frequency: "month",
291
+ timing: "fuzzy",
292
+ max: 8
293
+ }
294
+ },
282
295
  mirrorProps: {},
283
296
  lookupTables: [],
284
297
 
@@ -494,7 +507,7 @@ const config = {
494
507
 
495
508
  // ── SuperProps ──────────────────────────────────────────
496
509
  superProps: {
497
- platform: ["ios", "ios", "android"],
510
+ Platform: ["ios", "ios", "android"],
498
511
  workout_type: ["strength", "cardio", "yoga", "hiit", "running", "cycling"],
499
512
  },
500
513
 
@@ -506,6 +519,8 @@ const config = {
506
519
  total_workouts: u.weighNumRange(0, 0, 0.5),
507
520
  preferred_workout: ["strength", "cardio", "yoga", "hiit", "running", "cycling"],
508
521
  goal: ["weight_loss", "muscle_gain", "endurance", "flexibility", "general_health"],
522
+ Platform: ["ios", "ios", "android"],
523
+ workout_type: ["strength", "cardio", "yoga", "hiit", "running", "cycling"],
509
524
  },
510
525
 
511
526
  // ── Personas ──────────────────────────────────
@@ -673,16 +688,9 @@ const config = {
673
688
  }
674
689
 
675
690
  // ── HOOK 8: ANNUAL SUBSCRIBER WORKOUT FUNNEL LIFT (funnel-pre) ─
676
- // Annual and family subscribers convert 1.4x through workout loop.
691
+ // (conversionRate filtering moved to everything hook)
677
692
  if (type === "funnel-pre") {
678
- if (meta && meta.profile) {
679
- const tier = meta.profile.subscription_tier;
680
- if (tier === "annual" || tier === "family") {
681
- record.conversionRate = Math.min(record.conversionRate * 1.4, 95);
682
- } else if (tier === "monthly") {
683
- record.conversionRate = Math.min(record.conversionRate * 1.15, 90);
684
- }
685
- }
693
+ // no-op: conversion filtering handled via event dropping in everything hook
686
694
  }
687
695
 
688
696
  // ── HOOK 1: MORNING WORKOUT BOOST (event) ────────────
@@ -716,9 +724,33 @@ const config = {
716
724
 
717
725
  // ── EVERYTHING HOOKS ─────────────────────────────────
718
726
  if (type === "everything") {
719
- const events = record;
727
+ let events = record;
720
728
  if (!events.length) return record;
721
729
 
730
+ // ── SUPERPROP STAMPING ──────────────────────────
731
+ // Stamp superProps from profile so they are consistent per user.
732
+ if (meta && meta.profile) {
733
+ const p = meta.profile;
734
+ events.forEach(e => {
735
+ if (p.Platform) e.Platform = p.Platform;
736
+ if (p.workout_type) e.workout_type = p.workout_type;
737
+ });
738
+ }
739
+
740
+ // ── HOOK 8: ANNUAL SUBSCRIBER CONVERSION FILTER ─
741
+ // Free/monthly-tier users drop ~30% of "progress checked"
742
+ // (last step of Workout Loop funnel) to simulate lower conversion.
743
+ if (meta && meta.profile) {
744
+ const tier = meta.profile.subscription_tier;
745
+ if (tier !== "annual" && tier !== "family") {
746
+ record = record.filter(e => {
747
+ if (e.event === "progress checked" && chance.bool({ likelihood: 30 })) return false;
748
+ return true;
749
+ });
750
+ events = record;
751
+ }
752
+ }
753
+
722
754
  // ── HOOK 3: STREAK RETENTION ─────────────────────
723
755
  // Users with >10 workouts get streak_days updated and
724
756
  // cloned achievement events for milestones.