make-mp-data 3.0.4 → 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.
- package/README.md +46 -0
- package/dungeons/array-of-object-lookup-schema.json +327 -0
- package/dungeons/array-of-object-lookup.js +28 -8
- package/dungeons/capstone/capstone-ic3.js +291 -0
- package/dungeons/capstone/capstone-ic4.js +598 -0
- package/dungeons/capstone/capstone-ic5.js +668 -0
- package/dungeons/capstone/generate-product-lookup.js +309 -0
- package/dungeons/ecommerce-schema.json +462 -0
- package/dungeons/{copilot.js → ecommerce.js} +77 -15
- package/dungeons/education-schema.json +2409 -0
- package/dungeons/education.js +206 -442
- package/dungeons/fintech-schema.json +14034 -0
- package/dungeons/fintech.js +110 -389
- package/dungeons/foobar-schema.json +403 -0
- package/dungeons/foobar.js +27 -4
- package/dungeons/food-delivery-schema.json +192 -0
- package/dungeons/food-delivery.js +602 -0
- package/dungeons/food-schema.json +1152 -0
- package/dungeons/food.js +150 -383
- package/dungeons/gaming-schema.json +1270 -0
- package/dungeons/gaming.js +143 -3
- package/dungeons/insurance-application-schema.json +204 -0
- package/dungeons/insurance-application.js +605 -0
- package/dungeons/media-schema.json +906 -0
- package/dungeons/media.js +221 -391
- package/dungeons/retention-cadence-schema.json +78 -0
- package/dungeons/retention-cadence.js +35 -1
- package/dungeons/rpg-schema.json +4526 -0
- package/dungeons/rpg.js +130 -388
- package/dungeons/sanity-schema.json +255 -0
- package/dungeons/sanity.js +21 -10
- package/dungeons/sass-schema.json +1291 -0
- package/dungeons/sass.js +210 -337
- package/dungeons/scd-schema.json +919 -0
- package/dungeons/scd.js +38 -10
- package/dungeons/simple-schema.json +608 -0
- package/dungeons/simple.js +48 -11
- package/dungeons/simplest-schema.json +1418 -0
- package/dungeons/simplest.js +392 -0
- package/dungeons/social-schema.json +1118 -0
- package/dungeons/social.js +124 -365
- package/dungeons/text-generation-schema.json +3096 -0
- package/dungeons/text-generation.js +71 -0
- package/index.js +6 -3
- package/lib/core/config-validator.js +18 -0
- package/lib/core/storage.js +5 -5
- package/lib/generators/events.js +4 -4
- package/lib/orchestrators/mixpanel-sender.js +12 -7
- package/lib/orchestrators/user-loop.js +14 -6
- package/lib/templates/soup-presets.js +188 -0
- package/lib/utils/utils.js +52 -6
- package/package.json +1 -1
- package/types.d.ts +20 -3
- package/dungeons/adspend.js +0 -117
- package/dungeons/anon.js +0 -128
- package/dungeons/benchmark-heavy.js +0 -240
- package/dungeons/benchmark-light.js +0 -126
- package/dungeons/big.js +0 -226
- package/dungeons/business.js +0 -391
- package/dungeons/complex.js +0 -428
- package/dungeons/experiments.js +0 -137
- package/dungeons/funnels.js +0 -309
- package/dungeons/mil.js +0 -323
- package/dungeons/mirror.js +0 -160
- package/dungeons/soup-test.js +0 -52
- package/dungeons/streaming.js +0 -372
- package/dungeons/strict-event-test.js +0 -30
- package/dungeons/student-teacher.js +0 -438
- package/dungeons/too-big-events.js +0 -203
- 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("
|
|
13
|
+
/** @typedef {import("../types.js").Dungeon} Config */
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
|
-
*
|
|
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.
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
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
|
|
@@ -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
|
|
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
|
-
|
|
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
|
|
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 &&
|
|
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
|
|
575
|
-
if (isFreeTier && adImpressionCount >=
|
|
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
|
-
*/
|