@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
@@ -120,9 +120,9 @@
120
120
  "enterprise"
121
121
  ],
122
122
  "signup_source": [
123
- "referral",
123
+ "organic",
124
124
  "paid",
125
- "organic"
125
+ "referral"
126
126
  ]
127
127
  }
128
128
  }
@@ -1,3 +1,13 @@
1
+ // ── TWEAK THESE ──
2
+ const SEED = "ad spend test";
3
+ const num_days = 90;
4
+ const num_users = 1_000;
5
+ const avg_events_per_user = 50;
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 Chance from 'chance';
2
12
  let chance = new Chance();
3
13
  import dayjs from "dayjs";
@@ -6,6 +16,7 @@ dayjs.extend(utc);
6
16
  import { uid, comma } from 'ak-tools';
7
17
  import { weighNumRange, date, integer, weighChoices } from "../../lib/utils/utils.js";
8
18
 
19
+ /** @typedef {import("../../types").Dungeon} Config */
9
20
  /**
10
21
  * ═══════════════════════════════════════════════════════════════
11
22
  * TECHNICAL TEST: Ad Spend & Campaign Attribution
@@ -24,11 +35,12 @@ import { weighNumRange, date, integer, weighChoices } from "../../lib/utils/util
24
35
 
25
36
  /** @type {import('../../types').Dungeon} */
26
37
  const config = {
27
- seed: "ad spend test",
38
+ token,
39
+ seed: SEED,
28
40
  name: "ad-spend",
29
- numDays: 90,
30
- numEvents: 50_000,
31
- numUsers: 1_000,
41
+ numDays: num_days,
42
+ numEvents: num_users * avg_events_per_user,
43
+ numUsers: num_users,
32
44
  format: 'json',
33
45
  region: "US",
34
46
  hasAnonIds: true,
@@ -43,7 +55,6 @@ const config = {
43
55
  isAnonymous: false,
44
56
  alsoInferFunnels: false,
45
57
  concurrency: 1,
46
- batchSize: 500_000,
47
58
  writeToDisk: false,
48
59
 
49
60
  events: [
@@ -5,9 +5,10 @@
5
5
  "weight": 10,
6
6
  "properties": {
7
7
  "page": [
8
+ "/",
8
9
  "/features",
9
- "/docs",
10
10
  "/pricing",
11
+ "/docs",
11
12
  "/blog"
12
13
  ],
13
14
  "referrer": [
@@ -50,8 +51,8 @@
50
51
  "properties": {
51
52
  "amount": {
52
53
  "$range": [
53
- 108,
54
- 392
54
+ 114,
55
+ 397
55
56
  ]
56
57
  },
57
58
  "plan": [
@@ -1,3 +1,13 @@
1
+ // ── TWEAK THESE ──
2
+ const SEED = "anonymous-users";
3
+ const num_days = 180;
4
+ const num_users = 1_000;
5
+ const avg_events_per_user = 50;
6
+ let token = "your-mixpanel-token";
7
+
8
+ // ── env overrides ──
9
+ if (process.env.MP_TOKEN) token = process.env.MP_TOKEN;
10
+
1
11
  /**
2
12
  * Anonymous Users — tests anonymous user mode, anonIds, and identity merge.
3
13
  *
@@ -14,13 +24,14 @@ import Chance from 'chance';
14
24
  let chance = new Chance();
15
25
  import { weighNumRange, weighChoices } from "../../lib/utils/utils.js";
16
26
 
27
+ /** @typedef {import("../../types").Dungeon} Config */
17
28
  /** @type {import('../../types').Dungeon} */
18
29
  const config = {
19
- token: "",
20
- seed: "anonymous-users",
21
- numDays: 180,
22
- numEvents: 50_000,
23
- numUsers: 1_000,
30
+ token,
31
+ seed: SEED,
32
+ numDays: num_days,
33
+ numEvents: num_users * avg_events_per_user,
34
+ numUsers: num_users,
24
35
  format: "json",
25
36
  region: "US",
26
37
  isAnonymous: true,
@@ -35,7 +46,6 @@ const config = {
35
46
  hasCampaigns: false,
36
47
  alsoInferFunnels: false,
37
48
  concurrency: 1,
38
- batchSize: 2_500_000,
39
49
  writeToDisk: false,
40
50
 
41
51
  events: [
@@ -92,8 +92,8 @@
92
92
  ],
93
93
  "superProps": {
94
94
  "theme": [
95
- "dark",
96
95
  "light",
96
+ "dark",
97
97
  "custom"
98
98
  ]
99
99
  },
@@ -1,3 +1,13 @@
1
+ // ── TWEAK THESE ──
2
+ const SEED = "dm4-array-of-object-lookup";
3
+ const num_days = 60;
4
+ const num_users = 1_000;
5
+ const avg_events_per_user = 100;
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 Chance from 'chance';
2
12
  let chance = new Chance();
3
13
  import dayjs from "dayjs";
@@ -6,6 +16,7 @@ dayjs.extend(utc);
6
16
  import { uid, comma } from 'ak-tools';
7
17
  import { weighNumRange, date, integer, weighChoices } from "../../lib/utils/utils.js";
8
18
 
19
+ /** @typedef {import("../../types").Dungeon} Config */
9
20
  const videoCategories = ["funny", "educational", "inspirational", "music", "news", "sports", "cooking", "DIY", "travel", "gaming"];
10
21
  const spiritAnimals = ["duck", "dog", "otter", "penguin", "cat", "elephant", "lion", "cheetah", "giraffe", "zebra", "rhino", "hippo", "whale", "dolphin", "shark", "octopus", "squid", "jellyfish", "starfish", "seahorse", "crab", "lobster", "shrimp", "clam", "snail", "slug", "butterfly", "moth", "bee", "wasp", "ant", "beetle", "ladybug", "caterpillar", "centipede", "millipede", "scorpion", "spider", "tarantula", "tick", "mite", "mosquito", "fly", "dragonfly", "damselfly", "grasshopper", "cricket", "locust", "mantis", "cockroach", "termite", "praying mantis", "walking stick", "stick bug", "leaf insect", "lacewing", "aphid", "cicada", "thrips", "psyllid", "scale insect", "whitefly", "mealybug", "planthopper", "leafhopper", "treehopper", "flea", "louse", "bedbug", "flea beetle", "weevil", "longhorn beetle", "leaf beetle", "tiger beetle", "ground beetle", "lady beetle", "firefly", "click beetle", "rove beetle", "scarab beetle", "dung beetle", "stag beetle", "rhinoceros beetle", "hercules beetle", "goliath beetle", "jewel beetle", "tortoise beetle"];
11
22
 
@@ -39,12 +50,12 @@ const spiritAnimals = ["duck", "dog", "otter", "penguin", "cat", "elephant", "li
39
50
 
40
51
  /** @type {import('../types.js').Dungeon} */
41
52
  const config = {
42
- // token: "",
43
- seed: "test array of objects lookup",
53
+ token,
54
+ seed: SEED,
44
55
  name: "array-of-object-lookup",
45
- numDays: 60, //how many days worth1 of data
46
- numEvents: 100_000, //how many events
47
- numUsers: 1_000, //how many users
56
+ numDays: num_days,
57
+ numEvents: num_users * avg_events_per_user,
58
+ numUsers: num_users,
48
59
  format: 'json', //csv or json
49
60
  region: "US",
50
61
  hasAnonIds: true, //if true, anonymousIds are created for each user
@@ -59,7 +70,6 @@ const config = {
59
70
  isAnonymous: false,
60
71
  alsoInferFunnels: true,
61
72
  concurrency: 1,
62
- batchSize: 250_000,
63
73
  writeToDisk: false,
64
74
  events: [
65
75
  {
@@ -109,6 +119,7 @@ const config = {
109
119
  each key should be an array or function reference
110
120
  */
111
121
  userProps: {
122
+ theme: ["light", "dark", "custom", "light", "dark"],
112
123
  // title: chance.profession.bind(chance),
113
124
  // luckyNumber: weighNumRange(1, 500, .3),
114
125
  spiritAnimal: spiritAnimals
@@ -160,6 +171,11 @@ const config = {
160
171
  }
161
172
 
162
173
  if (type === "everything") {
174
+ const profile = meta.profile;
175
+ record.forEach(e => {
176
+ e.theme = profile.theme;
177
+ });
178
+
163
179
  // Pattern 3: Users who view 5+ items but never checkout are tagged as window shoppers
164
180
  const views = record.filter(e => e.event === "view item").length;
165
181
  const checkouts = record.filter(e => e.event === "checkout").length;
@@ -5,8 +5,9 @@
5
5
  "weight": 10,
6
6
  "properties": {
7
7
  "page": [
8
- "/pricing",
8
+ "/",
9
9
  "/features",
10
+ "/pricing",
10
11
  "/docs",
11
12
  "/about"
12
13
  ]
@@ -72,8 +73,8 @@
72
73
  "properties": {
73
74
  "amount": {
74
75
  "$range": [
75
- 129,
76
- 400
76
+ 123,
77
+ 389
77
78
  ]
78
79
  },
79
80
  "plan": [
@@ -120,21 +121,6 @@
120
121
  }
121
122
  }
122
123
  ],
123
- "superProps": {
124
- "platform": [
125
- "ios",
126
- "web",
127
- "android"
128
- ]
129
- },
130
- "userProps": {
131
- "plan": [
132
- "free",
133
- "starter",
134
- "growth",
135
- "enterprise"
136
- ]
137
- },
138
124
  "funnels": [
139
125
  {
140
126
  "sequence": [
@@ -143,6 +129,7 @@
143
129
  "feature viewed",
144
130
  "action taken"
145
131
  ],
132
+ "name": "Onboarding Flow",
146
133
  "isFirstFunnel": true,
147
134
  "conversionRate": 45,
148
135
  "timeToConvert": 3,
@@ -156,6 +143,7 @@
156
143
  "button click",
157
144
  "checkout"
158
145
  ],
146
+ "name": "Purchase Funnel",
159
147
  "conversionRate": 30,
160
148
  "timeToConvert": 5,
161
149
  "order": "first-and-last-fixed",
@@ -169,12 +157,14 @@
169
157
  "help viewed",
170
158
  "action taken"
171
159
  ],
160
+ "name": "Feature Adoption",
172
161
  "conversionRate": 50,
173
162
  "timeToConvert": 2,
174
163
  "order": "random",
175
164
  "weight": 4,
176
165
  "requireRepeats": true,
177
166
  "experiment": true,
167
+ "bindPropsIndex": 2,
178
168
  "props": {
179
169
  "experiment_cohort": [
180
170
  "new_ui",
@@ -188,10 +178,26 @@
188
178
  "button click",
189
179
  "signup"
190
180
  ],
181
+ "name": "Quick Signup",
191
182
  "isFirstFunnel": true,
192
183
  "conversionRate": 40,
193
184
  "timeToConvert": 1,
194
185
  "weight": 6
195
186
  }
196
- ]
187
+ ],
188
+ "superProps": {
189
+ "platform": [
190
+ "web",
191
+ "ios",
192
+ "android"
193
+ ]
194
+ },
195
+ "userProps": {
196
+ "plan": [
197
+ "free",
198
+ "starter",
199
+ "growth",
200
+ "enterprise"
201
+ ]
202
+ }
197
203
  }
@@ -1,3 +1,13 @@
1
+ // ── TWEAK THESE ──
2
+ const SEED = "experiments";
3
+ const num_days = 60;
4
+ const num_users = 2_000;
5
+ const avg_events_per_user = 50;
6
+ let token = "your-mixpanel-token";
7
+
8
+ // ── env overrides ──
9
+ if (process.env.MP_TOKEN) token = process.env.MP_TOKEN;
10
+
1
11
  /**
2
12
  * Experiments — tests funnel experiments with A/B/C variants.
3
13
  *
@@ -14,13 +24,14 @@ import Chance from 'chance';
14
24
  let chance = new Chance();
15
25
  import { weighNumRange, weighChoices } from "../../lib/utils/utils.js";
16
26
 
27
+ /** @typedef {import("../../types").Dungeon} Config */
17
28
  /** @type {import('../../types').Dungeon} */
18
29
  const config = {
19
- token: "",
20
- seed: "experiments",
21
- numDays: 60,
22
- numEvents: 100_000,
23
- numUsers: 2_000,
30
+ token,
31
+ seed: SEED,
32
+ numDays: num_days,
33
+ numEvents: num_users * avg_events_per_user,
34
+ numUsers: num_users,
24
35
  format: "json",
25
36
  region: "US",
26
37
  hasAnonIds: false,
@@ -35,7 +46,6 @@ const config = {
35
46
  isAnonymous: false,
36
47
  alsoInferFunnels: false,
37
48
  concurrency: 1,
38
- batchSize: 2_500_000,
39
49
  writeToDisk: false,
40
50
 
41
51
  events: [
@@ -152,6 +162,7 @@ const config = {
152
162
 
153
163
  userProps: {
154
164
  plan: weighChoices(["free", "free", "free", "starter", "growth", "enterprise"]),
165
+ platform: ["web", "web", "ios", "android"],
155
166
  },
156
167
 
157
168
  scdProps: {},
@@ -161,6 +172,13 @@ const config = {
161
172
  lookupTables: [],
162
173
 
163
174
  hook: function (record, type, meta) {
175
+ if (type === "everything") {
176
+ const profile = meta.profile;
177
+ record.forEach(e => {
178
+ e.platform = profile.platform;
179
+ });
180
+ return record;
181
+ }
164
182
  return record;
165
183
  }
166
184
  };
@@ -1,3 +1,13 @@
1
+ // ── TWEAK THESE ──
2
+ const SEED = "dm4-foobar";
3
+ const num_days = 30;
4
+ const num_users = 4_000_000;
5
+ const avg_events_per_user = 500;
6
+ let token = "your-mixpanel-token";
7
+
8
+ // ── env overrides ──
9
+ if (process.env.MP_TOKEN) token = process.env.MP_TOKEN;
10
+
1
11
  /**
2
12
  * ═══════════════════════════════════════════════════════════════
3
13
  * DATASET OVERVIEW
@@ -46,6 +56,7 @@ function integer(min = 1, max = 100) {
46
56
  return Math.floor(Math.random() * (max - min + 1)) + min;
47
57
  }
48
58
 
59
+ /** @typedef {import("../../types").Dungeon} Config */
49
60
 
50
61
  const dates = [
51
62
  "2024-09-18T21:48:28.173Z",
@@ -150,25 +161,17 @@ const dates = [
150
161
  "2024-06-03T06:52:21.652Z"
151
162
  ];
152
163
 
153
- const billionsOfEvents = 2
154
-
155
- const numEvents = billionsOfEvents * 1_000_000_000;
156
- const eventPerUser = 1_000;
157
- const numUsers = Math.floor(numEvents / eventPerUser);
158
- const seed = Math.random().toString()
159
-
160
164
  /** @type {import('../../types').Dungeon} */
161
165
  const config = {
162
- token: "",
163
- seed: seed,
164
- numDays: 30, //how many days worth of data
165
- numEvents: numEvents, //how many events
166
- numUsers: numUsers, //how many users
166
+ token,
167
+ seed: SEED,
168
+ numDays: num_days,
169
+ numEvents: num_users * avg_events_per_user,
170
+ numUsers: num_users,
167
171
  format: 'json', //csv or json
168
172
  region: "US",
169
173
  hasAnonIds: false, //if true, anonymousIds are created for each user
170
174
  hasSessionIds: false, //if true, hasSessionIds are created for each user
171
- batchSize: 2_500_000,
172
175
  hasAdSpend: false,
173
176
  hasAvatar: false,
174
177
  hasBrowser: false,
@@ -244,6 +247,11 @@ const config = {
244
247
  luckyNumber: integer,
245
248
  spiritAnimal: ["duck", "dog", "otter", "penguin", "cat", "elephant", "lion", "cheetah", "giraffe", "zebra", "rhino", "hippo", "whale", "dolphin", "shark", "octopus", "squid", "jellyfish", "starfish", "seahorse", "crab", "lobster", "shrimp", "clam", "snail", "slug", "butterfly", "moth", "bee", "wasp", "ant", "beetle", "ladybug", "caterpillar", "centipede", "millipede", "scorpion", "spider", "tarantula", "tick", "mite", "mosquito", "fly", "dragonfly", "damselfly", "grasshopper", "cricket", "locust", "mantis", "cockroach", "termite", "praying mantis", "walking stick", "stick bug", "leaf insect", "lacewing", "aphid", "cicada", "thrips", "psyllid", "scale insect", "whitefly", "mealybug", "planthopper", "leafhopper", "treehopper", "flea", "louse", "bedbug", "flea beetle", "weevil", "longhorn beetle", "leaf beetle", "tiger beetle", "ground beetle", "lady beetle", "firefly", "click beetle", "rove beetle", "scarab beetle", "dung beetle", "stag beetle", "rhinoceros beetle", "hercules beetle", "goliath beetle", "jewel beetle", "tortoise beetle"],
246
249
  created: dates,
250
+ string: ["red", "orange", "yellow", "green", "blue", "indigo", "violet"],
251
+ number: integer,
252
+ boolean: [true, false],
253
+ date: dates,
254
+ temperature: ["warm"],
247
255
  },
248
256
 
249
257
  scdProps: {},
@@ -270,6 +278,14 @@ const config = {
270
278
 
271
279
  // everything hook: hash-based cohort — 10% of users (by distinct_id) get doubled events
272
280
  if (type === "everything") {
281
+ const profile = meta.profile;
282
+ record.forEach(e => {
283
+ e.string = profile.string;
284
+ e.number = profile.number;
285
+ e.boolean = profile.boolean;
286
+ e.date = profile.date;
287
+ e.temperature = profile.temperature;
288
+ });
273
289
  if (record.length > 0) {
274
290
  const userId = record[0].user_id || record[0].distinct_id || "";
275
291
  if (userId && userId.charCodeAt(0) % 10 === 0) {
@@ -145,5 +145,97 @@
145
145
  "manager",
146
146
  "exec"
147
147
  ]
148
+ },
149
+ "groupKeys": [
150
+ {
151
+ "key": "company_id",
152
+ "count": 50,
153
+ "affectsEvents": [
154
+ "feature used",
155
+ "subscription change",
156
+ "support ticket"
157
+ ]
158
+ },
159
+ {
160
+ "key": "team_id",
161
+ "count": 200,
162
+ "affectsEvents": [
163
+ "feature used",
164
+ "task completed",
165
+ "meeting scheduled"
166
+ ]
167
+ },
168
+ {
169
+ "key": "project_id",
170
+ "count": 500,
171
+ "affectsEvents": [
172
+ "task completed",
173
+ "code committed",
174
+ "deployment run"
175
+ ]
176
+ }
177
+ ],
178
+ "groupProps": {
179
+ "company_id": {
180
+ "name": {
181
+ "$type": "string"
182
+ },
183
+ "industry": [
184
+ "technology",
185
+ "finance",
186
+ "healthcare",
187
+ "retail",
188
+ "education",
189
+ "manufacturing"
190
+ ],
191
+ "plan": [
192
+ "free",
193
+ "starter",
194
+ "business",
195
+ "enterprise"
196
+ ],
197
+ "employee_count": {
198
+ "$range": [
199
+ 964,
200
+ 3784
201
+ ]
202
+ }
203
+ },
204
+ "team_id": {
205
+ "name": {
206
+ "$type": "string"
207
+ },
208
+ "department": [
209
+ "engineering",
210
+ "design",
211
+ "product",
212
+ "marketing",
213
+ "sales",
214
+ "support"
215
+ ],
216
+ "size": {
217
+ "$range": [
218
+ 3,
219
+ 20
220
+ ]
221
+ }
222
+ },
223
+ "project_id": {
224
+ "name": {
225
+ "$type": "string"
226
+ },
227
+ "status": [
228
+ "active",
229
+ "paused",
230
+ "completed",
231
+ "archived"
232
+ ],
233
+ "priority": [
234
+ "low",
235
+ "medium",
236
+ "high",
237
+ "critical"
238
+ ]
239
+ }
148
240
  }
149
241
  }
@@ -1,3 +1,13 @@
1
+ // ── TWEAK THESE ──
2
+ const SEED = "group-analytics";
3
+ const num_days = 60;
4
+ const num_users = 500;
5
+ const avg_events_per_user = 60;
6
+ let token = "your-mixpanel-token";
7
+
8
+ // ── env overrides ──
9
+ if (process.env.MP_TOKEN) token = process.env.MP_TOKEN;
10
+
1
11
  /**
2
12
  * Group Analytics — tests multiple group keys with varied entity counts.
3
13
  *
@@ -14,13 +24,14 @@ import Chance from 'chance';
14
24
  let chance = new Chance();
15
25
  import { weighNumRange, weighChoices } from "../../lib/utils/utils.js";
16
26
 
27
+ /** @typedef {import("../../types").Dungeon} Config */
17
28
  /** @type {import('../../types').Dungeon} */
18
29
  const config = {
19
- token: "",
20
- seed: "group-analytics",
21
- numDays: 60,
22
- numEvents: 30_000,
23
- numUsers: 500,
30
+ token,
31
+ seed: SEED,
32
+ numDays: num_days,
33
+ numEvents: num_users * avg_events_per_user,
34
+ numUsers: num_users,
24
35
  format: "json",
25
36
  region: "US",
26
37
  hasAnonIds: false,
@@ -35,7 +46,6 @@ const config = {
35
46
  isAnonymous: false,
36
47
  alsoInferFunnels: false,
37
48
  concurrency: 1,
38
- batchSize: 2_500_000,
39
49
  writeToDisk: false,
40
50
 
41
51
  events: [
@@ -5,11 +5,11 @@
5
5
  "weight": 10,
6
6
  "properties": {
7
7
  "page": [
8
- "/account",
9
8
  "/",
10
9
  "/help",
11
- "/product",
12
- "/pricing"
10
+ "/account",
11
+ "/pricing",
12
+ "/product"
13
13
  ]
14
14
  }
15
15
  },
@@ -20,7 +20,7 @@
20
20
  "amount": {
21
21
  "$range": [
22
22
  44,
23
- 154
23
+ 157
24
24
  ]
25
25
  },
26
26
  "currency": [
@@ -1,3 +1,13 @@
1
+ // ── TWEAK THESE ──
2
+ const SEED = "mirror-strategies";
3
+ const num_days = 30;
4
+ const num_users = 500;
5
+ const avg_events_per_user = 60;
6
+ let token = "your-mixpanel-token";
7
+
8
+ // ── env overrides ──
9
+ if (process.env.MP_TOKEN) token = process.env.MP_TOKEN;
10
+
1
11
  /**
2
12
  * Mirror Strategies — tests all 4 mirror data strategies.
3
13
  *
@@ -13,13 +23,14 @@ import Chance from 'chance';
13
23
  let chance = new Chance();
14
24
  import { weighNumRange, weighChoices } from "../../lib/utils/utils.js";
15
25
 
26
+ /** @typedef {import("../../types").Dungeon} Config */
16
27
  /** @type {import('../../types').Dungeon} */
17
28
  const config = {
18
- token: "",
19
- seed: "mirror-strategies",
20
- numDays: 30,
21
- numEvents: 30_000,
22
- numUsers: 500,
29
+ token,
30
+ seed: SEED,
31
+ numDays: num_days,
32
+ numEvents: num_users * avg_events_per_user,
33
+ numUsers: num_users,
23
34
  format: "json",
24
35
  region: "US",
25
36
  hasAnonIds: false,
@@ -34,7 +45,6 @@ const config = {
34
45
  isAnonymous: false,
35
46
  alsoInferFunnels: false,
36
47
  concurrency: 1,
37
- batchSize: 2_500_000,
38
48
  writeToDisk: false,
39
49
 
40
50
  events: [