make-mp-data 1.5.1 → 1.5.3
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/.gcloudignore +17 -0
- package/.vscode/launch.json +37 -14
- package/.vscode/settings.json +2 -0
- package/.vscode/tasks.json +12 -0
- package/components/ai.js +93 -0
- package/components/chart.js +14 -0
- package/components/cli.js +8 -2
- package/components/project.js +11 -0
- package/components/prompt.txt +98 -0
- package/components/utils.js +126 -5
- package/{schemas → dungeons}/adspend.js +1 -1
- package/{schemas → dungeons}/anon.js +1 -1
- package/{schemas → dungeons}/big.js +1 -1
- package/{schemas → dungeons}/business.js +1 -1
- package/{schemas → dungeons}/complex.js +9 -9
- package/dungeons/foobar.js +241 -0
- package/{schemas → dungeons}/funnels.js +2 -3
- package/dungeons/gaming.js +314 -0
- package/{schemas → dungeons}/mirror.js +1 -1
- package/{schemas → dungeons}/sanity.js +1 -1
- package/dungeons/scd.js +205 -0
- package/dungeons/session-replay.js +175 -0
- package/{schemas → dungeons}/simple.js +1 -1
- package/dungeons/userAgent.js +190 -0
- package/env.yaml +1 -0
- package/index.js +453 -154
- package/package.json +9 -5
- package/scripts/deploy.sh +11 -0
- package/scripts/new-dungeon.sh +10 -4
- package/tests/benchmark/concurrency.mjs +2 -2
- package/tests/cli.test.js +121 -0
- package/tests/e2e.test.js +134 -186
- package/tests/int.test.js +3 -2
- package/tests/jest.config.js +8 -0
- package/tests/unit.test.js +1 -1
- package/tsconfig.json +1 -1
- package/types.d.ts +40 -9
- package/schemas/foobar.js +0 -125
- package/schemas/session-replay.js +0 -136
- /package/dungeons/{.gitkeep → customers/.gitkeep} +0 -0
package/types.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ declare namespace main {
|
|
|
12
12
|
/**
|
|
13
13
|
* main config object for the entire data generation
|
|
14
14
|
*/
|
|
15
|
-
export interface
|
|
15
|
+
export interface Dungeon {
|
|
16
16
|
// constants
|
|
17
17
|
token?: string;
|
|
18
18
|
seed?: string;
|
|
@@ -23,9 +23,13 @@ declare namespace main {
|
|
|
23
23
|
numUsers?: number;
|
|
24
24
|
format?: "csv" | "json" | string;
|
|
25
25
|
region?: "US" | "EU";
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
concurrency?: number;
|
|
27
|
+
batchSize?: number;
|
|
28
28
|
|
|
29
|
+
serviceAccount?: string;
|
|
30
|
+
serviceSecret?: string;
|
|
31
|
+
projectId?: string;
|
|
32
|
+
|
|
29
33
|
// ids
|
|
30
34
|
simulationName?: string;
|
|
31
35
|
name?: string;
|
|
@@ -44,7 +48,7 @@ declare namespace main {
|
|
|
44
48
|
verbose?: boolean;
|
|
45
49
|
hasAnonIds?: boolean;
|
|
46
50
|
hasSessionIds?: boolean;
|
|
47
|
-
|
|
51
|
+
alsoInferFunnels?: boolean;
|
|
48
52
|
makeChart?: boolean | string;
|
|
49
53
|
|
|
50
54
|
//models
|
|
@@ -52,18 +56,34 @@ declare namespace main {
|
|
|
52
56
|
superProps?: Record<string, ValueValid>;
|
|
53
57
|
funnels?: Funnel[];
|
|
54
58
|
userProps?: Record<string, ValueValid>;
|
|
55
|
-
scdProps?: Record<string,
|
|
59
|
+
scdProps?: Record<string, SCDProp>;
|
|
56
60
|
mirrorProps?: Record<string, MirrorProps>;
|
|
57
61
|
groupKeys?: [string, number][] | [string, number, string[]][]; // [key, numGroups, [events]]
|
|
58
62
|
groupProps?: Record<string, Record<string, ValueValid>>;
|
|
63
|
+
groupEvents?: GroupEventConfig[];
|
|
59
64
|
lookupTables?: LookupTableSchema[];
|
|
60
65
|
soup?: soup;
|
|
61
66
|
hook?: Hook<any>;
|
|
62
67
|
|
|
63
68
|
//allow anything to be on the config
|
|
64
69
|
[key: string]: any;
|
|
70
|
+
|
|
71
|
+
//probabilities
|
|
72
|
+
percentUsersBornInDataset?: number;
|
|
65
73
|
}
|
|
66
74
|
|
|
75
|
+
export type complexSCDProp = {
|
|
76
|
+
type: string;
|
|
77
|
+
frequency: "day" | "week" | "month" | "year";
|
|
78
|
+
values: ValueValid;
|
|
79
|
+
timing: "fixed" | "fuzzy";
|
|
80
|
+
max?: number;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export type SimpleSCDProp = string[];
|
|
84
|
+
|
|
85
|
+
export type SCDProp = complexSCDProp | SimpleSCDProp;
|
|
86
|
+
|
|
67
87
|
/**
|
|
68
88
|
* the soup is a set of parameters that determine the distribution of events over time
|
|
69
89
|
*/
|
|
@@ -82,11 +102,14 @@ declare namespace main {
|
|
|
82
102
|
| "group"
|
|
83
103
|
| "lookup"
|
|
84
104
|
| "scd"
|
|
105
|
+
| "scd-pre"
|
|
85
106
|
| "mirror"
|
|
86
107
|
| "funnel-pre"
|
|
87
108
|
| "funnel-post"
|
|
88
109
|
| "ad-spend"
|
|
89
110
|
| "churn"
|
|
111
|
+
| "group-event"
|
|
112
|
+
| "everything"
|
|
90
113
|
| "";
|
|
91
114
|
|
|
92
115
|
/**
|
|
@@ -99,7 +122,7 @@ declare namespace main {
|
|
|
99
122
|
type?: hookTypes;
|
|
100
123
|
filename?: string;
|
|
101
124
|
format?: "csv" | "json" | string;
|
|
102
|
-
|
|
125
|
+
concurrency?: number;
|
|
103
126
|
[key: string]: any;
|
|
104
127
|
}
|
|
105
128
|
|
|
@@ -107,10 +130,10 @@ declare namespace main {
|
|
|
107
130
|
* an enriched array is an array that has a hookPush method that can be used to transform-then-push items into the array
|
|
108
131
|
*/
|
|
109
132
|
export interface HookedArray<T> extends Array<T> {
|
|
110
|
-
hookPush: (item: T | T[]) => any;
|
|
133
|
+
hookPush: (item: T | T[], ...meta) => any;
|
|
111
134
|
flush: () => void;
|
|
112
135
|
getWriteDir: () => string;
|
|
113
|
-
|
|
136
|
+
getWritePath: () => string;
|
|
114
137
|
[key: string]: any;
|
|
115
138
|
}
|
|
116
139
|
|
|
@@ -133,6 +156,7 @@ declare namespace main {
|
|
|
133
156
|
groupProfilesData?: HookedArray<GroupProfileSchema>[];
|
|
134
157
|
lookupTableData?: HookedArray<LookupTableSchema>[];
|
|
135
158
|
scdTableData?: HookedArray<SCDSchema>[];
|
|
159
|
+
groupEventData?: HookedArray<EventSchema>;
|
|
136
160
|
}
|
|
137
161
|
|
|
138
162
|
/**
|
|
@@ -147,6 +171,13 @@ declare namespace main {
|
|
|
147
171
|
relativeTimeMs?: number;
|
|
148
172
|
}
|
|
149
173
|
|
|
174
|
+
export interface GroupEventConfig extends EventConfig {
|
|
175
|
+
frequency: number; //how often the event occurs (in days)
|
|
176
|
+
group_key: string; //the key that the group is based on
|
|
177
|
+
attribute_to_user: boolean; //if true, the event also goes to a user
|
|
178
|
+
group_size: number; //the number of users in the group
|
|
179
|
+
}
|
|
180
|
+
|
|
150
181
|
/**
|
|
151
182
|
* the generated event data
|
|
152
183
|
*/
|
|
@@ -324,6 +355,6 @@ declare namespace main {
|
|
|
324
355
|
* const gen = require('make-mp-data')
|
|
325
356
|
* const dta = gen({writeToDisk: false})
|
|
326
357
|
*/
|
|
327
|
-
declare function main(config: main.
|
|
358
|
+
declare function main(config: main.Dungeon): Promise<main.Result>;
|
|
328
359
|
|
|
329
360
|
export = main;
|
package/schemas/foobar.js
DELETED
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This is the default configuration file for the data generator in SIMPLE mode
|
|
3
|
-
* notice how the config object is structured, and see it's type definition in ./types.d.ts
|
|
4
|
-
* feel free to modify this file to customize the data you generate
|
|
5
|
-
* see helper functions in utils.js for more ways to generate data
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const Chance = require('chance');
|
|
12
|
-
const chance = new Chance();
|
|
13
|
-
const dayjs = require("dayjs");
|
|
14
|
-
const utc = require("dayjs/plugin/utc");
|
|
15
|
-
dayjs.extend(utc);
|
|
16
|
-
const { uid, comma } = require('ak-tools');
|
|
17
|
-
const { pickAWinner, weighNumRange, date, integer } = require('../components/utils');
|
|
18
|
-
|
|
19
|
-
const itemCategories = ["Books", "Movies", "Music", "Games", "Electronics", "Computers", "Smart Home", "Home", "Garden", "Pet", "Beauty", "Health", "Toys", "Kids", "Baby", "Handmade", "Sports", "Outdoors", "Automotive", "Industrial", "Entertainment", "Art", "Food", "Appliances", "Office", "Wedding", "Software"];
|
|
20
|
-
|
|
21
|
-
const videoCategories = ["funny", "educational", "inspirational", "music", "news", "sports", "cooking", "DIY", "travel", "gaming"];
|
|
22
|
-
|
|
23
|
-
/** @type {import('../types').Config} */
|
|
24
|
-
const config = {
|
|
25
|
-
token: "",
|
|
26
|
-
seed: "foo bar",
|
|
27
|
-
numDays: 365, //how many days worth of data
|
|
28
|
-
numEvents: 10000000, //how many events
|
|
29
|
-
numUsers: 25000, //how many users
|
|
30
|
-
format: 'json', //csv or json
|
|
31
|
-
region: "US",
|
|
32
|
-
hasAnonIds: true, //if true, anonymousIds are created for each user
|
|
33
|
-
hasSessionIds: false, //if true, hasSessionIds are created for each user
|
|
34
|
-
|
|
35
|
-
events: [
|
|
36
|
-
{
|
|
37
|
-
event: "foo",
|
|
38
|
-
weight: 10,
|
|
39
|
-
properties: {}
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
event: "bar",
|
|
43
|
-
weight: 9,
|
|
44
|
-
properties: {}
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
event: "baz",
|
|
48
|
-
weight: 8,
|
|
49
|
-
properties: {}
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
event: "qux",
|
|
53
|
-
weight: 7,
|
|
54
|
-
properties: {}
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
event: "garply",
|
|
58
|
-
weight: 6,
|
|
59
|
-
properties: {}
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
event: "durtle",
|
|
63
|
-
weight: 5,
|
|
64
|
-
properties: {}
|
|
65
|
-
},
|
|
66
|
-
{
|
|
67
|
-
event: "linny",
|
|
68
|
-
weight: 4,
|
|
69
|
-
properties: {}
|
|
70
|
-
},
|
|
71
|
-
{
|
|
72
|
-
event: "fonk",
|
|
73
|
-
weight: 3,
|
|
74
|
-
properties: {}
|
|
75
|
-
},
|
|
76
|
-
{
|
|
77
|
-
event: "crumn",
|
|
78
|
-
weight: 2,
|
|
79
|
-
properties: {}
|
|
80
|
-
},
|
|
81
|
-
{
|
|
82
|
-
event: "yak",
|
|
83
|
-
weight: 1,
|
|
84
|
-
properties: {}
|
|
85
|
-
}
|
|
86
|
-
],
|
|
87
|
-
superProps: {
|
|
88
|
-
color: ["red", "orange", "yellow", "green", "blue", "indigo", "violet"],
|
|
89
|
-
number: integer,
|
|
90
|
-
|
|
91
|
-
},
|
|
92
|
-
userProps: {
|
|
93
|
-
title: chance.profession.bind(chance),
|
|
94
|
-
luckyNumber: weighNumRange(42, 420),
|
|
95
|
-
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"]
|
|
96
|
-
},
|
|
97
|
-
|
|
98
|
-
scdProps: {},
|
|
99
|
-
mirrorProps: {},
|
|
100
|
-
lookupTables: [],
|
|
101
|
-
groupKeys: [
|
|
102
|
-
["company_id", 1000],
|
|
103
|
-
["product_id", 10000]
|
|
104
|
-
],
|
|
105
|
-
groupProps: {
|
|
106
|
-
company_id: {
|
|
107
|
-
name: chance.company.bind(chance),
|
|
108
|
-
industry: chance.pickone.bind(chance, ["tech", "retail", "finance", "healthcare", "manufacturing", "media", "entertainment", "education", "government", "nonprofit", "other"])
|
|
109
|
-
},
|
|
110
|
-
product_id: {
|
|
111
|
-
name: chance.sentence.bind(chance, { words: 3 }),
|
|
112
|
-
category: chance.pickone.bind(chance, itemCategories),
|
|
113
|
-
price: chance.floating.bind(chance, { min: 0, max: 1000, fixed: 2 }),
|
|
114
|
-
quantity: integer
|
|
115
|
-
}
|
|
116
|
-
},
|
|
117
|
-
|
|
118
|
-
hook: function (record, type, meta) {
|
|
119
|
-
return record;
|
|
120
|
-
}
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
module.exports = config;
|
|
@@ -1,136 +0,0 @@
|
|
|
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 = 1000;
|
|
11
|
-
const days = 90;
|
|
12
|
-
|
|
13
|
-
/** @type {import("../types").Config} */
|
|
14
|
-
const config = {
|
|
15
|
-
token: "0135b13525b21294e9e599a483eb35b2",
|
|
16
|
-
seed: SEED,
|
|
17
|
-
numDays: days,
|
|
18
|
-
numEvents: num_users * 100,
|
|
19
|
-
numUsers: num_users,
|
|
20
|
-
hasAnonIds: false,
|
|
21
|
-
hasSessionIds: false,
|
|
22
|
-
format: "json",
|
|
23
|
-
alsoInferFunnels: false,
|
|
24
|
-
hasLocation: true,
|
|
25
|
-
hasAndroidDevices: false,
|
|
26
|
-
hasIOSDevices: false,
|
|
27
|
-
hasDesktopDevices: true,
|
|
28
|
-
hasBrowser: true,
|
|
29
|
-
hasCampaigns: true,
|
|
30
|
-
isAnonymous: false,
|
|
31
|
-
hasAdSpend: true,
|
|
32
|
-
|
|
33
|
-
hasAvatar: true,
|
|
34
|
-
makeChart: true,
|
|
35
|
-
|
|
36
|
-
batchSize: 500_000,
|
|
37
|
-
concurrency: 500,
|
|
38
|
-
writeToDisk: false,
|
|
39
|
-
|
|
40
|
-
funnels: [
|
|
41
|
-
{
|
|
42
|
-
sequence: ["view page", "watch video", "like video"],
|
|
43
|
-
conversionRate: 25,
|
|
44
|
-
timeToConvert: 1
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
sequence: ["view page", "watch video", "dislike video"],
|
|
48
|
-
conversionRate: 20,
|
|
49
|
-
timeToConvert: 1
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
sequence: ["view page", "watch video", "comment on video"],
|
|
53
|
-
conversionRate: 15,
|
|
54
|
-
timeToConvert: 1
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
sequence: ["view page", "sign up"],
|
|
58
|
-
conversionRate: 70,
|
|
59
|
-
isFirstFunnel: true,
|
|
60
|
-
|
|
61
|
-
}
|
|
62
|
-
],
|
|
63
|
-
events: [
|
|
64
|
-
{
|
|
65
|
-
"event": "view page",
|
|
66
|
-
weight: 100,
|
|
67
|
-
|
|
68
|
-
},
|
|
69
|
-
{
|
|
70
|
-
"event": "watch video",
|
|
71
|
-
weight: 150,
|
|
72
|
-
"properties": {
|
|
73
|
-
"watch time (mins)": u.weighNumRange(1, 60, .34)
|
|
74
|
-
}
|
|
75
|
-
},
|
|
76
|
-
{
|
|
77
|
-
"event": "like video",
|
|
78
|
-
weight: 50
|
|
79
|
-
},
|
|
80
|
-
{
|
|
81
|
-
"event": "dislike video",
|
|
82
|
-
weight: 40
|
|
83
|
-
},
|
|
84
|
-
{
|
|
85
|
-
"event": "comment on video",
|
|
86
|
-
weight: 30
|
|
87
|
-
},
|
|
88
|
-
{
|
|
89
|
-
"event": "new feature: AI Filters",
|
|
90
|
-
weight: 10
|
|
91
|
-
},
|
|
92
|
-
{
|
|
93
|
-
"event": "sign up",
|
|
94
|
-
weight: 10,
|
|
95
|
-
"isFirstEvent": true,
|
|
96
|
-
}
|
|
97
|
-
],
|
|
98
|
-
superProps: {},
|
|
99
|
-
userProps: {},
|
|
100
|
-
scdProps: {},
|
|
101
|
-
mirrorProps: {},
|
|
102
|
-
groupKeys: [],
|
|
103
|
-
groupProps: {},
|
|
104
|
-
lookupTables: [],
|
|
105
|
-
hook: function (record, type, meta) {
|
|
106
|
-
const NOW = dayjs();
|
|
107
|
-
const bugStartDate = NOW.subtract(14, 'days');
|
|
108
|
-
const bugFixedDate = NOW.subtract(3, 'days');
|
|
109
|
-
const featureReleaseData = NOW.subtract(7, 'days');
|
|
110
|
-
|
|
111
|
-
if (type === "event") {
|
|
112
|
-
const EVENT_TIME = dayjs(record.time);
|
|
113
|
-
if (record.event === "new feature: AI Filters" && EVENT_TIME.isBefore(featureReleaseData)) {
|
|
114
|
-
return null;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
if (type === "funnel-post") {
|
|
119
|
-
// there's a bug in Chrome where users can't complete the funnel
|
|
120
|
-
if (dayjs(record[0].time).isAfter(bugStartDate) && dayjs(record[0].time).isBefore(bugFixedDate)) {
|
|
121
|
-
if (record[0].browser === "Chrome") {
|
|
122
|
-
if (record.length > 2) {
|
|
123
|
-
record.pop(); // remove the last event
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
return record;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
};
|
|
135
|
-
|
|
136
|
-
module.exports = config;
|
|
File without changes
|