@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-education";
|
|
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-education";
|
|
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
|
* ═══════════════════════════════════════════════════════════════════════════════
|
|
@@ -183,10 +190,10 @@ const problemIds = v.range(1, 601).map(n => `problem_${v.uid(6)}`);
|
|
|
183
190
|
|
|
184
191
|
/** @type {Config} */
|
|
185
192
|
const config = {
|
|
186
|
-
token
|
|
193
|
+
token,
|
|
187
194
|
seed: SEED,
|
|
188
|
-
numDays:
|
|
189
|
-
numEvents: num_users *
|
|
195
|
+
numDays: num_days,
|
|
196
|
+
numEvents: num_users * avg_events_per_user,
|
|
190
197
|
numUsers: num_users,
|
|
191
198
|
hasAnonIds: false,
|
|
192
199
|
hasSessionIds: true,
|
|
@@ -203,7 +210,6 @@ const config = {
|
|
|
203
210
|
hasAdSpend: false,
|
|
204
211
|
percentUsersBornInDataset: 50,
|
|
205
212
|
hasAvatar: true,
|
|
206
|
-
batchSize: 2_500_000,
|
|
207
213
|
concurrency: 1,
|
|
208
214
|
writeToDisk: false,
|
|
209
215
|
|
|
@@ -437,10 +443,24 @@ const config = {
|
|
|
437
443
|
],
|
|
438
444
|
|
|
439
445
|
superProps: {
|
|
440
|
-
|
|
446
|
+
Platform: ["Web", "iOS", "Android", "iPad"],
|
|
441
447
|
},
|
|
442
448
|
|
|
443
|
-
scdProps: {
|
|
449
|
+
scdProps: {
|
|
450
|
+
enrollment_status: {
|
|
451
|
+
values: ["enrolled", "active", "completed", "dropped"],
|
|
452
|
+
frequency: "month",
|
|
453
|
+
timing: "fuzzy",
|
|
454
|
+
max: 6
|
|
455
|
+
},
|
|
456
|
+
course_status: {
|
|
457
|
+
values: ["draft", "published", "archived", "deprecated"],
|
|
458
|
+
frequency: "month",
|
|
459
|
+
timing: "fixed",
|
|
460
|
+
max: 6,
|
|
461
|
+
type: "course_id"
|
|
462
|
+
}
|
|
463
|
+
},
|
|
444
464
|
|
|
445
465
|
userProps: {
|
|
446
466
|
"account_type": ["student", "student", "student", "student", "student", "student", "student", "student", "instructor"],
|
|
@@ -453,6 +473,7 @@ const config = {
|
|
|
453
473
|
"instructor_rating": [0],
|
|
454
474
|
"learning_goal": ["none"],
|
|
455
475
|
"study_hours_per_week": [0],
|
|
476
|
+
"Platform": ["Web", "iOS", "Android", "iPad"],
|
|
456
477
|
},
|
|
457
478
|
|
|
458
479
|
groupKeys: [
|
|
@@ -492,7 +513,7 @@ const config = {
|
|
|
492
513
|
*/
|
|
493
514
|
hook: function (record, type, meta) {
|
|
494
515
|
const NOW = dayjs();
|
|
495
|
-
const DATASET_START = NOW.subtract(
|
|
516
|
+
const DATASET_START = NOW.subtract(num_days, 'days');
|
|
496
517
|
|
|
497
518
|
// ═══════════════════════════════════════════════════════════════════
|
|
498
519
|
// Hook #1: STUDENT VS INSTRUCTOR PROFILES
|
|
@@ -608,8 +629,16 @@ const config = {
|
|
|
608
629
|
// ═══════════════════════════════════════════════════════════════════
|
|
609
630
|
if (type === "everything") {
|
|
610
631
|
const userEvents = record;
|
|
632
|
+
const profile = meta.profile;
|
|
611
633
|
const firstEventTime = userEvents.length > 0 ? dayjs(userEvents[0].time) : null;
|
|
612
634
|
|
|
635
|
+
// ── Stamp superProps from profile so they stay consistent per user ──
|
|
636
|
+
if (profile) {
|
|
637
|
+
userEvents.forEach((event) => {
|
|
638
|
+
if (profile.Platform !== undefined) event.Platform = profile.Platform;
|
|
639
|
+
});
|
|
640
|
+
}
|
|
641
|
+
|
|
613
642
|
// ---------------------------------------------------------------
|
|
614
643
|
// First pass: identify user patterns
|
|
615
644
|
// ---------------------------------------------------------------
|
|
@@ -707,7 +736,7 @@ const config = {
|
|
|
707
736
|
}
|
|
708
737
|
|
|
709
738
|
// Hook #7: FREE VS PAID - reinforce the subscription effect on certificates
|
|
710
|
-
const subStatus =
|
|
739
|
+
const subStatus = profile ? profile.subscription_status : "free";
|
|
711
740
|
if (subStatus === "free") {
|
|
712
741
|
// Free users lose 55% of their certificates (simulating lower completion)
|
|
713
742
|
for (let i = userEvents.length - 1; i >= 0; i--) {
|
|
@@ -765,17 +794,11 @@ const config = {
|
|
|
765
794
|
// Hook #7: FREE VS PAID COURSES (funnel-pre)
|
|
766
795
|
// ═══════════════════════════════════════════════════════════════════
|
|
767
796
|
if (type === "funnel-pre") {
|
|
768
|
-
//
|
|
797
|
+
// Hook #7: FREE VS PAID — prop tagging only
|
|
798
|
+
// conversionRate manipulation removed; the everything hook handles
|
|
799
|
+
// the completion gap by dropping 55% of free-user certificates
|
|
769
800
|
if (meta && meta.profile && meta.funnel) {
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
if (subscriptionStatus === "free") {
|
|
773
|
-
// Free users convert at 0.5x rate
|
|
774
|
-
record.conversionRate = (record.conversionRate || 0.25) * 0.5;
|
|
775
|
-
} else if (subscriptionStatus === "monthly" || subscriptionStatus === "annual") {
|
|
776
|
-
// Paid subscribers convert at 1.5x rate
|
|
777
|
-
record.conversionRate = (record.conversionRate || 0.25) * 1.5;
|
|
778
|
-
}
|
|
801
|
+
// no-op: kept for future prop-setting if needed
|
|
779
802
|
}
|
|
780
803
|
}
|
|
781
804
|
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
"isFirstEvent": true,
|
|
6
6
|
"properties": {
|
|
7
7
|
"account_type": [
|
|
8
|
-
"
|
|
9
|
-
"
|
|
8
|
+
"personal",
|
|
9
|
+
"business"
|
|
10
10
|
],
|
|
11
11
|
"signup_channel": [
|
|
12
12
|
"app",
|
|
@@ -22,14 +22,14 @@
|
|
|
22
22
|
"properties": {
|
|
23
23
|
"session_duration_sec": {
|
|
24
24
|
"$range": [
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
115,
|
|
26
|
+
487
|
|
27
27
|
]
|
|
28
28
|
},
|
|
29
29
|
"pages_viewed": [
|
|
30
30
|
5,
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
10,
|
|
32
|
+
4
|
|
33
33
|
],
|
|
34
34
|
"month_end_anxiety": [
|
|
35
35
|
false
|
|
@@ -140,9 +140,10 @@
|
|
|
140
140
|
2710
|
|
141
141
|
]
|
|
142
142
|
},
|
|
143
|
-
"auto_pay":
|
|
144
|
-
|
|
145
|
-
|
|
143
|
+
"auto_pay": [
|
|
144
|
+
false,
|
|
145
|
+
true
|
|
146
|
+
],
|
|
146
147
|
"missed_payment": [
|
|
147
148
|
false
|
|
148
149
|
],
|
|
@@ -235,7 +236,8 @@
|
|
|
235
236
|
]
|
|
236
237
|
},
|
|
237
238
|
"action": [
|
|
238
|
-
"buy"
|
|
239
|
+
"buy",
|
|
240
|
+
"sell"
|
|
239
241
|
],
|
|
240
242
|
"premium_returns": [
|
|
241
243
|
false
|
|
@@ -316,13 +318,12 @@
|
|
|
316
318
|
]
|
|
317
319
|
},
|
|
318
320
|
"interest_rate": [
|
|
319
|
-
4,
|
|
320
|
-
14,
|
|
321
|
-
7,
|
|
322
321
|
17,
|
|
323
322
|
10,
|
|
324
323
|
18,
|
|
325
|
-
8
|
|
324
|
+
8,
|
|
325
|
+
9,
|
|
326
|
+
6
|
|
326
327
|
]
|
|
327
328
|
}
|
|
328
329
|
},
|
|
@@ -336,13 +337,13 @@
|
|
|
336
337
|
"premium"
|
|
337
338
|
],
|
|
338
339
|
"new_tier": [
|
|
339
|
-
"
|
|
340
|
-
"
|
|
340
|
+
"plus",
|
|
341
|
+
"premium"
|
|
341
342
|
],
|
|
342
343
|
"monthly_fee": [
|
|
343
|
-
14.99,
|
|
344
344
|
4.99,
|
|
345
|
-
9.99
|
|
345
|
+
9.99,
|
|
346
|
+
14.99
|
|
346
347
|
]
|
|
347
348
|
}
|
|
348
349
|
},
|
|
@@ -363,9 +364,10 @@
|
|
|
363
364
|
"transfer",
|
|
364
365
|
"technical"
|
|
365
366
|
],
|
|
366
|
-
"resolved":
|
|
367
|
-
|
|
368
|
-
|
|
367
|
+
"resolved": [
|
|
368
|
+
false,
|
|
369
|
+
true
|
|
370
|
+
],
|
|
369
371
|
"fraud_sequence": [
|
|
370
372
|
false
|
|
371
373
|
]
|
|
@@ -383,9 +385,10 @@
|
|
|
383
385
|
"security",
|
|
384
386
|
"promo"
|
|
385
387
|
],
|
|
386
|
-
"action_taken":
|
|
387
|
-
|
|
388
|
-
|
|
388
|
+
"action_taken": [
|
|
389
|
+
false,
|
|
390
|
+
true
|
|
391
|
+
]
|
|
389
392
|
}
|
|
390
393
|
},
|
|
391
394
|
{
|
|
@@ -399,15 +402,15 @@
|
|
|
399
402
|
"partner_offer"
|
|
400
403
|
],
|
|
401
404
|
"value": [
|
|
405
|
+
74,
|
|
406
|
+
39,
|
|
402
407
|
23,
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
47,
|
|
410
|
-
20
|
|
408
|
+
30,
|
|
409
|
+
60,
|
|
410
|
+
73,
|
|
411
|
+
46,
|
|
412
|
+
25,
|
|
413
|
+
27
|
|
411
414
|
],
|
|
412
415
|
"premium_reward": [
|
|
413
416
|
false
|
|
@@ -415,71 +418,6 @@
|
|
|
415
418
|
}
|
|
416
419
|
}
|
|
417
420
|
],
|
|
418
|
-
"superProps": {
|
|
419
|
-
"account_tier": [
|
|
420
|
-
"plus",
|
|
421
|
-
"basic",
|
|
422
|
-
"premium"
|
|
423
|
-
],
|
|
424
|
-
"platform": [
|
|
425
|
-
"ios",
|
|
426
|
-
"android",
|
|
427
|
-
"web"
|
|
428
|
-
],
|
|
429
|
-
"low_balance_churn": [
|
|
430
|
-
false
|
|
431
|
-
]
|
|
432
|
-
},
|
|
433
|
-
"userProps": {
|
|
434
|
-
"credit_score_range": [
|
|
435
|
-
"300-579",
|
|
436
|
-
"580-669",
|
|
437
|
-
"670-739",
|
|
438
|
-
"740-799",
|
|
439
|
-
"800-850"
|
|
440
|
-
],
|
|
441
|
-
"income_bracket": [
|
|
442
|
-
"under_30k",
|
|
443
|
-
"30k_50k",
|
|
444
|
-
"50k_75k",
|
|
445
|
-
"75k_100k",
|
|
446
|
-
"100k_150k",
|
|
447
|
-
"over_150k"
|
|
448
|
-
],
|
|
449
|
-
"account_age_months": {
|
|
450
|
-
"$range": [
|
|
451
|
-
17,
|
|
452
|
-
46
|
|
453
|
-
]
|
|
454
|
-
},
|
|
455
|
-
"total_balance": {
|
|
456
|
-
"$range": [
|
|
457
|
-
16006,
|
|
458
|
-
83008
|
|
459
|
-
]
|
|
460
|
-
},
|
|
461
|
-
"has_direct_deposit": {
|
|
462
|
-
"$type": "array"
|
|
463
|
-
},
|
|
464
|
-
"account_segment": [
|
|
465
|
-
"personal"
|
|
466
|
-
],
|
|
467
|
-
"employee_count": [
|
|
468
|
-
0
|
|
469
|
-
],
|
|
470
|
-
"annual_revenue": [
|
|
471
|
-
0
|
|
472
|
-
],
|
|
473
|
-
"industry": [
|
|
474
|
-
""
|
|
475
|
-
],
|
|
476
|
-
"age_range": [
|
|
477
|
-
""
|
|
478
|
-
],
|
|
479
|
-
"life_stage": [
|
|
480
|
-
""
|
|
481
|
-
]
|
|
482
|
-
},
|
|
483
421
|
"funnels": [
|
|
484
422
|
{
|
|
485
423
|
"sequence": [
|
|
@@ -559,5 +497,134 @@
|
|
|
559
497
|
"conversionRate": 25,
|
|
560
498
|
"timeToConvert": 10
|
|
561
499
|
}
|
|
562
|
-
]
|
|
500
|
+
],
|
|
501
|
+
"superProps": {
|
|
502
|
+
"account_tier": [
|
|
503
|
+
"basic",
|
|
504
|
+
"plus",
|
|
505
|
+
"premium"
|
|
506
|
+
],
|
|
507
|
+
"Platform": [
|
|
508
|
+
"ios",
|
|
509
|
+
"android",
|
|
510
|
+
"web"
|
|
511
|
+
],
|
|
512
|
+
"low_balance_churn": [
|
|
513
|
+
false
|
|
514
|
+
]
|
|
515
|
+
},
|
|
516
|
+
"userProps": {
|
|
517
|
+
"credit_score_range": [
|
|
518
|
+
"300-579",
|
|
519
|
+
"580-669",
|
|
520
|
+
"670-739",
|
|
521
|
+
"740-799",
|
|
522
|
+
"800-850"
|
|
523
|
+
],
|
|
524
|
+
"income_bracket": [
|
|
525
|
+
"under_30k",
|
|
526
|
+
"30k_50k",
|
|
527
|
+
"50k_75k",
|
|
528
|
+
"75k_100k",
|
|
529
|
+
"100k_150k",
|
|
530
|
+
"over_150k"
|
|
531
|
+
],
|
|
532
|
+
"account_age_months": {
|
|
533
|
+
"$range": [
|
|
534
|
+
15,
|
|
535
|
+
44
|
|
536
|
+
]
|
|
537
|
+
},
|
|
538
|
+
"total_balance": {
|
|
539
|
+
"$range": [
|
|
540
|
+
16006,
|
|
541
|
+
83008
|
|
542
|
+
]
|
|
543
|
+
},
|
|
544
|
+
"has_direct_deposit": [
|
|
545
|
+
false,
|
|
546
|
+
true
|
|
547
|
+
],
|
|
548
|
+
"account_segment": [
|
|
549
|
+
"personal"
|
|
550
|
+
],
|
|
551
|
+
"employee_count": [
|
|
552
|
+
0
|
|
553
|
+
],
|
|
554
|
+
"annual_revenue": [
|
|
555
|
+
0
|
|
556
|
+
],
|
|
557
|
+
"industry": [
|
|
558
|
+
""
|
|
559
|
+
],
|
|
560
|
+
"age_range": [
|
|
561
|
+
""
|
|
562
|
+
],
|
|
563
|
+
"life_stage": [
|
|
564
|
+
""
|
|
565
|
+
]
|
|
566
|
+
},
|
|
567
|
+
"groupKeys": [
|
|
568
|
+
{
|
|
569
|
+
"key": "household_id",
|
|
570
|
+
"count": 500,
|
|
571
|
+
"affectsEvents": [
|
|
572
|
+
"transaction completed",
|
|
573
|
+
"transfer sent",
|
|
574
|
+
"bill paid",
|
|
575
|
+
"savings goal set"
|
|
576
|
+
]
|
|
577
|
+
}
|
|
578
|
+
],
|
|
579
|
+
"groupProps": {
|
|
580
|
+
"household_id": {
|
|
581
|
+
"household_size": {
|
|
582
|
+
"$range": [
|
|
583
|
+
1,
|
|
584
|
+
6
|
|
585
|
+
]
|
|
586
|
+
},
|
|
587
|
+
"combined_income": {
|
|
588
|
+
"$range": [
|
|
589
|
+
61633,
|
|
590
|
+
263131
|
|
591
|
+
]
|
|
592
|
+
},
|
|
593
|
+
"financial_health_score": {
|
|
594
|
+
"$range": [
|
|
595
|
+
12,
|
|
596
|
+
81
|
|
597
|
+
]
|
|
598
|
+
},
|
|
599
|
+
"primary_bank": [
|
|
600
|
+
"NexBank_only",
|
|
601
|
+
"multi_bank"
|
|
602
|
+
]
|
|
603
|
+
}
|
|
604
|
+
},
|
|
605
|
+
"scdProps": {
|
|
606
|
+
"account_tier": {
|
|
607
|
+
"type": "user",
|
|
608
|
+
"frequency": "month",
|
|
609
|
+
"timing": "fuzzy",
|
|
610
|
+
"max": 6,
|
|
611
|
+
"values": [
|
|
612
|
+
"basic",
|
|
613
|
+
"plus",
|
|
614
|
+
"premium"
|
|
615
|
+
]
|
|
616
|
+
},
|
|
617
|
+
"risk_category": {
|
|
618
|
+
"type": "household_id",
|
|
619
|
+
"frequency": "month",
|
|
620
|
+
"timing": "fixed",
|
|
621
|
+
"max": 8,
|
|
622
|
+
"values": [
|
|
623
|
+
"low",
|
|
624
|
+
"medium",
|
|
625
|
+
"high",
|
|
626
|
+
"critical"
|
|
627
|
+
]
|
|
628
|
+
}
|
|
629
|
+
}
|
|
563
630
|
}
|
|
@@ -1,15 +1,22 @@
|
|
|
1
|
+
// ── TWEAK THESE ──
|
|
2
|
+
const SEED = "harness-fintech";
|
|
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 = "harness-fintech";
|
|
7
16
|
dayjs.extend(utc);
|
|
8
17
|
const chance = u.initChance(SEED);
|
|
9
|
-
const num_users = 5_000;
|
|
10
|
-
const days = 100;
|
|
11
18
|
|
|
12
|
-
/** @typedef {import("
|
|
19
|
+
/** @typedef {import("../../types").Dungeon} Config */
|
|
13
20
|
|
|
14
21
|
/**
|
|
15
22
|
* ===================================================================
|
|
@@ -129,10 +136,10 @@ const days = 100;
|
|
|
129
136
|
|
|
130
137
|
/** @type {Config} */
|
|
131
138
|
const config = {
|
|
132
|
-
token
|
|
139
|
+
token,
|
|
133
140
|
seed: SEED,
|
|
134
|
-
numDays:
|
|
135
|
-
numEvents: num_users *
|
|
141
|
+
numDays: num_days,
|
|
142
|
+
numEvents: num_users * avg_events_per_user,
|
|
136
143
|
numUsers: num_users,
|
|
137
144
|
hasAnonIds: false,
|
|
138
145
|
hasSessionIds: true,
|
|
@@ -151,11 +158,24 @@ const config = {
|
|
|
151
158
|
|
|
152
159
|
hasAvatar: true,
|
|
153
160
|
|
|
154
|
-
batchSize: 2_500_000,
|
|
155
161
|
concurrency: 1,
|
|
156
162
|
writeToDisk: false,
|
|
157
163
|
|
|
158
|
-
scdProps: {
|
|
164
|
+
scdProps: {
|
|
165
|
+
account_tier: {
|
|
166
|
+
values: ["basic", "plus", "premium"],
|
|
167
|
+
frequency: "month",
|
|
168
|
+
timing: "fuzzy",
|
|
169
|
+
max: 6
|
|
170
|
+
},
|
|
171
|
+
risk_category: {
|
|
172
|
+
values: ["low", "medium", "high", "critical"],
|
|
173
|
+
frequency: "month",
|
|
174
|
+
timing: "fixed",
|
|
175
|
+
max: 8,
|
|
176
|
+
type: "household_id"
|
|
177
|
+
}
|
|
178
|
+
},
|
|
159
179
|
|
|
160
180
|
funnels: [
|
|
161
181
|
{
|
|
@@ -387,11 +407,14 @@ const config = {
|
|
|
387
407
|
|
|
388
408
|
superProps: {
|
|
389
409
|
account_tier: ["basic", "basic", "basic", "plus", "plus", "premium"],
|
|
390
|
-
|
|
410
|
+
Platform: ["ios", "android", "web"],
|
|
391
411
|
low_balance_churn: [false],
|
|
392
412
|
},
|
|
393
413
|
|
|
394
414
|
userProps: {
|
|
415
|
+
account_tier: ["basic", "basic", "basic", "plus", "plus", "premium"],
|
|
416
|
+
Platform: ["ios", "android", "web"],
|
|
417
|
+
low_balance_churn: [false],
|
|
395
418
|
"credit_score_range": ["300-579", "580-669", "670-739", "740-799", "800-850"],
|
|
396
419
|
"income_bracket": ["under_30k", "30k_50k", "50k_75k", "75k_100k", "100k_150k", "over_150k"],
|
|
397
420
|
"account_age_months": u.weighNumRange(1, 60, 0.5, 12),
|
|
@@ -436,7 +459,7 @@ const config = {
|
|
|
436
459
|
*/
|
|
437
460
|
hook: function (record, type, meta) {
|
|
438
461
|
const NOW = dayjs();
|
|
439
|
-
const DATASET_START = NOW.subtract(
|
|
462
|
+
const DATASET_START = NOW.subtract(num_days, "days");
|
|
440
463
|
|
|
441
464
|
// ===============================================================
|
|
442
465
|
// Hook #1: PERSONAL VS BUSINESS ACCOUNTS (user)
|
|
@@ -568,6 +591,15 @@ const config = {
|
|
|
568
591
|
// ===============================================================
|
|
569
592
|
if (type === "everything") {
|
|
570
593
|
const userEvents = record;
|
|
594
|
+
|
|
595
|
+
// Stamp superProps from profile for consistency
|
|
596
|
+
const profile = meta.profile;
|
|
597
|
+
userEvents.forEach(e => {
|
|
598
|
+
e.account_tier = profile.account_tier;
|
|
599
|
+
e.Platform = profile.Platform;
|
|
600
|
+
e.low_balance_churn = profile.low_balance_churn;
|
|
601
|
+
});
|
|
602
|
+
|
|
571
603
|
const firstEventTime = userEvents.length > 0 ? dayjs(userEvents[0].time) : null;
|
|
572
604
|
|
|
573
605
|
// -----------------------------------------------------------
|