make-mp-data 1.3.3 → 1.4.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.
@@ -15,7 +15,13 @@
15
15
  "name": "complex",
16
16
  "request": "launch",
17
17
  "type": "node-terminal"
18
- },
18
+ },
19
+ {
20
+ "command": "npm run dev",
21
+ "name": "dev",
22
+ "request": "launch",
23
+ "type": "node-terminal"
24
+ },
19
25
  {
20
26
  "type": "node",
21
27
  "request": "launch",
@@ -25,8 +31,10 @@
25
31
  "restart": true,
26
32
  "console": "integratedTerminal",
27
33
  "internalConsoleOptions": "neverOpen",
28
- "args": ["--ignore", "./data/"]
34
+ "args": [
35
+ "--ignore",
36
+ "./data/"
37
+ ]
29
38
  }
30
-
31
39
  ]
32
40
  }
@@ -1,27 +1,37 @@
1
1
  {
2
2
  "cSpell.words": [
3
3
  "AVCHD",
4
+ "chartjs",
4
5
  "chupacabra",
6
+ "Colour",
7
+ "crumn",
5
8
  "darr",
6
9
  "dislikers",
7
10
  "Dont",
11
+ "durtle",
12
+ "fonk",
13
+ "garply",
8
14
  "jackalope",
15
+ "linny",
9
16
  "mbembe",
10
17
  "megalodon",
11
18
  "Miley",
12
19
  "mokele",
13
20
  "mothman",
21
+ "nanodegree",
14
22
  "nessie",
15
23
  "nesty",
16
24
  "planthopper",
17
25
  "psyllid",
18
26
  "tatzelwurm",
19
27
  "timesoup",
28
+ "udacity",
20
29
  "unparse",
21
30
  "Vlogs",
22
- "weindgo"
31
+ "weindgo",
32
+ "whomacity"
23
33
  ],
24
34
  "jest.runMode": "on-demand",
25
35
  "jest.jestCommandLine": "npm run test --",
26
- "js/ts.implicitProjectConfig.checkJs": false,
36
+ "js/ts.implicitProjectConfig.checkJs": true,
27
37
  }
package/README.md CHANGED
@@ -69,7 +69,7 @@ npx make-mp-data ecommSpec.js --token 1234 --numDays 30 --numUsers 1000 --numEve
69
69
 
70
70
  ### Data Models
71
71
 
72
- Check out `./models/` for example `dataModel.js` files to get started quickly.
72
+ Check out `./schemas/` for example `dataModel.js` files to get started quickly.
73
73
 
74
74
  ## 🛠️ CLI Options
75
75
 
@@ -91,7 +91,7 @@ Here's a breakdown of the CLI options you can use with `make-mp-data`:
91
91
  Check out the examples directory for sample data models:
92
92
 
93
93
  ```bash
94
- ls ./models/
94
+ ls ./schemas/
95
95
  ```
96
96
 
97
97
  These models provide a great starting point for creating your own custom data generation scripts.
package/chart.js ADDED
@@ -0,0 +1,180 @@
1
+ const { ChartJSNodeCanvas } = require('chartjs-node-canvas');
2
+ const fs = require('fs');
3
+ const u = require('ak-tools');
4
+ const dayjs = require('dayjs');
5
+ const { openFinder } = require('./utils');
6
+
7
+ const tempDir = u.mkdir('./tmp');
8
+
9
+ // Function to count events per day
10
+ function countDailyEvents(eventData) {
11
+ const dailyCounts = {};
12
+
13
+ eventData.forEach(event => {
14
+ const date = dayjs(event.time).format('YYYY-MM-DD');
15
+ if (!dailyCounts[date]) {
16
+ dailyCounts[date] = 0;
17
+ }
18
+ dailyCounts[date]++;
19
+ });
20
+
21
+ return dailyCounts;
22
+ }
23
+
24
+ // Function to count daily users
25
+ function countDailyUsers(eventData) {
26
+ const dailyUsers = {};
27
+
28
+ eventData.forEach(event => {
29
+ const date = dayjs(event.time).format('YYYY-MM-DD');
30
+ if (!dailyUsers[date]) {
31
+ dailyUsers[date] = new Set();
32
+ }
33
+ dailyUsers[date].add(event.user_id);
34
+ });
35
+
36
+ return dailyUsers;
37
+ }
38
+
39
+ // Function to count daily new users based on signup events
40
+ function countDailyNewUsers(eventData, signupEvents) {
41
+ const dailyNewUsers = {};
42
+ const seenUsers = new Set();
43
+
44
+ eventData.forEach(event => {
45
+ const date = dayjs(event.time).format('YYYY-MM-DD');
46
+ if (!dailyNewUsers[date]) {
47
+ dailyNewUsers[date] = new Set();
48
+ }
49
+ if (signupEvents.includes(event.event) && !seenUsers.has(event.user_id)) {
50
+ dailyNewUsers[date].add(event.user_id);
51
+ seenUsers.add(event.user_id);
52
+ }
53
+ });
54
+
55
+ return dailyNewUsers;
56
+ }
57
+
58
+ // Function to generate line chart
59
+ async function generateLineChart(rawData, signupEvents = ["sign up"], fileName) {
60
+ const width = 1600;
61
+ const height = 1200;
62
+ const chartJSNodeCanvas = new ChartJSNodeCanvas({ width, height, backgroundColour: 'black' });
63
+ const eventData = countDailyEvents(rawData);
64
+ const userData = countDailyUsers(rawData);
65
+ const newUserData = countDailyNewUsers(rawData, signupEvents);
66
+
67
+ // @ts-ignore
68
+ const sortedEventEntries = Object.entries(eventData).sort((a, b) => new Date(a[0]) - new Date(b[0]));
69
+ const eventLabels = sortedEventEntries.map(entry => entry[0]);
70
+ const eventValues = sortedEventEntries.map(entry => entry[1]);
71
+
72
+ // @ts-ignore
73
+ const sortedUserEntries = Object.entries(userData).sort((a, b) => new Date(a[0]) - new Date(b[0]));
74
+ const userLabels = sortedUserEntries.map(entry => entry[0]);
75
+ const userValues = sortedUserEntries.map(entry => entry[1].size);
76
+
77
+ // @ts-ignore
78
+ const sortedNewUserEntries = Object.entries(newUserData).sort((a, b) => new Date(a[0]) - new Date(b[0]));
79
+ const newUserLabels = sortedNewUserEntries.map(entry => entry[0]);
80
+ const newUserValues = sortedNewUserEntries.map(entry => entry[1].size);
81
+
82
+ const configuration = {
83
+ type: 'line',
84
+ data: {
85
+ labels: eventLabels,
86
+ datasets: [
87
+ {
88
+ label: '# EVENTS',
89
+ data: eventValues,
90
+ yAxisID: 'y1',
91
+ fill: true,
92
+ borderColor: '#4F44E0',
93
+ tension: 0.1
94
+ },
95
+ // {
96
+ // label: '# USERS',
97
+ // data: userValues,
98
+ // yAxisID: 'y2',
99
+ // fill: true,
100
+ // borderColor: '#E34F2F',
101
+ // tension: 0.1
102
+ // },
103
+ {
104
+ label: '# NEW',
105
+ data: newUserValues,
106
+ yAxisID: 'y3',
107
+ fill: true,
108
+ borderColor: '#219464',
109
+ tension: 0.1
110
+ }
111
+ ]
112
+ },
113
+ options: {
114
+ scales: {
115
+ x: {
116
+ title: {
117
+ display: true,
118
+ text: 'Date',
119
+ color: 'white'
120
+ },
121
+ ticks: {
122
+ color: 'white'
123
+ }
124
+ },
125
+ y1: {
126
+ type: 'linear',
127
+ display: true,
128
+ position: 'left',
129
+ title: {
130
+ display: true,
131
+ text: 'Count of Events',
132
+ color: '#4F44E0'
133
+ },
134
+ ticks: {
135
+ color: '#4F44E0'
136
+ }
137
+ },
138
+ y3: {
139
+ type: 'linear',
140
+ display: true,
141
+ position: 'right',
142
+ offset: true,
143
+ title: {
144
+ display: true,
145
+ text: 'Count of New Users',
146
+ color: '#219464'
147
+ },
148
+ ticks: {
149
+ color: '#219464'
150
+ },
151
+ grid: {
152
+ drawOnChartArea: false
153
+ }
154
+ }
155
+ },
156
+ plugins: {
157
+ legend: {
158
+ labels: {
159
+ color: 'white'
160
+ }
161
+ }
162
+ }
163
+ }
164
+ };
165
+
166
+ // @ts-ignore
167
+ if (typeof fileName === undefined) fileName = 'chart';
168
+ if (typeof fileName !== 'string') fileName = 'chart';
169
+ // @ts-ignore
170
+ const imageBuffer = await chartJSNodeCanvas.renderToBuffer(configuration);
171
+ const path = `./tmp/${fileName}.png`;
172
+ const removed = await u.rm(path);
173
+ const file = await u.touch(path, imageBuffer);
174
+
175
+ console.log(`Chart saved as ${fileName}.png`);
176
+ openFinder(path)
177
+ return file;
178
+ }
179
+
180
+ module.exports = { generateLineChart };
package/cli.js CHANGED
@@ -15,6 +15,7 @@ by ak@mixpanel.com
15
15
 
16
16
  function cliParams() {
17
17
  console.log(hero);
18
+ // @ts-ignore
18
19
  const args = yargs(process.argv.splice(2))
19
20
  .scriptName("make-mp-data")
20
21
  .usage(`\nusage:\nnpx $0 [dataModel.js] [options]
@@ -78,17 +79,7 @@ DATA MODEL: https://github.com/ak--47/make-mp-data/blob/main/default.js
78
79
  describe: 'use complex data model (model all entities)',
79
80
  alias: 'c',
80
81
  type: 'boolean',
81
- coerce: (value) => {
82
- if (typeof value === 'boolean') return value;
83
- if (value === 'true') {
84
- return true;
85
- }
86
- if (value === 'false') {
87
- return false;
88
- }
89
-
90
- return true;
91
- }
82
+ coerce: boolCoerce
92
83
  })
93
84
  .option("writeToDisk", {
94
85
  demandOption: false,
@@ -96,13 +87,25 @@ DATA MODEL: https://github.com/ak--47/make-mp-data/blob/main/default.js
96
87
  describe: 'write data to disk',
97
88
  alias: 'w',
98
89
  type: 'boolean',
99
- coerce: (value) => {
100
- if (typeof value === 'string') {
101
- return value.toLowerCase() === 'true';
102
- }
103
- return value;
104
- }
90
+ coerce: boolCoerce
91
+ })
92
+ .option("sessionIds", {
93
+ demandOption: false,
94
+ default: false,
95
+ describe: 'create session ids in the data',
96
+ alias: 'sid',
97
+ type: 'boolean',
98
+ coerce: boolCoerce
99
+ })
100
+ .option("anonIds", {
101
+ demandOption: false,
102
+ default: false,
103
+ describe: 'create anonymous ids in the data',
104
+ alias: 'aid',
105
+ type: 'boolean',
106
+ coerce: boolCoerce
105
107
  })
108
+
106
109
  .help()
107
110
  .wrap(null)
108
111
  .argv;
@@ -115,4 +118,14 @@ DATA MODEL: https://github.com/ak--47/make-mp-data/blob/main/default.js
115
118
  }
116
119
 
117
120
 
121
+ function boolCoerce(value, foo) {
122
+ if (typeof value === 'boolean') return value;
123
+ if (typeof value === 'string') {
124
+ return value.toLowerCase() === 'true';
125
+ }
126
+ return value;
127
+
128
+ }
129
+
130
+
118
131
  module.exports = cliParams;