@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-media";
|
|
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-media";
|
|
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
|
* ═══════════════════════════════════════════════════════════════════════════════
|
|
@@ -218,10 +225,10 @@ const blockbusterId = `blockbuster_${v.uid(8)}`;
|
|
|
218
225
|
|
|
219
226
|
/** @type {Config} */
|
|
220
227
|
const config = {
|
|
221
|
-
token
|
|
228
|
+
token,
|
|
222
229
|
seed: SEED,
|
|
223
|
-
numDays:
|
|
224
|
-
numEvents: num_users *
|
|
230
|
+
numDays: num_days,
|
|
231
|
+
numEvents: num_users * avg_events_per_user,
|
|
225
232
|
numUsers: num_users,
|
|
226
233
|
hasAnonIds: false,
|
|
227
234
|
hasSessionIds: true,
|
|
@@ -238,7 +245,6 @@ const config = {
|
|
|
238
245
|
hasAdSpend: false,
|
|
239
246
|
percentUsersBornInDataset: 50,
|
|
240
247
|
hasAvatar: true,
|
|
241
|
-
batchSize: 2_500_000,
|
|
242
248
|
concurrency: 1,
|
|
243
249
|
writeToDisk: false,
|
|
244
250
|
|
|
@@ -541,7 +547,14 @@ const config = {
|
|
|
541
547
|
device_type: ["smart_tv", "mobile", "tablet", "laptop", "desktop"],
|
|
542
548
|
},
|
|
543
549
|
|
|
544
|
-
scdProps: {
|
|
550
|
+
scdProps: {
|
|
551
|
+
subscription_plan: {
|
|
552
|
+
values: ["free", "basic", "standard", "premium"],
|
|
553
|
+
frequency: "month",
|
|
554
|
+
timing: "fuzzy",
|
|
555
|
+
max: 6
|
|
556
|
+
}
|
|
557
|
+
},
|
|
545
558
|
|
|
546
559
|
userProps: {
|
|
547
560
|
"preferred_genre": ["action", "comedy", "drama", "documentary", "horror", "sci_fi", "animation"],
|
|
@@ -549,6 +562,8 @@ const config = {
|
|
|
549
562
|
"total_watch_hours": u.weighNumRange(0, 500, 0.8, 50),
|
|
550
563
|
"profiles_count": u.weighNumRange(1, 5),
|
|
551
564
|
"downloads_enabled": [false, false, false, true, true],
|
|
565
|
+
"subscription_plan": ["free", "free", "standard", "standard", "standard", "premium"],
|
|
566
|
+
"device_type": ["smart_tv", "mobile", "tablet", "laptop", "desktop"],
|
|
552
567
|
},
|
|
553
568
|
|
|
554
569
|
lookupTables: [],
|
|
@@ -558,22 +573,22 @@ const config = {
|
|
|
558
573
|
*
|
|
559
574
|
* This hook function creates 8 deliberate patterns in the data:
|
|
560
575
|
*
|
|
561
|
-
* 1. GENRE FUNNEL CONVERSION: Comedy/Animation
|
|
576
|
+
* 1. GENRE FUNNEL CONVERSION: Comedy/Animation props in funnel-pre; documentary completion drop in everything
|
|
562
577
|
* 2. BINGE-WATCHING: Users with 3+ consecutive completions get extra episodes (everything)
|
|
563
578
|
* 3. WEEKEND vs WEEKDAY: Weekend sessions 1.5x longer; weekday prime-time tagging (event)
|
|
564
579
|
* 4. AD FATIGUE CHURN: Free-tier users with 10+ ads churn after day 45 (everything)
|
|
565
580
|
* 5. NEW RELEASE SPIKE: Blockbuster release on day 50 drives content selection (event)
|
|
566
581
|
* 6. KIDS PROFILE SAFETY: Kids mode restricts genres and drops ads (event)
|
|
567
|
-
* 7. RECOMMENDATION ENGINE IMPROVEMENT:
|
|
582
|
+
* 7. RECOMMENDATION ENGINE IMPROVEMENT: Props in funnel-pre; pre-day-60 content rated drop in everything
|
|
568
583
|
* 8. SUBTITLE USERS WATCH MORE: Subtitle-enabled users have higher completion rates (everything)
|
|
569
584
|
*/
|
|
570
585
|
hook: function (record, type, meta) {
|
|
571
586
|
const NOW = dayjs();
|
|
572
|
-
const DATASET_START = NOW.subtract(
|
|
587
|
+
const DATASET_START = NOW.subtract(num_days, 'days');
|
|
573
588
|
// FIXED_START is the pre-shift time range start; needed because
|
|
574
589
|
// meta.firstEventTime in funnel-pre is in the FIXED (pre-shift) timeframe
|
|
575
590
|
const FIXED_NOW_UNIX = dayjs('2024-02-02').unix();
|
|
576
|
-
const FIXED_START = dayjs.unix(FIXED_NOW_UNIX).subtract(
|
|
591
|
+
const FIXED_START = dayjs.unix(FIXED_NOW_UNIX).subtract(num_days, 'days');
|
|
577
592
|
|
|
578
593
|
// ─────────────────────────────────────────────────────────────
|
|
579
594
|
// Hook #1: GENRE FUNNEL CONVERSION (funnel-pre)
|
|
@@ -584,21 +599,17 @@ const config = {
|
|
|
584
599
|
const genre = record.props.genre;
|
|
585
600
|
|
|
586
601
|
if (genre === "comedy" || genre === "animation") {
|
|
587
|
-
record.conversionRate = record.conversionRate * 1.3;
|
|
588
602
|
record.props.genre_boost = true;
|
|
589
603
|
record.props.genre_penalty = false;
|
|
590
604
|
} else if (genre === "documentary") {
|
|
591
|
-
record.conversionRate = record.conversionRate * 0.7;
|
|
592
605
|
record.props.genre_boost = false;
|
|
593
606
|
record.props.genre_penalty = true;
|
|
594
607
|
} else if (!genre && chance.bool({ likelihood: 25 })) {
|
|
595
608
|
// Randomly apply genre effects when genre isn't in funnel props
|
|
596
609
|
if (chance.bool({ likelihood: 60 })) {
|
|
597
|
-
record.conversionRate = record.conversionRate * 1.3;
|
|
598
610
|
record.props.genre_boost = true;
|
|
599
611
|
record.props.genre_penalty = false;
|
|
600
612
|
} else {
|
|
601
|
-
record.conversionRate = record.conversionRate * 0.7;
|
|
602
613
|
record.props.genre_boost = false;
|
|
603
614
|
record.props.genre_penalty = true;
|
|
604
615
|
}
|
|
@@ -617,7 +628,6 @@ const config = {
|
|
|
617
628
|
const isAfterImprovement = funnelTime && funnelTime.isAfter(FIXED_START.add(60, 'days'));
|
|
618
629
|
|
|
619
630
|
if (isEngagementFunnel && isAfterImprovement) {
|
|
620
|
-
record.conversionRate = record.conversionRate * 1.5;
|
|
621
631
|
record.props.improved_recs = true;
|
|
622
632
|
} else {
|
|
623
633
|
record.props.improved_recs = false;
|
|
@@ -705,6 +715,43 @@ const config = {
|
|
|
705
715
|
const userEvents = record;
|
|
706
716
|
if (!userEvents || userEvents.length === 0) return record;
|
|
707
717
|
|
|
718
|
+
const profile = meta.profile;
|
|
719
|
+
|
|
720
|
+
// ─── Stamp superProps from profile (consistent per user) ───
|
|
721
|
+
const stampPlan = profile && profile.subscription_plan ? profile.subscription_plan : undefined;
|
|
722
|
+
const stampDevice = profile && profile.device_type ? profile.device_type : undefined;
|
|
723
|
+
if (stampPlan || stampDevice) {
|
|
724
|
+
userEvents.forEach(e => {
|
|
725
|
+
if (stampPlan) e.subscription_plan = stampPlan;
|
|
726
|
+
if (stampDevice) e.device_type = stampDevice;
|
|
727
|
+
});
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
// ─── Bug 2 fix: Genre funnel conversion filtering ───
|
|
731
|
+
// Drop ~25% of "playback completed" events for documentary genre
|
|
732
|
+
// to simulate lower documentary funnel completion (was conversionRate * 0.7)
|
|
733
|
+
for (let i = userEvents.length - 1; i >= 0; i--) {
|
|
734
|
+
const evt = userEvents[i];
|
|
735
|
+
if (evt.event === "playback completed" && evt.genre_penalty === true) {
|
|
736
|
+
if (chance.bool({ likelihood: 25 })) {
|
|
737
|
+
userEvents.splice(i, 1);
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
// ─── Bug 2 fix: Recommendation engine improvement filtering ───
|
|
743
|
+
// Drop ~30% of "content rated" events that occur BEFORE day 60
|
|
744
|
+
// to simulate lower pre-improvement rec engine conversion (was conversionRate * 1.5)
|
|
745
|
+
const IMPROVEMENT_DATE = DATASET_START.add(60, 'days');
|
|
746
|
+
for (let i = userEvents.length - 1; i >= 0; i--) {
|
|
747
|
+
const evt = userEvents[i];
|
|
748
|
+
if (evt.event === "content rated" && dayjs(evt.time).isBefore(IMPROVEMENT_DATE)) {
|
|
749
|
+
if (chance.bool({ likelihood: 30 })) {
|
|
750
|
+
userEvents.splice(i, 1);
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
|
|
708
755
|
const firstEventTime = dayjs(userEvents[0].time);
|
|
709
756
|
|
|
710
757
|
// ─── First pass: identify user patterns ───
|