make-mp-data 3.0.3 → 3.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +46 -0
- package/dungeons/array-of-object-lookup-schema.json +327 -0
- package/dungeons/array-of-object-lookup.js +29 -9
- 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} +79 -17
- package/dungeons/education-schema.json +2409 -0
- package/dungeons/education.js +226 -462
- package/dungeons/fintech-schema.json +14034 -0
- package/dungeons/fintech.js +134 -413
- 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 +173 -406
- package/dungeons/gaming-schema.json +1270 -0
- package/dungeons/gaming.js +182 -42
- 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 +250 -420
- 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 +171 -429
- package/dungeons/sanity-schema.json +255 -0
- package/dungeons/sanity.js +21 -10
- package/dungeons/sass-schema.json +1291 -0
- package/dungeons/sass.js +241 -368
- package/dungeons/scd-schema.json +919 -0
- package/dungeons/scd.js +41 -13
- package/dungeons/simple-schema.json +608 -0
- package/dungeons/simple.js +52 -15
- package/dungeons/simplest-schema.json +1418 -0
- package/dungeons/simplest.js +392 -0
- package/dungeons/social-schema.json +1118 -0
- package/dungeons/social.js +150 -391
- package/dungeons/text-generation-schema.json +3096 -0
- package/dungeons/text-generation.js +71 -0
- package/index.js +8 -6
- package/lib/core/config-validator.js +28 -8
- package/lib/core/storage.js +5 -5
- package/lib/generators/events.js +4 -4
- package/lib/orchestrators/mixpanel-sender.js +16 -13
- 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 -130
- package/dungeons/anon.js +0 -128
- package/dungeons/benchmark-heavy.js +0 -240
- package/dungeons/benchmark-light.js +0 -140
- 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 -161
- 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
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema": {
|
|
3
|
+
"token": "",
|
|
4
|
+
"seed": "lets go",
|
|
5
|
+
"numDays": 360,
|
|
6
|
+
"numEvents": 5000,
|
|
7
|
+
"numUsers": 100,
|
|
8
|
+
"hasAnonIds": false,
|
|
9
|
+
"hasSessionIds": false,
|
|
10
|
+
"format": "json",
|
|
11
|
+
"alsoInferFunnels": false,
|
|
12
|
+
"hasLocation": false,
|
|
13
|
+
"hasAndroidDevices": false,
|
|
14
|
+
"hasIOSDevices": false,
|
|
15
|
+
"hasDesktopDevices": false,
|
|
16
|
+
"hasBrowser": false,
|
|
17
|
+
"hasCampaigns": false,
|
|
18
|
+
"isAnonymous": false,
|
|
19
|
+
"hasAdSpend": false,
|
|
20
|
+
"hasAvatar": false,
|
|
21
|
+
"batchSize": 5500000,
|
|
22
|
+
"concurrency": 1,
|
|
23
|
+
"writeToDisk": false,
|
|
24
|
+
"percentUsersBornInDataset": 100,
|
|
25
|
+
"funnels": [],
|
|
26
|
+
"events": [
|
|
27
|
+
{
|
|
28
|
+
"event": "first behavior",
|
|
29
|
+
"weight": 1,
|
|
30
|
+
"isFirstEvent": true,
|
|
31
|
+
"properties": {}
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"event": "hourly behavior",
|
|
35
|
+
"weight": 40,
|
|
36
|
+
"properties": {}
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"event": "daily behavior",
|
|
40
|
+
"weight": 30,
|
|
41
|
+
"properties": {}
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"event": "weekly behavior",
|
|
45
|
+
"weight": 15,
|
|
46
|
+
"properties": {}
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"event": "monthly behavior",
|
|
50
|
+
"weight": 10,
|
|
51
|
+
"properties": {}
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"event": "placeholder",
|
|
55
|
+
"weight": 50,
|
|
56
|
+
"properties": {}
|
|
57
|
+
}
|
|
58
|
+
],
|
|
59
|
+
"superProps": {},
|
|
60
|
+
"userProps": {
|
|
61
|
+
"favorite color": [
|
|
62
|
+
"red",
|
|
63
|
+
"blue",
|
|
64
|
+
"green",
|
|
65
|
+
"yellow",
|
|
66
|
+
"purple"
|
|
67
|
+
]
|
|
68
|
+
},
|
|
69
|
+
"scdProps": {},
|
|
70
|
+
"mirrorProps": {},
|
|
71
|
+
"groupKeys": [],
|
|
72
|
+
"groupProps": {},
|
|
73
|
+
"lookupTables": []
|
|
74
|
+
},
|
|
75
|
+
"hooks": "function (record, type, meta) {\n\t\tif (type === \"everything\") {\n\t\t\tif (!record.length) return record;\n\n\t\t\tconst userId = record[0].user_id || record[0].device_id;\n\t\t\tif (!userId) return record;\n\n\t\t\tconst favoriteColor = meta.profile?.[\"favorite color\"] || \"green\";\n\t\t\tconst colorChurnRates = CHURN_RATES[favoriteColor] || CHURN_RATES.green;\n\n\t\t\t// Find the time range from the raw events\n\t\t\tconst times = record.map(e => new Date(e.time).getTime()).filter(t => !isNaN(t));\n\t\t\tif (!times.length) return record;\n\t\t\tconst startTime = dayjs(Math.min(...times));\n\t\t\tconst endTime = dayjs(Math.max(...times));\n\t\t\tconst totalSpanHours = endTime.diff(startTime, 'hour');\n\n\t\t\tif (totalSpanHours < 1) return record;\n\n\t\t\t// Keep the \"first behavior\" event from the original stream\n\t\t\tconst firstBehavior = record.find(e => e.event === \"first behavior\");\n\t\t\tconst newEvents = [];\n\n\t\t\tif (firstBehavior) {\n\t\t\t\tnewEvents.push(firstBehavior);\n\t\t\t} else {\n\t\t\t\t// Create a first behavior event at the start\n\t\t\t\tnewEvents.push({\n\t\t\t\t\tevent: \"first behavior\",\n\t\t\t\t\ttime: startTime.toISOString(),\n\t\t\t\t\tuser_id: userId,\n\t\t\t\t\tinsert_id: v.uid(12),\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// For each behavior type, determine churn and generate cadenced events\n\t\t\tfor (const [behaviorKey, cadence] of Object.entries(BEHAVIORS)) {\n\t\t\t\tconst churnRate = colorChurnRates[behaviorKey];\n\t\t\t\tlet churnTime = null;\n\n\t\t\t\tif (chance.bool({ likelihood: churnRate })) {\n\t\t\t\t\t// Pick churn time between 20% and 80% into the active period\n\t\t\t\t\tconst churnOffsetHours = chance.integer({\n\t\t\t\t\t\tmin: Math.floor(totalSpanHours * 0.2),\n\t\t\t\t\t\tmax: Math.floor(totalSpanHours * 0.8),\n\t\t\t\t\t});\n\t\t\t\t\tchurnTime = startTime.add(churnOffsetHours, 'hour');\n\t\t\t\t}\n\n\t\t\t\tconst behaviorEvents = generateCadencedEvents(\n\t\t\t\t\tbehaviorKey,\n\t\t\t\t\tcadence,\n\t\t\t\t\tstartTime,\n\t\t\t\t\tendTime,\n\t\t\t\t\tchurnTime,\n\t\t\t\t\tuserId\n\t\t\t\t);\n\t\t\t\tnewEvents.push(...behaviorEvents);\n\t\t\t}\n\n\t\t\t// Sort all events by time\n\t\t\tnewEvents.sort((a, b) => new Date(a.time) - new Date(b.time));\n\t\t\treturn newEvents;\n\t\t}\n\n\t\treturn record;\n\t}",
|
|
76
|
+
"timestamp": "2026-04-10T01:39:07.299Z",
|
|
77
|
+
"version": "4.0"
|
|
78
|
+
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
1
|
const SEED = "kurby-retention";
|
|
3
2
|
import dayjs from 'dayjs';
|
|
4
3
|
import utc from 'dayjs/plugin/utc.js';
|
|
@@ -12,6 +11,41 @@ const days = 360;
|
|
|
12
11
|
|
|
13
12
|
/** @typedef {import("../types.js").Dungeon} Config */
|
|
14
13
|
|
|
14
|
+
/**
|
|
15
|
+
* ═══════════════════════════════════════════════════════════════
|
|
16
|
+
* DATASET OVERVIEW
|
|
17
|
+
* ═══════════════════════════════════════════════════════════════
|
|
18
|
+
*
|
|
19
|
+
* Retention Cadence — tests behavior frequency and color-based churn.
|
|
20
|
+
* - 100 users over 360 days, ~5K base events (replaced by cadenced events)
|
|
21
|
+
* - 4 behavior cadences: hourly, daily, weekly, monthly
|
|
22
|
+
* - Churn rates vary by user's "favorite color" (red, blue, green, yellow, purple)
|
|
23
|
+
* - The everything hook REPLACES all generated events with precisely
|
|
24
|
+
* cadenced behavior events, making this a pure retention analysis dataset
|
|
25
|
+
*
|
|
26
|
+
* ═══════════════════════════════════════════════════════════════
|
|
27
|
+
* ANALYTICS HOOKS (1 pattern — everything hook)
|
|
28
|
+
* ═══════════════════════════════════════════════════════════════
|
|
29
|
+
*
|
|
30
|
+
* 1. COLOR-BASED CADENCED CHURN (everything hook)
|
|
31
|
+
* All raw events are replaced with 4 cadenced behavior streams
|
|
32
|
+
* (hourly/daily/weekly/monthly). Each user's "favorite color"
|
|
33
|
+
* determines their churn likelihood per cadence:
|
|
34
|
+
* - red: high daily churn (40%)
|
|
35
|
+
* - blue: high weekly churn (40%)
|
|
36
|
+
* - green: low churn across all cadences (5%)
|
|
37
|
+
* - yellow: high monthly churn (40%)
|
|
38
|
+
* - purple: high hourly churn (40%)
|
|
39
|
+
* Churned behaviors get a "churn - X behavior" event at the churn point.
|
|
40
|
+
*
|
|
41
|
+
* Mixpanel Report:
|
|
42
|
+
* - Retention: Event A: "first behavior", Event B: "daily behavior",
|
|
43
|
+
* breakdown by "favorite color"
|
|
44
|
+
* Expected: red users show ~40% daily churn, green users retain well
|
|
45
|
+
* - Insights: "churn - *" events, breakdown by "favorite color"
|
|
46
|
+
* Expected: each color dominates its respective cadence's churn events
|
|
47
|
+
*/
|
|
48
|
+
|
|
15
49
|
// Churn rates by favorite color per behavior type (percentage likelihood)
|
|
16
50
|
const CHURN_RATES = {
|
|
17
51
|
red: { hourly: 15, daily: 40, weekly: 15, monthly: 10 },
|