@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.
- package/dungeons/technical/ad-spend-schema.json +2 -2
- package/dungeons/technical/ad-spend.js +16 -5
- package/dungeons/technical/anonymous-users-schema.json +4 -3
- package/dungeons/technical/anonymous-users.js +16 -6
- package/dungeons/technical/array-of-object-lookup-schema.json +1 -1
- package/dungeons/technical/array-of-object-lookup.js +22 -6
- package/dungeons/technical/experiments-schema.json +25 -19
- package/dungeons/technical/experiments.js +24 -6
- package/dungeons/technical/foobar.js +29 -13
- package/dungeons/technical/group-analytics-schema.json +92 -0
- package/dungeons/technical/group-analytics.js +16 -6
- package/dungeons/technical/mirror-strategies-schema.json +4 -4
- package/dungeons/technical/mirror-strategies.js +16 -6
- package/dungeons/technical/nested-objects.js +16 -5
- package/dungeons/technical/retention-cadence.js +14 -9
- package/dungeons/technical/sanity-schema.json +22 -22
- package/dungeons/technical/sanity.js +26 -6
- package/dungeons/technical/scale-test.js +16 -5
- package/dungeons/technical/scd-schema.json +230 -33
- package/dungeons/technical/scd.js +25 -5
- package/dungeons/technical/simple-schema.json +132 -48
- package/dungeons/technical/simple.js +21 -6
- package/dungeons/technical/simplest-schema.json +168 -79
- package/dungeons/technical/simplest.js +24 -7
- package/dungeons/technical/text-generation-schema.json +7 -4
- package/dungeons/technical/text-generation.js +23 -8
- package/dungeons/user/.gitkeep +0 -0
- package/dungeons/user/shalini.js +847 -0
- package/dungeons/vertical/community-schema.json +71 -49
- package/dungeons/vertical/community.js +57 -30
- package/dungeons/vertical/devtools-schema.json +69 -48
- package/dungeons/vertical/devtools.js +58 -31
- package/dungeons/vertical/ecommerce-schema.json +126 -108
- package/dungeons/vertical/ecommerce.js +32 -8
- package/dungeons/vertical/education-schema.json +5261 -272
- package/dungeons/vertical/education.js +45 -22
- package/dungeons/vertical/fintech-schema.json +165 -98
- package/dungeons/vertical/fintech.js +43 -11
- package/dungeons/vertical/fitness-schema.json +69 -47
- package/dungeons/vertical/fitness.js +56 -24
- package/dungeons/vertical/food-delivery-schema.json +36237 -187
- package/dungeons/vertical/food-delivery.js +67 -15
- package/dungeons/vertical/gaming-schema.json +104 -60
- package/dungeons/vertical/gaming.js +61 -16
- package/dungeons/vertical/healthcare-schema.json +70 -48
- package/dungeons/vertical/healthcare.js +77 -42
- package/dungeons/vertical/insurance-application-schema.json +66 -47
- package/dungeons/vertical/insurance-application.js +34 -10
- package/dungeons/vertical/logistics-schema.json +60 -38
- package/dungeons/vertical/logistics.js +77 -43
- package/dungeons/vertical/marketplace-schema.json +65 -43
- package/dungeons/vertical/marketplace.js +52 -21
- package/dungeons/vertical/media-schema.json +4085 -123
- package/dungeons/vertical/media.js +65 -18
- package/dungeons/vertical/rpg-schema.json +1984 -147
- package/dungeons/vertical/rpg.js +47 -11
- package/dungeons/vertical/sass-schema.json +2622 -147
- package/dungeons/vertical/sass.js +40 -10
- package/dungeons/vertical/social-schema.json +146 -78
- package/dungeons/vertical/social.js +39 -10
- package/dungeons/vertical/travel-schema.json +57 -35
- package/dungeons/vertical/travel.js +58 -21
- package/index.js +4 -1
- package/lib/core/config-validator.js +13 -2
- package/lib/core/context.js +9 -0
- package/lib/core/storage.js +2 -0
- package/lib/generators/events.js +3 -5
- package/lib/orchestrators/user-loop.js +24 -1
- package/lib/utils/utils.js +129 -9
- package/package.json +1 -1
- package/scripts/extract-dungeon-schema.mjs +64 -18
- package/types.d.ts +8 -3
|
@@ -1,16 +1,23 @@
|
|
|
1
|
+
// ── TWEAK THESE ──
|
|
2
|
+
const SEED = "harness-food";
|
|
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
|
import * as v from "ak-tools";
|
|
6
16
|
|
|
7
|
-
const SEED = "harness-food";
|
|
8
17
|
dayjs.extend(utc);
|
|
9
18
|
const chance = u.initChance(SEED);
|
|
10
|
-
const num_users = 5_000;
|
|
11
|
-
const days = 100;
|
|
12
19
|
|
|
13
|
-
/** @typedef {import("
|
|
20
|
+
/** @typedef {import("../../types").Dungeon} Config */
|
|
14
21
|
|
|
15
22
|
/*
|
|
16
23
|
* ═══════════════════════════════════════════════════════════════════════════════
|
|
@@ -156,10 +163,10 @@ const couponCodes = v.range(1, 51).map(n => `QUICK${v.uid(5).toUpperCase()}`);
|
|
|
156
163
|
|
|
157
164
|
/** @type {Config} */
|
|
158
165
|
const config = {
|
|
159
|
-
token
|
|
166
|
+
token,
|
|
160
167
|
seed: SEED,
|
|
161
|
-
numDays:
|
|
162
|
-
numEvents: num_users *
|
|
168
|
+
numDays: num_days,
|
|
169
|
+
numEvents: num_users * avg_events_per_user,
|
|
163
170
|
numUsers: num_users,
|
|
164
171
|
hasAnonIds: false,
|
|
165
172
|
hasSessionIds: true,
|
|
@@ -176,10 +183,23 @@ const config = {
|
|
|
176
183
|
hasAdSpend: false,
|
|
177
184
|
percentUsersBornInDataset: 50,
|
|
178
185
|
hasAvatar: true,
|
|
179
|
-
batchSize: 2_500_000,
|
|
180
186
|
concurrency: 1,
|
|
181
187
|
writeToDisk: false,
|
|
182
|
-
scdProps: {
|
|
188
|
+
scdProps: {
|
|
189
|
+
subscription_tier: {
|
|
190
|
+
values: ["free", "trial", "monthly", "annual"],
|
|
191
|
+
frequency: "month",
|
|
192
|
+
timing: "fuzzy",
|
|
193
|
+
max: 6
|
|
194
|
+
},
|
|
195
|
+
restaurant_tier: {
|
|
196
|
+
values: ["new", "verified", "featured", "premium"],
|
|
197
|
+
frequency: "month",
|
|
198
|
+
timing: "fixed",
|
|
199
|
+
max: 6,
|
|
200
|
+
type: "restaurant_id"
|
|
201
|
+
}
|
|
202
|
+
},
|
|
183
203
|
|
|
184
204
|
funnels: [
|
|
185
205
|
{
|
|
@@ -366,6 +386,9 @@ const config = {
|
|
|
366
386
|
"order_id": orderIds,
|
|
367
387
|
"actual_delivery_mins": u.weighNumRange(12, 90, 1.0, 40),
|
|
368
388
|
"on_time": [false, false, false, true, true, true, true, true, true, true],
|
|
389
|
+
"lunch_rush": [false],
|
|
390
|
+
"dinner_rush": [false],
|
|
391
|
+
"first_order_bonus": [false],
|
|
369
392
|
"trial_retained": [false],
|
|
370
393
|
}
|
|
371
394
|
},
|
|
@@ -446,7 +469,7 @@ const config = {
|
|
|
446
469
|
],
|
|
447
470
|
|
|
448
471
|
superProps: {
|
|
449
|
-
|
|
472
|
+
Platform: ["iOS", "Android", "Web"],
|
|
450
473
|
subscription_tier: ["Free", "Free", "Free", "Free", "QuickBite+"],
|
|
451
474
|
city: ["New York", "Los Angeles", "Chicago", "Houston", "Phoenix", "San Francisco"],
|
|
452
475
|
},
|
|
@@ -467,6 +490,9 @@ const config = {
|
|
|
467
490
|
"favorite_restaurant_count": u.weighNumRange(1, 10),
|
|
468
491
|
"is_high_risk": [false],
|
|
469
492
|
"churn_risk_score": [0],
|
|
493
|
+
"Platform": ["iOS", "Android", "Web"],
|
|
494
|
+
"subscription_tier": ["Free", "Free", "Free", "Free", "QuickBite+"],
|
|
495
|
+
"city": ["New York", "Los Angeles", "Chicago", "Houston", "Phoenix", "San Francisco"],
|
|
470
496
|
},
|
|
471
497
|
|
|
472
498
|
groupKeys: [
|
|
@@ -509,7 +535,7 @@ const config = {
|
|
|
509
535
|
*/
|
|
510
536
|
hook: function (record, type, meta) {
|
|
511
537
|
const NOW = dayjs();
|
|
512
|
-
const DATASET_START = NOW.subtract(
|
|
538
|
+
const DATASET_START = NOW.subtract(num_days, 'days');
|
|
513
539
|
const RAINY_WEEK_START = DATASET_START.add(20, 'days');
|
|
514
540
|
const RAINY_WEEK_END = DATASET_START.add(27, 'days');
|
|
515
541
|
|
|
@@ -526,13 +552,11 @@ const config = {
|
|
|
526
552
|
|
|
527
553
|
// Lunch rush: 11AM - 1PM
|
|
528
554
|
if (hour >= 11 && hour <= 13) {
|
|
529
|
-
record.conversionRate = record.conversionRate * 1.4;
|
|
530
555
|
record.props.lunch_rush = true;
|
|
531
556
|
record.props.dinner_rush = false;
|
|
532
557
|
}
|
|
533
558
|
// Dinner rush: 5PM - 8PM
|
|
534
559
|
else if (hour >= 17 && hour <= 20) {
|
|
535
|
-
record.conversionRate = record.conversionRate * 1.2;
|
|
536
560
|
record.props.lunch_rush = false;
|
|
537
561
|
record.props.dinner_rush = true;
|
|
538
562
|
} else {
|
|
@@ -555,7 +579,6 @@ const config = {
|
|
|
555
579
|
const userId = meta && meta.user && (meta.user.distinct_id || String(meta.user));
|
|
556
580
|
const isNewUser = userId && userId.charCodeAt(0) % 2 === 0;
|
|
557
581
|
if (isNewUser) {
|
|
558
|
-
record.conversionRate = Math.min(98, record.conversionRate * 1.4);
|
|
559
582
|
record.props.first_order_bonus = true;
|
|
560
583
|
} else {
|
|
561
584
|
record.props.first_order_bonus = false;
|
|
@@ -592,7 +615,7 @@ const config = {
|
|
|
592
615
|
time: midTime,
|
|
593
616
|
user_id: firstEvent.user_id,
|
|
594
617
|
subscription_tier: firstEvent.subscription_tier,
|
|
595
|
-
|
|
618
|
+
Platform: firstEvent.Platform,
|
|
596
619
|
city: firstEvent.city,
|
|
597
620
|
coupon_code: chance.pickone(couponCodes),
|
|
598
621
|
discount_type: chance.pickone(["percent", "flat", "free_delivery"]),
|
|
@@ -660,6 +683,35 @@ const config = {
|
|
|
660
683
|
// ═══════════════════════════════════════════════════════════════════
|
|
661
684
|
if (type === "everything") {
|
|
662
685
|
const userEvents = record;
|
|
686
|
+
const profile = meta.profile;
|
|
687
|
+
|
|
688
|
+
// ── Stamp superProps from profile so they stay consistent per user ──
|
|
689
|
+
if (profile) {
|
|
690
|
+
userEvents.forEach((event) => {
|
|
691
|
+
if (profile.Platform !== undefined) event.Platform = profile.Platform;
|
|
692
|
+
if (profile.subscription_tier !== undefined) event.subscription_tier = profile.subscription_tier;
|
|
693
|
+
if (profile.city !== undefined) event.city = profile.city;
|
|
694
|
+
});
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
// ── Bug 2 fix: Conversion filtering for lunch rush + first order ──
|
|
698
|
+
// Hook 1: Non-lunch/dinner-hour events → drop ~30% of final funnel step
|
|
699
|
+
// Hook 8: Returning users (no first_order_bonus) → drop ~30% of final funnel step
|
|
700
|
+
for (let i = userEvents.length - 1; i >= 0; i--) {
|
|
701
|
+
const event = userEvents[i];
|
|
702
|
+
if (event.event === "order delivered") {
|
|
703
|
+
// Hook 1: if not during lunch or dinner rush, drop 30%
|
|
704
|
+
if (!event.lunch_rush && !event.dinner_rush && chance.bool({ likelihood: 30 })) {
|
|
705
|
+
userEvents.splice(i, 1);
|
|
706
|
+
continue;
|
|
707
|
+
}
|
|
708
|
+
// Hook 8: returning users (no first_order_bonus) drop 30%
|
|
709
|
+
if (event.first_order_bonus === false && chance.bool({ likelihood: 30 })) {
|
|
710
|
+
userEvents.splice(i, 1);
|
|
711
|
+
continue;
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
}
|
|
663
715
|
|
|
664
716
|
// First pass: identify user patterns
|
|
665
717
|
let isReferralUser = false;
|
|
@@ -69,12 +69,14 @@
|
|
|
69
69
|
5
|
|
70
70
|
]
|
|
71
71
|
},
|
|
72
|
-
"used hint":
|
|
73
|
-
"
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
72
|
+
"used hint": [
|
|
73
|
+
"no",
|
|
74
|
+
"yes"
|
|
75
|
+
],
|
|
76
|
+
"used boost": [
|
|
77
|
+
"no",
|
|
78
|
+
"yes"
|
|
79
|
+
],
|
|
78
80
|
"level at start": {
|
|
79
81
|
"$range": [
|
|
80
82
|
2,
|
|
@@ -99,15 +101,18 @@
|
|
|
99
101
|
451
|
|
100
102
|
]
|
|
101
103
|
},
|
|
102
|
-
"quest success":
|
|
103
|
-
"
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
104
|
+
"quest success": [
|
|
105
|
+
"yes",
|
|
106
|
+
"no"
|
|
107
|
+
],
|
|
108
|
+
"used hint": [
|
|
109
|
+
"no",
|
|
110
|
+
"yes"
|
|
111
|
+
],
|
|
112
|
+
"used boost": [
|
|
113
|
+
"no",
|
|
114
|
+
"yes"
|
|
115
|
+
],
|
|
111
116
|
"number of deaths": [
|
|
112
117
|
1,
|
|
113
118
|
3
|
|
@@ -247,8 +252,51 @@
|
|
|
247
252
|
}
|
|
248
253
|
}
|
|
249
254
|
],
|
|
255
|
+
"funnels": [
|
|
256
|
+
{
|
|
257
|
+
"sequence": [
|
|
258
|
+
"app install",
|
|
259
|
+
"character creation",
|
|
260
|
+
"join party"
|
|
261
|
+
],
|
|
262
|
+
"isFirstFunnel": true,
|
|
263
|
+
"conversionRate": 0.8,
|
|
264
|
+
"timeToConvert": 0.25
|
|
265
|
+
},
|
|
266
|
+
{
|
|
267
|
+
"sequence": [
|
|
268
|
+
"start quest",
|
|
269
|
+
"gameplay summary",
|
|
270
|
+
"complete quest"
|
|
271
|
+
],
|
|
272
|
+
"conversionRate": 0.99,
|
|
273
|
+
"timeToConvert": 1,
|
|
274
|
+
"props": {
|
|
275
|
+
"quest type": [
|
|
276
|
+
"Rescue",
|
|
277
|
+
"Retrieve",
|
|
278
|
+
"Explore",
|
|
279
|
+
"Destroy",
|
|
280
|
+
"Investigate"
|
|
281
|
+
],
|
|
282
|
+
"quest difficulty": [
|
|
283
|
+
"Easy",
|
|
284
|
+
"Medium",
|
|
285
|
+
"Hard",
|
|
286
|
+
"Legendary"
|
|
287
|
+
],
|
|
288
|
+
"quest location": [
|
|
289
|
+
"Forest",
|
|
290
|
+
"Dungeon",
|
|
291
|
+
"Mountain",
|
|
292
|
+
"City",
|
|
293
|
+
"Desert"
|
|
294
|
+
]
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
],
|
|
250
298
|
"superProps": {
|
|
251
|
-
"
|
|
299
|
+
"Platform": [
|
|
252
300
|
"Mobile",
|
|
253
301
|
"Xbox",
|
|
254
302
|
"Playstation",
|
|
@@ -319,8 +367,8 @@
|
|
|
319
367
|
],
|
|
320
368
|
"level": {
|
|
321
369
|
"$range": [
|
|
322
|
-
|
|
323
|
-
|
|
370
|
+
3,
|
|
371
|
+
15
|
|
324
372
|
]
|
|
325
373
|
},
|
|
326
374
|
"background": [
|
|
@@ -340,55 +388,51 @@
|
|
|
340
388
|
],
|
|
341
389
|
"subscription MRR": {
|
|
342
390
|
"$range": [
|
|
343
|
-
|
|
344
|
-
|
|
391
|
+
0,
|
|
392
|
+
244
|
|
345
393
|
]
|
|
346
394
|
},
|
|
347
395
|
"archetype": [
|
|
348
396
|
"neutral"
|
|
349
397
|
]
|
|
350
398
|
},
|
|
351
|
-
"
|
|
352
|
-
{
|
|
353
|
-
"
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
},
|
|
362
|
-
{
|
|
363
|
-
"sequence": [
|
|
364
|
-
"start quest",
|
|
365
|
-
"gameplay summary",
|
|
366
|
-
"complete quest"
|
|
367
|
-
],
|
|
368
|
-
"conversionRate": 0.99,
|
|
369
|
-
"timeToConvert": 1,
|
|
370
|
-
"props": {
|
|
371
|
-
"quest type": [
|
|
372
|
-
"Rescue",
|
|
373
|
-
"Retrieve",
|
|
374
|
-
"Explore",
|
|
375
|
-
"Destroy",
|
|
376
|
-
"Investigate"
|
|
377
|
-
],
|
|
378
|
-
"quest difficulty": [
|
|
379
|
-
"Easy",
|
|
380
|
-
"Medium",
|
|
381
|
-
"Hard",
|
|
382
|
-
"Legendary"
|
|
383
|
-
],
|
|
384
|
-
"quest location": [
|
|
385
|
-
"Forest",
|
|
386
|
-
"Dungeon",
|
|
387
|
-
"Mountain",
|
|
388
|
-
"City",
|
|
389
|
-
"Desert"
|
|
399
|
+
"scdProps": {
|
|
400
|
+
"subscription MRR": {
|
|
401
|
+
"type": "user",
|
|
402
|
+
"frequency": "week",
|
|
403
|
+
"timing": "fixed",
|
|
404
|
+
"max": 250,
|
|
405
|
+
"values": {
|
|
406
|
+
"$range": [
|
|
407
|
+
1,
|
|
408
|
+
221
|
|
390
409
|
]
|
|
391
410
|
}
|
|
411
|
+
},
|
|
412
|
+
"player_rank": {
|
|
413
|
+
"type": "user",
|
|
414
|
+
"frequency": "week",
|
|
415
|
+
"timing": "fuzzy",
|
|
416
|
+
"max": 250,
|
|
417
|
+
"values": [
|
|
418
|
+
"bronze",
|
|
419
|
+
"silver",
|
|
420
|
+
"gold",
|
|
421
|
+
"diamond",
|
|
422
|
+
"legendary"
|
|
423
|
+
]
|
|
424
|
+
},
|
|
425
|
+
"guild_rank": {
|
|
426
|
+
"type": "guild_id",
|
|
427
|
+
"frequency": "month",
|
|
428
|
+
"timing": "fixed",
|
|
429
|
+
"max": 6,
|
|
430
|
+
"values": [
|
|
431
|
+
"bronze",
|
|
432
|
+
"silver",
|
|
433
|
+
"gold",
|
|
434
|
+
"legendary"
|
|
435
|
+
]
|
|
392
436
|
}
|
|
393
|
-
|
|
437
|
+
}
|
|
394
438
|
}
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
// ── TWEAK THESE ──
|
|
2
|
+
const SEED = "my-seed";
|
|
3
|
+
const num_days = 180;
|
|
4
|
+
const num_users = 12_000;
|
|
5
|
+
const avg_events_per_user = 90;
|
|
6
|
+
let token = "your-mixpanel-token";
|
|
7
|
+
|
|
8
|
+
// ── env overrides ──
|
|
9
|
+
if (process.env.MP_TOKEN) token = process.env.MP_TOKEN;
|
|
1
10
|
|
|
2
11
|
import dayjs from "dayjs";
|
|
3
12
|
import utc from "dayjs/plugin/utc.js";
|
|
@@ -5,13 +14,10 @@ import "dotenv/config";
|
|
|
5
14
|
import * as u from "../../lib/utils/utils.js";
|
|
6
15
|
import * as v from "ak-tools";
|
|
7
16
|
|
|
8
|
-
const SEED = "my-seed";
|
|
9
17
|
dayjs.extend(utc);
|
|
10
18
|
const chance = u.initChance(SEED);
|
|
11
|
-
const num_users = 12_000;
|
|
12
|
-
const days = 180;
|
|
13
19
|
|
|
14
|
-
/** @typedef {import("
|
|
20
|
+
/** @typedef {import("../../types").Dungeon} Config */
|
|
15
21
|
|
|
16
22
|
/*
|
|
17
23
|
* ═══════════════════════════════════════════════════════════════════════════════
|
|
@@ -154,10 +160,10 @@ const days = 180;
|
|
|
154
160
|
|
|
155
161
|
/** @type {Config} */
|
|
156
162
|
const config = {
|
|
157
|
-
token
|
|
163
|
+
token,
|
|
158
164
|
seed: "i am gamer face",
|
|
159
|
-
numDays:
|
|
160
|
-
numEvents: num_users *
|
|
165
|
+
numDays: num_days,
|
|
166
|
+
numEvents: num_users * avg_events_per_user,
|
|
161
167
|
numUsers: num_users,
|
|
162
168
|
hasAnonIds: false,
|
|
163
169
|
hasSessionIds: false,
|
|
@@ -175,7 +181,6 @@ const config = {
|
|
|
175
181
|
|
|
176
182
|
hasAvatar: true,
|
|
177
183
|
|
|
178
|
-
batchSize: 2_500_000,
|
|
179
184
|
concurrency: 1,
|
|
180
185
|
writeToDisk: false,
|
|
181
186
|
funnels: [
|
|
@@ -361,7 +366,7 @@ const config = {
|
|
|
361
366
|
},
|
|
362
367
|
],
|
|
363
368
|
superProps: {
|
|
364
|
-
|
|
369
|
+
Platform: [
|
|
365
370
|
"Mobile",
|
|
366
371
|
"Xbox",
|
|
367
372
|
"Playstation",
|
|
@@ -384,15 +389,47 @@ const config = {
|
|
|
384
389
|
|
|
385
390
|
},
|
|
386
391
|
scdProps: {
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
392
|
+
"subscription MRR" : {
|
|
393
|
+
frequency: "week",
|
|
394
|
+
values: u.weighNumRange(0, 250, 1, 200),
|
|
395
|
+
timing: "fixed",
|
|
396
|
+
max: 250,
|
|
397
|
+
},
|
|
398
|
+
player_rank: {
|
|
399
|
+
values: ["bronze", "silver", "gold", "diamond", "legendary"],
|
|
400
|
+
frequency: "week",
|
|
401
|
+
timing: "fuzzy",
|
|
402
|
+
max: 250
|
|
403
|
+
},
|
|
404
|
+
guild_rank: {
|
|
405
|
+
values: ["bronze", "silver", "gold", "legendary"],
|
|
406
|
+
frequency: "month",
|
|
407
|
+
timing: "fixed",
|
|
408
|
+
max: 6,
|
|
409
|
+
type: "guild_id"
|
|
410
|
+
}
|
|
394
411
|
},
|
|
395
412
|
userProps: {
|
|
413
|
+
Platform: [
|
|
414
|
+
"Mobile",
|
|
415
|
+
"Xbox",
|
|
416
|
+
"Playstation",
|
|
417
|
+
"Switch",
|
|
418
|
+
"Web"
|
|
419
|
+
],
|
|
420
|
+
"game mode": u.pickAWinner([
|
|
421
|
+
"Single Player",
|
|
422
|
+
"Multiplayer",
|
|
423
|
+
], 1),
|
|
424
|
+
language: [
|
|
425
|
+
"English",
|
|
426
|
+
"Spanish",
|
|
427
|
+
"French",
|
|
428
|
+
"German",
|
|
429
|
+
"Japanese",
|
|
430
|
+
"Korean",
|
|
431
|
+
"Chinese",
|
|
432
|
+
],
|
|
396
433
|
experiment: [
|
|
397
434
|
"fast leveling",
|
|
398
435
|
"tension economy",
|
|
@@ -500,7 +537,15 @@ const config = {
|
|
|
500
537
|
}
|
|
501
538
|
|
|
502
539
|
if (type === "everything") {
|
|
540
|
+
// Stamp superProps from profile for consistency
|
|
541
|
+
const profile = meta.profile;
|
|
542
|
+
record.forEach(e => {
|
|
543
|
+
e.Platform = profile.Platform;
|
|
544
|
+
e["game mode"] = profile["game mode"];
|
|
545
|
+
e.language = profile.language;
|
|
546
|
+
});
|
|
503
547
|
|
|
548
|
+
return record;
|
|
504
549
|
}
|
|
505
550
|
|
|
506
551
|
return record;
|
|
@@ -411,6 +411,9 @@
|
|
|
411
411
|
},
|
|
412
412
|
{
|
|
413
413
|
"event": "account deactivated",
|
|
414
|
+
"isChurnEvent": true,
|
|
415
|
+
"returnLikelihood": 0.15,
|
|
416
|
+
"isStrictEvent": true,
|
|
414
417
|
"properties": {
|
|
415
418
|
"reason": [
|
|
416
419
|
"switched_provider",
|
|
@@ -422,53 +425,6 @@
|
|
|
422
425
|
}
|
|
423
426
|
}
|
|
424
427
|
],
|
|
425
|
-
"superProps": {
|
|
426
|
-
"subscription_tier": [
|
|
427
|
-
"free",
|
|
428
|
-
"basic",
|
|
429
|
-
"premium"
|
|
430
|
-
],
|
|
431
|
-
"platform": [
|
|
432
|
-
"ios",
|
|
433
|
-
"android",
|
|
434
|
-
"web"
|
|
435
|
-
]
|
|
436
|
-
},
|
|
437
|
-
"userProps": {
|
|
438
|
-
"role": [
|
|
439
|
-
"patient",
|
|
440
|
-
"nurse",
|
|
441
|
-
"doctor"
|
|
442
|
-
],
|
|
443
|
-
"specialty": [
|
|
444
|
-
"none"
|
|
445
|
-
],
|
|
446
|
-
"years_experience": {
|
|
447
|
-
"$range": [
|
|
448
|
-
0,
|
|
449
|
-
5
|
|
450
|
-
]
|
|
451
|
-
},
|
|
452
|
-
"preferred_language": [
|
|
453
|
-
"en",
|
|
454
|
-
"es",
|
|
455
|
-
"pt",
|
|
456
|
-
"de",
|
|
457
|
-
"fr"
|
|
458
|
-
],
|
|
459
|
-
"has_chronic_condition": [
|
|
460
|
-
false,
|
|
461
|
-
true
|
|
462
|
-
],
|
|
463
|
-
"age_range": [
|
|
464
|
-
"18-25",
|
|
465
|
-
"26-35",
|
|
466
|
-
"36-45",
|
|
467
|
-
"46-55",
|
|
468
|
-
"56-65",
|
|
469
|
-
"65+"
|
|
470
|
-
]
|
|
471
|
-
},
|
|
472
428
|
"funnels": [
|
|
473
429
|
{
|
|
474
430
|
"sequence": [
|
|
@@ -477,6 +433,7 @@
|
|
|
477
433
|
"symptom search",
|
|
478
434
|
"appointment booked"
|
|
479
435
|
],
|
|
436
|
+
"name": "Onboarding Flow",
|
|
480
437
|
"isFirstFunnel": true,
|
|
481
438
|
"conversionRate": 45,
|
|
482
439
|
"timeToConvert": 72,
|
|
@@ -488,6 +445,7 @@
|
|
|
488
445
|
"appointment booked",
|
|
489
446
|
"consultation completed"
|
|
490
447
|
],
|
|
448
|
+
"name": "Booking to Consultation",
|
|
491
449
|
"conversionRate": 40,
|
|
492
450
|
"timeToConvert": 48,
|
|
493
451
|
"weight": 5
|
|
@@ -499,6 +457,7 @@
|
|
|
499
457
|
"prescription issued",
|
|
500
458
|
"follow up scheduled"
|
|
501
459
|
],
|
|
460
|
+
"name": "Full Care Journey",
|
|
502
461
|
"conversionRate": 30,
|
|
503
462
|
"timeToConvert": 168,
|
|
504
463
|
"weight": 3
|
|
@@ -509,6 +468,7 @@
|
|
|
509
468
|
"prescription refill",
|
|
510
469
|
"payment processed"
|
|
511
470
|
],
|
|
471
|
+
"name": "Prescription Lifecycle",
|
|
512
472
|
"conversionRate": 55,
|
|
513
473
|
"timeToConvert": 720,
|
|
514
474
|
"weight": 2
|
|
@@ -519,9 +479,71 @@
|
|
|
519
479
|
"provider rated",
|
|
520
480
|
"follow up scheduled"
|
|
521
481
|
],
|
|
482
|
+
"name": "Patient Satisfaction",
|
|
522
483
|
"conversionRate": 25,
|
|
523
484
|
"timeToConvert": 72,
|
|
524
485
|
"weight": 2
|
|
525
486
|
}
|
|
526
|
-
]
|
|
487
|
+
],
|
|
488
|
+
"superProps": {
|
|
489
|
+
"subscription_tier": [
|
|
490
|
+
"free",
|
|
491
|
+
"basic",
|
|
492
|
+
"premium"
|
|
493
|
+
],
|
|
494
|
+
"Platform": [
|
|
495
|
+
"ios",
|
|
496
|
+
"android",
|
|
497
|
+
"web"
|
|
498
|
+
]
|
|
499
|
+
},
|
|
500
|
+
"userProps": {
|
|
501
|
+
"role": [
|
|
502
|
+
"patient",
|
|
503
|
+
"nurse",
|
|
504
|
+
"doctor"
|
|
505
|
+
],
|
|
506
|
+
"specialty": [
|
|
507
|
+
"none"
|
|
508
|
+
],
|
|
509
|
+
"years_experience": {
|
|
510
|
+
"$range": [
|
|
511
|
+
0,
|
|
512
|
+
5
|
|
513
|
+
]
|
|
514
|
+
},
|
|
515
|
+
"preferred_language": [
|
|
516
|
+
"en",
|
|
517
|
+
"es",
|
|
518
|
+
"pt",
|
|
519
|
+
"de",
|
|
520
|
+
"fr"
|
|
521
|
+
],
|
|
522
|
+
"has_chronic_condition": [
|
|
523
|
+
false,
|
|
524
|
+
true
|
|
525
|
+
],
|
|
526
|
+
"age_range": [
|
|
527
|
+
"18-25",
|
|
528
|
+
"26-35",
|
|
529
|
+
"36-45",
|
|
530
|
+
"46-55",
|
|
531
|
+
"56-65",
|
|
532
|
+
"65+"
|
|
533
|
+
]
|
|
534
|
+
},
|
|
535
|
+
"scdProps": {
|
|
536
|
+
"care_plan": {
|
|
537
|
+
"type": "user",
|
|
538
|
+
"frequency": "month",
|
|
539
|
+
"timing": "fuzzy",
|
|
540
|
+
"max": 8,
|
|
541
|
+
"values": [
|
|
542
|
+
"preventive",
|
|
543
|
+
"routine",
|
|
544
|
+
"chronic",
|
|
545
|
+
"acute"
|
|
546
|
+
]
|
|
547
|
+
}
|
|
548
|
+
}
|
|
527
549
|
}
|