make-mp-data 3.0.3 → 3.0.5

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 (70) hide show
  1. package/README.md +46 -0
  2. package/dungeons/array-of-object-lookup-schema.json +327 -0
  3. package/dungeons/array-of-object-lookup.js +29 -9
  4. package/dungeons/capstone/capstone-ic3.js +291 -0
  5. package/dungeons/capstone/capstone-ic4.js +598 -0
  6. package/dungeons/capstone/capstone-ic5.js +668 -0
  7. package/dungeons/capstone/generate-product-lookup.js +309 -0
  8. package/dungeons/ecommerce-schema.json +462 -0
  9. package/dungeons/{copilot.js → ecommerce.js} +79 -17
  10. package/dungeons/education-schema.json +2409 -0
  11. package/dungeons/education.js +226 -462
  12. package/dungeons/fintech-schema.json +14034 -0
  13. package/dungeons/fintech.js +134 -413
  14. package/dungeons/foobar-schema.json +403 -0
  15. package/dungeons/foobar.js +27 -4
  16. package/dungeons/food-delivery-schema.json +192 -0
  17. package/dungeons/food-delivery.js +602 -0
  18. package/dungeons/food-schema.json +1152 -0
  19. package/dungeons/food.js +173 -406
  20. package/dungeons/gaming-schema.json +1270 -0
  21. package/dungeons/gaming.js +182 -42
  22. package/dungeons/insurance-application-schema.json +204 -0
  23. package/dungeons/insurance-application.js +605 -0
  24. package/dungeons/media-schema.json +906 -0
  25. package/dungeons/media.js +250 -420
  26. package/dungeons/retention-cadence-schema.json +78 -0
  27. package/dungeons/retention-cadence.js +35 -1
  28. package/dungeons/rpg-schema.json +4526 -0
  29. package/dungeons/rpg.js +171 -429
  30. package/dungeons/sanity-schema.json +255 -0
  31. package/dungeons/sanity.js +21 -10
  32. package/dungeons/sass-schema.json +1291 -0
  33. package/dungeons/sass.js +241 -368
  34. package/dungeons/scd-schema.json +919 -0
  35. package/dungeons/scd.js +41 -13
  36. package/dungeons/simple-schema.json +608 -0
  37. package/dungeons/simple.js +52 -15
  38. package/dungeons/simplest-schema.json +1418 -0
  39. package/dungeons/simplest.js +392 -0
  40. package/dungeons/social-schema.json +1118 -0
  41. package/dungeons/social.js +150 -391
  42. package/dungeons/text-generation-schema.json +3096 -0
  43. package/dungeons/text-generation.js +71 -0
  44. package/index.js +8 -6
  45. package/lib/core/config-validator.js +28 -8
  46. package/lib/core/storage.js +5 -5
  47. package/lib/generators/events.js +4 -4
  48. package/lib/orchestrators/mixpanel-sender.js +16 -13
  49. package/lib/orchestrators/user-loop.js +14 -6
  50. package/lib/templates/soup-presets.js +188 -0
  51. package/lib/utils/utils.js +52 -6
  52. package/package.json +1 -1
  53. package/types.d.ts +20 -3
  54. package/dungeons/adspend.js +0 -130
  55. package/dungeons/anon.js +0 -128
  56. package/dungeons/benchmark-heavy.js +0 -240
  57. package/dungeons/benchmark-light.js +0 -140
  58. package/dungeons/big.js +0 -226
  59. package/dungeons/business.js +0 -391
  60. package/dungeons/complex.js +0 -428
  61. package/dungeons/experiments.js +0 -137
  62. package/dungeons/funnels.js +0 -309
  63. package/dungeons/mil.js +0 -323
  64. package/dungeons/mirror.js +0 -161
  65. package/dungeons/soup-test.js +0 -52
  66. package/dungeons/streaming.js +0 -372
  67. package/dungeons/strict-event-test.js +0 -30
  68. package/dungeons/student-teacher.js +0 -438
  69. package/dungeons/too-big-events.js +0 -203
  70. package/dungeons/user-agent.js +0 -209
package/dungeons/media.js CHANGED
@@ -10,59 +10,206 @@ const chance = u.initChance(SEED);
10
10
  const num_users = 5_000;
11
11
  const days = 100;
12
12
 
13
- /** @typedef {import("../../types.js").Dungeon} Config */
13
+ /** @typedef {import("../types.js").Dungeon} Config */
14
14
 
15
15
  /**
16
- * STREAMVAULT - Video Streaming Platform Analytics
16
+ * ═══════════════════════════════════════════════════════════════════════════════
17
+ * DATASET OVERVIEW — STREAMVAULT VIDEO STREAMING PLATFORM
18
+ * ═══════════════════════════════════════════════════════════════════════════════
17
19
  *
18
20
  * StreamVault is a Netflix/Hulu-style video streaming platform where users browse a rich
19
21
  * catalog of movies, series, documentaries, and specials. Users manage watchlists, watch
20
22
  * content with configurable playback options, rate and share content, and manage family
21
- * profiles under a single account. Monetization runs through tiered subscriptions:
22
- * Free (ad-supported), Standard (ad-free HD), and Premium (4K, offline downloads, 5 profiles).
23
- *
24
- * CONTENT DISCOVERY:
25
- * Users land on a personalized home screen with sections like "Continue Watching",
26
- * "Trending Now", "New Releases", and genre-based rows. A recommendation engine (using
27
- * collaborative filtering, content-based, trending, and editorial algorithms) surfaces
28
- * relevant content. Users can also search by title, actor, director, or genre. The browse
29
- * and search patterns reveal how users navigate the catalog and which discovery paths
30
- * lead to actual viewership.
31
- *
32
- * PLAYBACK EXPERIENCE:
33
- * Once content is selected, playback begins with quality auto-selected based on connection
34
- * speed (480p to 4K). Users can adjust playback speed, toggle subtitles in multiple
35
- * languages, and pause/resume. Playback completion percentage and watch duration are
36
- * tracked to understand engagement depth. Some users exhibit "binge-watching" behavior,
37
- * consuming multiple episodes consecutively with high completion rates and minimal pausing.
38
- *
39
- * PROFILE MANAGEMENT:
40
- * A single account supports multiple profiles: main, kids, partner, and guest. The kids
41
- * profile has content restrictions (only animation and documentaries, no ads). Profile
42
- * switching events reveal household composition and viewing patterns across family members.
43
- *
44
- * MONETIZATION MODEL:
45
- * - Free tier: Ad-supported with pre-roll, mid-roll, banner, and interstitial ads. Users
46
- * on this tier experience ad fatigue over time, which drives churn or upgrades.
47
- * - Standard tier ($9.99/mo): Ad-free viewing in HD, 2 simultaneous streams.
48
- * - Premium tier ($14.99/mo): 4K streaming, offline downloads, 5 profiles, early access.
49
- * - Subscription changes (upgrades, downgrades, cancellations, resubscriptions) are tracked
50
- * with reasons to understand the lifecycle of subscriber value.
51
- *
52
- * CONTENT ENGAGEMENT:
53
- * Users rate content (1-5 stars with optional review text), add/remove items from their
54
- * watchlist, share content via link/social/DM/email, and download content for offline
55
- * viewing. These engagement signals feed back into the recommendation engine and reveal
56
- * content quality and user satisfaction patterns.
57
- *
58
- * WHY THESE EVENTS/PROPERTIES?
59
- * - Events model the full streaming lifecycle: onboarding -> discovery -> consumption -> engagement -> monetization
60
- * - Properties enable cohort analysis: subscription tier, device type, genre preference, viewing patterns
61
- * - Funnels reveal friction: where do users drop off between browsing, selecting, starting, and finishing content?
62
- * - The recommendation engine creates measurable A/B-testable discovery paths
63
- * - Ad impression tracking enables fatigue analysis and churn prediction for free-tier users
64
- * - Profile switching reveals household dynamics and kids safety patterns
65
- * - The 8 "needle in haystack" hooks simulate real product insights hidden in production data
23
+ * profiles under a single account.
24
+ *
25
+ * - 5,000 users over 100 days
26
+ * - ~600,000 events across 17 event types
27
+ * - 9 funnels (onboarding, content discovery, engagement loop, search, watchlist, etc.)
28
+ * - Subscription tiers: Free (ad-supported), Standard ($9.99/mo), Premium ($14.99/mo)
29
+ * - Device types: Smart TV, Mobile, Tablet, Laptop, Desktop
30
+ * - Content catalog: 500 titles with genres, types, and a blockbuster release event
31
+ *
32
+ * Core loop: onboarding -> discovery -> consumption -> engagement -> monetization.
33
+ * Users land on a personalized home screen, discover content via browse/search/recommendations,
34
+ * watch with quality and subtitle options, rate and share, and manage subscriptions.
35
+ * Profile switching (main, kids, partner, guest) reveals household dynamics.
36
+ */
37
+
38
+ /**
39
+ * ═══════════════════════════════════════════════════════════════════════════════
40
+ * ANALYTICS HOOKS (8 architected patterns)
41
+ * ═══════════════════════════════════════════════════════════════════════════════
42
+ *
43
+ * ───────────────────────────────────────────────────────────────────────────────
44
+ * 1. GENRE FUNNEL CONVERSION (funnel-pre)
45
+ * ───────────────────────────────────────────────────────────────────────────────
46
+ *
47
+ * PATTERN: Comedy and Animation content has 1.3x higher funnel conversion rates,
48
+ * while Documentary content has 0.7x conversion (users browse but abandon more).
49
+ *
50
+ * HOW TO FIND IT:
51
+ * - Funnels: "content browsed" -> "content selected" -> "playback started" -> "playback completed"
52
+ * - Breakdown: "genre"
53
+ * - Expected: Comedy/Animation convert at ~65% vs Documentary at ~35%
54
+ * - Also try: Insights on "content selected", breakdown by "genre_boost"
55
+ *
56
+ * ───────────────────────────────────────────────────────────────────────────────
57
+ * 2. BINGE-WATCHING PATTERN (everything)
58
+ * ───────────────────────────────────────────────────────────────────────────────
59
+ *
60
+ * PATTERN: Users who complete 3+ episodes consecutively become "binge-watchers":
61
+ * - Extra playback started + playback completed events are spliced in
62
+ * - Completion percentages are 90-100% (they finish every episode)
63
+ * - Pause events are reduced by 60% (they don't stop watching)
64
+ * - Events tagged with binge_session = true
65
+ *
66
+ * HOW TO FIND IT:
67
+ * - Insights: "playback completed", total events per user, breakdown by "binge_session"
68
+ * - Expected: binge_session=true users have 40-60% more completions per user
69
+ * - Also try: Average of "completion_percent" by "binge_session" (90-100% vs ~70%)
70
+ *
71
+ * ───────────────────────────────────────────────────────────────────────────────
72
+ * 3. WEEKEND vs WEEKDAY PATTERNS (event)
73
+ * ───────────────────────────────────────────────────────────────────────────────
74
+ *
75
+ * PATTERN: Weekend viewing sessions are 1.5x longer than weekday sessions.
76
+ * Weekday viewing concentrates in evening prime-time (6PM-11PM).
77
+ *
78
+ * HOW TO FIND IT:
79
+ * - Insights: "playback completed", average of "watch_duration_min", breakdown by "weekend_viewing"
80
+ * - Expected: weekend_viewing=true ~67 min avg vs false ~45 min avg (1.5x)
81
+ * - Also try: Total "playback completed" events by "prime_time" (60-70% of weekday views)
82
+ *
83
+ * ───────────────────────────────────────────────────────────────────────────────
84
+ * 4. AD FATIGUE CHURN (everything)
85
+ * ───────────────────────────────────────────────────────────────────────────────
86
+ *
87
+ * PATTERN: Free-tier users who see 10+ ad impressions experience 50% churn
88
+ * after day 45 of their lifecycle.
89
+ *
90
+ * HOW TO FIND IT:
91
+ * - Retention: any event (filter subscription_plan=free), segment by ad impression count >= 10 vs < 10
92
+ * - Expected: 10+ ad users show ~50% retention drop after day 45
93
+ * - Also try: Insights line chart, any event filtered by "ad_fatigue" = true, weekly trend
94
+ *
95
+ * ───────────────────────────────────────────────────────────────────────────────
96
+ * 5. NEW RELEASE SPIKE (event)
97
+ * ───────────────────────────────────────────────────────────────────────────────
98
+ *
99
+ * PATTERN: On day 50, a blockbuster movie releases, creating a content spike:
100
+ * - 20% of content selected and playback started events redirect to the blockbuster
101
+ * - Content rated events for the blockbuster skew to 4-5 star ratings
102
+ * - All affected events tagged with blockbuster_release = true
103
+ *
104
+ * HOW TO FIND IT:
105
+ * - Insights line chart: "content selected", filter "blockbuster_release" = true, daily trend
106
+ * - Expected: Zero before day 50, then ~20% of content selections
107
+ * - Also try: "content rated" average of "rating" by "blockbuster_release" (4-5 vs ~3.5)
108
+ *
109
+ * ───────────────────────────────────────────────────────────────────────────────
110
+ * 6. KIDS PROFILE SAFETY (event)
111
+ * ───────────────────────────────────────────────────────────────────────────────
112
+ *
113
+ * PATTERN: 15% of the time, events are tagged as kids profile activity:
114
+ * - Content selection restricted to animation and documentary genres
115
+ * - Ad impressions are blocked (ad_blocked = true)
116
+ * - Events tagged with kids_profile = true
117
+ *
118
+ * HOW TO FIND IT:
119
+ * - Insights: "content selected", breakdown by "genre", filter "kids_profile" = true
120
+ * - Expected: 100% animation and documentary genres only
121
+ * - Also try: "ad impression" breakdown by "kids_profile" — kids should have ad_blocked=true
122
+ *
123
+ * ───────────────────────────────────────────────────────────────────────────────
124
+ * 7. RECOMMENDATION ENGINE IMPROVEMENT (funnel-pre)
125
+ * ───────────────────────────────────────────────────────────────────────────────
126
+ *
127
+ * PATTERN: After day 60, the engagement loop funnel (recommendation clicked ->
128
+ * playback started -> content rated) gets a 1.5x conversion rate boost,
129
+ * simulating a recommendation engine improvement.
130
+ *
131
+ * HOW TO FIND IT:
132
+ * - Funnels: "recommendation clicked" -> "playback started" -> "playback completed" -> "content rated"
133
+ * - Breakdown: "improved_recs"
134
+ * - Expected: improved_recs=true shows ~1.5x higher conversion rate
135
+ * - Also try: Insights line chart of "recommendation clicked" filtered by "improved_recs" = true
136
+ *
137
+ * ───────────────────────────────────────────────────────────────────────────────
138
+ * 8. SUBTITLE USERS WATCH MORE (everything)
139
+ * ───────────────────────────────────────────────────────────────────────────────
140
+ *
141
+ * PATTERN: Users who enable subtitles have measurably higher engagement:
142
+ * - 25% higher completion_percent on playback completed events (capped at 100)
143
+ * - 15% longer watch_duration_min
144
+ * - 20% more playback completed events (extra content consumption)
145
+ * - Events tagged with subtitle_user = true
146
+ *
147
+ * HOW TO FIND IT:
148
+ * - Insights: "playback completed", average of "completion_percent", breakdown by "subtitle_user"
149
+ * - Expected: subtitle_user=true ~85% completion vs false ~68% (1.25x)
150
+ * - Also try: Average of "watch_duration_min" by "subtitle_user" (~15% longer)
151
+ * - Also try: Total events per user by "subtitle_user" (~20% more completions)
152
+ *
153
+ * ═══════════════════════════════════════════════════════════════════════════════
154
+ * EXPECTED METRICS SUMMARY
155
+ * ═══════════════════════════════════════════════════════════════════════════════
156
+ *
157
+ * Hook | Metric | Baseline | Hook Effect | Ratio
158
+ * ─────────────────────────|─────────────────────────|───────────|─────────────|──────
159
+ * Genre Funnel Conversion | Funnel conversion rate | 50% | 65% / 35% | 1.3x / 0.7x
160
+ * Binge-Watching | Content consumed/user | 12 | 18-20 | ~1.5x
161
+ * Weekend vs Weekday | Watch duration (min) | 45 | 67 (weekend)| 1.5x
162
+ * Ad Fatigue Churn | Post-day-45 activity | 100% | 50% | 0.5x
163
+ * New Release Spike | Content selections/day | baseline | +20% spike | 1.2x
164
+ * Kids Profile Safety | Ad impressions | normal | 0 (dropped) | 0x
165
+ * Rec Engine Improvement | Engagement funnel conv | 30% | 45% | 1.5x
166
+ * Subtitle Users | Completion percent | 68% | 85% | 1.25x
167
+ *
168
+ * ═══════════════════════════════════════════════════════════════════════════════
169
+ * ADVANCED ANALYSIS IDEAS
170
+ * ═══════════════════════════════════════════════════════════════════════════════
171
+ *
172
+ * CROSS-HOOK PATTERNS:
173
+ *
174
+ * 1. Binge + Subtitle: Do subtitle-enabled binge-watchers have the highest
175
+ * total watch hours? (Hooks #2 + #8 combined)
176
+ *
177
+ * 2. Ad Fatigue + Blockbuster: Does the blockbuster release (Hook #5) rescue
178
+ * free-tier users from ad fatigue churn (Hook #4)?
179
+ *
180
+ * 3. Kids + Weekend: Is kids profile viewing concentrated on weekends (Hook #6
181
+ * + #3)? Does weekend kids viewing show different genre preferences?
182
+ *
183
+ * 4. Rec Engine + Genre: Does the recommendation engine improvement (Hook #7)
184
+ * disproportionately help certain genres (Hook #1)?
185
+ *
186
+ * 5. Subtitle + Binge + Weekend: The "super viewer" - subtitle-enabled,
187
+ * binge-watching on weekends. What is their lifetime watch hours?
188
+ *
189
+ * COHORT ANALYSIS:
190
+ *
191
+ * - Cohort by signup_source: Do referral users binge more than organic?
192
+ * - Cohort by device_type: Do smart TV users watch longer than mobile?
193
+ * - Cohort by subscription_plan: Do premium users binge more, or does
194
+ * ad-free viewing change consumption patterns?
195
+ * - Cohort by preferred_genre: Does genre preference predict churn?
196
+ *
197
+ * FUNNEL ANALYSIS:
198
+ *
199
+ * - Onboarding Funnel: account created -> content browsed -> playback started.
200
+ * How does signup_source affect first-session conversion?
201
+ * - Content Discovery Funnel: Does the browse_section (home vs trending vs
202
+ * genre) affect downstream completion rates?
203
+ * - Engagement Loop: How does recommendation algorithm type (collaborative
204
+ * filtering vs editorial) affect the full loop conversion?
205
+ *
206
+ * MONETIZATION ANALYSIS:
207
+ *
208
+ * - Free-to-Standard conversion: Which events predict upgrade?
209
+ * - Ad tolerance threshold: At what ad count do free users start churning?
210
+ * - Premium value: Do premium users actually consume more content, or just
211
+ * consume at higher quality (4K)?
212
+ * - Download behavior: Does offline download usage correlate with retention?
66
213
  */
67
214
 
68
215
  // Generate consistent content IDs for lookup tables and events
@@ -108,6 +255,9 @@ const config = {
108
255
  conversionRate: 55,
109
256
  timeToConvert: 2,
110
257
  weight: 5,
258
+ props: {
259
+ genre: ["action", "comedy", "drama", "documentary", "horror", "sci_fi", "animation", "thriller", "romance"],
260
+ },
111
261
  },
112
262
  {
113
263
  // Recommendation-driven viewing
@@ -166,24 +316,24 @@ const config = {
166
316
  weight: 1,
167
317
  isFirstEvent: true,
168
318
  properties: {
169
- "signup_source": u.pickAWinner(["organic", "referral", "trial_offer", "ad"]),
170
- "plan_selected": u.pickAWinner(["free", "standard", "premium"]),
319
+ "signup_source": ["organic", "referral", "trial_offer", "ad"],
320
+ "plan_selected": ["free", "standard", "premium"],
171
321
  }
172
322
  },
173
323
  {
174
324
  event: "content browsed",
175
325
  weight: 20,
176
326
  properties: {
177
- "browse_section": u.pickAWinner(["home", "trending", "new_releases", "genre", "continue_watching"]),
178
- "genre": u.pickAWinner(["action", "comedy", "drama", "documentary", "horror", "sci_fi", "animation", "thriller", "romance"]),
327
+ "browse_section": ["home", "trending", "new_releases", "genre", "continue_watching"],
328
+ "genre": ["action", "comedy", "drama", "documentary", "horror", "sci_fi", "animation", "thriller", "romance"],
179
329
  }
180
330
  },
181
331
  {
182
332
  event: "content selected",
183
333
  weight: 15,
184
334
  properties: {
185
- "content_type": u.pickAWinner(["movie", "series", "documentary", "special"]),
186
- "genre": u.pickAWinner(["action", "comedy", "drama", "documentary", "horror", "sci_fi", "animation", "thriller", "romance"]),
335
+ "content_type": ["movie", "series", "documentary", "special"],
336
+ "genre": ["action", "comedy", "drama", "documentary", "horror", "sci_fi", "animation", "thriller", "romance"],
187
337
  "content_id": u.pickAWinner(contentIds),
188
338
  }
189
339
  },
@@ -192,9 +342,9 @@ const config = {
192
342
  weight: 18,
193
343
  properties: {
194
344
  "content_id": u.pickAWinner(contentIds),
195
- "content_type": u.pickAWinner(["movie", "series", "documentary", "special"]),
196
- "playback_quality": u.pickAWinner(["480p", "720p", "1080p", "4k"]),
197
- "subtitle_language": u.pickAWinner(["none", "english", "spanish", "french", "japanese", "korean"], 0),
345
+ "content_type": ["movie", "series", "documentary", "special"],
346
+ "playback_quality": ["480p", "720p", "1080p", "4k"],
347
+ "subtitle_language": ["none", "english", "spanish", "french", "japanese", "korean"],
198
348
  "playback_speed": u.pickAWinner(["0.5x", "1x", "1x", "1x", "1.25x", "1.5x", "2x"]),
199
349
  }
200
350
  },
@@ -203,7 +353,7 @@ const config = {
203
353
  weight: 12,
204
354
  properties: {
205
355
  "content_id": u.pickAWinner(contentIds),
206
- "content_type": u.pickAWinner(["movie", "series", "documentary", "special"]),
356
+ "content_type": ["movie", "series", "documentary", "special"],
207
357
  "watch_duration_min": u.weighNumRange(5, 180, 0.5, 45),
208
358
  "completion_percent": u.weighNumRange(10, 100, 1.5, 85),
209
359
  }
@@ -213,7 +363,7 @@ const config = {
213
363
  weight: 10,
214
364
  properties: {
215
365
  "content_id": u.pickAWinner(contentIds),
216
- "pause_reason": u.pickAWinner(["manual", "ad_break", "buffering", "notification"]),
366
+ "pause_reason": ["manual", "ad_break", "buffering", "notification"],
217
367
  }
218
368
  },
219
369
  {
@@ -230,8 +380,8 @@ const config = {
230
380
  weight: 8,
231
381
  properties: {
232
382
  "content_id": u.pickAWinner(contentIds),
233
- "content_type": u.pickAWinner(["movie", "series", "documentary", "special"]),
234
- "genre": u.pickAWinner(["action", "comedy", "drama", "documentary", "horror", "sci_fi", "animation", "thriller", "romance"]),
383
+ "content_type": ["movie", "series", "documentary", "special"],
384
+ "genre": ["action", "comedy", "drama", "documentary", "horror", "sci_fi", "animation", "thriller", "romance"],
235
385
  }
236
386
  },
237
387
  {
@@ -239,7 +389,7 @@ const config = {
239
389
  weight: 3,
240
390
  properties: {
241
391
  "content_id": u.pickAWinner(contentIds),
242
- "reason": u.pickAWinner(["watched", "not_interested", "expired"]),
392
+ "reason": ["watched", "not_interested", "expired"],
243
393
  }
244
394
  },
245
395
  {
@@ -248,14 +398,14 @@ const config = {
248
398
  properties: {
249
399
  "search_term": () => chance.word(),
250
400
  "results_count": u.weighNumRange(0, 50, 0.5, 15),
251
- "search_type": u.pickAWinner(["title", "actor", "director", "genre"]),
401
+ "search_type": ["title", "actor", "director", "genre"],
252
402
  }
253
403
  },
254
404
  {
255
405
  event: "recommendation clicked",
256
406
  weight: 9,
257
407
  properties: {
258
- "algorithm": u.pickAWinner(["collaborative_filtering", "content_based", "trending", "editorial"]),
408
+ "algorithm": ["collaborative_filtering", "content_based", "trending", "editorial"],
259
409
  "position": u.weighNumRange(1, 20),
260
410
  }
261
411
  },
@@ -263,14 +413,14 @@ const config = {
263
413
  event: "profile switched",
264
414
  weight: 4,
265
415
  properties: {
266
- "profile_type": u.pickAWinner(["main", "kids", "partner", "guest"]),
416
+ "profile_type": ["main", "kids", "partner", "guest"],
267
417
  }
268
418
  },
269
419
  {
270
420
  event: "ad impression",
271
421
  weight: 8,
272
422
  properties: {
273
- "ad_type": u.pickAWinner(["pre_roll", "mid_roll", "banner", "interstitial"]),
423
+ "ad_type": ["pre_roll", "mid_roll", "banner", "interstitial"],
274
424
  "ad_duration_sec": u.weighNumRange(5, 30),
275
425
  "skipped": u.pickAWinner([true, false], 0.4),
276
426
  }
@@ -279,9 +429,9 @@ const config = {
279
429
  event: "subscription changed",
280
430
  weight: 2,
281
431
  properties: {
282
- "old_plan": u.pickAWinner(["free", "standard", "premium"]),
283
- "new_plan": u.pickAWinner(["free", "standard", "premium"]),
284
- "change_reason": u.pickAWinner(["upgrade", "downgrade", "cancel", "resubscribe"]),
432
+ "old_plan": ["free", "standard", "premium"],
433
+ "new_plan": ["free", "standard", "premium"],
434
+ "change_reason": ["upgrade", "downgrade", "cancel", "resubscribe"],
285
435
  }
286
436
  },
287
437
  {
@@ -289,37 +439,37 @@ const config = {
289
439
  weight: 5,
290
440
  properties: {
291
441
  "content_id": u.pickAWinner(contentIds),
292
- "content_type": u.pickAWinner(["movie", "series", "documentary", "special"]),
293
- "download_quality": u.pickAWinner(["720p", "1080p", "4k"]),
442
+ "content_type": ["movie", "series", "documentary", "special"],
443
+ "download_quality": ["720p", "1080p", "4k"],
294
444
  }
295
445
  },
296
446
  {
297
447
  event: "share content",
298
448
  weight: 3,
299
449
  properties: {
300
- "share_method": u.pickAWinner(["link", "social", "dm", "email"]),
301
- "content_type": u.pickAWinner(["movie", "series", "documentary", "special"]),
450
+ "share_method": ["link", "social", "dm", "email"],
451
+ "content_type": ["movie", "series", "documentary", "special"],
302
452
  }
303
453
  },
304
454
  {
305
455
  event: "subtitle toggled",
306
456
  weight: 4,
307
457
  properties: {
308
- "subtitle_language": u.pickAWinner(["none", "english", "spanish", "french", "japanese", "korean"], 0),
309
- "action": u.pickAWinner(["enabled", "disabled", "changed"]),
458
+ "subtitle_language": ["none", "english", "spanish", "french", "japanese", "korean"],
459
+ "action": ["enabled", "disabled", "changed"],
310
460
  }
311
461
  },
312
462
  ],
313
463
 
314
464
  superProps: {
315
465
  subscription_plan: u.pickAWinner(["free", "free", "standard", "standard", "standard", "premium"]),
316
- device_type: u.pickAWinner(["smart_tv", "mobile", "tablet", "laptop", "desktop"]),
466
+ device_type: ["smart_tv", "mobile", "tablet", "laptop", "desktop"],
317
467
  },
318
468
 
319
469
  scdProps: {},
320
470
 
321
471
  userProps: {
322
- "preferred_genre": u.pickAWinner(["action", "comedy", "drama", "documentary", "horror", "sci_fi", "animation"]),
472
+ "preferred_genre": ["action", "comedy", "drama", "documentary", "horror", "sci_fi", "animation"],
323
473
  "avg_session_duration_min": u.weighNumRange(10, 180, 0.5, 45),
324
474
  "total_watch_hours": u.weighNumRange(0, 500, 0.8, 50),
325
475
  "profiles_count": u.weighNumRange(1, 5),
@@ -336,7 +486,7 @@ const config = {
336
486
  * 1. GENRE FUNNEL CONVERSION: Comedy/Animation complete more; Documentary abandons more (funnel-pre)
337
487
  * 2. BINGE-WATCHING: Users with 3+ consecutive completions get extra episodes (everything)
338
488
  * 3. WEEKEND vs WEEKDAY: Weekend sessions 1.5x longer; weekday prime-time tagging (event)
339
- * 4. AD FATIGUE CHURN: Free-tier users with 20+ ads churn after day 45 (everything)
489
+ * 4. AD FATIGUE CHURN: Free-tier users with 10+ ads churn after day 45 (everything)
340
490
  * 5. NEW RELEASE SPIKE: Blockbuster release on day 50 drives content selection (event)
341
491
  * 6. KIDS PROFILE SAFETY: Kids mode restricts genres and drops ads (event)
342
492
  * 7. RECOMMENDATION ENGINE IMPROVEMENT: Post-day-60 boost to engagement funnel (funnel-pre)
@@ -345,51 +495,56 @@ const config = {
345
495
  hook: function (record, type, meta) {
346
496
  const NOW = dayjs();
347
497
  const DATASET_START = NOW.subtract(days, 'days');
498
+ // FIXED_START is the pre-shift time range start; needed because
499
+ // meta.firstEventTime in funnel-pre is in the FIXED (pre-shift) timeframe
500
+ const FIXED_START = dayjs.unix(global.FIXED_NOW).subtract(days, 'days');
348
501
 
349
502
  // ─────────────────────────────────────────────────────────────
350
503
  // Hook #1: GENRE FUNNEL CONVERSION (funnel-pre)
351
504
  // Comedy/Animation funnels convert 1.3x better; Documentary 0.7x
352
505
  // ─────────────────────────────────────────────────────────────
353
506
  if (type === "funnel-pre") {
354
- const props = record.props || {};
355
- const genre = props.genre;
507
+ record.props = record.props || {};
508
+ const genre = record.props.genre;
356
509
 
357
510
  if (genre === "comedy" || genre === "animation") {
358
511
  record.conversionRate = record.conversionRate * 1.3;
359
- record.genre_boost = true;
360
- record.genre_penalty = false;
512
+ record.props.genre_boost = true;
513
+ record.props.genre_penalty = false;
361
514
  } else if (genre === "documentary") {
362
515
  record.conversionRate = record.conversionRate * 0.7;
363
- record.genre_boost = false;
364
- record.genre_penalty = true;
516
+ record.props.genre_boost = false;
517
+ record.props.genre_penalty = true;
365
518
  } else if (!genre && chance.bool({ likelihood: 25 })) {
366
519
  // Randomly apply genre effects when genre isn't in funnel props
367
520
  if (chance.bool({ likelihood: 60 })) {
368
521
  record.conversionRate = record.conversionRate * 1.3;
369
- record.genre_boost = true;
370
- record.genre_penalty = false;
522
+ record.props.genre_boost = true;
523
+ record.props.genre_penalty = false;
371
524
  } else {
372
525
  record.conversionRate = record.conversionRate * 0.7;
373
- record.genre_boost = false;
374
- record.genre_penalty = true;
526
+ record.props.genre_boost = false;
527
+ record.props.genre_penalty = true;
375
528
  }
376
529
  } else {
377
- record.genre_boost = false;
378
- record.genre_penalty = false;
530
+ record.props.genre_boost = false;
531
+ record.props.genre_penalty = false;
379
532
  }
380
533
 
381
534
  // ─────────────────────────────────────────────────────────────
382
535
  // Hook #7: RECOMMENDATION ENGINE IMPROVEMENT (funnel-pre)
383
- // After day 60 (proxied by 50% chance), engagement funnel gets 1.5x boost
536
+ // After day 60, engagement funnel gets 1.5x boost
384
537
  // ─────────────────────────────────────────────────────────────
385
538
  const seq = record.sequence || [];
386
539
  const isEngagementFunnel = seq.includes("recommendation clicked");
540
+ const funnelTime = meta && meta.firstEventTime ? dayjs.unix(meta.firstEventTime) : null;
541
+ const isAfterImprovement = funnelTime && funnelTime.isAfter(FIXED_START.add(60, 'days'));
387
542
 
388
- if (isEngagementFunnel && chance.bool({ likelihood: 50 })) {
543
+ if (isEngagementFunnel && isAfterImprovement) {
389
544
  record.conversionRate = record.conversionRate * 1.5;
390
- record.improved_recs = true;
545
+ record.props.improved_recs = true;
391
546
  } else {
392
- record.improved_recs = false;
547
+ record.props.improved_recs = false;
393
548
  }
394
549
 
395
550
  return record;
@@ -571,8 +726,8 @@ const config = {
571
726
  }
572
727
 
573
728
  // Hook #4: AD FATIGUE CHURN
574
- // Free-tier users with 20+ ads lose 50% of events after day 45
575
- if (isFreeTier && adImpressionCount >= 20) {
729
+ // Free-tier users with 10+ ads lose 50% of events after day 45
730
+ if (isFreeTier && adImpressionCount >= 10) {
576
731
  const churnCutoff = firstEventTime.add(45, 'days');
577
732
  for (let i = userEvents.length - 1; i >= 0; i--) {
578
733
  const evt = userEvents[i];
@@ -633,328 +788,3 @@ const config = {
633
788
  };
634
789
 
635
790
  export default config;
636
-
637
- /**
638
- * ═══════════════════════════════════════════════════════════════════════════════
639
- * NEEDLE IN A HAYSTACK - STREAMVAULT VIDEO STREAMING ANALYTICS
640
- * ═══════════════════════════════════════════════════════════════════════════════
641
- *
642
- * A video streaming platform dungeon with 8 deliberately architected analytics
643
- * insights hidden in the data. This dungeon simulates a Netflix/Hulu-style service
644
- * and is designed to showcase advanced product analytics patterns for streaming
645
- * media businesses.
646
- *
647
- * ═══════════════════════════════════════════════════════════════════════════════
648
- * DATASET OVERVIEW
649
- * ═══════════════════════════════════════════════════════════════════════════════
650
- *
651
- * - 5,000 users over 100 days
652
- * - 360,000 events across 17 event types
653
- * - 3 funnels (onboarding, content discovery, engagement loop)
654
- * - 1 lookup table (content catalog with 500 titles)
655
- * - Subscription tiers: Free (ad-supported), Standard, Premium
656
- * - Device types: Smart TV, Mobile, Tablet, Laptop, Desktop
657
- *
658
- * ═══════════════════════════════════════════════════════════════════════════════
659
- * THE 8 ARCHITECTED HOOKS
660
- * ═══════════════════════════════════════════════════════════════════════════════
661
- *
662
- * Each hook creates a specific, discoverable analytics insight that simulates
663
- * real-world streaming platform behavior patterns.
664
- *
665
- * ───────────────────────────────────────────────────────────────────────────────
666
- * 1. GENRE FUNNEL CONVERSION (funnel-pre)
667
- * ───────────────────────────────────────────────────────────────────────────────
668
- *
669
- * PATTERN: Comedy and Animation content has 1.3x higher funnel conversion rates,
670
- * while Documentary content has 0.7x conversion (users browse but abandon more).
671
- *
672
- * HOW TO FIND IT:
673
- * - Break down funnels by genre property
674
- * - Compare: conversion rate for Comedy/Animation vs Documentary vs other genres
675
- * - Look for: genre_boost = true or genre_penalty = true tags
676
- *
677
- * EXPECTED INSIGHT: Comedy and Animation content converts browsers to completers
678
- * at 1.3x the baseline rate. Documentary has high browse rates but low completion,
679
- * suggesting users are interested but find long-form docs harder to finish.
680
- *
681
- * REAL-WORLD ANALOGUE: Content genre significantly affects engagement depth.
682
- * Light entertainment converts better than educational content, informing
683
- * content acquisition and recommendation strategy.
684
- *
685
- * ───────────────────────────────────────────────────────────────────────────────
686
- * 2. BINGE-WATCHING PATTERN (everything)
687
- * ───────────────────────────────────────────────────────────────────────────────
688
- *
689
- * PATTERN: Users who complete 3+ episodes consecutively become "binge-watchers":
690
- * - Extra playback started + playback completed events are spliced in
691
- * - Completion percentages are 90-100% (they finish every episode)
692
- * - Pause events are reduced by 60% (they don't stop watching)
693
- * - Events tagged with binge_session = true
694
- *
695
- * HOW TO FIND IT:
696
- * - Segment users by: binge_session = true on any event
697
- * - Compare: total playback completed count per user
698
- * - Compare: average completion_percent for binge vs non-binge users
699
- * - Compare: playback paused frequency
700
- *
701
- * EXPECTED INSIGHT: Binge-watchers consume 40-60% more content, with near-perfect
702
- * completion rates. They pause far less frequently. This cohort drives the majority
703
- * of total watch hours on the platform.
704
- *
705
- * REAL-WORLD ANALOGUE: Netflix's binge-viewing behavior - a small percentage of
706
- * users generate a disproportionate share of total viewing. Identifying and
707
- * nurturing binge-watchers is critical for retention and content ROI.
708
- *
709
- * ───────────────────────────────────────────────────────────────────────────────
710
- * 3. WEEKEND vs WEEKDAY PATTERNS (event)
711
- * ───────────────────────────────────────────────────────────────────────────────
712
- *
713
- * PATTERN: Weekend viewing sessions are 1.5x longer than weekday sessions.
714
- * Weekday viewing concentrates in evening prime-time (6PM-11PM).
715
- *
716
- * HOW TO FIND IT:
717
- * - Filter: playback completed events
718
- * - Compare: average watch_duration_min by day of week
719
- * - Filter: weekend_viewing = true vs prime_time = true
720
- * - Chart: event volume by hour of day, split by weekend vs weekday
721
- *
722
- * EXPECTED INSIGHT: Weekend watch_duration_min averages ~67 mins vs ~45 mins
723
- * weekday. Weekday prime-time (6PM-11PM) accounts for 60-70% of weekday views.
724
- *
725
- * REAL-WORLD ANALOGUE: All streaming platforms see this pattern. Understanding
726
- * peak viewing windows drives content release strategy (release on Friday for
727
- * weekend binge), ad pricing, and infrastructure capacity planning.
728
- *
729
- * ───────────────────────────────────────────────────────────────────────────────
730
- * 4. AD FATIGUE CHURN (everything)
731
- * ───────────────────────────────────────────────────────────────────────────────
732
- *
733
- * PATTERN: Free-tier users who see 20+ ad impressions experience 50% churn
734
- * after day 45 of their lifecycle.
735
- *
736
- * HOW TO FIND IT:
737
- * - Segment: subscription_plan = "free"
738
- * - Count: ad impression events per user
739
- * - Compare: users with 20+ ads vs <20 ads
740
- * - Chart: event activity over time for high-ad-exposure free users
741
- * - Look for: ad_fatigue = true tag on surviving events
742
- *
743
- * EXPECTED INSIGHT: Free-tier users with heavy ad exposure show a sharp activity
744
- * cliff around day 45. Remaining events carry the ad_fatigue tag. This simulates
745
- * the real tension between ad revenue and user experience on free tiers.
746
- *
747
- * REAL-WORLD ANALOGUE: Ad-supported streaming tiers (Hulu, Peacock) must balance
748
- * ad load against churn. Too many ads drive users to cancel or switch to
749
- * competitors. This hook reveals the "ad tolerance threshold."
750
- *
751
- * ───────────────────────────────────────────────────────────────────────────────
752
- * 5. NEW RELEASE SPIKE (event)
753
- * ───────────────────────────────────────────────────────────────────────────────
754
- *
755
- * PATTERN: On day 50, a blockbuster movie releases, creating a content spike:
756
- * - 20% of content selected and playback started events redirect to the blockbuster
757
- * - Content rated events for the blockbuster skew to 4-5 star ratings
758
- * - All affected events tagged with blockbuster_release = true
759
- *
760
- * HOW TO FIND IT:
761
- * - Chart: content selected and playback started by day
762
- * - Filter: blockbuster_release = true
763
- * - Filter: content_id = blockbuster ID
764
- * - Compare: ratings distribution before vs after day 50
765
- *
766
- * EXPECTED INSIGHT: Clear spike in content engagement after day 50, with a
767
- * single content_id dominating selections. Ratings for this title cluster at
768
- * 4-5 stars, showing strong audience reception.
769
- *
770
- * REAL-WORLD ANALOGUE: Major content releases (Stranger Things season drop,
771
- * Disney+ Marvel premiere) create massive engagement spikes that affect all
772
- * platform metrics. Understanding release impact is crucial for content
773
- * scheduling and marketing spend.
774
- *
775
- * ───────────────────────────────────────────────────────────────────────────────
776
- * 6. KIDS PROFILE SAFETY (event)
777
- * ───────────────────────────────────────────────────────────────────────────────
778
- *
779
- * PATTERN: 15% of the time, events are tagged as kids profile activity:
780
- * - Content selection restricted to animation and documentary genres
781
- * - Ad impressions are dropped entirely (no ads for kids)
782
- * - Events tagged with kids_profile = true
783
- *
784
- * HOW TO FIND IT:
785
- * - Filter: kids_profile = true
786
- * - Compare: genre distribution for kids vs non-kids events
787
- * - Count: ad impression events for kids vs non-kids
788
- * - Notice: zero ad impressions when kids_profile = true
789
- *
790
- * EXPECTED INSIGHT: Kids profile content is 100% animation/documentary. Zero ads
791
- * served to kids profiles. This shows proper content gating and ad-free kids
792
- * experience, which is a regulatory and trust requirement.
793
- *
794
- * REAL-WORLD ANALOGUE: COPPA compliance and parental controls. All major
795
- * streaming platforms (Netflix Kids, Disney+, YouTube Kids) restrict content
796
- * and ads for children's profiles. Verifying this works correctly is critical.
797
- *
798
- * ───────────────────────────────────────────────────────────────────────────────
799
- * 7. RECOMMENDATION ENGINE IMPROVEMENT (funnel-pre)
800
- * ───────────────────────────────────────────────────────────────────────────────
801
- *
802
- * PATTERN: After day 60 (proxied by 50% probability), the engagement loop funnel
803
- * (recommendation clicked -> playback started -> content rated) gets a 1.5x
804
- * conversion rate boost, simulating a recommendation engine improvement.
805
- *
806
- * HOW TO FIND IT:
807
- * - Compare: engagement funnel conversion over time (first half vs second half)
808
- * - Filter: improved_recs = true on funnel events
809
- * - Chart: recommendation clicked -> playback started conversion by week
810
- *
811
- * EXPECTED INSIGHT: The engagement funnel conversion rate improves ~1.5x in the
812
- * latter half of the dataset. Events tagged with improved_recs = true show higher
813
- * conversion, simulating an A/B test or algorithm deployment.
814
- *
815
- * REAL-WORLD ANALOGUE: Recommendation engine updates are the highest-leverage
816
- * product changes at streaming companies. Netflix estimates its rec engine saves
817
- * $1B/year in retention. Measuring before/after impact of algorithm changes is
818
- * critical product analytics.
819
- *
820
- * ───────────────────────────────────────────────────────────────────────────────
821
- * 8. SUBTITLE USERS WATCH MORE (everything)
822
- * ───────────────────────────────────────────────────────────────────────────────
823
- *
824
- * PATTERN: Users who enable subtitles have measurably higher engagement:
825
- * - 25% higher completion_percent on playback completed events (capped at 100)
826
- * - 15% longer watch_duration_min
827
- * - 20% more playback completed events (extra content consumption)
828
- * - Events tagged with subtitle_user = true
829
- *
830
- * HOW TO FIND IT:
831
- * - Create segment: users who did "subtitle toggled" where action = "enabled"
832
- * - Compare: average completion_percent (subtitle users vs non-subtitle users)
833
- * - Compare: average watch_duration_min
834
- * - Compare: total playback completed count per user
835
- *
836
- * EXPECTED INSIGHT: Subtitle users complete content 25% more often and watch 15%
837
- * longer per session. They also consume 20% more titles overall. This suggests
838
- * subtitles reduce comprehension friction and keep viewers engaged.
839
- *
840
- * REAL-WORLD ANALOGUE: Subtitle usage has exploded on streaming platforms.
841
- * Netflix reports 40%+ of viewing uses subtitles. Subtitle users exhibit higher
842
- * engagement, especially with foreign-language content (Korean dramas, anime).
843
- * This insight drives investment in subtitle/dub quality and availability.
844
- *
845
- * ═══════════════════════════════════════════════════════════════════════════════
846
- * EXPECTED METRICS SUMMARY
847
- * ═══════════════════════════════════════════════════════════════════════════════
848
- *
849
- * Hook | Metric | Baseline | Hook Effect | Ratio
850
- * ─────────────────────────|─────────────────────────|───────────|─────────────|──────
851
- * Genre Funnel Conversion | Funnel conversion rate | 50% | 65% / 35% | 1.3x / 0.7x
852
- * Binge-Watching | Content consumed/user | 12 | 18-20 | ~1.5x
853
- * Weekend vs Weekday | Watch duration (min) | 45 | 67 (weekend)| 1.5x
854
- * Ad Fatigue Churn | Post-day-45 activity | 100% | 50% | 0.5x
855
- * New Release Spike | Content selections/day | baseline | +20% spike | 1.2x
856
- * Kids Profile Safety | Ad impressions | normal | 0 (dropped) | 0x
857
- * Rec Engine Improvement | Engagement funnel conv | 30% | 45% | 1.5x
858
- * Subtitle Users | Completion percent | 68% | 85% | 1.25x
859
- *
860
- * ═══════════════════════════════════════════════════════════════════════════════
861
- * ADVANCED ANALYSIS IDEAS
862
- * ═══════════════════════════════════════════════════════════════════════════════
863
- *
864
- * CROSS-HOOK PATTERNS:
865
- *
866
- * 1. Binge + Subtitle: Do subtitle-enabled binge-watchers have the highest
867
- * total watch hours? (Hooks #2 + #8 combined)
868
- *
869
- * 2. Ad Fatigue + Blockbuster: Does the blockbuster release (Hook #5) rescue
870
- * free-tier users from ad fatigue churn (Hook #4)?
871
- *
872
- * 3. Kids + Weekend: Is kids profile viewing concentrated on weekends (Hook #6
873
- * + #3)? Does weekend kids viewing show different genre preferences?
874
- *
875
- * 4. Rec Engine + Genre: Does the recommendation engine improvement (Hook #7)
876
- * disproportionately help certain genres (Hook #1)?
877
- *
878
- * 5. Subtitle + Binge + Weekend: The "super viewer" - subtitle-enabled,
879
- * binge-watching on weekends. What is their lifetime watch hours?
880
- *
881
- * COHORT ANALYSIS:
882
- *
883
- * - Cohort by signup_source: Do referral users binge more than organic?
884
- * - Cohort by device_type: Do smart TV users watch longer than mobile?
885
- * - Cohort by subscription_plan: Do premium users binge more, or does
886
- * ad-free viewing change consumption patterns?
887
- * - Cohort by preferred_genre: Does genre preference predict churn?
888
- *
889
- * FUNNEL ANALYSIS:
890
- *
891
- * - Onboarding Funnel: account created -> content browsed -> playback started.
892
- * How does signup_source affect first-session conversion?
893
- * - Content Discovery Funnel: Does the browse_section (home vs trending vs
894
- * genre) affect downstream completion rates?
895
- * - Engagement Loop: How does recommendation algorithm type (collaborative
896
- * filtering vs editorial) affect the full loop conversion?
897
- *
898
- * MONETIZATION ANALYSIS:
899
- *
900
- * - Free-to-Standard conversion: Which events predict upgrade?
901
- * - Ad tolerance threshold: At what ad count do free users start churning?
902
- * - Premium value: Do premium users actually consume more content, or just
903
- * consume at higher quality (4K)?
904
- * - Download behavior: Does offline download usage correlate with retention?
905
- *
906
- * ═══════════════════════════════════════════════════════════════════════════════
907
- * HOW TO RUN THIS DUNGEON
908
- * ═══════════════════════════════════════════════════════════════════════════════
909
- *
910
- * From the dm4 root directory:
911
- *
912
- * npm start
913
- *
914
- * Or programmatically:
915
- *
916
- * import generate from './index.js';
917
- * import config from './dungeons/harness-media.js';
918
- * const results = await generate(config);
919
- *
920
- * OUTPUT FILES (with writeToDisk: false, format: "json", gzip: true):
921
- *
922
- * - needle-haystack-streaming__events.json.gz - All event data
923
- * - needle-haystack-streaming__user_profiles.json.gz - User profiles
924
- * - needle-haystack-streaming__content_id_lookup.json.gz - Content catalog
925
- *
926
- * ═══════════════════════════════════════════════════════════════════════════════
927
- * TESTING YOUR ANALYTICS PLATFORM
928
- * ═══════════════════════════════════════════════════════════════════════════════
929
- *
930
- * This dungeon is perfect for testing:
931
- *
932
- * 1. Funnel Breakdown: Can you break down funnels by genre to find conversion differences?
933
- * 2. Behavioral Clustering: Can you identify binge-watchers from event patterns?
934
- * 3. Time-Based Analysis: Can you detect weekend vs weekday viewing patterns?
935
- * 4. Churn Prediction: Can you predict ad-fatigue churn before it happens?
936
- * 5. Content Impact: Can you measure the blockbuster release's platform-wide effect?
937
- * 6. Safety Compliance: Can you verify kids profiles never see ads?
938
- * 7. A/B Testing: Can you measure the recommendation engine improvement's impact?
939
- * 8. Feature Impact: Can you quantify the subtitle-engagement correlation?
940
- *
941
- * ═══════════════════════════════════════════════════════════════════════════════
942
- * WHY "NEEDLE IN A HAYSTACK"?
943
- * ═══════════════════════════════════════════════════════════════════════════════
944
- *
945
- * Each hook is a "needle" - a meaningful, actionable insight hidden in a
946
- * "haystack" of 360K events. The challenge is:
947
- *
948
- * 1. FINDING the needles (discovery)
949
- * 2. VALIDATING they're real patterns (statistical significance)
950
- * 3. UNDERSTANDING why they matter (business impact)
951
- * 4. ACTING on them (product decisions)
952
- *
953
- * This mirrors real-world streaming analytics: your data contains valuable
954
- * insights about viewer behavior, content performance, and monetization
955
- * efficiency, but you need the right tools and skills to find them.
956
- *
957
- * Happy Streaming!
958
- *
959
- * ═══════════════════════════════════════════════════════════════════════════════
960
- */