make-mp-data 1.5.56 → 2.0.0
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/.claude/settings.local.json +20 -0
- package/.gcloudignore +2 -1
- package/.vscode/launch.json +6 -17
- package/.vscode/settings.json +31 -2
- package/dungeons/media.js +371 -0
- package/index.js +353 -1766
- package/{components → lib/cli}/cli.js +21 -6
- package/lib/cloud-function.js +20 -0
- package/lib/core/config-validator.js +248 -0
- package/lib/core/context.js +180 -0
- package/lib/core/storage.js +268 -0
- package/{components → lib/data}/defaults.js +17 -14
- package/lib/generators/adspend.js +133 -0
- package/lib/generators/events.js +242 -0
- package/lib/generators/funnels.js +330 -0
- package/lib/generators/mirror.js +168 -0
- package/lib/generators/profiles.js +93 -0
- package/lib/generators/scd.js +102 -0
- package/lib/orchestrators/mixpanel-sender.js +222 -0
- package/lib/orchestrators/user-loop.js +194 -0
- package/lib/orchestrators/worker-manager.js +200 -0
- package/{components → lib/utils}/ai.js +8 -36
- package/{components → lib/utils}/chart.js +9 -9
- package/{components → lib/utils}/project.js +4 -4
- package/{components → lib/utils}/utils.js +35 -23
- package/package.json +15 -15
- package/scripts/dana.mjs +137 -0
- package/scripts/new-dungeon.sh +7 -6
- package/scripts/update-deps.sh +2 -1
- package/tests/cli.test.js +28 -25
- package/tests/e2e.test.js +38 -36
- package/tests/int.test.js +151 -56
- package/tests/testSoup.mjs +1 -1
- package/tests/unit.test.js +15 -14
- package/tsconfig.json +1 -1
- package/types.d.ts +68 -11
- package/vitest.config.js +47 -0
- package/log.json +0 -1678
- package/tests/jest.config.js +0 -47
- /package/{components → lib/utils}/prompt.txt +0 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"Bash(node:*)",
|
|
5
|
+
"Bash(mkdir:*)",
|
|
6
|
+
"Bash(npm install)",
|
|
7
|
+
"Bash(npx vitest run:*)",
|
|
8
|
+
"Bash(npm test)",
|
|
9
|
+
"Bash(grep:*)",
|
|
10
|
+
"Bash(rg:*)",
|
|
11
|
+
"Bash(./scripts/new-dungeon.sh:*)",
|
|
12
|
+
"Bash(cp:*)",
|
|
13
|
+
"Bash(find:*)",
|
|
14
|
+
"Bash(npm test:*)",
|
|
15
|
+
"Bash(npm run test:*)",
|
|
16
|
+
"Bash(npx tsc:*)"
|
|
17
|
+
],
|
|
18
|
+
"deny": []
|
|
19
|
+
}
|
|
20
|
+
}
|
package/.gcloudignore
CHANGED
package/.vscode/launch.json
CHANGED
|
@@ -13,23 +13,8 @@
|
|
|
13
13
|
{
|
|
14
14
|
"type": "node",
|
|
15
15
|
"request": "launch",
|
|
16
|
-
"name": "run dungeon
|
|
17
|
-
"runtimeExecutable": "nodemon",
|
|
18
|
-
"runtimeArgs": ["--inspect", "--ignore", "./data"],
|
|
19
|
-
"program": "${workspaceFolder}/index.js",
|
|
20
|
-
"args": ["${file}"],
|
|
21
|
-
"restart": true,
|
|
22
|
-
"console": "integratedTerminal",
|
|
23
|
-
"internalConsoleOptions": "neverOpen",
|
|
24
|
-
"skipFiles": ["<node_internals>/**"],
|
|
25
|
-
"preLaunchTask": "npm: prune",
|
|
26
|
-
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
"type": "node",
|
|
30
|
-
"request": "launch",
|
|
31
|
-
"name": "run dungeon (one shot)",
|
|
32
|
-
"runtimeExecutable": "node",
|
|
16
|
+
"name": "run dungeon",
|
|
17
|
+
"runtimeExecutable": "nodemon",
|
|
33
18
|
"program": "${workspaceFolder}/index.js",
|
|
34
19
|
"args": ["${file}"],
|
|
35
20
|
"restart": true,
|
|
@@ -37,6 +22,10 @@
|
|
|
37
22
|
"internalConsoleOptions": "neverOpen",
|
|
38
23
|
"skipFiles": ["<node_internals>/**"],
|
|
39
24
|
"preLaunchTask": "npm: prune",
|
|
25
|
+
"runtimeArgs": [
|
|
26
|
+
"--ignore",
|
|
27
|
+
"./data"
|
|
28
|
+
]
|
|
40
29
|
|
|
41
30
|
},
|
|
42
31
|
{
|
package/.vscode/settings.json
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
"Colour",
|
|
8
8
|
"crumn",
|
|
9
9
|
"darr",
|
|
10
|
+
"datagenerator",
|
|
10
11
|
"dislikers",
|
|
11
12
|
"Dont",
|
|
12
13
|
"durtle",
|
|
@@ -34,7 +35,35 @@
|
|
|
34
35
|
"weindgo",
|
|
35
36
|
"whomacity"
|
|
36
37
|
],
|
|
37
|
-
|
|
38
|
-
"
|
|
38
|
+
// Vitest settings
|
|
39
|
+
"vitest.enable": true,
|
|
40
|
+
"vitest.commandLine": "npx vitest",
|
|
41
|
+
"vitest.include": ["tests/**/*.test.js"],
|
|
42
|
+
"vitest.exclude": ["**/node_modules/**", "**/coverage/**", "**/data/**", "**/tmp/**"],
|
|
43
|
+
|
|
44
|
+
// Test Explorer settings
|
|
45
|
+
"testing.automaticallyOpenPeekView": "never",
|
|
46
|
+
"testing.openTesting": "neverOpen",
|
|
39
47
|
"js/ts.implicitProjectConfig.checkJs": true,
|
|
48
|
+
|
|
49
|
+
// ESM and import settings
|
|
50
|
+
"typescript.preferences.includePackageJsonAutoImports": "auto",
|
|
51
|
+
"typescript.suggest.autoImports": true,
|
|
52
|
+
"javascript.suggest.autoImports": true,
|
|
53
|
+
|
|
54
|
+
// File associations
|
|
55
|
+
"files.associations": {
|
|
56
|
+
"*.js": "javascript",
|
|
57
|
+
"*.mjs": "javascript",
|
|
58
|
+
"*.cjs": "javascript"
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
// Search settings
|
|
62
|
+
"search.exclude": {
|
|
63
|
+
"**/node_modules": true,
|
|
64
|
+
"**/coverage": true,
|
|
65
|
+
"**/data": true,
|
|
66
|
+
"**/tmp": true
|
|
67
|
+
},
|
|
68
|
+
"testing.automaticallyOpenTestResults": "neverOpen"
|
|
40
69
|
}
|
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
|
|
2
|
+
const SEED = "my-seed";
|
|
3
|
+
const dayjs = require("dayjs");
|
|
4
|
+
const utc = require("dayjs/plugin/utc");
|
|
5
|
+
dayjs.extend(utc);
|
|
6
|
+
require("dotenv").config();
|
|
7
|
+
const u = require("../components/utils");
|
|
8
|
+
const v = require("ak-tools");
|
|
9
|
+
const chance = u.initChance(SEED);
|
|
10
|
+
const num_users = 10_000;
|
|
11
|
+
const days = 125;
|
|
12
|
+
|
|
13
|
+
/** @typedef {import("../types").Dungeon} Config */
|
|
14
|
+
|
|
15
|
+
function genIds(numIds = 1000) {
|
|
16
|
+
const ids = [];
|
|
17
|
+
for (let i = 0; i < numIds; i++) {
|
|
18
|
+
ids.push(v.uid());
|
|
19
|
+
}
|
|
20
|
+
return ids;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const videoIds = genIds();
|
|
24
|
+
const channelIds = genIds(100);
|
|
25
|
+
|
|
26
|
+
/** @type {Config} */
|
|
27
|
+
const config = {
|
|
28
|
+
token: "32fd7149e2ac0cc030bda4c4b839b813",
|
|
29
|
+
seed: `LFG!`, //,
|
|
30
|
+
numDays: days,
|
|
31
|
+
numEvents: num_users * 69,
|
|
32
|
+
numUsers: num_users,
|
|
33
|
+
hasAnonIds: false,
|
|
34
|
+
hasSessionIds: false,
|
|
35
|
+
format: "json",
|
|
36
|
+
alsoInferFunnels: false,
|
|
37
|
+
hasLocation: false,
|
|
38
|
+
hasAndroidDevices: true,
|
|
39
|
+
hasIOSDevices: true,
|
|
40
|
+
hasDesktopDevices: true,
|
|
41
|
+
hasBrowser: false,
|
|
42
|
+
hasCampaigns: false,
|
|
43
|
+
isAnonymous: false,
|
|
44
|
+
hasAdSpend: false,
|
|
45
|
+
|
|
46
|
+
hasAvatar: false,
|
|
47
|
+
makeChart: false,
|
|
48
|
+
|
|
49
|
+
batchSize: 1_500_000,
|
|
50
|
+
concurrency: 1,
|
|
51
|
+
writeToDisk: false,
|
|
52
|
+
|
|
53
|
+
funnels: [],
|
|
54
|
+
|
|
55
|
+
events: [
|
|
56
|
+
{
|
|
57
|
+
event: "watch video",
|
|
58
|
+
weight: 55,
|
|
59
|
+
properties: {
|
|
60
|
+
video_id: u.pickAWinner(videoIds),
|
|
61
|
+
"watch percent": u.pickAWinner([
|
|
62
|
+
25,
|
|
63
|
+
50,
|
|
64
|
+
75,
|
|
65
|
+
100,
|
|
66
|
+
]),
|
|
67
|
+
"watch time": u.weighNumRange(1, 65, .89, 100),
|
|
68
|
+
|
|
69
|
+
"category": u.pickAWinner([
|
|
70
|
+
"comedy",
|
|
71
|
+
"educational",
|
|
72
|
+
"music",
|
|
73
|
+
"sports",
|
|
74
|
+
"news",
|
|
75
|
+
"gaming",
|
|
76
|
+
"travel",
|
|
77
|
+
]),
|
|
78
|
+
quality: u.pickAWinner([
|
|
79
|
+
"240p",
|
|
80
|
+
"360p",
|
|
81
|
+
"480p",
|
|
82
|
+
"720p",
|
|
83
|
+
"1080p",
|
|
84
|
+
"4k",
|
|
85
|
+
], 4),
|
|
86
|
+
autoplay: [
|
|
87
|
+
true,
|
|
88
|
+
false,
|
|
89
|
+
],
|
|
90
|
+
fullscreen: [
|
|
91
|
+
true,
|
|
92
|
+
false,
|
|
93
|
+
],
|
|
94
|
+
"ads?": [
|
|
95
|
+
true, true,
|
|
96
|
+
false,
|
|
97
|
+
],
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
event: "like",
|
|
102
|
+
weight: 10,
|
|
103
|
+
properties: {
|
|
104
|
+
video_id: u.pickAWinner(videoIds),
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
event: "comment",
|
|
109
|
+
weight: 5,
|
|
110
|
+
properties: {
|
|
111
|
+
video_id: u.pickAWinner(videoIds),
|
|
112
|
+
comment_length: [
|
|
113
|
+
"short",
|
|
114
|
+
"medium",
|
|
115
|
+
"long",
|
|
116
|
+
],
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
event: "share",
|
|
121
|
+
weight: 3,
|
|
122
|
+
properties: {
|
|
123
|
+
video_id: u.pickAWinner(videoIds),
|
|
124
|
+
"share network": u.pickAWinner([
|
|
125
|
+
"facebook",
|
|
126
|
+
"twitter",
|
|
127
|
+
"reddit",
|
|
128
|
+
"email",
|
|
129
|
+
"whatsapp",
|
|
130
|
+
]),
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
event: "search",
|
|
135
|
+
weight: 25,
|
|
136
|
+
properties: {
|
|
137
|
+
search_term: [
|
|
138
|
+
"cats",
|
|
139
|
+
"dogs",
|
|
140
|
+
"tutorial",
|
|
141
|
+
"news",
|
|
142
|
+
"music",
|
|
143
|
+
],
|
|
144
|
+
"results count": u.pickAWinner([
|
|
145
|
+
0,
|
|
146
|
+
1,
|
|
147
|
+
2,
|
|
148
|
+
3,
|
|
149
|
+
4,
|
|
150
|
+
5,
|
|
151
|
+
6, 7, 8, 9, 10
|
|
152
|
+
], 5),
|
|
153
|
+
"search category": [
|
|
154
|
+
"all",
|
|
155
|
+
"channels",
|
|
156
|
+
"playlists",
|
|
157
|
+
],
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
event: "subscribe",
|
|
162
|
+
weight: 7,
|
|
163
|
+
properties: {
|
|
164
|
+
channel_id: u.pickAWinner(genIds()),
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
event: "unsubscribe",
|
|
169
|
+
weight: 2,
|
|
170
|
+
properties: {
|
|
171
|
+
channel_id: u.pickAWinner(genIds()),
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
event: "create playlist",
|
|
176
|
+
weight: 4,
|
|
177
|
+
properties: {
|
|
178
|
+
"play list name": u.pickAWinner([
|
|
179
|
+
"favorites",
|
|
180
|
+
"watch later",
|
|
181
|
+
"my music",
|
|
182
|
+
"funny videos",
|
|
183
|
+
"educational",
|
|
184
|
+
]),
|
|
185
|
+
privacy: u.pickAWinner([
|
|
186
|
+
"public",
|
|
187
|
+
"private",
|
|
188
|
+
"unlisted",
|
|
189
|
+
]),
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
event: "account signup",
|
|
194
|
+
weight: 1,
|
|
195
|
+
isFirstEvent: true,
|
|
196
|
+
properties: {
|
|
197
|
+
"sign up method": [
|
|
198
|
+
"email",
|
|
199
|
+
"google",
|
|
200
|
+
"facebook",
|
|
201
|
+
],
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
event: "account login",
|
|
206
|
+
weight: 9,
|
|
207
|
+
properties: {
|
|
208
|
+
"log in method": u.pickAWinner([
|
|
209
|
+
"email",
|
|
210
|
+
"google",
|
|
211
|
+
"facebook",
|
|
212
|
+
]),
|
|
213
|
+
success: [
|
|
214
|
+
true,
|
|
215
|
+
false,
|
|
216
|
+
],
|
|
217
|
+
error_message: [
|
|
218
|
+
"incorrect password",
|
|
219
|
+
"user not found",
|
|
220
|
+
"account locked",
|
|
221
|
+
],
|
|
222
|
+
},
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
event: "$experiment_started",
|
|
226
|
+
weight: 5,
|
|
227
|
+
isSessionStartEvent: true,
|
|
228
|
+
properties: {
|
|
229
|
+
"$experiment_type": "ak_ad_hoc",
|
|
230
|
+
"Experiment name": "show results on empty search",
|
|
231
|
+
"Variant name": ["feature enabled", "feature disabled"],
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
],
|
|
235
|
+
superProps: {
|
|
236
|
+
platform: u.pickAWinner([
|
|
237
|
+
"web",
|
|
238
|
+
"ios",
|
|
239
|
+
"android",
|
|
240
|
+
]),
|
|
241
|
+
network_type: [
|
|
242
|
+
"wifi",
|
|
243
|
+
"cellular",
|
|
244
|
+
],
|
|
245
|
+
},
|
|
246
|
+
userProps: {
|
|
247
|
+
subscription_status: [
|
|
248
|
+
"free",
|
|
249
|
+
"free",
|
|
250
|
+
"premium",
|
|
251
|
+
],
|
|
252
|
+
age_range: [
|
|
253
|
+
"13-17",
|
|
254
|
+
"18-24",
|
|
255
|
+
"25-34",
|
|
256
|
+
"35-44",
|
|
257
|
+
"45-54",
|
|
258
|
+
"55+",
|
|
259
|
+
],
|
|
260
|
+
preferred_genre: u.pickAWinner([
|
|
261
|
+
"comedy",
|
|
262
|
+
"action",
|
|
263
|
+
"drama",
|
|
264
|
+
"sci-fi",
|
|
265
|
+
"horror",
|
|
266
|
+
]),
|
|
267
|
+
upload_count: [
|
|
268
|
+
0,
|
|
269
|
+
1,
|
|
270
|
+
5,
|
|
271
|
+
10,
|
|
272
|
+
20,
|
|
273
|
+
],
|
|
274
|
+
following_count: [
|
|
275
|
+
0,
|
|
276
|
+
10,
|
|
277
|
+
50,
|
|
278
|
+
100,
|
|
279
|
+
500,
|
|
280
|
+
],
|
|
281
|
+
dark_mode_enabled: [
|
|
282
|
+
true,
|
|
283
|
+
false,
|
|
284
|
+
],
|
|
285
|
+
},
|
|
286
|
+
|
|
287
|
+
scdProps: {},
|
|
288
|
+
mirrorProps: {},
|
|
289
|
+
groupKeys: [],
|
|
290
|
+
groupProps: {},
|
|
291
|
+
lookupTables: [],
|
|
292
|
+
hook: function (record, type, meta) {
|
|
293
|
+
const NOW = dayjs();
|
|
294
|
+
const TIME_WHEN_SEARCH_GOT_BAD = NOW.subtract(21, 'days');
|
|
295
|
+
const TIME_WE_EXPERIMENTED = NOW.subtract(14, 'days');
|
|
296
|
+
|
|
297
|
+
if (type === "event") {
|
|
298
|
+
const EVENT_TIME = dayjs(record.time);
|
|
299
|
+
//when search got bad, people started searching less
|
|
300
|
+
//and got fewer results
|
|
301
|
+
if (EVENT_TIME.isAfter(TIME_WHEN_SEARCH_GOT_BAD)) {
|
|
302
|
+
if (chance.bool({ likelihood: 50 })) {
|
|
303
|
+
if (record.event === "search") {
|
|
304
|
+
record["results count"] = 0;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
if (chance.bool({ likelihood: 18 })) {
|
|
309
|
+
return {};
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
if (EVENT_TIME.isBefore(TIME_WE_EXPERIMENTED)) {
|
|
314
|
+
if (record.event === "$experiment_started") {
|
|
315
|
+
return {};
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
if (type === "everything") {
|
|
323
|
+
|
|
324
|
+
const hadFeatureEnabled = record.some(event =>
|
|
325
|
+
event.event === "$experiment_started" &&
|
|
326
|
+
event["Variant name"] === "feature enabled"
|
|
327
|
+
);
|
|
328
|
+
|
|
329
|
+
const hadFeatureDisabled = record.some(event =>
|
|
330
|
+
event.event === "$experiment_started" &&
|
|
331
|
+
event["Variant name"] === "feature disabled"
|
|
332
|
+
);
|
|
333
|
+
|
|
334
|
+
record.forEach((event, idx) => {
|
|
335
|
+
const EVENT_TIME = dayjs(event.time);
|
|
336
|
+
|
|
337
|
+
if (EVENT_TIME.isAfter(TIME_WE_EXPERIMENTED)) {
|
|
338
|
+
if (hadFeatureEnabled) {
|
|
339
|
+
// Users with feature enabled variant have a higher likelihood of subscribing.
|
|
340
|
+
// Add an extra subscribe event 50% of the time immediately after watching a video.
|
|
341
|
+
if (event.event === "watch video" && chance.bool({ likelihood: 75 })) {
|
|
342
|
+
// watch time goes up
|
|
343
|
+
event["watch time"] = v.round(event["watch time"] * 1.7);
|
|
344
|
+
const subscribeEvent = {
|
|
345
|
+
event: "subscribe",
|
|
346
|
+
time: dayjs(event.time).add(1, 'minute').toISOString(),
|
|
347
|
+
user_id: event.user_id,
|
|
348
|
+
};
|
|
349
|
+
record.splice(idx + 1, 0, subscribeEvent);
|
|
350
|
+
}
|
|
351
|
+
} else if (hadFeatureDisabled) {
|
|
352
|
+
// Users with feature disabled variant have lower likelihood of subscribing.
|
|
353
|
+
// Drop subscribe events 50% of the time.
|
|
354
|
+
if (event.event === "subscribe" && chance.bool({ likelihood: 75 })) {
|
|
355
|
+
record.splice(idx, 1);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// watch time goes down
|
|
359
|
+
if (event.event === "watch video") {
|
|
360
|
+
event["watch time"] = v.round(event["watch time"] * 0.5);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
return record;
|
|
368
|
+
}
|
|
369
|
+
};
|
|
370
|
+
|
|
371
|
+
module.exports = config;
|