make-mp-data 2.0.23 → 2.1.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/dungeons/ai-chat-analytics-ed.js +274 -0
- package/dungeons/business.js +0 -1
- package/dungeons/complex.js +0 -1
- package/dungeons/experiments.js +0 -1
- package/dungeons/gaming.js +47 -14
- package/dungeons/media.js +5 -6
- package/dungeons/mil.js +296 -0
- package/dungeons/money2020-ed-also.js +277 -0
- package/dungeons/money2020-ed.js +579 -0
- package/dungeons/sanity.js +0 -1
- package/dungeons/scd.js +0 -1
- package/dungeons/simple.js +57 -18
- package/dungeons/student-teacher.js +0 -1
- package/dungeons/text-generation.js +706 -0
- package/dungeons/userAgent.js +1 -2
- package/entry.js +3 -0
- package/index.js +8 -36
- package/lib/cli/cli.js +0 -7
- package/lib/core/config-validator.js +6 -8
- package/lib/generators/adspend.js +1 -1
- package/lib/generators/events.js +1 -1
- package/lib/generators/funnels.js +293 -242
- package/lib/generators/text-bak-old.js +1121 -0
- package/lib/generators/text.js +1173 -0
- package/lib/orchestrators/mixpanel-sender.js +1 -1
- package/lib/templates/abbreviated.d.ts +13 -3
- package/lib/templates/defaults.js +311 -169
- package/lib/templates/hooks-instructions.txt +434 -0
- package/lib/templates/phrases-bak.js +925 -0
- package/lib/templates/phrases.js +2066 -0
- package/lib/templates/{instructions.txt → schema-instructions.txt} +78 -1
- package/lib/templates/scratch-dungeon-template.js +1 -1
- package/lib/templates/textQuickTest.js +172 -0
- package/lib/utils/ai.js +51 -2
- package/lib/utils/utils.js +29 -18
- package/package.json +7 -5
- package/types.d.ts +319 -4
- package/lib/utils/chart.js +0 -206
|
@@ -0,0 +1,579 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
import dayjs from "dayjs";
|
|
4
|
+
import utc from "dayjs/plugin/utc.js";
|
|
5
|
+
import "dotenv/config";
|
|
6
|
+
import { weighNumRange, range, date, initChance, exhaust, choose, integer, decimal } from "../lib/utils/utils.js";
|
|
7
|
+
|
|
8
|
+
const SEED = "thfdgdfgdfgank sup hello 2020 money!!!";
|
|
9
|
+
dayjs.extend(utc);
|
|
10
|
+
const chance = initChance(SEED);
|
|
11
|
+
const num_users = 4_200;
|
|
12
|
+
const days = 35;
|
|
13
|
+
|
|
14
|
+
/** @typedef {import("../types.js").Dungeon} Dungeon */
|
|
15
|
+
|
|
16
|
+
/** @type {Dungeon} */
|
|
17
|
+
const dungeon = {
|
|
18
|
+
token: "",
|
|
19
|
+
seed: SEED,
|
|
20
|
+
numDays: days,
|
|
21
|
+
numEvents: num_users * 120,
|
|
22
|
+
numUsers: num_users,
|
|
23
|
+
hasAnonIds: false,
|
|
24
|
+
hasSessionIds: false,
|
|
25
|
+
format: "json",
|
|
26
|
+
alsoInferFunnels: false,
|
|
27
|
+
hasLocation: true,
|
|
28
|
+
hasAndroidDevices: false,
|
|
29
|
+
hasIOSDevices: false,
|
|
30
|
+
hasDesktopDevices: true,
|
|
31
|
+
hasBrowser: true,
|
|
32
|
+
hasCampaigns: true,
|
|
33
|
+
isAnonymous: false,
|
|
34
|
+
hasAdSpend: false,
|
|
35
|
+
percentUsersBornInDataset: 40,
|
|
36
|
+
hasAvatar: true,
|
|
37
|
+
|
|
38
|
+
batchSize: 1_500_000,
|
|
39
|
+
concurrency: 1,
|
|
40
|
+
writeToDisk: false,
|
|
41
|
+
superProps: {
|
|
42
|
+
version: "2"
|
|
43
|
+
},
|
|
44
|
+
// AI-generated schema content:
|
|
45
|
+
funnels: [
|
|
46
|
+
{
|
|
47
|
+
"name": "User Onboarding",
|
|
48
|
+
"sequence": [
|
|
49
|
+
"App Opened",
|
|
50
|
+
"View Balance",
|
|
51
|
+
"Add Contact"
|
|
52
|
+
],
|
|
53
|
+
"weight": 10,
|
|
54
|
+
"isFirstFunnel": true,
|
|
55
|
+
"conversionRate": 80,
|
|
56
|
+
"timeToConvert": 0.1,
|
|
57
|
+
"order": "sequential"
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"name": "Standard Money Transfer",
|
|
61
|
+
"sequence": [
|
|
62
|
+
"App Opened",
|
|
63
|
+
"View Balance",
|
|
64
|
+
"Initiate Transfer",
|
|
65
|
+
"Send Money"
|
|
66
|
+
],
|
|
67
|
+
|
|
68
|
+
"weight": 20,
|
|
69
|
+
"conversionRate": 65,
|
|
70
|
+
"timeToConvert": 0.2,
|
|
71
|
+
"order": "first-and-last-fixed",
|
|
72
|
+
"experiment": true,
|
|
73
|
+
"conditions": {
|
|
74
|
+
"account_tier": [
|
|
75
|
+
"Basic",
|
|
76
|
+
"Plus"
|
|
77
|
+
]
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
"name": "Premium Money Transfer",
|
|
82
|
+
"sequence": [
|
|
83
|
+
"App Opened",
|
|
84
|
+
"View Balance",
|
|
85
|
+
"Initiate Transfer",
|
|
86
|
+
"Send Money"
|
|
87
|
+
],
|
|
88
|
+
experiment: true,
|
|
89
|
+
"weight": 15,
|
|
90
|
+
"conversionRate": 90,
|
|
91
|
+
"timeToConvert": 0.1,
|
|
92
|
+
"order": "sequential",
|
|
93
|
+
"conditions": {
|
|
94
|
+
"account_tier": "Premium"
|
|
95
|
+
},
|
|
96
|
+
"props": {
|
|
97
|
+
"is_priority_transfer": true
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"name": "Get Financial Advice",
|
|
102
|
+
"sequence": [
|
|
103
|
+
"App Opened",
|
|
104
|
+
"Prompt AI Chatbot"
|
|
105
|
+
],
|
|
106
|
+
"weight": 8,
|
|
107
|
+
"conversionRate": 95,
|
|
108
|
+
"timeToConvert": 0.1,
|
|
109
|
+
"order": "sequential"
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
"name": "Review and Save Transaction",
|
|
113
|
+
"sequence": [
|
|
114
|
+
"App Opened",
|
|
115
|
+
"View Transaction History",
|
|
116
|
+
"Print Receipt"
|
|
117
|
+
],
|
|
118
|
+
"weight": 12,
|
|
119
|
+
"conversionRate": 50,
|
|
120
|
+
"timeToConvert": 0.5,
|
|
121
|
+
"order": "random"
|
|
122
|
+
},
|
|
123
|
+
|
|
124
|
+
{
|
|
125
|
+
name: "Sign Up",
|
|
126
|
+
sequence: [
|
|
127
|
+
"Page View",
|
|
128
|
+
"Sign Up"
|
|
129
|
+
],
|
|
130
|
+
isFirstFunnel: true,
|
|
131
|
+
conversionRate: 20,
|
|
132
|
+
timeToConvert: 10,
|
|
133
|
+
order: "sequential"
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
name: "AI Interaction",
|
|
137
|
+
sequence: [
|
|
138
|
+
"Launch AI",
|
|
139
|
+
"AI Prompt Sent",
|
|
140
|
+
"AI Response Sent",
|
|
141
|
+
"User Feedback",
|
|
142
|
+
"AI Dismissed"
|
|
143
|
+
],
|
|
144
|
+
experiment: true,
|
|
145
|
+
isFirstFunnel: false,
|
|
146
|
+
conversionRate: 38,
|
|
147
|
+
timeToConvert: 5,
|
|
148
|
+
order: "sequential",
|
|
149
|
+
weight: 7,
|
|
150
|
+
props: { "AI Model": ["5-turbo", "5-flash", "5-flagship", "homegrown"] }
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
name: "AI Interaction Errors",
|
|
154
|
+
sequence: [
|
|
155
|
+
"Launch AI",
|
|
156
|
+
"AI Prompt Sent",
|
|
157
|
+
"AI Response Sent",
|
|
158
|
+
"API Error",
|
|
159
|
+
"User Feedback",
|
|
160
|
+
"AI Dismissed"
|
|
161
|
+
],
|
|
162
|
+
isFirstFunnel: false,
|
|
163
|
+
conversionRate: 27,
|
|
164
|
+
timeToConvert: 5,
|
|
165
|
+
order: "sequential",
|
|
166
|
+
weight: 3,
|
|
167
|
+
props: { "AI Model": ["5-turbo", "5-flash", "5-flagship", "homegrown"] }
|
|
168
|
+
}
|
|
169
|
+
],
|
|
170
|
+
events: [
|
|
171
|
+
{
|
|
172
|
+
"event": "Page View",
|
|
173
|
+
"weight": 15,
|
|
174
|
+
"isFirstEvent": true,
|
|
175
|
+
"properties": {
|
|
176
|
+
"page_url": [
|
|
177
|
+
"/",
|
|
178
|
+
"/features",
|
|
179
|
+
"/pricing",
|
|
180
|
+
"/about",
|
|
181
|
+
"/contact"
|
|
182
|
+
]
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
"event": "App Opened",
|
|
187
|
+
"weight": 10,
|
|
188
|
+
"isFirstEvent": true,
|
|
189
|
+
"properties": {
|
|
190
|
+
"platform": [
|
|
191
|
+
"iOS",
|
|
192
|
+
"Android",
|
|
193
|
+
"Web"
|
|
194
|
+
],
|
|
195
|
+
"app_version": [
|
|
196
|
+
"2.1.0",
|
|
197
|
+
"2.1.1",
|
|
198
|
+
"2.2.0",
|
|
199
|
+
"2.0.5"
|
|
200
|
+
]
|
|
201
|
+
}
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
"event": "View Balance",
|
|
205
|
+
"weight": 8,
|
|
206
|
+
"properties": {
|
|
207
|
+
"account_type": [
|
|
208
|
+
"Checking",
|
|
209
|
+
"Savings",
|
|
210
|
+
"Credit"
|
|
211
|
+
],
|
|
212
|
+
"currency": [
|
|
213
|
+
"USD",
|
|
214
|
+
"EUR",
|
|
215
|
+
"GBP",
|
|
216
|
+
"JPY"
|
|
217
|
+
]
|
|
218
|
+
}
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
"event": "Initiate Transfer",
|
|
222
|
+
"weight": 6,
|
|
223
|
+
"properties": {
|
|
224
|
+
"transfer_method": [
|
|
225
|
+
"Bank Transfer",
|
|
226
|
+
"Peer-to-Peer",
|
|
227
|
+
"Card Payment"
|
|
228
|
+
],
|
|
229
|
+
"is_international": [
|
|
230
|
+
true,
|
|
231
|
+
false,
|
|
232
|
+
false
|
|
233
|
+
]
|
|
234
|
+
}
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
"event": "Send Money",
|
|
238
|
+
"weight": 5,
|
|
239
|
+
"properties": {
|
|
240
|
+
"amount": weighNumRange(10, 5000, 0.3),
|
|
241
|
+
"currency": [
|
|
242
|
+
"USD",
|
|
243
|
+
"EUR",
|
|
244
|
+
"GBP",
|
|
245
|
+
"JPY",
|
|
246
|
+
"CAD"
|
|
247
|
+
],
|
|
248
|
+
"fee_amount": weighNumRange(0, 50, 0.1),
|
|
249
|
+
"transfer_speed": [
|
|
250
|
+
"Instant",
|
|
251
|
+
"Standard",
|
|
252
|
+
"Economy"
|
|
253
|
+
]
|
|
254
|
+
}
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
"event": "Add Contact",
|
|
258
|
+
"weight": 3,
|
|
259
|
+
"properties": {
|
|
260
|
+
"contact_method": [
|
|
261
|
+
"Phone Number",
|
|
262
|
+
"Email",
|
|
263
|
+
"Username"
|
|
264
|
+
],
|
|
265
|
+
"is_verified_user": [
|
|
266
|
+
true,
|
|
267
|
+
true,
|
|
268
|
+
false
|
|
269
|
+
]
|
|
270
|
+
}
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
"event": "Print Receipt",
|
|
274
|
+
"weight": 2,
|
|
275
|
+
"properties": {
|
|
276
|
+
"transaction_id": chance.guid.bind(chance),
|
|
277
|
+
"format": [
|
|
278
|
+
"PDF",
|
|
279
|
+
"Image",
|
|
280
|
+
"Text"
|
|
281
|
+
]
|
|
282
|
+
}
|
|
283
|
+
},
|
|
284
|
+
{
|
|
285
|
+
"event": "Prompt AI Chatbot",
|
|
286
|
+
"weight": 4,
|
|
287
|
+
"properties": {
|
|
288
|
+
"prompt_topic": [
|
|
289
|
+
"Budgeting",
|
|
290
|
+
"Investment Advice",
|
|
291
|
+
"Savings Goals",
|
|
292
|
+
"Credit Score",
|
|
293
|
+
"Fraud Prevention"
|
|
294
|
+
],
|
|
295
|
+
"prompt_length": weighNumRange(10, 200),
|
|
296
|
+
"response_quality_rating": weighNumRange(1, 5)
|
|
297
|
+
}
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
"event": "View Transaction History",
|
|
301
|
+
"weight": 7,
|
|
302
|
+
"properties": {
|
|
303
|
+
"time_range": [
|
|
304
|
+
"Last 7 Days",
|
|
305
|
+
"Last 30 Days",
|
|
306
|
+
"Last 90 Days",
|
|
307
|
+
"All Time"
|
|
308
|
+
],
|
|
309
|
+
"filter_by": [
|
|
310
|
+
"Sent",
|
|
311
|
+
"Received",
|
|
312
|
+
"Failed",
|
|
313
|
+
"None"
|
|
314
|
+
]
|
|
315
|
+
}
|
|
316
|
+
},
|
|
317
|
+
{
|
|
318
|
+
"event": "Request Money",
|
|
319
|
+
"weight": 3,
|
|
320
|
+
"properties": {
|
|
321
|
+
"amount": weighNumRange(5, 1000, 0.4),
|
|
322
|
+
"currency": [
|
|
323
|
+
"USD",
|
|
324
|
+
"EUR",
|
|
325
|
+
"GBP"
|
|
326
|
+
],
|
|
327
|
+
"request_status": [
|
|
328
|
+
"Pending",
|
|
329
|
+
"Accepted",
|
|
330
|
+
"Declined"
|
|
331
|
+
]
|
|
332
|
+
}
|
|
333
|
+
},
|
|
334
|
+
{
|
|
335
|
+
"event": "Account Deactivated",
|
|
336
|
+
"weight": 1,
|
|
337
|
+
"isChurnEvent": true,
|
|
338
|
+
"properties": {
|
|
339
|
+
"reason": [
|
|
340
|
+
"Switched to competitor",
|
|
341
|
+
"Security concerns",
|
|
342
|
+
"Poor user experience",
|
|
343
|
+
"No longer needed"
|
|
344
|
+
]
|
|
345
|
+
}
|
|
346
|
+
},
|
|
347
|
+
|
|
348
|
+
{
|
|
349
|
+
event: "Sign Up",
|
|
350
|
+
isFirstEvent: true,
|
|
351
|
+
weight: 0,
|
|
352
|
+
properties: {
|
|
353
|
+
signup_method: [
|
|
354
|
+
"email",
|
|
355
|
+
"google",
|
|
356
|
+
"github"
|
|
357
|
+
]
|
|
358
|
+
}
|
|
359
|
+
},
|
|
360
|
+
{
|
|
361
|
+
event: "Purchase",
|
|
362
|
+
weight: 40,
|
|
363
|
+
properties: {
|
|
364
|
+
amount: weighNumRange(20, 500, 0.3),
|
|
365
|
+
currency: [
|
|
366
|
+
"USD",
|
|
367
|
+
"EUR",
|
|
368
|
+
"GBP"
|
|
369
|
+
],
|
|
370
|
+
item_count: weighNumRange(1, 10)
|
|
371
|
+
}
|
|
372
|
+
},
|
|
373
|
+
{
|
|
374
|
+
event: "Launch AI",
|
|
375
|
+
weight: 2,
|
|
376
|
+
properties: {
|
|
377
|
+
entry_point: [
|
|
378
|
+
"dashboard_widget",
|
|
379
|
+
"header_button",
|
|
380
|
+
"in_app_prompt"
|
|
381
|
+
]
|
|
382
|
+
}
|
|
383
|
+
},
|
|
384
|
+
{
|
|
385
|
+
event: "AI Prompt Sent",
|
|
386
|
+
weight: 10,
|
|
387
|
+
properties: {
|
|
388
|
+
prompt: [
|
|
389
|
+
"how can I make a dashboard?",
|
|
390
|
+
"what is a funnel?",
|
|
391
|
+
"what drives new users?",
|
|
392
|
+
"show me my top performing campaigns",
|
|
393
|
+
"compare user retention by country"
|
|
394
|
+
],
|
|
395
|
+
prompt_length: weighNumRange(15, 150)
|
|
396
|
+
}
|
|
397
|
+
},
|
|
398
|
+
{
|
|
399
|
+
event: "AI Response Sent",
|
|
400
|
+
weight: 10,
|
|
401
|
+
properties: {
|
|
402
|
+
cost: weighNumRange(1, 10, 0.2),
|
|
403
|
+
tokens: weighNumRange(100, 1000, 0.4),
|
|
404
|
+
time_to_generate_ms: weighNumRange(1000, 10000, 0.2)
|
|
405
|
+
}
|
|
406
|
+
},
|
|
407
|
+
{
|
|
408
|
+
event: "User Feedback",
|
|
409
|
+
weight: 4,
|
|
410
|
+
properties: {
|
|
411
|
+
feedback: [
|
|
412
|
+
"I love it!",
|
|
413
|
+
"meh...",
|
|
414
|
+
"This sucks",
|
|
415
|
+
"Fine"
|
|
416
|
+
],
|
|
417
|
+
sentiment: [
|
|
418
|
+
"thumbs up",
|
|
419
|
+
"thumbs down"
|
|
420
|
+
]
|
|
421
|
+
}
|
|
422
|
+
},
|
|
423
|
+
{
|
|
424
|
+
event: "AI Dismissed",
|
|
425
|
+
weight: 2,
|
|
426
|
+
properties: {
|
|
427
|
+
reason: [
|
|
428
|
+
"finished",
|
|
429
|
+
"clicked_away",
|
|
430
|
+
"new_prompt",
|
|
431
|
+
"error"
|
|
432
|
+
]
|
|
433
|
+
}
|
|
434
|
+
},
|
|
435
|
+
{
|
|
436
|
+
event: "API Error",
|
|
437
|
+
weight: 2,
|
|
438
|
+
properties: {
|
|
439
|
+
error_code: [
|
|
440
|
+
400,
|
|
441
|
+
401,
|
|
442
|
+
429,
|
|
443
|
+
500,
|
|
444
|
+
503
|
|
445
|
+
],
|
|
446
|
+
error_message: [
|
|
447
|
+
"Bad Request",
|
|
448
|
+
"Unauthorized",
|
|
449
|
+
"Too Many Requests",
|
|
450
|
+
"Internal Server Error",
|
|
451
|
+
"Service Unavailable"
|
|
452
|
+
]
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
],
|
|
456
|
+
userProps: {
|
|
457
|
+
plan_type: [
|
|
458
|
+
"free",
|
|
459
|
+
"pro",
|
|
460
|
+
"pro",
|
|
461
|
+
"enterprise",
|
|
462
|
+
"free"
|
|
463
|
+
],
|
|
464
|
+
company_size: [
|
|
465
|
+
"1-10",
|
|
466
|
+
"11-50",
|
|
467
|
+
"51-200",
|
|
468
|
+
"201-1000",
|
|
469
|
+
"1000+"
|
|
470
|
+
],
|
|
471
|
+
account_tier: [
|
|
472
|
+
"Basic",
|
|
473
|
+
"Plus",
|
|
474
|
+
"Premium",
|
|
475
|
+
],
|
|
476
|
+
created_date: date(365, true, 'YYYY-MM-DD')
|
|
477
|
+
},
|
|
478
|
+
|
|
479
|
+
hook: function (record, type, meta) {
|
|
480
|
+
const NOW = dayjs();
|
|
481
|
+
const DATE_HOMEGROWN_LAUNCH = NOW.subtract(25, 'day');
|
|
482
|
+
const DATE_HOMEGROWN_IMPROVEMENT = NOW.subtract(10, 'day');
|
|
483
|
+
const OVER_THINGS_GET_BETTER = NOW.subtract(30, 'day');
|
|
484
|
+
|
|
485
|
+
if (type === "event") {
|
|
486
|
+
const EVENT_TIME = dayjs(record.time);
|
|
487
|
+
|
|
488
|
+
if (record.prompt) {
|
|
489
|
+
// calculate prompt length
|
|
490
|
+
record.prompt_length = record.prompt.length;
|
|
491
|
+
}
|
|
492
|
+
// models: "5-turbo", "5-flash", "5-flagship", "homegrown"
|
|
493
|
+
if (record?.["AI Model"]) {
|
|
494
|
+
const allModels = ["5-turbo", "5-flash", "5-flash", "5-flagship", "5-flagship", "5-flagship", "homegrown"];
|
|
495
|
+
const chosenModel = chance.pickone(allModels);
|
|
496
|
+
record["AI Model"] = chosenModel;
|
|
497
|
+
|
|
498
|
+
// choose which model based on date + weights
|
|
499
|
+
if (EVENT_TIME.isBefore(DATE_HOMEGROWN_LAUNCH)) {
|
|
500
|
+
if (chosenModel === "homegrown") {
|
|
501
|
+
if (chance.bool({ likelihood: 75 })) {
|
|
502
|
+
record["AI Model"] = "5-flagship";
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
if (EVENT_TIME.isAfter(DATE_HOMEGROWN_LAUNCH)) {
|
|
508
|
+
if (chosenModel !== "homegrown") {
|
|
509
|
+
if (chance.bool({ likelihood: 27 })) {
|
|
510
|
+
record["AI Model"] = "homegrown";
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
if (record["AI Model"] && record["cost"] && record["tokens"]) {
|
|
515
|
+
|
|
516
|
+
// update params
|
|
517
|
+
switch (record["AI Model"]) {
|
|
518
|
+
// 5 turbo is most expensive and slowest
|
|
519
|
+
case "5-turbo":
|
|
520
|
+
record["cost"] *= decimal(1.2, 1.7, 3);
|
|
521
|
+
record["tokens"] *= decimal(1.2, 1.7, 3);
|
|
522
|
+
break;
|
|
523
|
+
// 5 flash is least expensive and fastest
|
|
524
|
+
case "5-flash":
|
|
525
|
+
record["cost"] *= decimal(0.8, 0.8, 3);
|
|
526
|
+
record["tokens"] *= decimal(0.8, 0.8, 3);
|
|
527
|
+
break;
|
|
528
|
+
// 5 flagship is in between in both areas
|
|
529
|
+
case "5-flagship":
|
|
530
|
+
record["cost"] *= decimal(1.0, 1.0, 3);
|
|
531
|
+
record["tokens"] *= decimal(1.0, 1.0, 3);
|
|
532
|
+
break;
|
|
533
|
+
// homegrown is chaotic is chaotic
|
|
534
|
+
case "homegrown":
|
|
535
|
+
|
|
536
|
+
record["cost"] *= decimal(0.5, 2.5, 3);
|
|
537
|
+
record["tokens"] *= decimal(0.5, 2.5, 3);
|
|
538
|
+
if (EVENT_TIME.isBefore(DATE_HOMEGROWN_IMPROVEMENT)) {
|
|
539
|
+
record["cost"] *= decimal(1.2, 5.0, 3);
|
|
540
|
+
record["tokens"] *= decimal(1.2, 3.0, 3);
|
|
541
|
+
}
|
|
542
|
+
if (EVENT_TIME.isAfter(DATE_HOMEGROWN_IMPROVEMENT)) {
|
|
543
|
+
record["cost"] *= decimal(0.5, 1.0, 3);
|
|
544
|
+
record["tokens"] *= decimal(0.5, 0.75, 3);
|
|
545
|
+
}
|
|
546
|
+
break;
|
|
547
|
+
default:
|
|
548
|
+
break;
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
|
|
556
|
+
|
|
557
|
+
}
|
|
558
|
+
if (type === "funnel-pre") {
|
|
559
|
+
const parsedFirstEventTime = dayjs.unix(meta.firstEventTime);
|
|
560
|
+
if (!parsedFirstEventTime.isValid()) debugger;
|
|
561
|
+
//stupid offset thing we need to do...
|
|
562
|
+
const actualFunnelTime = parsedFirstEventTime.add(NOW.diff(dayjs.unix(global.FIXED_NOW), 'h'), 'h');
|
|
563
|
+
if (actualFunnelTime.isBefore(OVER_THINGS_GET_BETTER)) {
|
|
564
|
+
record.conversionRate *= decimal(0.5, 0.9, 3);
|
|
565
|
+
// record.timeToConvert *= decimal(1.5, 3.0, 3);
|
|
566
|
+
}
|
|
567
|
+
if (actualFunnelTime.isAfter(OVER_THINGS_GET_BETTER)) {
|
|
568
|
+
const distanceDays = Math.min(30, actualFunnelTime.diff(OVER_THINGS_GET_BETTER, 'day'));
|
|
569
|
+
const improvementFactor = 1.0 + (distanceDays / 30) * 0.5;
|
|
570
|
+
// record.timeToConvert *= decimal(0.5, 0.75, 3) / improvementFactor;
|
|
571
|
+
record.conversionRate *= decimal(1.0, 2.0, 4) * improvementFactor;
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
return record;
|
|
575
|
+
}
|
|
576
|
+
};
|
|
577
|
+
|
|
578
|
+
export default dungeon;
|
|
579
|
+
|
package/dungeons/sanity.js
CHANGED
|
@@ -28,7 +28,6 @@ const config = {
|
|
|
28
28
|
hasAnonIds: false, //if true, anonymousIds are created for each user
|
|
29
29
|
hasSessionIds: false, //if true, hasSessionIds are created for each user
|
|
30
30
|
alsoInferFunnels: true, //if true, infer funnels from events
|
|
31
|
-
makeChart: true,
|
|
32
31
|
writeToDisk: true,
|
|
33
32
|
concurrency: 25,
|
|
34
33
|
funnels: [
|
package/dungeons/scd.js
CHANGED
|
@@ -32,7 +32,6 @@ const config = {
|
|
|
32
32
|
hasAnonIds: false, //if true, anonymousIds are created for each user
|
|
33
33
|
hasSessionIds: false, //if true, hasSessionIds are created for each user
|
|
34
34
|
hasAdSpend: false,
|
|
35
|
-
makeChart: false,
|
|
36
35
|
hasLocation: true,
|
|
37
36
|
hasAndroidDevices: true,
|
|
38
37
|
hasIOSDevices: true,
|
package/dungeons/simple.js
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
import Chance from 'chance';
|
|
12
|
-
|
|
12
|
+
let chance = new Chance();
|
|
13
13
|
import dayjs from "dayjs";
|
|
14
14
|
import utc from "dayjs/plugin/utc.js";
|
|
15
15
|
dayjs.extend(utc);
|
|
@@ -23,25 +23,25 @@ const videoCategories = ["funny", "educational", "inspirational", "music", "news
|
|
|
23
23
|
/** @type {import('../types').Dungeon} */
|
|
24
24
|
const config = {
|
|
25
25
|
token: "",
|
|
26
|
-
seed: "simple is best",
|
|
27
|
-
numDays:
|
|
28
|
-
numEvents:
|
|
29
|
-
numUsers:
|
|
26
|
+
seed: "simple is best!",
|
|
27
|
+
numDays: 100, //how many days worth1 of data
|
|
28
|
+
numEvents: 250_000, //how many events
|
|
29
|
+
numUsers: 1_000, //how many users
|
|
30
30
|
format: 'csv', //csv or json
|
|
31
31
|
region: "US",
|
|
32
32
|
hasAnonIds: false, //if true, anonymousIds are created for each user
|
|
33
33
|
hasSessionIds: false, //if true, hasSessionIds are created for each user
|
|
34
34
|
hasAdSpend: false,
|
|
35
|
-
makeChart: false,
|
|
36
35
|
hasLocation: true,
|
|
37
|
-
hasAndroidDevices:
|
|
38
|
-
hasIOSDevices:
|
|
39
|
-
hasDesktopDevices:
|
|
40
|
-
hasBrowser:
|
|
36
|
+
hasAndroidDevices: false,
|
|
37
|
+
hasIOSDevices: false,
|
|
38
|
+
hasDesktopDevices: false,
|
|
39
|
+
hasBrowser: false,
|
|
41
40
|
hasCampaigns: true,
|
|
42
41
|
isAnonymous: false,
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
alsoInferFunnels: true,
|
|
43
|
+
concurrency: 1,
|
|
44
|
+
batchSize: 2_500_000,
|
|
45
45
|
|
|
46
46
|
|
|
47
47
|
events: [
|
|
@@ -109,16 +109,28 @@ const config = {
|
|
|
109
109
|
},
|
|
110
110
|
{
|
|
111
111
|
event: "sign up",
|
|
112
|
+
weight: 1,
|
|
112
113
|
isFirstEvent: true,
|
|
113
|
-
weight: 0,
|
|
114
114
|
properties: {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
flags: ["on", "off"],
|
|
118
|
-
experiment_ids: ["1234", "5678", "9012", "3456", "7890"],
|
|
119
|
-
multiVariate: [true, false]
|
|
115
|
+
signupMethod: pickAWinner(["email", "google", "facebook", "twitter", "linkedin", "github"]),
|
|
116
|
+
referral: weighChoices(["none", "none", "none", "friend", "ad", "ad", "ad", "friend", "friend", "friend", "friend"]),
|
|
120
117
|
}
|
|
118
|
+
},
|
|
119
|
+
|
|
120
|
+
],
|
|
121
|
+
funnels: [
|
|
122
|
+
{
|
|
123
|
+
sequence: ["page view", "view item", "save item", "page view", "sign up"],
|
|
124
|
+
conversionRate: 50,
|
|
125
|
+
order: "first-and-last-fixed",
|
|
126
|
+
weight: 1,
|
|
127
|
+
isFirstFunnel: true,
|
|
128
|
+
timeToConvert: 2,
|
|
129
|
+
experiment: true,
|
|
130
|
+
name: "Signup Flow"
|
|
131
|
+
|
|
121
132
|
}
|
|
133
|
+
|
|
122
134
|
],
|
|
123
135
|
superProps: {
|
|
124
136
|
theme: pickAWinner(["light", "dark", "custom", "light", "dark"]),
|
|
@@ -143,6 +155,33 @@ const config = {
|
|
|
143
155
|
groupProps: {},
|
|
144
156
|
lookupTables: [],
|
|
145
157
|
hook: function (record, type, meta) {
|
|
158
|
+
|
|
159
|
+
const NOW = dayjs();
|
|
160
|
+
// const DATE_HOMEGROWN_LAUNCH = NOW.subtract(25, 'day');
|
|
161
|
+
// const DATE_HOMEGROWN_IMPROVEMENT = NOW.subtract(10, 'day');
|
|
162
|
+
const OVER_THINGS_GET_BETTER = NOW.subtract(15, 'day');
|
|
163
|
+
|
|
164
|
+
if (type === "event") {
|
|
165
|
+
const EVENT_TIME = dayjs(record.time);
|
|
166
|
+
|
|
167
|
+
if (EVENT_TIME.isAfter(OVER_THINGS_GET_BETTER)) {
|
|
168
|
+
// checkouts are bigger
|
|
169
|
+
if (record.event === "checkout") {
|
|
170
|
+
record.amount = Math.round(record.amount * 1.5);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// videos are longer
|
|
174
|
+
if (record.event === "watch video") {
|
|
175
|
+
record.watchTimeSec = Math.round(record.watchTimeSec * 1.5);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if (EVENT_TIME.isBefore(OVER_THINGS_GET_BETTER)) {
|
|
180
|
+
// kill 33% of all volume
|
|
181
|
+
if (chance.bool({ likelihood: 33 })) return null;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
146
185
|
if (type === "everything") {
|
|
147
186
|
|
|
148
187
|
//custom themers purchase more:
|