make-mp-data 2.0.19 → 2.0.22
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/big.js +7 -6
- package/dungeons/business.js +21 -3
- package/dungeons/experiments.js +8 -7
- package/dungeons/media.js +7 -7
- package/dungeons/sanity.js +8 -14
- package/dungeons/simple.js +1 -0
- package/dungeons/student-teacher.js +426 -0
- package/dungeons/userAgent.js +7 -7
- package/entry.js +19 -3
- package/index.js +107 -7
- package/lib/cli/cli.js +8 -0
- package/lib/core/config-validator.js +244 -218
- package/lib/core/context.js +31 -16
- package/lib/core/storage.js +61 -27
- package/lib/generators/events.js +41 -18
- package/lib/orchestrators/mixpanel-sender.js +5 -2
- package/lib/orchestrators/user-loop.js +212 -181
- package/lib/orchestrators/worker-manager.js +5 -2
- package/lib/templates/abbreviated.d.ts +159 -0
- package/lib/{data → templates}/defaults.js +2 -2
- package/lib/templates/instructions.txt +78 -0
- package/lib/templates/scratch-dungeon-template.js +116 -0
- package/lib/templates/verbose-schema.js +338 -0
- package/lib/utils/ai.js +42 -64
- package/lib/utils/chart.js +5 -0
- package/lib/utils/utils.js +116 -55
- package/package.json +9 -10
- package/types.d.ts +138 -125
- package/lib/cloud-function.js +0 -20
- /package/lib/{utils/prompt.txt → templates/prompt (old).txt} +0 -0
package/dungeons/big.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
+
import Chance from 'chance';
|
|
2
|
+
import dayjs from 'dayjs';
|
|
3
|
+
import utc from 'dayjs/plugin/utc';
|
|
4
|
+
import { uid, comma, makeName } from 'ak-tools';
|
|
5
|
+
import { pickAWinner, weighNumRange, integer, date, choose } from '../lib/utils/utils.js';
|
|
6
|
+
|
|
1
7
|
const seed = "lets go big";
|
|
2
|
-
const Chance = require('chance');
|
|
3
8
|
const chance = new Chance();
|
|
4
|
-
const dayjs = require("dayjs");
|
|
5
|
-
const utc = require("dayjs/plugin/utc");
|
|
6
9
|
dayjs.extend(utc);
|
|
7
|
-
const { uid, comma, makeName } = require('ak-tools');
|
|
8
|
-
const { pickAWinner, weighNumRange, integer, date, choose } = require('../components/utils');
|
|
9
10
|
|
|
10
11
|
|
|
11
12
|
const eventsPerQuarter = 5_000_000_000 // ~5 billion
|
|
@@ -221,4 +222,4 @@ function buildObjArrayProp(maxItems = 5) {
|
|
|
221
222
|
};
|
|
222
223
|
|
|
223
224
|
|
|
224
|
-
|
|
225
|
+
export default config;
|
package/dungeons/business.js
CHANGED
|
@@ -195,9 +195,27 @@ const config = {
|
|
|
195
195
|
|
|
196
196
|
/** each generates it's own table */
|
|
197
197
|
scdProps: {
|
|
198
|
-
plan:
|
|
199
|
-
|
|
200
|
-
|
|
198
|
+
plan: {
|
|
199
|
+
type: "user",
|
|
200
|
+
frequency: "month",
|
|
201
|
+
values: ["free", "free", "free", "free", "basic", "basic", "basic", "premium", "premium", "enterprise"],
|
|
202
|
+
timing: "fixed",
|
|
203
|
+
max: 3
|
|
204
|
+
},
|
|
205
|
+
MRR: {
|
|
206
|
+
type: "user",
|
|
207
|
+
frequency: "month",
|
|
208
|
+
values: weighNumRange(0, 10000, .15),
|
|
209
|
+
timing: "fixed",
|
|
210
|
+
max: 5
|
|
211
|
+
},
|
|
212
|
+
NPS: {
|
|
213
|
+
type: "user",
|
|
214
|
+
frequency: "month",
|
|
215
|
+
values: weighNumRange(0, 10, 2, 150),
|
|
216
|
+
timing: "fixed",
|
|
217
|
+
max: 3
|
|
218
|
+
}
|
|
201
219
|
},
|
|
202
220
|
|
|
203
221
|
mirrorProps: {
|
package/dungeons/experiments.js
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
|
|
2
|
+
import dayjs from 'dayjs';
|
|
3
|
+
import utc from 'dayjs/plugin/utc';
|
|
4
|
+
import 'dotenv/config';
|
|
5
|
+
import * as u from '../lib/utils/utils.js';
|
|
6
|
+
import * as v from 'ak-tools';
|
|
7
|
+
|
|
2
8
|
const SEED = "my-seed";
|
|
3
|
-
const dayjs = require("dayjs");
|
|
4
|
-
const utc = require("dayjs/plugin/utc");
|
|
5
9
|
dayjs.extend(utc);
|
|
6
|
-
require("dotenv").config();
|
|
7
|
-
const u = require("../components/utils");
|
|
8
|
-
const v = require("ak-tools");
|
|
9
10
|
const chance = u.initChance(SEED);
|
|
10
11
|
const num_users = 5_000;
|
|
11
12
|
const days = 100;
|
|
12
13
|
|
|
13
|
-
/** @typedef {import("../types").Dungeon} Config */
|
|
14
|
+
/** @typedef {import("../types.js").Dungeon} Config */
|
|
14
15
|
|
|
15
16
|
/** @type {Config} */
|
|
16
17
|
const config = {
|
|
@@ -121,4 +122,4 @@ const config = {
|
|
|
121
122
|
}
|
|
122
123
|
};
|
|
123
124
|
|
|
124
|
-
|
|
125
|
+
export default config;
|
package/dungeons/media.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
|
|
2
2
|
const SEED = "my-seed";
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
import dayjs from 'dayjs';
|
|
4
|
+
import utc from 'dayjs/plugin/utc';
|
|
5
5
|
dayjs.extend(utc);
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
import 'dotenv/config';
|
|
7
|
+
import * as u from '../lib/utils/utils.js';
|
|
8
|
+
import * as v from 'ak-tools';
|
|
9
9
|
const chance = u.initChance(SEED);
|
|
10
10
|
const num_users = 10_000;
|
|
11
11
|
const days = 125;
|
|
12
12
|
|
|
13
|
-
/** @typedef {import("../types").Dungeon} Config */
|
|
13
|
+
/** @typedef {import("../types.js").Dungeon} Config */
|
|
14
14
|
|
|
15
15
|
function genIds(numIds = 1000) {
|
|
16
16
|
const ids = [];
|
|
@@ -368,4 +368,4 @@ const config = {
|
|
|
368
368
|
}
|
|
369
369
|
};
|
|
370
370
|
|
|
371
|
-
|
|
371
|
+
export default config;
|
package/dungeons/sanity.js
CHANGED
|
@@ -8,15 +8,15 @@
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
import Chance from 'chance';
|
|
12
12
|
const chance = new Chance();
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
import dayjs from 'dayjs';
|
|
14
|
+
import utc from 'dayjs/plugin/utc.js';
|
|
15
15
|
dayjs.extend(utc);
|
|
16
|
-
|
|
16
|
+
import { weighNumRange, integer } from '../lib/utils/utils.js';
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
/** @type {import('../types').Dungeon} */
|
|
19
|
+
/** @type {import('../types.js').Dungeon} */
|
|
20
20
|
const config = {
|
|
21
21
|
token: "",
|
|
22
22
|
seed: "foo bar",
|
|
@@ -29,7 +29,8 @@ const config = {
|
|
|
29
29
|
hasSessionIds: false, //if true, hasSessionIds are created for each user
|
|
30
30
|
alsoInferFunnels: true, //if true, infer funnels from events
|
|
31
31
|
makeChart: true,
|
|
32
|
-
|
|
32
|
+
writeToDisk: true,
|
|
33
|
+
concurrency: 25,
|
|
33
34
|
funnels: [
|
|
34
35
|
{
|
|
35
36
|
sequence: ["qux", "garply", "durtle", "linny", "fonk", "crumn", "yak"],
|
|
@@ -102,13 +103,6 @@ const config = {
|
|
|
102
103
|
luckyNumber: weighNumRange(42, 420),
|
|
103
104
|
spiritAnimal: ["duck", "dog", "otter", "penguin", "cat", "elephant", "lion", "cheetah", "giraffe", "zebra", "rhino", "hippo", "whale", "dolphin", "shark", "octopus", "squid", "jellyfish", "starfish", "seahorse", "crab", "lobster", "shrimp", "clam", "snail", "slug", "butterfly", "moth", "bee", "wasp", "ant", "beetle", "ladybug", "caterpillar", "centipede", "millipede", "scorpion", "spider", "tarantula", "tick", "mite", "mosquito", "fly", "dragonfly", "damselfly", "grasshopper", "cricket", "locust", "mantis", "cockroach", "termite", "praying mantis", "walking stick", "stick bug", "leaf insect", "lacewing", "aphid", "cicada", "thrips", "psyllid", "scale insect", "whitefly", "mealybug", "planthopper", "leafhopper", "treehopper", "flea", "louse", "bedbug", "flea beetle", "weevil", "longhorn beetle", "leaf beetle", "tiger beetle", "ground beetle", "lady beetle", "firefly", "click beetle", "rove beetle", "scarab beetle", "dung beetle", "stag beetle", "rhinoceros beetle", "hercules beetle", "goliath beetle", "jewel beetle", "tortoise beetle"]
|
|
104
105
|
},
|
|
105
|
-
|
|
106
|
-
scdProps: {},
|
|
107
|
-
mirrorProps: {},
|
|
108
|
-
lookupTables: [],
|
|
109
|
-
groupKeys: [],
|
|
110
|
-
groupProps: {},
|
|
111
|
-
|
|
112
106
|
hook: function (record, type, meta) {
|
|
113
107
|
return record;
|
|
114
108
|
}
|
|
@@ -116,4 +110,4 @@ const config = {
|
|
|
116
110
|
|
|
117
111
|
|
|
118
112
|
|
|
119
|
-
|
|
113
|
+
export default config;
|
package/dungeons/simple.js
CHANGED
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
|
|
2
|
+
import dayjs from "dayjs";
|
|
3
|
+
import utc from "dayjs/plugin/utc.js";
|
|
4
|
+
import "dotenv/config";
|
|
5
|
+
import * as u from "../lib/utils/utils.js";
|
|
6
|
+
import * as v from "ak-tools";
|
|
7
|
+
|
|
8
|
+
const SEED = "ai-generated-1754199343300";
|
|
9
|
+
dayjs.extend(utc);
|
|
10
|
+
const chance = u.initChance(SEED);
|
|
11
|
+
const num_users = 1_000;
|
|
12
|
+
const days = 100;
|
|
13
|
+
|
|
14
|
+
/** @typedef {import("../types.js").Dungeon} Config */
|
|
15
|
+
|
|
16
|
+
/** @type {Config} */
|
|
17
|
+
const config = {
|
|
18
|
+
token: "",
|
|
19
|
+
seed: SEED,
|
|
20
|
+
numDays: days,
|
|
21
|
+
numEvents: num_users * 100,
|
|
22
|
+
numUsers: num_users,
|
|
23
|
+
hasAnonIds: false,
|
|
24
|
+
hasSessionIds: false,
|
|
25
|
+
format: "json",
|
|
26
|
+
alsoInferFunnels: false,
|
|
27
|
+
hasLocation: true,
|
|
28
|
+
hasAndroidDevices: true,
|
|
29
|
+
hasIOSDevices: true,
|
|
30
|
+
hasDesktopDevices: true,
|
|
31
|
+
hasBrowser: true,
|
|
32
|
+
hasCampaigns: true,
|
|
33
|
+
isAnonymous: false,
|
|
34
|
+
hasAdSpend: true,
|
|
35
|
+
|
|
36
|
+
hasAvatar: true,
|
|
37
|
+
makeChart: false,
|
|
38
|
+
|
|
39
|
+
batchSize: 1_500_000,
|
|
40
|
+
concurrency: 1,
|
|
41
|
+
writeToDisk: false,
|
|
42
|
+
|
|
43
|
+
// AI-generated schema content:
|
|
44
|
+
|
|
45
|
+
"funnels": [
|
|
46
|
+
{
|
|
47
|
+
"name": "Student Onboarding",
|
|
48
|
+
"sequence": [
|
|
49
|
+
"student: login",
|
|
50
|
+
"student: join class"
|
|
51
|
+
],
|
|
52
|
+
"isFirstFunnel": true,
|
|
53
|
+
"conversionRate": 95,
|
|
54
|
+
"timeToConvert": 0.1,
|
|
55
|
+
"conditions": {
|
|
56
|
+
"role": "student"
|
|
57
|
+
},
|
|
58
|
+
"order": "sequential",
|
|
59
|
+
"props": {
|
|
60
|
+
"onboarding_source": [
|
|
61
|
+
"email_invite",
|
|
62
|
+
"class_code",
|
|
63
|
+
"school_roster"
|
|
64
|
+
]
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"name": "Teacher Creates Class",
|
|
69
|
+
"sequence": [
|
|
70
|
+
"teacher: login",
|
|
71
|
+
"teacher: create class",
|
|
72
|
+
"teacher: post announcement"
|
|
73
|
+
],
|
|
74
|
+
"conditions": {
|
|
75
|
+
"role": "teacher"
|
|
76
|
+
},
|
|
77
|
+
"isFirstFunnel": true,
|
|
78
|
+
"conversionRate": 98,
|
|
79
|
+
"timeToConvert": 0.2,
|
|
80
|
+
"order": "sequential"
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"name": "Student Completes Homework",
|
|
84
|
+
"sequence": [
|
|
85
|
+
"student: view assignment",
|
|
86
|
+
"student: start assignment",
|
|
87
|
+
"student: submit assignment",
|
|
88
|
+
"student: view grade"
|
|
89
|
+
],
|
|
90
|
+
"conditions": {
|
|
91
|
+
"role": "student"
|
|
92
|
+
},
|
|
93
|
+
"isFirstFunnel": false,
|
|
94
|
+
"conversionRate": 70,
|
|
95
|
+
"timeToConvert": 48,
|
|
96
|
+
"order": "first-and-last-fixed",
|
|
97
|
+
"props": {
|
|
98
|
+
"assignment_type": "homework"
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
"name": "Student Takes Test",
|
|
103
|
+
"conditions": {
|
|
104
|
+
"role": "student"
|
|
105
|
+
},
|
|
106
|
+
"sequence": [
|
|
107
|
+
"student: view assignment",
|
|
108
|
+
"student: start test",
|
|
109
|
+
"student: answer question",
|
|
110
|
+
"student: submit test",
|
|
111
|
+
"student: view grade"
|
|
112
|
+
],
|
|
113
|
+
"isFirstFunnel": false,
|
|
114
|
+
"conversionRate": 85,
|
|
115
|
+
"timeToConvert": 2,
|
|
116
|
+
"order": "sequential",
|
|
117
|
+
"props": {
|
|
118
|
+
"assignment_type": "test"
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
"name": "Teacher Grades Assignment",
|
|
123
|
+
"conditions": {
|
|
124
|
+
"role": "teacher"
|
|
125
|
+
},
|
|
126
|
+
"sequence": [
|
|
127
|
+
"teacher: create assignment",
|
|
128
|
+
"teacher: assign homework",
|
|
129
|
+
"teacher: grade submission"
|
|
130
|
+
],
|
|
131
|
+
"isFirstFunnel": false,
|
|
132
|
+
"conversionRate": 90,
|
|
133
|
+
"timeToConvert": 72,
|
|
134
|
+
"order": "sequential"
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
"name": "Teacher Daily Lesson",
|
|
138
|
+
"sequence": [
|
|
139
|
+
"teacher: take attendance",
|
|
140
|
+
"teacher: start lesson",
|
|
141
|
+
"teacher: end lesson"
|
|
142
|
+
],
|
|
143
|
+
"conditions": {
|
|
144
|
+
"role": "teacher"
|
|
145
|
+
},
|
|
146
|
+
"isFirstFunnel": false,
|
|
147
|
+
"conversionRate": 99,
|
|
148
|
+
"timeToConvert": 1,
|
|
149
|
+
"order": "sequential"
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
"name": "all peoples doing stuf (no conditions)",
|
|
153
|
+
"sequence": [
|
|
154
|
+
"foo",
|
|
155
|
+
"bar",
|
|
156
|
+
"baz"
|
|
157
|
+
]
|
|
158
|
+
}
|
|
159
|
+
],
|
|
160
|
+
"events": [
|
|
161
|
+
{
|
|
162
|
+
"event": "student: login",
|
|
163
|
+
"weight": 10,
|
|
164
|
+
"isFirstEvent": true
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
"event": "teacher: login",
|
|
168
|
+
"weight": 2,
|
|
169
|
+
"isFirstEvent": true
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
"event": "student: join class",
|
|
173
|
+
"weight": 5,
|
|
174
|
+
"properties": {
|
|
175
|
+
"join_method": [
|
|
176
|
+
"class_code",
|
|
177
|
+
"email_invite",
|
|
178
|
+
"admin_added"
|
|
179
|
+
]
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
"event": "teacher: create class",
|
|
184
|
+
"weight": 1
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
"event": "student: view assignment",
|
|
188
|
+
"weight": 15,
|
|
189
|
+
"properties": {
|
|
190
|
+
"assignment_id": "range(1, 500)",
|
|
191
|
+
"subject_id": "range(1, 20)"
|
|
192
|
+
}
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
"event": "student: start assignment",
|
|
196
|
+
"weight": 12,
|
|
197
|
+
"properties": {
|
|
198
|
+
"assignment_id": "range(1, 500)"
|
|
199
|
+
}
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
"event": "student: submit assignment",
|
|
203
|
+
"weight": 10,
|
|
204
|
+
"properties": {
|
|
205
|
+
"assignment_id": "range(1, 500)",
|
|
206
|
+
"time_spent_minutes": "weighNumRange(5, 120, 0.4)",
|
|
207
|
+
"is_late": [
|
|
208
|
+
true,
|
|
209
|
+
false,
|
|
210
|
+
false,
|
|
211
|
+
false,
|
|
212
|
+
false
|
|
213
|
+
]
|
|
214
|
+
}
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
"event": "student: start test",
|
|
218
|
+
"weight": 8,
|
|
219
|
+
"properties": {
|
|
220
|
+
"assignment_id": "range(1, 500)",
|
|
221
|
+
"subject_id": "range(1, 20)"
|
|
222
|
+
}
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
"event": "student: answer question",
|
|
226
|
+
"weight": 40,
|
|
227
|
+
"properties": {
|
|
228
|
+
"assignment_id": "range(1, 500)",
|
|
229
|
+
"is_correct": [
|
|
230
|
+
true,
|
|
231
|
+
true,
|
|
232
|
+
true,
|
|
233
|
+
false
|
|
234
|
+
],
|
|
235
|
+
"time_to_answer_sec": "weighNumRange(10, 300, 0.6)"
|
|
236
|
+
}
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
"event": "student: submit test",
|
|
240
|
+
"weight": 7,
|
|
241
|
+
"properties": {
|
|
242
|
+
"assignment_id": "range(1, 500)",
|
|
243
|
+
"time_spent_minutes": "weighNumRange(20, 90, 0.5)"
|
|
244
|
+
}
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
"event": "student: view grade",
|
|
248
|
+
"weight": 9,
|
|
249
|
+
"properties": {
|
|
250
|
+
"assignment_id": "range(1, 500)",
|
|
251
|
+
"score_percent": "weighNumRange(40, 100, 1.5)"
|
|
252
|
+
}
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
"event": "teacher: take attendance",
|
|
256
|
+
"weight": 3,
|
|
257
|
+
"properties": {
|
|
258
|
+
"absent_students": "weighNumRange(0, 5, 0.2)"
|
|
259
|
+
}
|
|
260
|
+
},
|
|
261
|
+
{
|
|
262
|
+
"event": "teacher: start lesson",
|
|
263
|
+
"weight": 4,
|
|
264
|
+
"properties": {
|
|
265
|
+
"subject_id": "range(1, 20)",
|
|
266
|
+
"lesson_topic": [
|
|
267
|
+
"Review",
|
|
268
|
+
"New Material",
|
|
269
|
+
"Group Work",
|
|
270
|
+
"Lab",
|
|
271
|
+
"Presentation"
|
|
272
|
+
]
|
|
273
|
+
}
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
"event": "teacher: end lesson",
|
|
277
|
+
"weight": 4
|
|
278
|
+
},
|
|
279
|
+
{
|
|
280
|
+
"event": "teacher: create assignment",
|
|
281
|
+
"weight": 2,
|
|
282
|
+
"properties": {
|
|
283
|
+
"assignment_id": "range(1, 500)",
|
|
284
|
+
"subject_id": "range(1, 20)"
|
|
285
|
+
}
|
|
286
|
+
},
|
|
287
|
+
{
|
|
288
|
+
"event": "teacher: assign homework",
|
|
289
|
+
"weight": 2,
|
|
290
|
+
"properties": {
|
|
291
|
+
"assignment_id": "range(1, 500)",
|
|
292
|
+
"due_date": "date(14, false, 'YYYY-MM-DD')"
|
|
293
|
+
}
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
"event": "teacher: grade submission",
|
|
297
|
+
"weight": 6,
|
|
298
|
+
"properties": {
|
|
299
|
+
"assignment_id": "range(1, 500)",
|
|
300
|
+
"score_percent": "weighNumRange(40, 100, 1.5)",
|
|
301
|
+
"feedback_provided": [
|
|
302
|
+
true,
|
|
303
|
+
true,
|
|
304
|
+
false
|
|
305
|
+
]
|
|
306
|
+
}
|
|
307
|
+
},
|
|
308
|
+
{
|
|
309
|
+
"event": "teacher: post announcement",
|
|
310
|
+
"weight": 1,
|
|
311
|
+
"properties": {
|
|
312
|
+
"category": [
|
|
313
|
+
"General",
|
|
314
|
+
"Reminder",
|
|
315
|
+
"Kudos",
|
|
316
|
+
"Event"
|
|
317
|
+
]
|
|
318
|
+
}
|
|
319
|
+
},
|
|
320
|
+
{
|
|
321
|
+
"event": "foo"
|
|
322
|
+
},
|
|
323
|
+
{
|
|
324
|
+
"event": "bar"
|
|
325
|
+
},
|
|
326
|
+
{
|
|
327
|
+
"event": "baz"
|
|
328
|
+
}
|
|
329
|
+
],
|
|
330
|
+
"superProps": {
|
|
331
|
+
"device_type": [
|
|
332
|
+
"desktop",
|
|
333
|
+
"tablet",
|
|
334
|
+
"desktop",
|
|
335
|
+
"chromebook"
|
|
336
|
+
],
|
|
337
|
+
"browser": [
|
|
338
|
+
"Chrome",
|
|
339
|
+
"Chrome",
|
|
340
|
+
"Chrome",
|
|
341
|
+
"Safari",
|
|
342
|
+
"Edge"
|
|
343
|
+
],
|
|
344
|
+
"connection_type": [
|
|
345
|
+
"wifi",
|
|
346
|
+
"wifi",
|
|
347
|
+
"ethernet"
|
|
348
|
+
]
|
|
349
|
+
},
|
|
350
|
+
"userProps": {
|
|
351
|
+
"role": [
|
|
352
|
+
"student",
|
|
353
|
+
"student",
|
|
354
|
+
"student",
|
|
355
|
+
"student",
|
|
356
|
+
"student",
|
|
357
|
+
"student",
|
|
358
|
+
"student",
|
|
359
|
+
"student",
|
|
360
|
+
"student",
|
|
361
|
+
"teacher"
|
|
362
|
+
],
|
|
363
|
+
},
|
|
364
|
+
"scdProps": {
|
|
365
|
+
"gpa": {
|
|
366
|
+
"type": "user",
|
|
367
|
+
"frequency": "month",
|
|
368
|
+
"values": "weighNumRange(1.0, 4.0, 1.2)",
|
|
369
|
+
"timing": "fuzzy",
|
|
370
|
+
"max": 12
|
|
371
|
+
},
|
|
372
|
+
"grade_level": {
|
|
373
|
+
"type": "user",
|
|
374
|
+
"frequency": "year",
|
|
375
|
+
"values": [
|
|
376
|
+
"1st",
|
|
377
|
+
"2nd",
|
|
378
|
+
"3rd",
|
|
379
|
+
"4th",
|
|
380
|
+
"5th",
|
|
381
|
+
"6th",
|
|
382
|
+
"7th",
|
|
383
|
+
"8th",
|
|
384
|
+
"9th",
|
|
385
|
+
"10th",
|
|
386
|
+
"11th",
|
|
387
|
+
"12th"
|
|
388
|
+
],
|
|
389
|
+
"timing": "fixed",
|
|
390
|
+
"max": 12
|
|
391
|
+
}
|
|
392
|
+
},
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
hook: function (record, type, meta) {
|
|
396
|
+
const NOW = dayjs();
|
|
397
|
+
|
|
398
|
+
if (type === "event") {
|
|
399
|
+
const EVENT_TIME = dayjs(record.time);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
if (type === "user") {
|
|
403
|
+
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
if (type === "funnel-post") {
|
|
407
|
+
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
if (type === "funnel-pre") {
|
|
411
|
+
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
if (type === "scd-pre") {
|
|
415
|
+
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
if (type === "everything") {
|
|
419
|
+
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
return record;
|
|
423
|
+
}
|
|
424
|
+
};
|
|
425
|
+
|
|
426
|
+
export default config;
|
package/dungeons/userAgent.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
|
|
2
2
|
const SEED = "my-seed";
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
import dayjs from 'dayjs';
|
|
4
|
+
import utc from 'dayjs/plugin/utc';
|
|
5
5
|
dayjs.extend(utc);
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
import 'dotenv/config';
|
|
7
|
+
import * as u from '../lib/utils/utils.js';
|
|
8
|
+
import * as v from 'ak-tools';
|
|
9
9
|
const chance = u.initChance(SEED);
|
|
10
10
|
const num_users = 1000;
|
|
11
11
|
const days = 30;
|
|
12
12
|
|
|
13
|
-
/** @typedef {import("../types").Dungeon} Config */
|
|
13
|
+
/** @typedef {import("../types.js").Dungeon} Config */
|
|
14
14
|
|
|
15
15
|
/** @type {Config} */
|
|
16
16
|
const config = {
|
|
@@ -187,4 +187,4 @@ const config = {
|
|
|
187
187
|
}
|
|
188
188
|
};
|
|
189
189
|
|
|
190
|
-
|
|
190
|
+
export default config;
|
package/entry.js
CHANGED
|
@@ -17,7 +17,12 @@ import getCliParams from './lib/cli/cli.js';
|
|
|
17
17
|
if (cliConfig.complex) {
|
|
18
18
|
const complexConfig = await import('./dungeons/complex.js');
|
|
19
19
|
finalConfig = { ...complexConfig.default, ...cliConfig };
|
|
20
|
-
}
|
|
20
|
+
}
|
|
21
|
+
else if (cliConfig.sanity) {
|
|
22
|
+
const sanityConfig = await import('./dungeons/sanity.js');
|
|
23
|
+
finalConfig = { ...sanityConfig.default, ...cliConfig };
|
|
24
|
+
}
|
|
25
|
+
else if (cliConfig.simple || (!cliConfig.complex && !cliConfig.simple)) {
|
|
21
26
|
// Default to simple mode when no flags or when --simple is explicitly set
|
|
22
27
|
const simpleConfig = await import('./dungeons/simple.js');
|
|
23
28
|
finalConfig = { ...simpleConfig.default, ...cliConfig };
|
|
@@ -27,14 +32,25 @@ import getCliParams from './lib/cli/cli.js';
|
|
|
27
32
|
const result = await main(finalConfig);
|
|
28
33
|
console.log(`📊 Generated ${(result.eventCount || 0).toLocaleString()} events for ${(result.userCount || 0).toLocaleString()} users`);
|
|
29
34
|
console.log(`⏱️ Total time: ${result.time?.human || 'unknown'}`);
|
|
30
|
-
|
|
35
|
+
const recordsPerSecond = result.eventCount / result.time.delta * 1000;
|
|
36
|
+
console.log(`⚡ Records per second: ${recordsPerSecond.toFixed(2)}`);
|
|
37
|
+
|
|
38
|
+
if (result.errors?.length) {
|
|
39
|
+
console.error(`\n❗ Errors encountered: ${result.errors.length}`);
|
|
40
|
+
if (cliConfig.verbose) {
|
|
41
|
+
result.errors.forEach(err => console.error(` ${err}`));
|
|
42
|
+
}
|
|
43
|
+
} else {
|
|
44
|
+
console.log(`\n🙌 No errors encountered.`);
|
|
45
|
+
}
|
|
46
|
+
|
|
31
47
|
if (result.files?.length) {
|
|
32
48
|
console.log(`📁 Files written: ${result.files.length}`);
|
|
33
49
|
if (cliConfig.verbose) {
|
|
34
50
|
result.files.forEach(file => console.log(` ${file}`));
|
|
35
51
|
}
|
|
36
52
|
}
|
|
37
|
-
console.log(`\n
|
|
53
|
+
console.log(`\n👋 Job completed successfully!\n`);
|
|
38
54
|
process.exit(0);
|
|
39
55
|
} catch (error) {
|
|
40
56
|
console.error(`\n❌ Job failed: ${error.message}`);
|