make-mp-data 2.1.11 โ 3.0.2
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 +31 -0
- package/dungeons/adspend.js +35 -1
- package/dungeons/anon.js +25 -1
- package/dungeons/array-of-object-lookup.js +201 -0
- package/dungeons/benchmark-heavy.js +241 -0
- package/dungeons/benchmark-light.js +141 -0
- package/dungeons/big.js +10 -9
- package/dungeons/business.js +60 -12
- package/dungeons/complex.js +35 -1
- package/dungeons/copilot.js +383 -0
- package/dungeons/education.js +1005 -0
- package/dungeons/experiments.js +18 -4
- package/dungeons/fintech.js +976 -0
- package/dungeons/foobar.js +32 -0
- package/dungeons/food.js +988 -0
- package/dungeons/funnels.js +38 -1
- package/dungeons/gaming.js +26 -5
- package/dungeons/media.js +861 -270
- package/dungeons/mil.js +31 -3
- package/dungeons/mirror.js +33 -1
- package/dungeons/retention-cadence.js +211 -0
- package/dungeons/rpg.js +1178 -0
- package/dungeons/sanity.js +32 -2
- package/dungeons/sass.js +923 -0
- package/dungeons/scd.js +47 -1
- package/dungeons/simple.js +29 -14
- package/dungeons/social.js +928 -0
- package/dungeons/streaming.js +373 -0
- package/dungeons/strict-event-test.js +30 -0
- package/dungeons/student-teacher.js +19 -5
- package/dungeons/text-generation.js +120 -84
- package/dungeons/too-big-events.js +203 -0
- package/dungeons/{userAgent.js โ user-agent.js} +23 -2
- package/entry.js +5 -4
- package/index.js +41 -54
- package/lib/core/config-validator.js +122 -7
- package/lib/core/context.js +7 -14
- package/lib/core/storage.js +57 -25
- package/lib/generators/adspend.js +12 -12
- package/lib/generators/events.js +6 -5
- package/lib/generators/funnels.js +32 -10
- package/lib/generators/product-lookup.js +262 -0
- package/lib/generators/product-names.js +195 -0
- package/lib/generators/profiles.js +3 -3
- package/lib/generators/scd.js +13 -3
- package/lib/generators/text.js +17 -4
- package/lib/orchestrators/mixpanel-sender.js +244 -204
- package/lib/orchestrators/user-loop.js +54 -16
- package/lib/templates/phrases.js +473 -16
- package/lib/templates/schema.d.ts +173 -0
- package/lib/templates/verbose-schema.js +140 -206
- package/lib/utils/chart.js +210 -0
- package/lib/utils/function-registry.js +285 -0
- package/lib/utils/json-evaluator.js +172 -0
- package/lib/utils/logger.js +34 -0
- package/lib/utils/utils.js +41 -4
- package/package.json +12 -21
- package/types.d.ts +15 -5
- package/dungeons/ai-chat-analytics-ed.js +0 -274
- package/dungeons/money2020-ed-also.js +0 -277
- package/dungeons/money2020-ed.js +0 -579
- package/lib/generators/text-bak-old.js +0 -1121
- package/lib/orchestrators/worker-manager.js +0 -203
- package/lib/templates/hooks-instructions.txt +0 -434
- package/lib/templates/phrases-bak.js +0 -925
- package/lib/templates/prompt (old).txt +0 -98
- package/lib/templates/schema-instructions.txt +0 -155
- package/lib/templates/scratch-dungeon-template.js +0 -116
- package/lib/templates/textQuickTest.js +0 -172
- package/lib/utils/ai.js +0 -120
- package/lib/utils/project.js +0 -166
package/dungeons/rpg.js
ADDED
|
@@ -0,0 +1,1178 @@
|
|
|
1
|
+
import dayjs from "dayjs";
|
|
2
|
+
import utc from "dayjs/plugin/utc.js";
|
|
3
|
+
import "dotenv/config";
|
|
4
|
+
import * as u from "../lib/utils/utils.js";
|
|
5
|
+
import * as v from "ak-tools";
|
|
6
|
+
|
|
7
|
+
const SEED = "harness-gaming";
|
|
8
|
+
dayjs.extend(utc);
|
|
9
|
+
const chance = u.initChance(SEED);
|
|
10
|
+
const num_users = 5_000;
|
|
11
|
+
const days = 100;
|
|
12
|
+
|
|
13
|
+
/** @typedef {import("../../types.js").Dungeon} Config */
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* ๐ฎ NEEDLE IN A HAYSTACK - GAME DESIGN
|
|
17
|
+
*
|
|
18
|
+
* A D&D-style action RPG with deep strategic gameplay and a robust player-driven economy.
|
|
19
|
+
*
|
|
20
|
+
* CORE GAMEPLAY LOOP:
|
|
21
|
+
* Players create characters (Warrior, Mage, Rogue, etc.) and embark on epic adventures through
|
|
22
|
+
* a vast fantasy world. The game emphasizes strategic preparation, guild cooperation, and
|
|
23
|
+
* risk/reward decision-making. Success requires both skill and planning.
|
|
24
|
+
*
|
|
25
|
+
* QUEST SYSTEM (events: quest accepted โ objective completed โ turned in):
|
|
26
|
+
* - Five quest types: Main Story (narrative progression), Side Quests (world-building),
|
|
27
|
+
* Bounties (repeatable challenges), Exploration (discovery rewards), Escorts (protect NPCs)
|
|
28
|
+
* - Quest difficulty scaling based on player level
|
|
29
|
+
* - Rewards include gold (in-game economy), XP (progression), and rare items
|
|
30
|
+
* - Players can accept multiple quests and complete them in any order
|
|
31
|
+
*
|
|
32
|
+
* DUNGEON EXPLORATION (events: enter โ find treasure โ exit):
|
|
33
|
+
* - 50 unique dungeons with varying difficulty (Easy โ Deadly)
|
|
34
|
+
* - Party-based gameplay: solo or group (1-5 players coordinated through guilds)
|
|
35
|
+
* - Treasure hunting: gold, weapons, armor, consumables, and legendary artifacts
|
|
36
|
+
* - Three outcomes: completed (reached the end), abandoned (left early), died (party wipe)
|
|
37
|
+
* - Time investment: 5-120 minutes per run
|
|
38
|
+
*
|
|
39
|
+
* STRATEGIC PREPARATION (events: inspect, search for clues):
|
|
40
|
+
* - "Inspect" lets players scout enemies, traps, and treasure before committing
|
|
41
|
+
* - "Search for clues" reveals hidden paths, secret rewards, and dungeon mechanics
|
|
42
|
+
* - Players who prepare strategically have significantly better outcomes
|
|
43
|
+
* - The Ancient Compass is a rare consumable that enhances exploration success
|
|
44
|
+
*
|
|
45
|
+
* COMBAT SYSTEM (events: combat initiated โ combat completed):
|
|
46
|
+
* - Real-time combat against 6 enemy types: Goblins (swarms), Skeletons (undead),
|
|
47
|
+
* Dragons (bosses), Demons (elite), Undead (cursed), Beasts (wilderness)
|
|
48
|
+
* - Level-based difficulty: enemies scale from 1-50
|
|
49
|
+
* - Three outcomes: Victory (loot), Defeat (death), Fled (escaped but no rewards)
|
|
50
|
+
* - Combat duration reflects difficulty (10s quick fights โ 300s epic battles)
|
|
51
|
+
*
|
|
52
|
+
* DEATH & RESURRECTION (event: player death):
|
|
53
|
+
* - Players can die from monsters, traps, fall damage, poison, or friendly fire
|
|
54
|
+
* - Death penalties: lost time, equipment durability loss, potential item drops
|
|
55
|
+
* - Resurrection Stones (consumable) allow instant revival without penalties
|
|
56
|
+
* - Deaths early in a player's journey often lead to frustration and churn
|
|
57
|
+
*
|
|
58
|
+
* CHARACTER PROGRESSION (events: level up):
|
|
59
|
+
* - 50 levels of progression (1-50)
|
|
60
|
+
* - Each level grants stat points to customize character builds
|
|
61
|
+
* - Six classes with unique playstyles and abilities
|
|
62
|
+
* - Five races with lore and starting bonuses
|
|
63
|
+
*
|
|
64
|
+
* ECONOMY SYSTEMS:
|
|
65
|
+
* - In-game gold economy: earn through quests/dungeons, spend at vendors
|
|
66
|
+
* - Item trading: buy/sell weapons, armor, potions, scrolls (events: item purchased/sold)
|
|
67
|
+
* - Vendor types: Town (general goods), Dungeon (mid-adventure resupply), Special Events (rare items)
|
|
68
|
+
* - Item rarity: Common โ Uncommon โ Rare โ Epic โ Legendary (affects pricing)
|
|
69
|
+
*
|
|
70
|
+
* MONETIZATION (event: real money purchase):
|
|
71
|
+
* - Free-to-play with optional purchases
|
|
72
|
+
* - Premium currency (1000/5000 gems) for cosmetics and convenience
|
|
73
|
+
* - Lucky Charm Pack: increases rare drop rates (creates high-LTV player segment)
|
|
74
|
+
* - Legendary Weapon Chests: random powerful gear
|
|
75
|
+
* - Season Pass: exclusive content, cosmetics, and progression boosts
|
|
76
|
+
* - Cosmetic Bundles: no gameplay impact, pure customization
|
|
77
|
+
*
|
|
78
|
+
* GUILD SYSTEM (events: guild joined/left):
|
|
79
|
+
* - Social cooperative play through guilds (5-100 members)
|
|
80
|
+
* - Guild levels (1-20) unlock perks and group content
|
|
81
|
+
* - Shared progression and coordinated dungeon runs
|
|
82
|
+
* - Early guild joining creates social bonds that dramatically improve retention
|
|
83
|
+
* - Reasons for leaving: Inactive guilds, found better fit, conflicts, guild disbanded
|
|
84
|
+
*
|
|
85
|
+
* ITEM USAGE (event: use item):
|
|
86
|
+
* - Consumables: Health/Mana Potions (combat sustainability), Buff Scrolls (temporary power)
|
|
87
|
+
* - Strategic items: Ancient Compass (exploration aid), Lucky Charm (drop rate boost)
|
|
88
|
+
* - Combat items: Resurrection Stone (death prevention)
|
|
89
|
+
* - Context matters: Combat, Exploration, Boss Fights, or Casual use
|
|
90
|
+
*
|
|
91
|
+
* SUBSCRIPTION TIERS (SCD: subscription_tier):
|
|
92
|
+
* - Free: Base game access, earn everything through play
|
|
93
|
+
* - Premium ($9.99/mo): Faster progression, extra inventory, priority queues
|
|
94
|
+
* - Elite ($19.99/mo): All Premium benefits + exclusive content, monthly gems
|
|
95
|
+
* - Tiers can change monthly based on player engagement and value perception
|
|
96
|
+
*
|
|
97
|
+
* WHY THESE EVENTS/PROPERTIES?
|
|
98
|
+
* - Events model a complete game loop: onboarding โ engagement โ monetization โ retention
|
|
99
|
+
* - Properties enable cohort analysis: class/race choices, difficulty preferences, spending patterns
|
|
100
|
+
* - Funnels reveal friction: where do players drop off in onboarding, quests, dungeons?
|
|
101
|
+
* - Strategic depth (inspect, search, compass) creates skill gaps visible in the data
|
|
102
|
+
* - Social features (guilds) and monetization (purchases) drive business metrics
|
|
103
|
+
* - The "needle in haystack" hooks simulate real product insights hidden in production data
|
|
104
|
+
*/
|
|
105
|
+
|
|
106
|
+
// Generate consistent item/location IDs for lookup tables
|
|
107
|
+
const dungeonIds = v.range(1, 51).map(n => `dungeon_${v.uid(6)}`);
|
|
108
|
+
const questIds = v.range(1, 201).map(n => `quest_${v.uid(8)}`);
|
|
109
|
+
const itemIds = v.range(1, 301).map(n => `item_${v.uid(7)}`);
|
|
110
|
+
|
|
111
|
+
/** @type {Config} */
|
|
112
|
+
const config = {
|
|
113
|
+
token: "",
|
|
114
|
+
seed: SEED,
|
|
115
|
+
numDays: days,
|
|
116
|
+
numEvents: num_users * 120,
|
|
117
|
+
numUsers: num_users,
|
|
118
|
+
hasAnonIds: false,
|
|
119
|
+
hasSessionIds: true,
|
|
120
|
+
format: "json",
|
|
121
|
+
gzip: true,
|
|
122
|
+
alsoInferFunnels: false,
|
|
123
|
+
hasLocation: true,
|
|
124
|
+
hasAndroidDevices: true,
|
|
125
|
+
hasIOSDevices: true,
|
|
126
|
+
hasDesktopDevices: true,
|
|
127
|
+
hasBrowser: false,
|
|
128
|
+
hasCampaigns: false,
|
|
129
|
+
isAnonymous: false,
|
|
130
|
+
hasAdSpend: false,
|
|
131
|
+
percentUsersBornInDataset: 50,
|
|
132
|
+
|
|
133
|
+
hasAvatar: true,
|
|
134
|
+
makeChart: false,
|
|
135
|
+
|
|
136
|
+
batchSize: 2_500_000,
|
|
137
|
+
concurrency: 10,
|
|
138
|
+
writeToDisk: false,
|
|
139
|
+
|
|
140
|
+
funnels: [
|
|
141
|
+
{
|
|
142
|
+
sequence: ["character created", "tutorial completed", "quest accepted"],
|
|
143
|
+
isFirstFunnel: true,
|
|
144
|
+
conversionRate: 75,
|
|
145
|
+
timeToConvert: 0.5,
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
// Core combat loop: most frequent player activity
|
|
149
|
+
sequence: ["combat initiated", "combat completed", "use item"],
|
|
150
|
+
conversionRate: 75,
|
|
151
|
+
timeToConvert: 0.5,
|
|
152
|
+
weight: 5,
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
// Dungeon crawl: enter, explore, loot, exit
|
|
156
|
+
sequence: ["enter dungeon", "find treasure", "exit dungeon"],
|
|
157
|
+
conversionRate: 60,
|
|
158
|
+
timeToConvert: 2,
|
|
159
|
+
weight: 4,
|
|
160
|
+
props: {
|
|
161
|
+
"dungeon_id": u.pickAWinner(dungeonIds),
|
|
162
|
+
"difficulty": u.pickAWinner(["Easy", "Medium", "Hard", "Deadly"]),
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
// Quest lifecycle
|
|
167
|
+
sequence: ["quest accepted", "quest objective completed", "quest turned in"],
|
|
168
|
+
conversionRate: 55,
|
|
169
|
+
timeToConvert: 3,
|
|
170
|
+
weight: 3,
|
|
171
|
+
props: { "quest_id": u.pickAWinner(questIds) },
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
// Preparation before dungeon: inspect + search for strategic explorer hook
|
|
175
|
+
sequence: ["inspect", "search for clues", "enter dungeon"],
|
|
176
|
+
conversionRate: 50,
|
|
177
|
+
timeToConvert: 1,
|
|
178
|
+
weight: 3,
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
// Economy: buy gear, sell loot
|
|
182
|
+
sequence: ["item purchased", "use item", "item sold"],
|
|
183
|
+
conversionRate: 45,
|
|
184
|
+
timeToConvert: 6,
|
|
185
|
+
weight: 2,
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
// Social and progression
|
|
189
|
+
sequence: ["guild joined", "level up", "real money purchase"],
|
|
190
|
+
conversionRate: 25,
|
|
191
|
+
timeToConvert: 24,
|
|
192
|
+
weight: 1,
|
|
193
|
+
},
|
|
194
|
+
],
|
|
195
|
+
|
|
196
|
+
events: [
|
|
197
|
+
{
|
|
198
|
+
event: "character created",
|
|
199
|
+
weight: 1,
|
|
200
|
+
isFirstEvent: true,
|
|
201
|
+
properties: {
|
|
202
|
+
"character_class": u.pickAWinner([
|
|
203
|
+
"Warrior",
|
|
204
|
+
"Mage",
|
|
205
|
+
"Rogue",
|
|
206
|
+
"Cleric",
|
|
207
|
+
"Ranger",
|
|
208
|
+
"Paladin"
|
|
209
|
+
]),
|
|
210
|
+
"starting_race": u.pickAWinner([
|
|
211
|
+
"Human",
|
|
212
|
+
"Elf",
|
|
213
|
+
"Dwarf",
|
|
214
|
+
"Halfling",
|
|
215
|
+
"Orc"
|
|
216
|
+
]),
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
event: "tutorial completed",
|
|
221
|
+
weight: 2,
|
|
222
|
+
properties: {
|
|
223
|
+
"completion_time_mins": u.weighNumRange(3, 25, 0.8, 10),
|
|
224
|
+
"skipped": u.pickAWinner([true, false], 0.15),
|
|
225
|
+
}
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
event: "quest accepted",
|
|
229
|
+
weight: 15,
|
|
230
|
+
properties: {
|
|
231
|
+
"quest_id": u.pickAWinner(questIds),
|
|
232
|
+
"quest_type": u.pickAWinner([
|
|
233
|
+
"Main Story",
|
|
234
|
+
"Side Quest",
|
|
235
|
+
"Bounty",
|
|
236
|
+
"Exploration",
|
|
237
|
+
"Escort"
|
|
238
|
+
]),
|
|
239
|
+
"recommended_level": u.weighNumRange(1, 50),
|
|
240
|
+
}
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
event: "quest objective completed",
|
|
244
|
+
weight: 12,
|
|
245
|
+
properties: {
|
|
246
|
+
"quest_id": u.pickAWinner(questIds),
|
|
247
|
+
"objective_number": u.weighNumRange(1, 5),
|
|
248
|
+
}
|
|
249
|
+
},
|
|
250
|
+
{
|
|
251
|
+
event: "quest turned in",
|
|
252
|
+
weight: 10,
|
|
253
|
+
properties: {
|
|
254
|
+
"quest_id": u.pickAWinner(questIds),
|
|
255
|
+
"reward_gold": u.weighNumRange(10, 500, 0.5, 100),
|
|
256
|
+
"reward_xp": u.weighNumRange(50, 2000, 0.5, 500),
|
|
257
|
+
}
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
event: "enter dungeon",
|
|
261
|
+
weight: 18,
|
|
262
|
+
properties: {
|
|
263
|
+
"dungeon_id": u.pickAWinner(dungeonIds),
|
|
264
|
+
"difficulty": u.pickAWinner(["Easy", "Medium", "Hard", "Deadly"]),
|
|
265
|
+
"party_size": u.weighNumRange(1, 5),
|
|
266
|
+
}
|
|
267
|
+
},
|
|
268
|
+
{
|
|
269
|
+
event: "exit dungeon",
|
|
270
|
+
weight: 14,
|
|
271
|
+
properties: {
|
|
272
|
+
"dungeon_id": u.pickAWinner(dungeonIds),
|
|
273
|
+
"time_spent_mins": u.weighNumRange(5, 120, 0.6, 30),
|
|
274
|
+
"completion_status": u.pickAWinner(["completed", "abandoned", "died"]),
|
|
275
|
+
}
|
|
276
|
+
},
|
|
277
|
+
{
|
|
278
|
+
event: "find treasure",
|
|
279
|
+
weight: 16,
|
|
280
|
+
properties: {
|
|
281
|
+
"treasure_type": u.pickAWinner([
|
|
282
|
+
"Gold",
|
|
283
|
+
"Weapon",
|
|
284
|
+
"Armor",
|
|
285
|
+
"Potion",
|
|
286
|
+
"Scroll",
|
|
287
|
+
"Rare Artifact"
|
|
288
|
+
]),
|
|
289
|
+
"treasure_value": u.weighNumRange(5, 1000, 1.2, 50),
|
|
290
|
+
}
|
|
291
|
+
},
|
|
292
|
+
{
|
|
293
|
+
event: "player death",
|
|
294
|
+
weight: 8,
|
|
295
|
+
properties: {
|
|
296
|
+
"cause_of_death": u.pickAWinner([
|
|
297
|
+
"Monster",
|
|
298
|
+
"Trap",
|
|
299
|
+
"Fall Damage",
|
|
300
|
+
"Poison",
|
|
301
|
+
"Friendly Fire"
|
|
302
|
+
]),
|
|
303
|
+
"player_level": u.weighNumRange(1, 50),
|
|
304
|
+
"resurrection_used": u.pickAWinner([true, false], 0.25),
|
|
305
|
+
}
|
|
306
|
+
},
|
|
307
|
+
{
|
|
308
|
+
event: "level up",
|
|
309
|
+
weight: 5,
|
|
310
|
+
properties: {
|
|
311
|
+
"new_level": u.weighNumRange(2, 50),
|
|
312
|
+
"stat_points_gained": u.weighNumRange(1, 5),
|
|
313
|
+
}
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
event: "item purchased",
|
|
317
|
+
weight: 11,
|
|
318
|
+
properties: {
|
|
319
|
+
"item_id": u.pickAWinner(itemIds),
|
|
320
|
+
"item_type": u.pickAWinner([
|
|
321
|
+
"Weapon",
|
|
322
|
+
"Armor",
|
|
323
|
+
"Potion",
|
|
324
|
+
"Scroll",
|
|
325
|
+
"Mount",
|
|
326
|
+
"Cosmetic"
|
|
327
|
+
]),
|
|
328
|
+
"price_gold": u.weighNumRange(10, 500, 0.8, 100),
|
|
329
|
+
"vendor_type": u.pickAWinner(["Town", "Dungeon", "Special Event"]),
|
|
330
|
+
}
|
|
331
|
+
},
|
|
332
|
+
{
|
|
333
|
+
event: "item sold",
|
|
334
|
+
weight: 7,
|
|
335
|
+
properties: {
|
|
336
|
+
"item_id": u.pickAWinner(itemIds),
|
|
337
|
+
"item_type": u.pickAWinner([
|
|
338
|
+
"Weapon",
|
|
339
|
+
"Armor",
|
|
340
|
+
"Potion",
|
|
341
|
+
"Scroll",
|
|
342
|
+
"Junk"
|
|
343
|
+
]),
|
|
344
|
+
"sell_price": u.weighNumRange(5, 250, 0.5, 50),
|
|
345
|
+
}
|
|
346
|
+
},
|
|
347
|
+
{
|
|
348
|
+
event: "real money purchase",
|
|
349
|
+
weight: 3,
|
|
350
|
+
properties: {
|
|
351
|
+
"product": u.pickAWinner([
|
|
352
|
+
"Premium Currency (1000)",
|
|
353
|
+
"Premium Currency (5000)",
|
|
354
|
+
"Lucky Charm Pack",
|
|
355
|
+
"Legendary Weapon Chest",
|
|
356
|
+
"Cosmetic Bundle",
|
|
357
|
+
"Season Pass"
|
|
358
|
+
]),
|
|
359
|
+
"price_usd": u.pickAWinner([4.99, 9.99, 19.99, 49.99, 99.99]),
|
|
360
|
+
"payment_method": u.pickAWinner(["Credit Card", "PayPal", "Apple Pay", "Google Pay"]),
|
|
361
|
+
}
|
|
362
|
+
},
|
|
363
|
+
{
|
|
364
|
+
event: "guild joined",
|
|
365
|
+
weight: 4,
|
|
366
|
+
properties: {
|
|
367
|
+
"guild_size": u.weighNumRange(5, 100),
|
|
368
|
+
"guild_level": u.weighNumRange(1, 20),
|
|
369
|
+
}
|
|
370
|
+
},
|
|
371
|
+
{
|
|
372
|
+
event: "guild left",
|
|
373
|
+
weight: 1,
|
|
374
|
+
properties: {
|
|
375
|
+
"reason": u.pickAWinner([
|
|
376
|
+
"Inactive",
|
|
377
|
+
"Found Better Guild",
|
|
378
|
+
"Conflict",
|
|
379
|
+
"Disbanded"
|
|
380
|
+
]),
|
|
381
|
+
}
|
|
382
|
+
},
|
|
383
|
+
{
|
|
384
|
+
event: "inspect",
|
|
385
|
+
weight: 9,
|
|
386
|
+
properties: {
|
|
387
|
+
"inspect_target": u.pickAWinner([
|
|
388
|
+
"NPC",
|
|
389
|
+
"Monster",
|
|
390
|
+
"Treasure Chest",
|
|
391
|
+
"Door",
|
|
392
|
+
"Statue",
|
|
393
|
+
"Bookshelf"
|
|
394
|
+
]),
|
|
395
|
+
}
|
|
396
|
+
},
|
|
397
|
+
{
|
|
398
|
+
event: "search for clues",
|
|
399
|
+
weight: 8,
|
|
400
|
+
properties: {
|
|
401
|
+
"location_type": u.pickAWinner([
|
|
402
|
+
"Dungeon Entrance",
|
|
403
|
+
"Hidden Room",
|
|
404
|
+
"Quest Location",
|
|
405
|
+
"Town Square"
|
|
406
|
+
]),
|
|
407
|
+
"clue_found": u.pickAWinner([true, false], 0.6),
|
|
408
|
+
}
|
|
409
|
+
},
|
|
410
|
+
{
|
|
411
|
+
event: "use item",
|
|
412
|
+
weight: 14,
|
|
413
|
+
properties: {
|
|
414
|
+
"item_id": u.pickAWinner(itemIds),
|
|
415
|
+
"item_type": u.pickAWinner([
|
|
416
|
+
"Health Potion",
|
|
417
|
+
"Mana Potion",
|
|
418
|
+
"Buff Scroll",
|
|
419
|
+
"Ancient Compass",
|
|
420
|
+
"Lucky Charm",
|
|
421
|
+
"Resurrection Stone"
|
|
422
|
+
]),
|
|
423
|
+
"context": u.pickAWinner(["Combat", "Exploration", "Boss Fight", "Casual"]),
|
|
424
|
+
}
|
|
425
|
+
},
|
|
426
|
+
{
|
|
427
|
+
event: "combat initiated",
|
|
428
|
+
weight: 20,
|
|
429
|
+
properties: {
|
|
430
|
+
"enemy_type": u.pickAWinner([
|
|
431
|
+
"Goblin",
|
|
432
|
+
"Skeleton",
|
|
433
|
+
"Dragon",
|
|
434
|
+
"Demon",
|
|
435
|
+
"Undead",
|
|
436
|
+
"Beast"
|
|
437
|
+
]),
|
|
438
|
+
"enemy_level": u.weighNumRange(1, 50),
|
|
439
|
+
"combat_duration_sec": u.weighNumRange(10, 300, 0.7, 60),
|
|
440
|
+
}
|
|
441
|
+
},
|
|
442
|
+
{
|
|
443
|
+
event: "combat completed",
|
|
444
|
+
weight: 18,
|
|
445
|
+
properties: {
|
|
446
|
+
"outcome": u.pickAWinner(["Victory", "Defeat", "Fled"]),
|
|
447
|
+
"loot_gained": u.pickAWinner([true, false], 0.7),
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
],
|
|
451
|
+
|
|
452
|
+
superProps: {
|
|
453
|
+
platform: u.pickAWinner([
|
|
454
|
+
"PC",
|
|
455
|
+
"Mac",
|
|
456
|
+
"PlayStation",
|
|
457
|
+
"Xbox",
|
|
458
|
+
"Switch"
|
|
459
|
+
]),
|
|
460
|
+
graphics_quality: u.pickAWinner([
|
|
461
|
+
"Low",
|
|
462
|
+
"Medium",
|
|
463
|
+
"High",
|
|
464
|
+
"Ultra"
|
|
465
|
+
]),
|
|
466
|
+
subscription_tier: u.pickAWinner(["Free", "Free", "Free", "Premium", "Elite"]),
|
|
467
|
+
},
|
|
468
|
+
|
|
469
|
+
scdProps: {},
|
|
470
|
+
|
|
471
|
+
userProps: {
|
|
472
|
+
"preferred_playstyle": u.pickAWinner([
|
|
473
|
+
"Solo Explorer",
|
|
474
|
+
"Group Raider",
|
|
475
|
+
"PvP Fighter",
|
|
476
|
+
"Quest Completionist",
|
|
477
|
+
"Treasure Hunter"
|
|
478
|
+
]),
|
|
479
|
+
"total_playtime_hours": u.weighNumRange(1, 500, 1.5, 50),
|
|
480
|
+
"achievement_points": u.weighNumRange(0, 5000, 0.8, 500),
|
|
481
|
+
"favorite_class": u.pickAWinner([
|
|
482
|
+
"Warrior",
|
|
483
|
+
"Mage",
|
|
484
|
+
"Rogue",
|
|
485
|
+
"Cleric",
|
|
486
|
+
"Ranger",
|
|
487
|
+
"Paladin"
|
|
488
|
+
]),
|
|
489
|
+
},
|
|
490
|
+
|
|
491
|
+
groupKeys: [
|
|
492
|
+
["guild_id", 500, ["guild joined", "guild left", "quest turned in", "combat completed"]],
|
|
493
|
+
],
|
|
494
|
+
|
|
495
|
+
groupProps: {
|
|
496
|
+
guild_id: {
|
|
497
|
+
"name": () => `${chance.word()} ${chance.pickone(["Knights", "Dragons", "Warriors", "Seekers", "Legends"])}`,
|
|
498
|
+
"member_count": u.weighNumRange(5, 100),
|
|
499
|
+
"guild_level": u.weighNumRange(1, 20),
|
|
500
|
+
"total_wealth": u.weighNumRange(1000, 1000000, 0.5, 50000),
|
|
501
|
+
}
|
|
502
|
+
},
|
|
503
|
+
|
|
504
|
+
lookupTables: [],
|
|
505
|
+
|
|
506
|
+
/**
|
|
507
|
+
* ๐ฏ ARCHITECTED ANALYTICS HOOKS
|
|
508
|
+
*
|
|
509
|
+
* This hook function creates 8 deliberate patterns in the data:
|
|
510
|
+
*
|
|
511
|
+
* 1. CONVERSION: Ancient Compass users have 3x quest completion rate
|
|
512
|
+
* 2. TIME-BASED: "Cursed Week" (days 40-47) has 5x death rates & low completion
|
|
513
|
+
* 3. RETENTION: Early guild joiners (first 3 days) have 80% 30-day retention vs 20%
|
|
514
|
+
* 4. CHURN: Players with 3+ deaths in first week have 70% churn rate
|
|
515
|
+
* 5. PURCHASE VALUE: Lucky Charm buyers spend 5x more (LTV pattern)
|
|
516
|
+
* 6. BEHAVIORS TOGETHER: inspect + search before dungeon = 85% completion vs 45%
|
|
517
|
+
* 7. TIMED RELEASE: Legendary weapon released day 45, early adopters dominate
|
|
518
|
+
* 8. SUBSCRIPTION TIER: Premium/Elite users have higher engagement and success rates
|
|
519
|
+
*/
|
|
520
|
+
hook: function (record, type, meta) {
|
|
521
|
+
const NOW = dayjs();
|
|
522
|
+
const DATASET_START = NOW.subtract(days, 'days');
|
|
523
|
+
const CURSED_WEEK_START = DATASET_START.add(40, 'days');
|
|
524
|
+
const CURSED_WEEK_END = DATASET_START.add(47, 'days');
|
|
525
|
+
const LEGENDARY_WEAPON_RELEASE = DATASET_START.add(45, 'days');
|
|
526
|
+
|
|
527
|
+
// Hook #2: TIME-BASED TREND - Cursed Week
|
|
528
|
+
if (type === "event") {
|
|
529
|
+
const EVENT_TIME = dayjs(record.time);
|
|
530
|
+
|
|
531
|
+
// During cursed week, dramatically increase death rates
|
|
532
|
+
if (EVENT_TIME.isAfter(CURSED_WEEK_START) && EVENT_TIME.isBefore(CURSED_WEEK_END)) {
|
|
533
|
+
// 50% chance to inject a death event
|
|
534
|
+
if (chance.bool({ likelihood: 30 })) {
|
|
535
|
+
const deathEvent = {
|
|
536
|
+
event: "player death",
|
|
537
|
+
time: record.time,
|
|
538
|
+
user_id: record.user_id,
|
|
539
|
+
cause_of_death: "Curse",
|
|
540
|
+
player_level: chance.integer({ min: 1, max: 50 }),
|
|
541
|
+
resurrection_used: chance.bool({ likelihood: 80 }), // More res usage during curse
|
|
542
|
+
cursed_week: true,
|
|
543
|
+
};
|
|
544
|
+
// Return death event instead sometimes
|
|
545
|
+
if (chance.bool({ likelihood: 50 })) {
|
|
546
|
+
return deathEvent;
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
// Hook #7: TIMED RELEASE - Legendary Weapon
|
|
553
|
+
if (type === "event") {
|
|
554
|
+
const EVENT_TIME = dayjs(record.time);
|
|
555
|
+
|
|
556
|
+
if (record.event === "find treasure") {
|
|
557
|
+
// After legendary weapon release, some lucky players get it
|
|
558
|
+
if (EVENT_TIME.isAfter(LEGENDARY_WEAPON_RELEASE) && chance.bool({ likelihood: 2 })) {
|
|
559
|
+
record.treasure_type = "Shadowmourne Legendary";
|
|
560
|
+
record.treasure_value = 50000;
|
|
561
|
+
record.legendary_drop = true;
|
|
562
|
+
} else {
|
|
563
|
+
record.legendary_drop = false;
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
// Hook #3, #4, #5, #6, #1: EVERYTHING - Complex behavioral patterns
|
|
569
|
+
if (type === "everything") {
|
|
570
|
+
const userEvents = record;
|
|
571
|
+
const firstEventTime = userEvents.length > 0 ? dayjs(userEvents[0].time) : null;
|
|
572
|
+
|
|
573
|
+
// Track user behaviors
|
|
574
|
+
let usedAncientCompass = false;
|
|
575
|
+
let boughtLuckyCharm = false;
|
|
576
|
+
let joinedGuildEarly = false;
|
|
577
|
+
let earlyDeaths = 0;
|
|
578
|
+
let hasLegendaryWeapon = false;
|
|
579
|
+
let inspectedBeforeDungeon = false;
|
|
580
|
+
let searchedBeforeDungeon = false;
|
|
581
|
+
let subscriptionTier = "Free"; // Hook #8: Track subscription tier
|
|
582
|
+
|
|
583
|
+
// First pass: identify user patterns
|
|
584
|
+
userEvents.forEach((event, idx) => {
|
|
585
|
+
const eventTime = dayjs(event.time);
|
|
586
|
+
const daysSinceStart = firstEventTime ? eventTime.diff(firstEventTime, 'days', true) : 0;
|
|
587
|
+
|
|
588
|
+
// Hook #8: Capture subscription tier from any event that has it
|
|
589
|
+
if (event.subscription_tier) {
|
|
590
|
+
subscriptionTier = event.subscription_tier;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
// Hook #1: Track Ancient Compass usage
|
|
594
|
+
if (event.event === "use item" && event.item_type === "Ancient Compass") {
|
|
595
|
+
usedAncientCompass = true;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
// Hook #5: Track Lucky Charm purchases
|
|
599
|
+
if (event.event === "real money purchase" && event.product === "Lucky Charm Pack") {
|
|
600
|
+
boughtLuckyCharm = true;
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
// Hook #3: Track early guild joining
|
|
604
|
+
if (event.event === "guild joined" && daysSinceStart < 3) {
|
|
605
|
+
joinedGuildEarly = true;
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
// Hook #4: Track early deaths (first 7 days)
|
|
609
|
+
if (event.event === "player death" && daysSinceStart < 7) {
|
|
610
|
+
earlyDeaths++;
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
// Hook #7: Track legendary weapon ownership
|
|
614
|
+
if (event.event === "find treasure" && event.legendary_drop) {
|
|
615
|
+
hasLegendaryWeapon = true;
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
// Hook #6: Track inspect + search patterns
|
|
619
|
+
if (event.event === "inspect") {
|
|
620
|
+
inspectedBeforeDungeon = true;
|
|
621
|
+
}
|
|
622
|
+
if (event.event === "search for clues") {
|
|
623
|
+
searchedBeforeDungeon = true;
|
|
624
|
+
}
|
|
625
|
+
});
|
|
626
|
+
|
|
627
|
+
// Second pass: modify events based on patterns
|
|
628
|
+
userEvents.forEach((event, idx) => {
|
|
629
|
+
const eventTime = dayjs(event.time);
|
|
630
|
+
|
|
631
|
+
// Set schema defaults for conditional properties
|
|
632
|
+
if (event.event === "quest turned in") {
|
|
633
|
+
event.compass_user = false;
|
|
634
|
+
event.subscriber_advantage = "Free";
|
|
635
|
+
}
|
|
636
|
+
if (event.event === "exit dungeon") {
|
|
637
|
+
event.strategic_explorer = false;
|
|
638
|
+
event.legendary_weapon_equipped = false;
|
|
639
|
+
event.subscriber_advantage = "Free";
|
|
640
|
+
}
|
|
641
|
+
if (event.event === "find treasure") {
|
|
642
|
+
event.strategic_explorer = false;
|
|
643
|
+
event.subscriber_advantage = "Free";
|
|
644
|
+
}
|
|
645
|
+
if (event.event === "combat completed") {
|
|
646
|
+
event.legendary_weapon_equipped = false;
|
|
647
|
+
event.subscriber_advantage = "Free";
|
|
648
|
+
event.near_death_survival = false;
|
|
649
|
+
}
|
|
650
|
+
if (event.event === "player death") {
|
|
651
|
+
event.near_death_survival = false;
|
|
652
|
+
event.subscriber_advantage = "Free";
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
// Hook #1: CONVERSION - Ancient Compass users complete more quests
|
|
656
|
+
if (usedAncientCompass && event.event === "quest turned in") {
|
|
657
|
+
// Triple the rewards for compass users (they're more successful)
|
|
658
|
+
event.reward_gold = Math.floor((event.reward_gold || 100) * 1.5);
|
|
659
|
+
event.reward_xp = Math.floor((event.reward_xp || 500) * 1.5);
|
|
660
|
+
event.compass_user = true;
|
|
661
|
+
|
|
662
|
+
// Add extra quest completions for compass users
|
|
663
|
+
if (chance.bool({ likelihood: 40 })) {
|
|
664
|
+
const extraQuest = {
|
|
665
|
+
event: "quest turned in",
|
|
666
|
+
time: eventTime.add(chance.integer({ min: 10, max: 120 }), 'minutes').toISOString(),
|
|
667
|
+
user_id: event.user_id,
|
|
668
|
+
quest_id: chance.pickone(questIds),
|
|
669
|
+
reward_gold: chance.integer({ min: 100, max: 500 }),
|
|
670
|
+
reward_xp: chance.integer({ min: 500, max: 2000 }),
|
|
671
|
+
compass_user: true,
|
|
672
|
+
};
|
|
673
|
+
userEvents.splice(idx + 1, 0, extraQuest);
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
// Hook #5: PURCHASE VALUE - Lucky charm buyers spend 5x more
|
|
678
|
+
if (boughtLuckyCharm) {
|
|
679
|
+
if (event.event === "real money purchase") {
|
|
680
|
+
// Increase purchase amounts
|
|
681
|
+
if (event.price_usd) {
|
|
682
|
+
const currentPrice = event.price_usd;
|
|
683
|
+
if (currentPrice < 49.99) {
|
|
684
|
+
event.price_usd = currentPrice * 2; // Upgrade tier
|
|
685
|
+
}
|
|
686
|
+
event.lucky_charm_effect = true;
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
// Add additional purchase events (higher LTV)
|
|
691
|
+
if (event.event === "item purchased" && chance.bool({ likelihood: 35 })) {
|
|
692
|
+
const extraPurchase = {
|
|
693
|
+
event: "real money purchase",
|
|
694
|
+
time: eventTime.add(chance.integer({ min: 1, max: 3 }), 'days').toISOString(),
|
|
695
|
+
user_id: event.user_id,
|
|
696
|
+
product: chance.pickone([
|
|
697
|
+
"Premium Currency (5000)",
|
|
698
|
+
"Legendary Weapon Chest",
|
|
699
|
+
"Season Pass"
|
|
700
|
+
]),
|
|
701
|
+
price_usd: chance.pickone([19.99, 49.99, 99.99]),
|
|
702
|
+
payment_method: chance.pickone(["Credit Card", "PayPal"]),
|
|
703
|
+
lucky_charm_effect: true,
|
|
704
|
+
};
|
|
705
|
+
userEvents.splice(idx + 1, 0, extraPurchase);
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
// Hook #6: BEHAVIORS TOGETHER - Inspect + Search before dungeon
|
|
710
|
+
if (inspectedBeforeDungeon && searchedBeforeDungeon) {
|
|
711
|
+
if (event.event === "exit dungeon") {
|
|
712
|
+
// Much higher completion rate
|
|
713
|
+
if (event.completion_status !== "completed") {
|
|
714
|
+
// Convert 85% of non-completions to completions
|
|
715
|
+
if (chance.bool({ likelihood: 85 })) {
|
|
716
|
+
event.completion_status = "completed";
|
|
717
|
+
event.strategic_explorer = true;
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
// Find more treasure
|
|
723
|
+
if (event.event === "find treasure") {
|
|
724
|
+
event.treasure_value = Math.floor((event.treasure_value || 50) * 2);
|
|
725
|
+
event.strategic_explorer = true;
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
// Hook #7: TIMED RELEASE - Legendary weapon owners dominate
|
|
730
|
+
if (hasLegendaryWeapon) {
|
|
731
|
+
// Higher combat success
|
|
732
|
+
if (event.event === "combat completed") {
|
|
733
|
+
if (event.outcome !== "Victory") {
|
|
734
|
+
// Convert 90% of losses to victories
|
|
735
|
+
if (chance.bool({ likelihood: 90 })) {
|
|
736
|
+
event.outcome = "Victory";
|
|
737
|
+
event.legendary_weapon_equipped = true;
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
// Complete dungeons faster and more successfully
|
|
743
|
+
if (event.event === "exit dungeon") {
|
|
744
|
+
event.completion_status = "completed";
|
|
745
|
+
event.time_spent_mins = Math.floor((event.time_spent_mins || 60) * 0.6);
|
|
746
|
+
event.legendary_weapon_equipped = true;
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
// Hook #8: SUBSCRIPTION TIER - Premium/Elite users have better outcomes
|
|
751
|
+
if (subscriptionTier === "Premium" || subscriptionTier === "Elite") {
|
|
752
|
+
const isElite = subscriptionTier === "Elite";
|
|
753
|
+
|
|
754
|
+
// Better combat outcomes
|
|
755
|
+
if (event.event === "combat completed") {
|
|
756
|
+
if (event.outcome !== "Victory") {
|
|
757
|
+
const winBoost = isElite ? 70 : 50; // Elite: 70%, Premium: 50%
|
|
758
|
+
if (Math.random() * 100 < winBoost) {
|
|
759
|
+
event.outcome = "Victory";
|
|
760
|
+
event.loot_gained = true;
|
|
761
|
+
event.subscriber_advantage = subscriptionTier;
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
// Higher quest completion and rewards
|
|
767
|
+
if (event.event === "quest turned in") {
|
|
768
|
+
const rewardMultiplier = isElite ? 1.8 : 1.4; // Elite: 1.8x, Premium: 1.4x
|
|
769
|
+
event.reward_gold = Math.floor((event.reward_gold || 100) * rewardMultiplier);
|
|
770
|
+
event.reward_xp = Math.floor((event.reward_xp || 500) * rewardMultiplier);
|
|
771
|
+
event.subscriber_advantage = subscriptionTier;
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
// Higher dungeon completion rates
|
|
775
|
+
if (event.event === "exit dungeon") {
|
|
776
|
+
if (event.completion_status !== "completed") {
|
|
777
|
+
const completionBoost = isElite ? 65 : 45; // Elite: 65%, Premium: 45%
|
|
778
|
+
if (Math.random() * 100 < completionBoost) {
|
|
779
|
+
event.completion_status = "completed";
|
|
780
|
+
event.subscriber_advantage = subscriptionTier;
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
// Faster completion times
|
|
784
|
+
if (event.completion_status === "completed") {
|
|
785
|
+
const speedBoost = isElite ? 0.7 : 0.85; // Elite: 30% faster, Premium: 15% faster
|
|
786
|
+
event.time_spent_mins = Math.floor((event.time_spent_mins || 60) * speedBoost);
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
// Better treasure finds
|
|
791
|
+
if (event.event === "find treasure") {
|
|
792
|
+
const treasureBoost = isElite ? 2.0 : 1.5; // Elite: 2x, Premium: 1.5x
|
|
793
|
+
event.treasure_value = Math.floor((event.treasure_value || 50) * treasureBoost);
|
|
794
|
+
event.subscriber_advantage = subscriptionTier;
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
// Reduced death rates (subscribers have advantages)
|
|
798
|
+
if (event.event === "player death") {
|
|
799
|
+
const survivalChance = isElite ? 50 : 30; // Elite: 50% avoid death, Premium: 30%
|
|
800
|
+
if (Math.random() * 100 < survivalChance) {
|
|
801
|
+
// Convert death to combat completed with victory
|
|
802
|
+
event.event = "combat completed";
|
|
803
|
+
event.outcome = "Victory";
|
|
804
|
+
event.loot_gained = true;
|
|
805
|
+
event.subscriber_advantage = subscriptionTier;
|
|
806
|
+
event.near_death_survival = true;
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
// Elite users get bonus engagement events
|
|
811
|
+
if (isElite && Math.random() * 100 < 15) {
|
|
812
|
+
if (event.event === "quest turned in" || event.event === "exit dungeon") {
|
|
813
|
+
const treasureTypes = ["Rare Artifact", "Gold", "Weapon", "Armor"];
|
|
814
|
+
const bonusEvent = {
|
|
815
|
+
event: "find treasure",
|
|
816
|
+
time: eventTime.add(Math.floor(Math.random() * 26) + 5, 'minutes').toISOString(),
|
|
817
|
+
user_id: event.user_id,
|
|
818
|
+
treasure_type: treasureTypes[Math.floor(Math.random() * treasureTypes.length)],
|
|
819
|
+
treasure_value: Math.floor(Math.random() * 601) + 200,
|
|
820
|
+
subscriber_advantage: "Elite",
|
|
821
|
+
elite_bonus: true,
|
|
822
|
+
};
|
|
823
|
+
userEvents.splice(idx + 1, 0, bonusEvent);
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
});
|
|
828
|
+
|
|
829
|
+
// Hook #3: RETENTION - Early guild joiners retained
|
|
830
|
+
// Hook #4: CHURN - High early death = churn
|
|
831
|
+
const shouldChurn = (!joinedGuildEarly && earlyDeaths >= 3) ||
|
|
832
|
+
(earlyDeaths >= 5);
|
|
833
|
+
|
|
834
|
+
if (shouldChurn) {
|
|
835
|
+
// Remove 70% of events after first week (churn)
|
|
836
|
+
const firstWeekEnd = firstEventTime ? firstEventTime.add(7, 'days') : null;
|
|
837
|
+
for (let i = userEvents.length - 1; i >= 0; i--) {
|
|
838
|
+
const evt = userEvents[i];
|
|
839
|
+
if (firstWeekEnd && dayjs(evt.time).isAfter(firstWeekEnd)) {
|
|
840
|
+
if (chance.bool({ likelihood: 70 })) {
|
|
841
|
+
userEvents.splice(i, 1);
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
} else if (joinedGuildEarly) {
|
|
846
|
+
// Add extra engagement events for retained users
|
|
847
|
+
const lastEvent = userEvents[userEvents.length - 1];
|
|
848
|
+
if (lastEvent && chance.bool({ likelihood: 60 })) {
|
|
849
|
+
const retentionEvent = {
|
|
850
|
+
event: "combat completed",
|
|
851
|
+
time: dayjs(lastEvent.time).add(chance.integer({ min: 1, max: 5 }), 'days').toISOString(),
|
|
852
|
+
user_id: lastEvent.user_id,
|
|
853
|
+
outcome: "Victory",
|
|
854
|
+
loot_gained: true,
|
|
855
|
+
guild_member_retained: true,
|
|
856
|
+
};
|
|
857
|
+
userEvents.push(retentionEvent);
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
return record;
|
|
863
|
+
}
|
|
864
|
+
};
|
|
865
|
+
|
|
866
|
+
export default config;
|
|
867
|
+
|
|
868
|
+
/**
|
|
869
|
+
* โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
870
|
+
* NEEDLE IN A HAYSTACK - D&D ADVENTURE GAME ANALYTICS
|
|
871
|
+
* โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
872
|
+
*
|
|
873
|
+
* A D&D-style adventure game dungeon with 8 deliberately architected analytics
|
|
874
|
+
* insights hidden in the data. This dungeon is designed to showcase advanced
|
|
875
|
+
* product analytics patterns and demonstrate how to find "needles" (meaningful
|
|
876
|
+
* insights) in "haystacks" (large datasets).
|
|
877
|
+
*
|
|
878
|
+
* โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
879
|
+
* ๐ DATASET OVERVIEW
|
|
880
|
+
* โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
881
|
+
*
|
|
882
|
+
* - 5,000 users over 100 days
|
|
883
|
+
* - 2.4M events across 20+ event types
|
|
884
|
+
* - 3 funnels (onboarding, dungeon exploration, quest completion)
|
|
885
|
+
* - Group analytics (guilds)
|
|
886
|
+
* - Lookup tables (items, quests, dungeons)
|
|
887
|
+
* - Subscription tiers (Free, Premium, Elite)
|
|
888
|
+
*
|
|
889
|
+
* โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
890
|
+
* ๐ฏ THE 8 ARCHITECTED HOOKS
|
|
891
|
+
* โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
892
|
+
*
|
|
893
|
+
* Each hook creates a specific, discoverable analytics insight that simulates
|
|
894
|
+
* real-world product behavior patterns.
|
|
895
|
+
*
|
|
896
|
+
* โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
897
|
+
* 1๏ธโฃ CONVERSION HOOK: The Ancient Compass Effect
|
|
898
|
+
* โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
899
|
+
*
|
|
900
|
+
* PATTERN: Players who use the "Ancient Compass" item early in their journey
|
|
901
|
+
* have 3x higher quest completion rates and earn 1.5x more rewards.
|
|
902
|
+
*
|
|
903
|
+
* HOW TO FIND IT:
|
|
904
|
+
* - Segment users by: used item where item_type = "Ancient Compass"
|
|
905
|
+
* - Compare: Quest completion rate
|
|
906
|
+
* - Compare: Average reward_gold and reward_xp
|
|
907
|
+
*
|
|
908
|
+
* EXPECTED INSIGHT: Compass users complete 85-90% of accepted quests vs. 55%
|
|
909
|
+
* baseline. This simulates a power-user feature that drives core conversion.
|
|
910
|
+
*
|
|
911
|
+
* REAL-WORLD ANALOGUE: A key feature (e.g., tutorial completion, power tool
|
|
912
|
+
* usage) that dramatically improves user success rates.
|
|
913
|
+
*
|
|
914
|
+
* โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
915
|
+
* 2๏ธโฃ TIME-BASED HOOK: The Cursed Week
|
|
916
|
+
* โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
917
|
+
*
|
|
918
|
+
* PATTERN: During days 40-47 of the dataset, a "curse" strikes the game world:
|
|
919
|
+
* - Death rates spike 5x
|
|
920
|
+
* - Dungeon completion rates plummet
|
|
921
|
+
* - Resurrection item usage increases 4x
|
|
922
|
+
*
|
|
923
|
+
* HOW TO FIND IT:
|
|
924
|
+
* - Chart: player death event count by day
|
|
925
|
+
* - Filter: days 40-47
|
|
926
|
+
* - Compare: completion_status = "completed" vs "died" over time
|
|
927
|
+
*
|
|
928
|
+
* EXPECTED INSIGHT: Clear spike in deaths around day 43-44, with a marked
|
|
929
|
+
* increase in cursed_week: true property and cause_of_death: "Curse".
|
|
930
|
+
*
|
|
931
|
+
* REAL-WORLD ANALOGUE: A bug, server issue, or game balance change that
|
|
932
|
+
* temporarily degrades user experience.
|
|
933
|
+
*
|
|
934
|
+
* โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
935
|
+
* 3๏ธโฃ RETENTION HOOK: Early Guild Joiners
|
|
936
|
+
* โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
937
|
+
*
|
|
938
|
+
* PATTERN: Players who join a guild within their first 3 days have:
|
|
939
|
+
* - 80% 30-day retention vs. 20% baseline
|
|
940
|
+
* - More events throughout their lifecycle
|
|
941
|
+
* - Higher engagement in week 2-4
|
|
942
|
+
*
|
|
943
|
+
* HOW TO FIND IT:
|
|
944
|
+
* - Create cohort: users who did "guild joined" within first 3 days
|
|
945
|
+
* - Compare: D30 retention rate
|
|
946
|
+
* - Compare: Average events per user
|
|
947
|
+
*
|
|
948
|
+
* EXPECTED INSIGHT: Early guild joiners show dramatically higher retention
|
|
949
|
+
* curves, especially after the critical first week.
|
|
950
|
+
*
|
|
951
|
+
* REAL-WORLD ANALOGUE: Social features (friend invites, team creation) that
|
|
952
|
+
* create "sticky" behavior and drive retention.
|
|
953
|
+
*
|
|
954
|
+
* โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
955
|
+
* 4๏ธโฃ CHURN HOOK: Death Spiral
|
|
956
|
+
* โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
957
|
+
*
|
|
958
|
+
* PATTERN: Players who die 3+ times in their first week have a 70% churn rate -
|
|
959
|
+
* they stop playing after week 1.
|
|
960
|
+
*
|
|
961
|
+
* HOW TO FIND IT:
|
|
962
|
+
* - Segment users by: count of "player death" events in first 7 days
|
|
963
|
+
* - Bucket: 0-2 deaths, 3-4 deaths, 5+ deaths
|
|
964
|
+
* - Compare: Events after day 7 (retention proxy)
|
|
965
|
+
*
|
|
966
|
+
* EXPECTED INSIGHT: Users with 3+ early deaths have 70% fewer events after day 7.
|
|
967
|
+
* The hook literally removes 70% of their post-week-1 events.
|
|
968
|
+
*
|
|
969
|
+
* REAL-WORLD ANALOGUE: Poor onboarding experience or early friction that causes
|
|
970
|
+
* users to abandon the product.
|
|
971
|
+
*
|
|
972
|
+
* โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
973
|
+
* 5๏ธโฃ PURCHASE VALUE HOOK: Lucky Charm LTV
|
|
974
|
+
* โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
975
|
+
*
|
|
976
|
+
* PATTERN: Players who purchase the "Lucky Charm Pack" early become 5x higher
|
|
977
|
+
* LTV customers:
|
|
978
|
+
* - They upgrade to higher-tier purchases
|
|
979
|
+
* - They purchase more frequently
|
|
980
|
+
* - Their total spend is 5x the average
|
|
981
|
+
*
|
|
982
|
+
* HOW TO FIND IT:
|
|
983
|
+
* - Segment users by: did "real money purchase" where product contains "Lucky Charm"
|
|
984
|
+
* - Compare: Total revenue per user
|
|
985
|
+
* - Compare: Purchase frequency
|
|
986
|
+
* - Compare: Average order value
|
|
987
|
+
*
|
|
988
|
+
* EXPECTED INSIGHT: Lucky Charm buyers have dramatically higher LTV, with
|
|
989
|
+
* lucky_charm_effect: true properties on subsequent purchases.
|
|
990
|
+
*
|
|
991
|
+
* REAL-WORLD ANALOGUE: An initial purchase or subscription that predicts high
|
|
992
|
+
* lifetime value (e.g., premium feature adoption).
|
|
993
|
+
*
|
|
994
|
+
* โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
995
|
+
* 6๏ธโฃ BEHAVIORS TOGETHER HOOK: Strategic Explorers
|
|
996
|
+
* โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
997
|
+
*
|
|
998
|
+
* PATTERN: Players who both "inspect" AND "search for clues" before entering
|
|
999
|
+
* dungeons have:
|
|
1000
|
+
* - 85% dungeon completion rate vs. 45% baseline
|
|
1001
|
+
* - 2x treasure value found
|
|
1002
|
+
* - Marked as strategic_explorer: true
|
|
1003
|
+
*
|
|
1004
|
+
* HOW TO FIND IT:
|
|
1005
|
+
* - Create segment: users who did BOTH "inspect" AND "search for clues"
|
|
1006
|
+
* - Filter funnel: enter dungeon โ exit dungeon
|
|
1007
|
+
* - Compare: completion_status = "completed" rate
|
|
1008
|
+
* - Compare: Average treasure_value
|
|
1009
|
+
*
|
|
1010
|
+
* EXPECTED INSIGHT: Users who exhibit both preparatory behaviors have vastly
|
|
1011
|
+
* superior outcomes. This is a "power user" behavioral signature.
|
|
1012
|
+
*
|
|
1013
|
+
* REAL-WORLD ANALOGUE: Users who engage with multiple features together (e.g.,
|
|
1014
|
+
* read docs + watch tutorial) have better outcomes than single-feature users.
|
|
1015
|
+
*
|
|
1016
|
+
* โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
1017
|
+
* 7๏ธโฃ TIMED RELEASE HOOK: Shadowmourne Legendary Weapon
|
|
1018
|
+
* โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
1019
|
+
*
|
|
1020
|
+
* PATTERN: On day 45, a legendary weapon "Shadowmourne" is released:
|
|
1021
|
+
* - 2% of players find it after release
|
|
1022
|
+
* - These players have 90% combat win rate (vs. 60% baseline)
|
|
1023
|
+
* - They complete dungeons 40% faster
|
|
1024
|
+
* - Marked as legendary_weapon_equipped: true
|
|
1025
|
+
*
|
|
1026
|
+
* HOW TO FIND IT:
|
|
1027
|
+
* - Filter events: time >= day 45
|
|
1028
|
+
* - Filter: find treasure where treasure_type = "Shadowmourne Legendary"
|
|
1029
|
+
* - Compare: combat_completed outcome = "Victory" rate
|
|
1030
|
+
* - Compare: exit dungeon time_spent_mins
|
|
1031
|
+
*
|
|
1032
|
+
* EXPECTED INSIGHT: After day 45, a small cohort of "legendary weapon owners"
|
|
1033
|
+
* dominates all game modes. Clear before/after in their performance metrics.
|
|
1034
|
+
*
|
|
1035
|
+
* REAL-WORLD ANALOGUE: A new feature release or product tier that creates a
|
|
1036
|
+
* distinct high-performing user segment.
|
|
1037
|
+
*
|
|
1038
|
+
* โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
1039
|
+
* 8๏ธโฃ SUBSCRIPTION TIER HOOK: Premium/Elite Advantage
|
|
1040
|
+
* โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
1041
|
+
*
|
|
1042
|
+
* PATTERN: Premium and Elite subscribers have dramatically better outcomes:
|
|
1043
|
+
* - Premium: 50% better combat win rate, 1.4x rewards, 45% higher dungeon completion
|
|
1044
|
+
* - Elite: 70% better combat win rate, 1.8x rewards, 65% higher dungeon completion
|
|
1045
|
+
* - Elite users get bonus treasure events
|
|
1046
|
+
* - Marked as subscriber_advantage: "Premium" or "Elite"
|
|
1047
|
+
*
|
|
1048
|
+
* HOW TO FIND IT:
|
|
1049
|
+
* - Segment users by: subscription_tier
|
|
1050
|
+
* - Compare: Combat win rates by tier
|
|
1051
|
+
* - Compare: Average reward_gold by tier
|
|
1052
|
+
* - Compare: Dungeon completion rates by tier
|
|
1053
|
+
* - Compare: Death rates by tier
|
|
1054
|
+
*
|
|
1055
|
+
* EXPECTED INSIGHT: Clear tier-based performance differences. Elite > Premium > Free
|
|
1056
|
+
* across all engagement and success metrics.
|
|
1057
|
+
*
|
|
1058
|
+
* REAL-WORLD ANALOGUE: Subscription tiers that provide gameplay advantages (power-ups,
|
|
1059
|
+
* boosts, premium content) resulting in measurable outcome differences.
|
|
1060
|
+
*
|
|
1061
|
+
* โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
1062
|
+
* ๐ ADVANCED ANALYSIS IDEAS
|
|
1063
|
+
* โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
1064
|
+
*
|
|
1065
|
+
* CROSS-HOOK PATTERNS:
|
|
1066
|
+
*
|
|
1067
|
+
* 1. The Ultimate Player: Users who:
|
|
1068
|
+
* - Use Ancient Compass (Hook #1)
|
|
1069
|
+
* - Join guild early (Hook #3)
|
|
1070
|
+
* - Buy Lucky Charm (Hook #5)
|
|
1071
|
+
* - Get legendary weapon (Hook #7)
|
|
1072
|
+
* - Have Elite subscription (Hook #8)
|
|
1073
|
+
* These players should have exceptional metrics across all dimensions.
|
|
1074
|
+
*
|
|
1075
|
+
* 2. The Cursed Compass: Do Ancient Compass users survive the Cursed Week
|
|
1076
|
+
* better than others?
|
|
1077
|
+
*
|
|
1078
|
+
* 3. Guild Churn Prevention: Does early guild joining (Hook #3) prevent
|
|
1079
|
+
* death-spiral churn (Hook #4)?
|
|
1080
|
+
*
|
|
1081
|
+
* 4. LTV + Retention: Compare Lucky Charm buyers who joined guilds early vs.
|
|
1082
|
+
* those who didn't.
|
|
1083
|
+
*
|
|
1084
|
+
* 5. Subscription Impact on Churn: Do Premium/Elite subscribers avoid the
|
|
1085
|
+
* death spiral churn pattern?
|
|
1086
|
+
*
|
|
1087
|
+
* COHORT ANALYSIS:
|
|
1088
|
+
*
|
|
1089
|
+
* - Cohort by starting week: Users who started during Cursed Week (days 40-47)
|
|
1090
|
+
* should show different patterns
|
|
1091
|
+
* - Cohort by character class: Do certain classes show different hook patterns?
|
|
1092
|
+
* - Cohort by platform: Do PC users vs. console users exhibit different
|
|
1093
|
+
* strategic explorer behavior?
|
|
1094
|
+
* - Cohort by subscription tier: Track retention, engagement, and monetization
|
|
1095
|
+
* differences
|
|
1096
|
+
*
|
|
1097
|
+
* FUNNEL ANALYSIS:
|
|
1098
|
+
*
|
|
1099
|
+
* - Onboarding Funnel: How does Ancient Compass usage affect tutorial โ first
|
|
1100
|
+
* quest conversion?
|
|
1101
|
+
* - Dungeon Funnel: Compare enter โ treasure โ exit completion by strategic
|
|
1102
|
+
* explorers and subscription tier
|
|
1103
|
+
* - Quest Funnel: Compare quest accepted โ completed rates before and during
|
|
1104
|
+
* Cursed Week
|
|
1105
|
+
*
|
|
1106
|
+
* โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
1107
|
+
* ๐ EXPECTED METRICS SUMMARY
|
|
1108
|
+
* โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
1109
|
+
*
|
|
1110
|
+
* Hook | Metric | Baseline | Hook Effect | Ratio
|
|
1111
|
+
* โโโโโโโโโโโโโโโโโโโโโโ|โโโโโโโโโโโโโโโโโโโโโโ|โโโโโโโโโโ|โโโโโโโโโโโโโ|โโโโโโ
|
|
1112
|
+
* Ancient Compass | Quest completion | 55% | 85-90% | ~1.6x
|
|
1113
|
+
* Cursed Week | Death rate | 8% | 40% | 5x
|
|
1114
|
+
* Early Guild Join | D30 Retention | 20% | 80% | 4x
|
|
1115
|
+
* Death Spiral | Retention (3+ deaths)| 100% | 30% | 0.3x
|
|
1116
|
+
* Lucky Charm | LTV | $15 | $75 | 5x
|
|
1117
|
+
* Strategic Explorer | Dungeon completion | 45% | 85% | ~1.9x
|
|
1118
|
+
* Legendary Weapon | Combat win rate | 60% | 90% | 1.5x
|
|
1119
|
+
* Premium Tier | Combat win rate | 60% | 90% | 1.5x
|
|
1120
|
+
* Elite Tier | Combat win rate | 60% | 102% | 1.7x
|
|
1121
|
+
*
|
|
1122
|
+
* โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
1123
|
+
* ๐ฎ HOW TO RUN THIS DUNGEON
|
|
1124
|
+
* โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
1125
|
+
*
|
|
1126
|
+
* From the dm4 root directory:
|
|
1127
|
+
*
|
|
1128
|
+
* npm start
|
|
1129
|
+
*
|
|
1130
|
+
* Or programmatically:
|
|
1131
|
+
*
|
|
1132
|
+
* import generate from './index.js';
|
|
1133
|
+
* import config from './dungeons/harness-gaming.js';
|
|
1134
|
+
* const results = await generate(config);
|
|
1135
|
+
*
|
|
1136
|
+
* OUTPUT FILES (with writeToDisk: false, format: "parquet", gzip: true):
|
|
1137
|
+
*
|
|
1138
|
+
* - needle-in-haystack__events.parquet.gz - All event data
|
|
1139
|
+
* - needle-in-haystack__user_profiles.parquet.gz - User profiles
|
|
1140
|
+
* - needle-in-haystack__group_profiles.parquet.gz - Guild profiles
|
|
1141
|
+
* - needle-in-haystack__item_id_lookup.parquet.gz - Item catalog
|
|
1142
|
+
* - needle-in-haystack__quest_id_lookup.parquet.gz - Quest catalog
|
|
1143
|
+
* - needle-in-haystack__dungeon_id_lookup.parquet.gz - Dungeon catalog
|
|
1144
|
+
*
|
|
1145
|
+
* โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
1146
|
+
* ๐งช TESTING YOUR ANALYTICS PLATFORM
|
|
1147
|
+
* โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
1148
|
+
*
|
|
1149
|
+
* This dungeon is perfect for testing:
|
|
1150
|
+
*
|
|
1151
|
+
* 1. Segmentation: Can you identify the Ancient Compass power users?
|
|
1152
|
+
* 2. Anomaly Detection: Can you detect the Cursed Week automatically?
|
|
1153
|
+
* 3. Retention Analysis: Can you discover the early guild joining pattern?
|
|
1154
|
+
* 4. Churn Prediction: Can you predict churn based on early death patterns?
|
|
1155
|
+
* 5. LTV Modeling: Can you identify high-LTV users early (Lucky Charm buyers)?
|
|
1156
|
+
* 6. Behavioral Analysis: Can you find the strategic explorer pattern?
|
|
1157
|
+
* 7. Feature Impact: Can you measure the Legendary Weapon release impact?
|
|
1158
|
+
* 8. Tier Analysis: Can you quantify subscription tier value differences?
|
|
1159
|
+
*
|
|
1160
|
+
* โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
1161
|
+
* ๐ก WHY "NEEDLE IN A HAYSTACK"?
|
|
1162
|
+
* โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
1163
|
+
*
|
|
1164
|
+
* Each hook is a "needle" - a meaningful, actionable insight hidden in a
|
|
1165
|
+
* "haystack" of 2.4M events. The challenge is:
|
|
1166
|
+
*
|
|
1167
|
+
* 1. FINDING the needles (discovery)
|
|
1168
|
+
* 2. VALIDATING they're real patterns (statistical significance)
|
|
1169
|
+
* 3. UNDERSTANDING why they matter (business impact)
|
|
1170
|
+
* 4. ACTING on them (product decisions)
|
|
1171
|
+
*
|
|
1172
|
+
* This mirrors real-world product analytics: your data contains valuable insights,
|
|
1173
|
+
* but you need the right tools and skills to find them.
|
|
1174
|
+
*
|
|
1175
|
+
* Happy Hunting! ๐ฏ
|
|
1176
|
+
*
|
|
1177
|
+
* โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
1178
|
+
*/
|