make-mp-data 2.0.23 → 2.1.1

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.
Files changed (38) hide show
  1. package/dungeons/ai-chat-analytics-ed.js +274 -0
  2. package/dungeons/business.js +0 -1
  3. package/dungeons/complex.js +0 -1
  4. package/dungeons/experiments.js +0 -1
  5. package/dungeons/gaming.js +47 -14
  6. package/dungeons/media.js +5 -6
  7. package/dungeons/mil.js +296 -0
  8. package/dungeons/money2020-ed-also.js +277 -0
  9. package/dungeons/money2020-ed.js +579 -0
  10. package/dungeons/sanity.js +0 -1
  11. package/dungeons/scd.js +0 -1
  12. package/dungeons/simple.js +57 -18
  13. package/dungeons/student-teacher.js +0 -1
  14. package/dungeons/text-generation.js +706 -0
  15. package/dungeons/userAgent.js +1 -2
  16. package/entry.js +3 -0
  17. package/index.js +13 -40
  18. package/lib/cli/cli.js +0 -7
  19. package/lib/core/config-validator.js +6 -8
  20. package/lib/generators/adspend.js +1 -1
  21. package/lib/generators/events.js +1 -1
  22. package/lib/generators/funnels.js +293 -242
  23. package/lib/generators/text-bak-old.js +1121 -0
  24. package/lib/generators/text.js +1173 -0
  25. package/lib/orchestrators/mixpanel-sender.js +1 -1
  26. package/lib/templates/abbreviated.d.ts +13 -3
  27. package/lib/templates/defaults.js +311 -169
  28. package/lib/templates/hooks-instructions.txt +434 -0
  29. package/lib/templates/phrases-bak.js +925 -0
  30. package/lib/templates/phrases.js +2066 -0
  31. package/lib/templates/{instructions.txt → schema-instructions.txt} +78 -1
  32. package/lib/templates/scratch-dungeon-template.js +1 -1
  33. package/lib/templates/textQuickTest.js +172 -0
  34. package/lib/utils/ai.js +51 -2
  35. package/lib/utils/utils.js +29 -18
  36. package/package.json +7 -5
  37. package/types.d.ts +319 -4
  38. package/lib/utils/chart.js +0 -206
@@ -14,7 +14,7 @@ const days = 30;
14
14
 
15
15
  /** @type {Config} */
16
16
  const config = {
17
- token: "a854e82c2c91ada31c502139d99e8e0d",
17
+ token: "",
18
18
  seed: SEED,
19
19
  numDays: days,
20
20
  numEvents: num_users * 100,
@@ -33,7 +33,6 @@ const config = {
33
33
  hasAdSpend: true,
34
34
 
35
35
  hasAvatar: true,
36
- makeChart: false,
37
36
 
38
37
  batchSize: 500_000,
39
38
  concurrency: 500,
package/entry.js CHANGED
@@ -36,9 +36,12 @@ import getCliParams from './lib/cli/cli.js';
36
36
  const recordsPerSecond = result.eventCount / result.time.delta * 1000;
37
37
  console.log(`⚡ Records per second: ${recordsPerSecond.toFixed(2)}`);
38
38
 
39
+ // @ts-ignore
39
40
  if (result.errors?.length) {
41
+ // @ts-ignore
40
42
  console.error(`\n❗ Errors encountered: ${result.errors.length}`);
41
43
  if (cliConfig.verbose) {
44
+ // @ts-ignore
42
45
  result.errors.forEach(err => console.error(` ${err}`));
43
46
  }
44
47
  } else {
package/index.js CHANGED
@@ -29,16 +29,13 @@ import { makeMirror } from './lib/generators/mirror.js';
29
29
  import { makeGroupProfile, makeProfile } from './lib/generators/profiles.js';
30
30
 
31
31
  // Utilities
32
- import { generateLineChart } from './lib/utils/chart.js';
33
32
 
34
33
  // External dependencies
35
34
  import dayjs from "dayjs";
36
35
  import utc from "dayjs/plugin/utc.js";
37
36
  import functions from '@google-cloud/functions-framework';
38
37
  import { timer, sLog } from 'ak-tools';
39
- import fs, { existsSync } from 'fs';
40
- import path from 'path';
41
- import { fileURLToPath } from 'url';
38
+ import { existsSync } from 'fs';
42
39
 
43
40
  // Initialize dayjs and time constants
44
41
  dayjs.extend(utc);
@@ -66,7 +63,6 @@ function displayConfigurationSummary(config) {
66
63
  if (config.hasAnonIds) features.push('anonymous IDs');
67
64
  if (config.hasSessionIds) features.push('session IDs');
68
65
  if (config.alsoInferFunnels) features.push('funnel inference');
69
- if (config.makeChart) features.push('chart generation');
70
66
  if (config.writeToDisk) features.push('disk output');
71
67
 
72
68
  if (features.length > 0) {
@@ -100,7 +96,10 @@ function displayConfigurationSummary(config) {
100
96
 
101
97
  // Group analytics
102
98
  if (config.groupKeys && config.groupKeys.length > 0) {
103
- const groups = config.groupKeys.map(([key, count]) => `${count} ${key}s`).join(', ');
99
+ const groups = config.groupKeys.map((group) => {
100
+ const [key, count] = Array.isArray(group) ? group : [group, 0];
101
+ return `${count} ${key}s`;
102
+ }).join(', ');
104
103
  console.log(`👥 Groups: ${groups}`);
105
104
  }
106
105
 
@@ -189,27 +188,23 @@ async function main(config) {
189
188
 
190
189
  // ! DATA GENERATION ENDS HERE
191
190
 
192
- // Step 10: Generate charts (if enabled)
193
- if (validatedConfig.makeChart) {
194
- await generateCharts(context);
191
+ // Step 10: Send to Mixpanel (if token provided)
192
+ // IMPORTANT: Must happen BEFORE flushing to disk, because flush() clears the arrays
193
+ let importResults;
194
+ if (validatedConfig.token) {
195
+ importResults = await sendToMixpanel(context);
195
196
  }
196
197
 
197
- // Step 11a: flush lookup tables to disk (always as CSVs)
198
+ // Step 11: Flush lookup tables to disk (always as CSVs)
198
199
  if (validatedConfig.writeToDisk) {
199
200
  await flushLookupTablesToDisk(storage, validatedConfig);
200
201
  }
201
202
 
202
- // Step 11b: Flush other storage containers to disk (if writeToDisk enabled)
203
+ // Step 12: Flush other storage containers to disk (if writeToDisk enabled)
203
204
  if (validatedConfig.writeToDisk) {
204
205
  await flushStorageToDisk(storage, validatedConfig);
205
206
  }
206
207
 
207
- // Step 12: Send to Mixpanel (if token provided)
208
- let importResults;
209
- if (validatedConfig.token) {
210
- importResults = await sendToMixpanel(context);
211
- }
212
-
213
208
  // Step 13: Compile results
214
209
  jobTimer.stop(false);
215
210
  const { start, end, delta, human } = jobTimer.report(false);
@@ -418,28 +413,6 @@ async function generateGroupSCDs(context) {
418
413
  }
419
414
  }
420
415
 
421
- /**
422
- * Generate charts for data visualization
423
- * @param {Context} context - Context object
424
- */
425
- async function generateCharts(context) {
426
- const { config, storage } = context;
427
-
428
- if (config.makeChart && storage.eventData?.length > 0) {
429
- const chartPath = typeof config.makeChart === 'string'
430
- ? config.makeChart
431
- : `./${config.name}-timeline`;
432
-
433
- await generateLineChart(storage.eventData, undefined, chartPath);
434
-
435
- if (context.isCLI() || config.verbose) {
436
- console.log(`📊 Chart generated: ${chartPath}`);
437
- } else {
438
- sLog("Chart generated", { path: chartPath });
439
- }
440
- }
441
- }
442
-
443
416
  /**
444
417
  * Flush lookup tables to disk (always runs, regardless of writeToDisk setting)
445
418
  * @param {import('./types').Storage} storage - Storage containers
@@ -505,7 +478,7 @@ async function flushStorageToDisk(storage, config) {
505
478
  * Extract file information from storage containers
506
479
  * @param {import('./types').Storage} storage - Storage object
507
480
  * @param {import('./types').Dungeon} config - Configuration object
508
- * @returns {string[]} Array of file paths
481
+ * @returns {Promise<string[]>} Array of file paths
509
482
  */
510
483
  async function extractFileInfo(storage, config) {
511
484
  const files = [];
package/lib/cli/cli.js CHANGED
@@ -160,13 +160,6 @@ DATA MODEL: https://github.com/ak--47/make-mp-data/blob/main/default.js
160
160
  type: 'boolean',
161
161
  coerce: boolCoerce
162
162
  })
163
- .option("makeChart", {
164
- alias: 'mc',
165
- demandOption: false,
166
- describe: 'create a PNG chart from data',
167
- type: 'boolean',
168
- coerce: boolCoerce
169
- })
170
163
  .option("hasAdSpend", {
171
164
  alias: 'ads',
172
165
  demandOption: false,
@@ -101,7 +101,6 @@ export function validateDungeonConfig(config) {
101
101
  region = "US",
102
102
  writeToDisk = false,
103
103
  verbose = true,
104
- makeChart = false,
105
104
  soup = {},
106
105
  hook = (record) => record,
107
106
  hasAdSpend = false,
@@ -115,13 +114,13 @@ export function validateDungeonConfig(config) {
115
114
  hasIOSDevices = false,
116
115
  alsoInferFunnels = false,
117
116
  name = "",
118
- batchSize = 500_000,
119
- concurrency
117
+ batchSize = 2_500_000,
118
+ concurrency = 1
120
119
  } = config;
121
120
 
122
- // Set concurrency default only if not provided
123
- if (concurrency === undefined || concurrency === null) {
124
- concurrency = Math.min(os.cpus().length * 2, 16);
121
+ // Allow concurrency override from config (default is now 1)
122
+ if (config.concurrency === undefined || config.concurrency === null) {
123
+ concurrency = 1;
125
124
  }
126
125
 
127
126
  // Ensure defaults for deep objects
@@ -196,7 +195,7 @@ export function validateDungeonConfig(config) {
196
195
  const definedEvents = events.map(e => e.event);
197
196
  const missingEvents = eventInFunnels.filter(event => !definedEvents.includes(event));
198
197
  if (missingEvents.length) {
199
- throw new Error(`Funnel sequences contain events that are not defined in the events config:\n${missingEvents.join(', ')}\nPlease ensure all events in funnel sequences are defined in the events array.`);
198
+ throw new Error(`Funnel sequences contain events that are not defined in the events config:\n\n${missingEvents.join(', ')}\n\nPlease ensure all events in funnel sequences are defined in the events array.`);
200
199
  }
201
200
 
202
201
 
@@ -231,7 +230,6 @@ export function validateDungeonConfig(config) {
231
230
  region,
232
231
  writeToDisk,
233
232
  verbose,
234
- makeChart,
235
233
  soup,
236
234
  hook,
237
235
  hasAdSpend,
@@ -78,7 +78,7 @@ function createAdSpendEvent(network, campaign, day, chance) {
78
78
  return {
79
79
  event: "$ad_spend",
80
80
  time: day,
81
- source: 'dm4',
81
+ // source: 'dm4',
82
82
  utm_campaign: campaign,
83
83
  campaign_id: id,
84
84
  insert_id: uid,
@@ -66,7 +66,7 @@ export async function makeEvent(
66
66
  // Create base event template
67
67
  const eventTemplate = {
68
68
  event: chosenEvent.event,
69
- source: "dm4",
69
+ // source: "dm4",
70
70
  time: "",
71
71
  insert_id: "",
72
72
  };