modestbench 0.1.0 → 0.2.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.
Files changed (267) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/README.md +39 -31
  3. package/dist/bootstrap.cjs +10 -10
  4. package/dist/bootstrap.cjs.map +1 -1
  5. package/dist/bootstrap.d.cts.map +1 -1
  6. package/dist/bootstrap.d.ts.map +1 -1
  7. package/dist/bootstrap.js +5 -5
  8. package/dist/bootstrap.js.map +1 -1
  9. package/dist/cli/commands/history.cjs +108 -266
  10. package/dist/cli/commands/history.cjs.map +1 -1
  11. package/dist/cli/commands/history.d.cts +75 -12
  12. package/dist/cli/commands/history.d.cts.map +1 -1
  13. package/dist/cli/commands/history.d.ts +75 -12
  14. package/dist/cli/commands/history.d.ts.map +1 -1
  15. package/dist/cli/commands/history.js +105 -268
  16. package/dist/cli/commands/history.js.map +1 -1
  17. package/dist/cli/commands/run.cjs +18 -5
  18. package/dist/cli/commands/run.cjs.map +1 -1
  19. package/dist/cli/commands/run.d.cts +1 -0
  20. package/dist/cli/commands/run.d.cts.map +1 -1
  21. package/dist/cli/commands/run.d.ts +1 -0
  22. package/dist/cli/commands/run.d.ts.map +1 -1
  23. package/dist/cli/commands/run.js +18 -5
  24. package/dist/cli/commands/run.js.map +1 -1
  25. package/dist/cli/index.cjs +307 -91
  26. package/dist/cli/index.cjs.map +1 -1
  27. package/dist/cli/index.d.cts.map +1 -1
  28. package/dist/cli/index.d.ts.map +1 -1
  29. package/dist/cli/index.js +308 -92
  30. package/dist/cli/index.js.map +1 -1
  31. package/dist/core/engine.cjs +8 -1
  32. package/dist/core/engine.cjs.map +1 -1
  33. package/dist/core/engine.d.cts +3 -0
  34. package/dist/core/engine.d.cts.map +1 -1
  35. package/dist/core/engine.d.ts +3 -0
  36. package/dist/core/engine.d.ts.map +1 -1
  37. package/dist/core/engine.js +8 -1
  38. package/dist/core/engine.js.map +1 -1
  39. package/dist/core/output-path-resolver.cjs +34 -0
  40. package/dist/core/output-path-resolver.cjs.map +1 -0
  41. package/dist/core/output-path-resolver.d.cts +10 -0
  42. package/dist/core/output-path-resolver.d.cts.map +1 -0
  43. package/dist/core/output-path-resolver.d.ts +10 -0
  44. package/dist/core/output-path-resolver.d.ts.map +1 -0
  45. package/dist/core/output-path-resolver.js +30 -0
  46. package/dist/core/output-path-resolver.js.map +1 -0
  47. package/dist/formatters/history/base.cjs +9 -0
  48. package/dist/formatters/history/base.cjs.map +1 -0
  49. package/dist/formatters/history/base.d.cts +26 -0
  50. package/dist/formatters/history/base.d.cts.map +1 -0
  51. package/dist/formatters/history/base.d.ts +26 -0
  52. package/dist/formatters/history/base.d.ts.map +1 -0
  53. package/dist/formatters/history/base.js +8 -0
  54. package/dist/formatters/history/base.js.map +1 -0
  55. package/dist/formatters/history/compare.cjs +127 -0
  56. package/dist/formatters/history/compare.cjs.map +1 -0
  57. package/dist/formatters/history/compare.d.cts +21 -0
  58. package/dist/formatters/history/compare.d.cts.map +1 -0
  59. package/dist/formatters/history/compare.d.ts +21 -0
  60. package/dist/formatters/history/compare.d.ts.map +1 -0
  61. package/dist/formatters/history/compare.js +123 -0
  62. package/dist/formatters/history/compare.js.map +1 -0
  63. package/dist/formatters/history/list.cjs +74 -0
  64. package/dist/formatters/history/list.cjs.map +1 -0
  65. package/dist/formatters/history/list.d.cts +25 -0
  66. package/dist/formatters/history/list.d.cts.map +1 -0
  67. package/dist/formatters/history/list.d.ts +25 -0
  68. package/dist/formatters/history/list.d.ts.map +1 -0
  69. package/dist/formatters/history/list.js +70 -0
  70. package/dist/formatters/history/list.js.map +1 -0
  71. package/dist/formatters/history/show.cjs +98 -0
  72. package/dist/formatters/history/show.cjs.map +1 -0
  73. package/dist/formatters/history/show.d.cts +21 -0
  74. package/dist/formatters/history/show.d.cts.map +1 -0
  75. package/dist/formatters/history/show.d.ts +21 -0
  76. package/dist/formatters/history/show.d.ts.map +1 -0
  77. package/dist/formatters/history/show.js +94 -0
  78. package/dist/formatters/history/show.js.map +1 -0
  79. package/dist/formatters/history/trends.cjs +194 -0
  80. package/dist/formatters/history/trends.cjs.map +1 -0
  81. package/dist/formatters/history/trends.d.cts +22 -0
  82. package/dist/formatters/history/trends.d.cts.map +1 -0
  83. package/dist/formatters/history/trends.d.ts +22 -0
  84. package/dist/formatters/history/trends.d.ts.map +1 -0
  85. package/dist/formatters/history/trends.js +190 -0
  86. package/dist/formatters/history/trends.js.map +1 -0
  87. package/dist/formatters/history/visualization.cjs +79 -0
  88. package/dist/formatters/history/visualization.cjs.map +1 -0
  89. package/dist/formatters/history/visualization.d.cts +24 -0
  90. package/dist/formatters/history/visualization.d.cts.map +1 -0
  91. package/dist/formatters/history/visualization.d.ts +24 -0
  92. package/dist/formatters/history/visualization.d.ts.map +1 -0
  93. package/dist/formatters/history/visualization.js +74 -0
  94. package/dist/formatters/history/visualization.js.map +1 -0
  95. package/dist/index.cjs +15 -17
  96. package/dist/index.cjs.map +1 -1
  97. package/dist/index.d.cts +5 -5
  98. package/dist/index.d.cts.map +1 -1
  99. package/dist/index.d.ts +5 -5
  100. package/dist/index.d.ts.map +1 -1
  101. package/dist/index.js +7 -9
  102. package/dist/index.js.map +1 -1
  103. package/dist/reporters/csv.cjs +2 -2
  104. package/dist/reporters/csv.cjs.map +1 -1
  105. package/dist/reporters/csv.d.cts +1 -1
  106. package/dist/reporters/csv.d.cts.map +1 -1
  107. package/dist/reporters/csv.d.ts +1 -1
  108. package/dist/reporters/csv.d.ts.map +1 -1
  109. package/dist/reporters/csv.js +1 -1
  110. package/dist/reporters/csv.js.map +1 -1
  111. package/dist/reporters/human.cjs +24 -62
  112. package/dist/reporters/human.cjs.map +1 -1
  113. package/dist/reporters/human.d.cts +1 -1
  114. package/dist/reporters/human.d.cts.map +1 -1
  115. package/dist/reporters/human.d.ts +1 -1
  116. package/dist/reporters/human.d.ts.map +1 -1
  117. package/dist/reporters/human.js +2 -40
  118. package/dist/reporters/human.js.map +1 -1
  119. package/dist/reporters/json.cjs +2 -2
  120. package/dist/reporters/json.cjs.map +1 -1
  121. package/dist/reporters/json.d.cts +1 -1
  122. package/dist/reporters/json.d.cts.map +1 -1
  123. package/dist/reporters/json.d.ts +1 -1
  124. package/dist/reporters/json.d.ts.map +1 -1
  125. package/dist/reporters/json.js +1 -1
  126. package/dist/reporters/json.js.map +1 -1
  127. package/dist/reporters/simple.cjs +2 -2
  128. package/dist/reporters/simple.cjs.map +1 -1
  129. package/dist/reporters/simple.d.cts +1 -1
  130. package/dist/reporters/simple.d.cts.map +1 -1
  131. package/dist/reporters/simple.d.ts +1 -1
  132. package/dist/reporters/simple.d.ts.map +1 -1
  133. package/dist/reporters/simple.js +1 -1
  134. package/dist/reporters/simple.js.map +1 -1
  135. package/dist/{config/manager.cjs → services/config-manager.cjs} +2 -2
  136. package/dist/services/config-manager.cjs.map +1 -0
  137. package/dist/{config/manager.d.cts → services/config-manager.d.cts} +1 -1
  138. package/dist/services/config-manager.d.cts.map +1 -0
  139. package/dist/{config/manager.d.ts → services/config-manager.d.ts} +1 -1
  140. package/dist/services/config-manager.d.ts.map +1 -0
  141. package/dist/{config/manager.js → services/config-manager.js} +2 -2
  142. package/dist/services/config-manager.js.map +1 -0
  143. package/dist/{core/loader.cjs → services/file-loader.cjs} +2 -2
  144. package/dist/services/file-loader.cjs.map +1 -0
  145. package/dist/{core/loader.d.cts → services/file-loader.d.cts} +1 -1
  146. package/dist/services/file-loader.d.cts.map +1 -0
  147. package/dist/{core/loader.d.ts → services/file-loader.d.ts} +1 -1
  148. package/dist/services/file-loader.d.ts.map +1 -0
  149. package/dist/{core/loader.js → services/file-loader.js} +2 -2
  150. package/dist/services/file-loader.js.map +1 -0
  151. package/dist/services/history/comparison.cjs +124 -0
  152. package/dist/services/history/comparison.cjs.map +1 -0
  153. package/dist/services/history/comparison.d.cts +18 -0
  154. package/dist/services/history/comparison.d.cts.map +1 -0
  155. package/dist/services/history/comparison.d.ts +18 -0
  156. package/dist/services/history/comparison.d.ts.map +1 -0
  157. package/dist/services/history/comparison.js +120 -0
  158. package/dist/services/history/comparison.js.map +1 -0
  159. package/dist/services/history/models.cjs +9 -0
  160. package/dist/services/history/models.cjs.map +1 -0
  161. package/dist/services/history/models.d.cts +139 -0
  162. package/dist/services/history/models.d.cts.map +1 -0
  163. package/dist/services/history/models.d.ts +139 -0
  164. package/dist/services/history/models.d.ts.map +1 -0
  165. package/dist/services/history/models.js +8 -0
  166. package/dist/services/history/models.js.map +1 -0
  167. package/dist/services/history/query.cjs +97 -0
  168. package/dist/services/history/query.cjs.map +1 -0
  169. package/dist/services/history/query.d.cts +38 -0
  170. package/dist/services/history/query.d.cts.map +1 -0
  171. package/dist/services/history/query.d.ts +38 -0
  172. package/dist/services/history/query.d.ts.map +1 -0
  173. package/dist/services/history/query.js +92 -0
  174. package/dist/services/history/query.js.map +1 -0
  175. package/dist/services/history/trend-analysis.cjs +187 -0
  176. package/dist/services/history/trend-analysis.cjs.map +1 -0
  177. package/dist/services/history/trend-analysis.d.cts +34 -0
  178. package/dist/services/history/trend-analysis.d.cts.map +1 -0
  179. package/dist/services/history/trend-analysis.d.ts +34 -0
  180. package/dist/services/history/trend-analysis.d.ts.map +1 -0
  181. package/dist/services/history/trend-analysis.js +179 -0
  182. package/dist/services/history/trend-analysis.js.map +1 -0
  183. package/dist/{storage/history.cjs → services/history-storage.cjs} +1 -1
  184. package/dist/services/history-storage.cjs.map +1 -0
  185. package/dist/{storage/history.d.cts → services/history-storage.d.cts} +1 -1
  186. package/dist/services/history-storage.d.cts.map +1 -0
  187. package/dist/{storage/history.d.ts → services/history-storage.d.ts} +1 -1
  188. package/dist/services/history-storage.d.ts.map +1 -0
  189. package/dist/{storage/history.js → services/history-storage.js} +1 -1
  190. package/dist/services/history-storage.js.map +1 -0
  191. package/dist/{progress/manager.cjs → services/progress-manager.cjs} +1 -1
  192. package/dist/services/progress-manager.cjs.map +1 -0
  193. package/dist/{progress/manager.d.cts → services/progress-manager.d.cts} +1 -1
  194. package/dist/services/progress-manager.d.cts.map +1 -0
  195. package/dist/{progress/manager.d.ts → services/progress-manager.d.ts} +1 -1
  196. package/dist/services/progress-manager.d.ts.map +1 -0
  197. package/dist/{progress/manager.js → services/progress-manager.js} +1 -1
  198. package/dist/services/progress-manager.js.map +1 -0
  199. package/dist/{reporters/registry.cjs → services/reporter-registry.cjs} +1 -1
  200. package/dist/services/reporter-registry.cjs.map +1 -0
  201. package/dist/{reporters/registry.d.cts → services/reporter-registry.d.cts} +1 -1
  202. package/dist/services/reporter-registry.d.cts.map +1 -0
  203. package/dist/{reporters/registry.d.ts → services/reporter-registry.d.ts} +1 -1
  204. package/dist/services/reporter-registry.d.ts.map +1 -0
  205. package/dist/{reporters/registry.js → services/reporter-registry.js} +1 -1
  206. package/dist/services/reporter-registry.js.map +1 -0
  207. package/dist/types/cli.d.cts +3 -0
  208. package/dist/types/cli.d.cts.map +1 -1
  209. package/dist/types/cli.d.ts +3 -0
  210. package/dist/types/cli.d.ts.map +1 -1
  211. package/dist/utils/ansi.cjs +61 -0
  212. package/dist/utils/ansi.cjs.map +1 -0
  213. package/dist/utils/ansi.d.cts +53 -0
  214. package/dist/utils/ansi.d.cts.map +1 -0
  215. package/dist/utils/ansi.d.ts +53 -0
  216. package/dist/utils/ansi.d.ts.map +1 -0
  217. package/dist/utils/ansi.js +57 -0
  218. package/dist/utils/ansi.js.map +1 -0
  219. package/package.json +5 -4
  220. package/src/bootstrap.ts +5 -5
  221. package/src/cli/commands/history.ts +194 -342
  222. package/src/cli/commands/run.ts +32 -3
  223. package/src/cli/index.ts +361 -106
  224. package/src/core/engine.ts +9 -1
  225. package/src/core/output-path-resolver.ts +38 -0
  226. package/src/formatters/history/base.ts +28 -0
  227. package/src/formatters/history/compare.ts +186 -0
  228. package/src/formatters/history/list.ts +101 -0
  229. package/src/formatters/history/show.ts +155 -0
  230. package/src/formatters/history/trends.ts +281 -0
  231. package/src/formatters/history/visualization.ts +93 -0
  232. package/src/index.ts +7 -11
  233. package/src/reporters/csv.ts +1 -1
  234. package/src/reporters/human.ts +2 -42
  235. package/src/reporters/json.ts +1 -1
  236. package/src/reporters/simple.ts +1 -1
  237. package/src/{config/manager.ts → services/config-manager.ts} +1 -1
  238. package/src/{core/loader.ts → services/file-loader.ts} +1 -1
  239. package/src/services/history/comparison.ts +130 -0
  240. package/src/services/history/models.ts +148 -0
  241. package/src/services/history/query.ts +116 -0
  242. package/src/services/history/trend-analysis.ts +238 -0
  243. package/src/types/cli.ts +3 -0
  244. package/src/utils/ansi.ts +59 -0
  245. package/dist/config/manager.cjs.map +0 -1
  246. package/dist/config/manager.d.cts.map +0 -1
  247. package/dist/config/manager.d.ts.map +0 -1
  248. package/dist/config/manager.js.map +0 -1
  249. package/dist/core/loader.cjs.map +0 -1
  250. package/dist/core/loader.d.cts.map +0 -1
  251. package/dist/core/loader.d.ts.map +0 -1
  252. package/dist/core/loader.js.map +0 -1
  253. package/dist/progress/manager.cjs.map +0 -1
  254. package/dist/progress/manager.d.cts.map +0 -1
  255. package/dist/progress/manager.d.ts.map +0 -1
  256. package/dist/progress/manager.js.map +0 -1
  257. package/dist/reporters/registry.cjs.map +0 -1
  258. package/dist/reporters/registry.d.cts.map +0 -1
  259. package/dist/reporters/registry.d.ts.map +0 -1
  260. package/dist/reporters/registry.js.map +0 -1
  261. package/dist/storage/history.cjs.map +0 -1
  262. package/dist/storage/history.d.cts.map +0 -1
  263. package/dist/storage/history.d.ts.map +0 -1
  264. package/dist/storage/history.js.map +0 -1
  265. /package/src/{storage/history.ts → services/history-storage.ts} +0 -0
  266. /package/src/{progress/manager.ts → services/progress-manager.ts} +0 -0
  267. /package/src/{reporters/registry.ts → services/reporter-registry.ts} +0 -0
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Show Formatter
3
+ *
4
+ * Formats detailed benchmark run display in human and JSON formats.
5
+ */
6
+ import { relative } from 'node:path';
7
+ import { ansiChars, colorize } from "../../utils/ansi.js";
8
+ /**
9
+ * Formatter for history show command
10
+ */
11
+ export class HistoryShowFormatter {
12
+ /**
13
+ * Format as human-readable detailed view
14
+ */
15
+ formatHuman(data) {
16
+ const lines = [];
17
+ // Header with run ID
18
+ lines.push(colorize('cyan', colorize('bold', `\nBenchmark Run: ${colorize('brightWhite', colorize('bold', data.id))}`)));
19
+ // Run details (indented by 2 spaces)
20
+ lines.push(` ${colorize('brightCyan', ansiChars.bullet)} ${colorize('white', data.startTime.toLocaleString())}`);
21
+ lines.push(` ${colorize('brightCyan', ansiChars.bullet)} ${colorize('white', 'Duration:')} ${colorize('magenta', `${(data.duration / 1000).toFixed(1)}s`)}`);
22
+ lines.push(` ${colorize('brightCyan', ansiChars.bullet)} Node.js ${colorize('brightWhite', data.environment.nodeVersion)} on ${colorize('brightWhite', data.environment.platform)} (${colorize('brightWhite', data.environment.arch)})`);
23
+ // CPU and system info
24
+ lines.push(` ${colorize('brightCyan', ansiChars.bullet)} ${colorize('brightWhite', String(data.environment.cpu.cores))} cores @ ${colorize('brightWhite', `${data.environment.cpu.speed}MHz`)} on ${colorize('brightWhite', data.environment.cpu.model)}`);
25
+ if (data.git) {
26
+ lines.push(` ${colorize('brightCyan', ansiChars.bullet)} ${colorize('brightBlue', data.git.branch)}@${colorize('dim', data.git.commit.substring(0, 8))}`);
27
+ }
28
+ // Summary section
29
+ lines.push('');
30
+ lines.push(colorize('cyan', 'Summary'));
31
+ lines.push(` ${colorize('dim', ansiChars.smallSquare)} Files: ${colorize('brightWhite', String(data.summary.totalFiles))}`);
32
+ lines.push(` ${colorize('dim', ansiChars.smallSquare)} Suites: ${colorize('brightWhite', String(data.summary.totalSuites))}`);
33
+ lines.push(` ${colorize('dim', ansiChars.smallSquare)} Tasks: ${colorize('brightWhite', String(data.summary.totalTasks))}`);
34
+ lines.push(` ${colorize('dim', ansiChars.smallSquare)} Passed: ${colorize('brightCyan', String(data.summary.passedTasks))}`);
35
+ if (data.summary.failedTasks > 0) {
36
+ lines.push(` ${colorize('dim', ansiChars.smallSquare)} Failed: ${colorize('brightRed', colorize('bold', String(data.summary.failedTasks)))}`);
37
+ }
38
+ // Detailed results
39
+ lines.push('');
40
+ lines.push(colorize('cyan', 'Results'));
41
+ lines.push('');
42
+ for (const file of data.files) {
43
+ // Display filepath as relative if within cwd, otherwise absolute
44
+ const displayPath = relative(process.cwd(), file.filePath);
45
+ const finalPath = displayPath.startsWith('..')
46
+ ? file.filePath
47
+ : displayPath;
48
+ lines.push(`${colorize('dim', ansiChars.bullet)} ${colorize('brightMagenta', colorize('bold', finalPath))}`);
49
+ for (const suite of file.suites) {
50
+ lines.push(` ${colorize('dim', ansiChars.bullet)} ${colorize('brightWhite', suite.name)}`);
51
+ for (const task of suite.tasks) {
52
+ const statusIcon = task.error
53
+ ? colorize('brightRed', ansiChars.cross)
54
+ : colorize('brightCyan', ansiChars.checkmark);
55
+ if (task.error) {
56
+ lines.push(` ${statusIcon} ${colorize('white', task.name)} ${colorize('dim', ansiChars.bullet)} ${colorize('brightRed', 'failed')}`);
57
+ }
58
+ else {
59
+ const mean = formatTime(task.mean);
60
+ const opsStr = task.opsPerSecond.toLocaleString('en-US', {
61
+ maximumFractionDigits: 0,
62
+ });
63
+ const rmeStr = task.marginOfError.toFixed(2);
64
+ lines.push(` ${statusIcon} ${colorize('white', task.name)}: ${colorize('brightMagenta', mean)} ${colorize('dim', ansiChars.bullet)} ${colorize('brightBlue', `${ansiChars.plusMinus}${rmeStr}`)} ${colorize('dim', ansiChars.bullet)} ${colorize('magenta', opsStr)} ops/sec`);
65
+ if (task.iterations > 0) {
66
+ lines.push(` ${colorize('dim', `${task.iterations} iterations, cv: ${task.cv.toFixed(1)}%`)}`);
67
+ }
68
+ }
69
+ }
70
+ }
71
+ lines.push('');
72
+ }
73
+ return lines.join('\n');
74
+ }
75
+ /**
76
+ * Format as complete JSON
77
+ */
78
+ formatJson(data) {
79
+ return JSON.stringify(data, null, 2);
80
+ }
81
+ }
82
+ /**
83
+ * Format nanoseconds as a human-readable time string
84
+ */
85
+ const formatTime = (ns) => {
86
+ if (ns < 1000) {
87
+ return `${ns.toFixed(2)}ns`;
88
+ }
89
+ if (ns < 1000000) {
90
+ return `${(ns / 1000).toFixed(3)}µs`;
91
+ }
92
+ return `${(ns / 1000000).toFixed(3)}ms`;
93
+ };
94
+ //# sourceMappingURL=show.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"show.js","sourceRoot":"","sources":["../../../src/formatters/history/show.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,194 @@
1
+ "use strict";
2
+ /**
3
+ * Trends Formatter
4
+ *
5
+ * Formats performance trend analysis with visualizations in human and JSON
6
+ * formats.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.HistoryTrendsFormatter = void 0;
10
+ const node_util_1 = require("node:util");
11
+ const ansi_js_1 = require("../../utils/ansi.cjs");
12
+ const visualization_js_1 = require("./visualization.cjs");
13
+ /**
14
+ * Nanoseconds per millisecond conversion constant
15
+ */
16
+ const NS_PER_MS = 1_000_000;
17
+ /**
18
+ * Nanoseconds per microsecond conversion constant
19
+ */
20
+ const NS_PER_US = 1_000;
21
+ /**
22
+ * Intelligently format a time range with appropriate precision Displays
23
+ * microseconds for small values (< 1ms) for better clarity
24
+ */
25
+ const formatTimeRange = (minNs, maxNs) => {
26
+ // If both values are below 1ms, show in microseconds for better precision
27
+ if (maxNs < NS_PER_MS) {
28
+ const minUs = minNs / NS_PER_US;
29
+ const maxUs = maxNs / NS_PER_US;
30
+ return `${minUs.toFixed(2)}-${maxUs.toFixed(2)}µs`;
31
+ }
32
+ // Otherwise show in milliseconds
33
+ const minMs = minNs / NS_PER_MS;
34
+ const maxMs = maxNs / NS_PER_MS;
35
+ return `${minMs.toFixed(3)}-${maxMs.toFixed(3)}ms`;
36
+ };
37
+ /**
38
+ * Calculate visible string length, stripping ANSI escape codes
39
+ */
40
+ const getVisualLength = (str) => (0, node_util_1.stripVTControlCharacters)(str).length;
41
+ /**
42
+ * Formatter for history trends command
43
+ */
44
+ class HistoryTrendsFormatter {
45
+ /**
46
+ * Format as human-readable trends with visualizations
47
+ */
48
+ formatHuman(data) {
49
+ const lines = [];
50
+ lines.push((0, ansi_js_1.colorize)('brightMagenta', (0, ansi_js_1.colorize)('bold', `\nPerformance Trends (${data.runs} runs)`)));
51
+ if (data.timespan.start && data.timespan.end) {
52
+ lines.push((0, ansi_js_1.colorize)('dim', `Time range: ${data.timespan.start.toLocaleDateString()} to ${data.timespan.end.toLocaleDateString()}`));
53
+ }
54
+ lines.push('');
55
+ // Summary statistics
56
+ lines.push((0, ansi_js_1.colorize)('brightBlue', 'Summary:'));
57
+ lines.push(` ${(0, ansi_js_1.colorize)('brightCyan', '▲')} ${data.summary.improvingTasks} improving ${(0, ansi_js_1.colorize)('brightRed', '▼')} ${data.summary.degradingTasks} degrading ${(0, ansi_js_1.colorize)('dim', '→')} ${data.summary.stableTasks} stable`);
58
+ lines.push('');
59
+ // Task Performance Summary Table
60
+ lines.push((0, ansi_js_1.colorize)('brightMagenta', 'Task Performance Summary:'));
61
+ lines.push('');
62
+ for (const trendData of data.trends) {
63
+ // Show top 20
64
+ const trendIcon = trendData.trend === 'improving'
65
+ ? (0, ansi_js_1.colorize)('brightCyan', '▲')
66
+ : trendData.trend === 'degrading'
67
+ ? (0, ansi_js_1.colorize)('brightRed', '▼')
68
+ : (0, ansi_js_1.colorize)('dim', '→');
69
+ const changeColor = trendData.percentChange < -5
70
+ ? 'brightCyan'
71
+ : trendData.percentChange > 5
72
+ ? 'brightRed'
73
+ : 'dim';
74
+ const changeSign = trendData.percentChange >= 0 ? '+' : '';
75
+ const changeStr = `${changeSign}${trendData.percentChange.toFixed(1)}%`;
76
+ // Generate sparkline - scale with number of data points (min 12, max 20)
77
+ const values = trendData.dataPoints.map((dp) => dp.mean);
78
+ const sparklineWidth = Math.min(20, Math.max(12, trendData.runs));
79
+ const sparkline = (0, visualization_js_1.generateSparkline)(values, sparklineWidth);
80
+ const sparklineColor = trendData.trend === 'improving'
81
+ ? 'brightCyan'
82
+ : trendData.trend === 'degrading'
83
+ ? 'brightRed'
84
+ : 'cyan';
85
+ const taskName = (0, ansi_js_1.colorize)('white', trendData.task);
86
+ const percentDisplay = (0, ansi_js_1.colorize)(changeColor, changeStr.padStart(8));
87
+ const sparklineDisplay = (0, ansi_js_1.colorize)(sparklineColor, sparkline);
88
+ // Layout: icon (2) + task name + padding + percent (8) + spaces (2) + sparkline
89
+ // Position percent+graph at visual column 60 for consistent alignment
90
+ const prefix = ` ${trendIcon} ${taskName}`;
91
+ const prefixVisualLength = getVisualLength(prefix);
92
+ const targetColumn = 60;
93
+ if (prefixVisualLength > targetColumn) {
94
+ // Task name is too long, wrap to next line
95
+ lines.push(prefix);
96
+ lines.push(`${' '.repeat(targetColumn)}${percentDisplay} ${sparklineDisplay}`);
97
+ }
98
+ else {
99
+ // Fit on one line with padding
100
+ const padding = Math.max(1, targetColumn - prefixVisualLength);
101
+ const paddingStr = ' '.repeat(padding);
102
+ lines.push(`${prefix}${paddingStr}${percentDisplay} ${sparklineDisplay}`);
103
+ }
104
+ }
105
+ // Show all trends (no limit)
106
+ lines.push('');
107
+ // Show regressions if any
108
+ if (data.regressions.length > 0) {
109
+ lines.push((0, ansi_js_1.colorize)('brightRed', (0, ansi_js_1.colorize)('bold', 'Regressions Detected:')));
110
+ lines.push('');
111
+ for (const regression of data.regressions) {
112
+ lines.push(` ${(0, ansi_js_1.colorize)('brightRed', '▼')} ${(0, ansi_js_1.colorize)('white', regression.task)}: ${(0, ansi_js_1.colorize)('brightRed', `${regression.percentChange.toFixed(1)}% slower`)} (${regression.runs} runs)`);
113
+ }
114
+ lines.push('');
115
+ }
116
+ // Show low-confidence regressions (insufficient data)
117
+ if (data.lowConfidenceRegressions.length > 0) {
118
+ lines.push((0, ansi_js_1.colorize)('brightYellow', (0, ansi_js_1.colorize)('bold', '! Potential Regressions (insufficient data):')));
119
+ lines.push('');
120
+ for (const regression of data.lowConfidenceRegressions) {
121
+ lines.push(` ${(0, ansi_js_1.colorize)('brightYellow', '!')} ${(0, ansi_js_1.colorize)('white', regression.task)}: ${(0, ansi_js_1.colorize)('brightYellow', `${regression.percentChange.toFixed(1)}% slower`)} (${regression.runs} run${regression.runs !== 1 ? 's' : ''})`);
122
+ }
123
+ lines.push('');
124
+ }
125
+ // Show performance distribution for most important task (highest RME) if we have enough data
126
+ // Find task with highest relative margin of error - the most variable/unreliable one
127
+ const mostImportantTrend = data.trends
128
+ .filter((t) => t.runs >= 5)
129
+ .sort((a, b) => {
130
+ const rmeA = (a.statistics.stdDeviation / a.statistics.mean) * 100;
131
+ const rmeB = (b.statistics.stdDeviation / b.statistics.mean) * 100;
132
+ return rmeB - rmeA; // Descending order (highest RME first)
133
+ })[0];
134
+ if (mostImportantTrend) {
135
+ lines.push((0, ansi_js_1.colorize)('brightMagenta', 'Performance Distribution (most variable task):'));
136
+ lines.push((0, ansi_js_1.colorize)('white', mostImportantTrend.task));
137
+ const cv = ((mostImportantTrend.statistics.stdDeviation /
138
+ mostImportantTrend.statistics.mean) *
139
+ 100).toFixed(1);
140
+ lines.push((0, ansi_js_1.colorize)('dim', ` Variability: ${cv}%`));
141
+ lines.push('');
142
+ // Create distribution buckets
143
+ const values = mostImportantTrend.dataPoints.map((dp) => dp.mean);
144
+ const min = Math.min(...values);
145
+ const max = Math.max(...values);
146
+ const range = max - min;
147
+ const numBuckets = Math.min(5, mostImportantTrend.runs);
148
+ const bucketSize = range / numBuckets;
149
+ const buckets = [];
150
+ for (let i = 0; i < numBuckets; i++) {
151
+ const bucketMin = min + i * bucketSize;
152
+ const bucketMax = min + (i + 1) * bucketSize;
153
+ const count = values.filter((v) => v >= bucketMin &&
154
+ (i === numBuckets - 1 ? v <= bucketMax : v < bucketMax)).length;
155
+ const label = formatTimeRange(bucketMin, bucketMax);
156
+ buckets.push({
157
+ count,
158
+ label,
159
+ max: bucketMax,
160
+ min: bucketMin,
161
+ });
162
+ }
163
+ // Filter out empty buckets for cleaner display
164
+ const nonEmptyBuckets = buckets.filter((b) => b.count > 0);
165
+ const chart = (0, visualization_js_1.generateBarChart)(nonEmptyBuckets, 25);
166
+ for (const line of chart) {
167
+ lines.push((0, ansi_js_1.colorize)('brightCyan', line));
168
+ }
169
+ lines.push('');
170
+ lines.push((0, ansi_js_1.colorize)('dim', ` Mean: ${(mostImportantTrend.statistics.mean / NS_PER_MS).toFixed(3)}ms Median: ${(mostImportantTrend.statistics.median / NS_PER_MS).toFixed(3)}ms StdDev: ${(mostImportantTrend.statistics.stdDeviation / NS_PER_MS).toFixed(3)}ms`));
171
+ lines.push('');
172
+ }
173
+ return lines.join('\n');
174
+ }
175
+ /**
176
+ * Format as JSON
177
+ */
178
+ formatJson(data) {
179
+ return JSON.stringify({
180
+ regressions: data.regressions,
181
+ summary: {
182
+ degradingTasks: data.summary.degradingTasks,
183
+ improvingTasks: data.summary.improvingTasks,
184
+ runs: data.runs,
185
+ stableTasks: data.summary.stableTasks,
186
+ timespan: data.timespan,
187
+ totalTasks: data.summary.totalTasks,
188
+ },
189
+ trends: data.trends,
190
+ }, null, 2);
191
+ }
192
+ }
193
+ exports.HistoryTrendsFormatter = HistoryTrendsFormatter;
194
+ //# sourceMappingURL=trends.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trends.js","sourceRoot":"","sources":["../../../src/formatters/history/trends.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Trends Formatter
3
+ *
4
+ * Formats performance trend analysis with visualizations in human and JSON
5
+ * formats.
6
+ */
7
+ import type { TrendsResult } from "../../services/history/models.cjs";
8
+ import type { HistoryFormatter } from "./base.cjs";
9
+ /**
10
+ * Formatter for history trends command
11
+ */
12
+ export declare class HistoryTrendsFormatter implements HistoryFormatter<TrendsResult> {
13
+ /**
14
+ * Format as human-readable trends with visualizations
15
+ */
16
+ formatHuman(data: TrendsResult): string;
17
+ /**
18
+ * Format as JSON
19
+ */
20
+ formatJson(data: TrendsResult): string;
21
+ }
22
+ //# sourceMappingURL=trends.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trends.d.ts","sourceRoot":"","sources":["../../../src/formatters/history/trends.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAEV,YAAY,EACb,0CAAyC;AAC1C,OAAO,KAAK,EAAE,gBAAgB,EAAE,mBAAkB;AAuClD;;GAEG;AACH,qBAAa,sBAAuB,YAAW,gBAAgB,CAAC,YAAY,CAAC;IAC3E;;OAEG;IACH,WAAW,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM;IAwMvC;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM;CAkBvC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Trends Formatter
3
+ *
4
+ * Formats performance trend analysis with visualizations in human and JSON
5
+ * formats.
6
+ */
7
+ import type { TrendsResult } from "../../services/history/models.js";
8
+ import type { HistoryFormatter } from "./base.js";
9
+ /**
10
+ * Formatter for history trends command
11
+ */
12
+ export declare class HistoryTrendsFormatter implements HistoryFormatter<TrendsResult> {
13
+ /**
14
+ * Format as human-readable trends with visualizations
15
+ */
16
+ formatHuman(data: TrendsResult): string;
17
+ /**
18
+ * Format as JSON
19
+ */
20
+ formatJson(data: TrendsResult): string;
21
+ }
22
+ //# sourceMappingURL=trends.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trends.d.ts","sourceRoot":"","sources":["../../../src/formatters/history/trends.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAEV,YAAY,EACb,yCAAyC;AAC1C,OAAO,KAAK,EAAE,gBAAgB,EAAE,kBAAkB;AAuClD;;GAEG;AACH,qBAAa,sBAAuB,YAAW,gBAAgB,CAAC,YAAY,CAAC;IAC3E;;OAEG;IACH,WAAW,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM;IAwMvC;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM;CAkBvC"}
@@ -0,0 +1,190 @@
1
+ /**
2
+ * Trends Formatter
3
+ *
4
+ * Formats performance trend analysis with visualizations in human and JSON
5
+ * formats.
6
+ */
7
+ import { stripVTControlCharacters } from 'node:util';
8
+ import { colorize } from "../../utils/ansi.js";
9
+ import { generateBarChart, generateSparkline } from "./visualization.js";
10
+ /**
11
+ * Nanoseconds per millisecond conversion constant
12
+ */
13
+ const NS_PER_MS = 1_000_000;
14
+ /**
15
+ * Nanoseconds per microsecond conversion constant
16
+ */
17
+ const NS_PER_US = 1_000;
18
+ /**
19
+ * Intelligently format a time range with appropriate precision Displays
20
+ * microseconds for small values (< 1ms) for better clarity
21
+ */
22
+ const formatTimeRange = (minNs, maxNs) => {
23
+ // If both values are below 1ms, show in microseconds for better precision
24
+ if (maxNs < NS_PER_MS) {
25
+ const minUs = minNs / NS_PER_US;
26
+ const maxUs = maxNs / NS_PER_US;
27
+ return `${minUs.toFixed(2)}-${maxUs.toFixed(2)}µs`;
28
+ }
29
+ // Otherwise show in milliseconds
30
+ const minMs = minNs / NS_PER_MS;
31
+ const maxMs = maxNs / NS_PER_MS;
32
+ return `${minMs.toFixed(3)}-${maxMs.toFixed(3)}ms`;
33
+ };
34
+ /**
35
+ * Calculate visible string length, stripping ANSI escape codes
36
+ */
37
+ const getVisualLength = (str) => stripVTControlCharacters(str).length;
38
+ /**
39
+ * Formatter for history trends command
40
+ */
41
+ export class HistoryTrendsFormatter {
42
+ /**
43
+ * Format as human-readable trends with visualizations
44
+ */
45
+ formatHuman(data) {
46
+ const lines = [];
47
+ lines.push(colorize('brightMagenta', colorize('bold', `\nPerformance Trends (${data.runs} runs)`)));
48
+ if (data.timespan.start && data.timespan.end) {
49
+ lines.push(colorize('dim', `Time range: ${data.timespan.start.toLocaleDateString()} to ${data.timespan.end.toLocaleDateString()}`));
50
+ }
51
+ lines.push('');
52
+ // Summary statistics
53
+ lines.push(colorize('brightBlue', 'Summary:'));
54
+ lines.push(` ${colorize('brightCyan', '▲')} ${data.summary.improvingTasks} improving ${colorize('brightRed', '▼')} ${data.summary.degradingTasks} degrading ${colorize('dim', '→')} ${data.summary.stableTasks} stable`);
55
+ lines.push('');
56
+ // Task Performance Summary Table
57
+ lines.push(colorize('brightMagenta', 'Task Performance Summary:'));
58
+ lines.push('');
59
+ for (const trendData of data.trends) {
60
+ // Show top 20
61
+ const trendIcon = trendData.trend === 'improving'
62
+ ? colorize('brightCyan', '▲')
63
+ : trendData.trend === 'degrading'
64
+ ? colorize('brightRed', '▼')
65
+ : colorize('dim', '→');
66
+ const changeColor = trendData.percentChange < -5
67
+ ? 'brightCyan'
68
+ : trendData.percentChange > 5
69
+ ? 'brightRed'
70
+ : 'dim';
71
+ const changeSign = trendData.percentChange >= 0 ? '+' : '';
72
+ const changeStr = `${changeSign}${trendData.percentChange.toFixed(1)}%`;
73
+ // Generate sparkline - scale with number of data points (min 12, max 20)
74
+ const values = trendData.dataPoints.map((dp) => dp.mean);
75
+ const sparklineWidth = Math.min(20, Math.max(12, trendData.runs));
76
+ const sparkline = generateSparkline(values, sparklineWidth);
77
+ const sparklineColor = trendData.trend === 'improving'
78
+ ? 'brightCyan'
79
+ : trendData.trend === 'degrading'
80
+ ? 'brightRed'
81
+ : 'cyan';
82
+ const taskName = colorize('white', trendData.task);
83
+ const percentDisplay = colorize(changeColor, changeStr.padStart(8));
84
+ const sparklineDisplay = colorize(sparklineColor, sparkline);
85
+ // Layout: icon (2) + task name + padding + percent (8) + spaces (2) + sparkline
86
+ // Position percent+graph at visual column 60 for consistent alignment
87
+ const prefix = ` ${trendIcon} ${taskName}`;
88
+ const prefixVisualLength = getVisualLength(prefix);
89
+ const targetColumn = 60;
90
+ if (prefixVisualLength > targetColumn) {
91
+ // Task name is too long, wrap to next line
92
+ lines.push(prefix);
93
+ lines.push(`${' '.repeat(targetColumn)}${percentDisplay} ${sparklineDisplay}`);
94
+ }
95
+ else {
96
+ // Fit on one line with padding
97
+ const padding = Math.max(1, targetColumn - prefixVisualLength);
98
+ const paddingStr = ' '.repeat(padding);
99
+ lines.push(`${prefix}${paddingStr}${percentDisplay} ${sparklineDisplay}`);
100
+ }
101
+ }
102
+ // Show all trends (no limit)
103
+ lines.push('');
104
+ // Show regressions if any
105
+ if (data.regressions.length > 0) {
106
+ lines.push(colorize('brightRed', colorize('bold', 'Regressions Detected:')));
107
+ lines.push('');
108
+ for (const regression of data.regressions) {
109
+ lines.push(` ${colorize('brightRed', '▼')} ${colorize('white', regression.task)}: ${colorize('brightRed', `${regression.percentChange.toFixed(1)}% slower`)} (${regression.runs} runs)`);
110
+ }
111
+ lines.push('');
112
+ }
113
+ // Show low-confidence regressions (insufficient data)
114
+ if (data.lowConfidenceRegressions.length > 0) {
115
+ lines.push(colorize('brightYellow', colorize('bold', '! Potential Regressions (insufficient data):')));
116
+ lines.push('');
117
+ for (const regression of data.lowConfidenceRegressions) {
118
+ lines.push(` ${colorize('brightYellow', '!')} ${colorize('white', regression.task)}: ${colorize('brightYellow', `${regression.percentChange.toFixed(1)}% slower`)} (${regression.runs} run${regression.runs !== 1 ? 's' : ''})`);
119
+ }
120
+ lines.push('');
121
+ }
122
+ // Show performance distribution for most important task (highest RME) if we have enough data
123
+ // Find task with highest relative margin of error - the most variable/unreliable one
124
+ const mostImportantTrend = data.trends
125
+ .filter((t) => t.runs >= 5)
126
+ .sort((a, b) => {
127
+ const rmeA = (a.statistics.stdDeviation / a.statistics.mean) * 100;
128
+ const rmeB = (b.statistics.stdDeviation / b.statistics.mean) * 100;
129
+ return rmeB - rmeA; // Descending order (highest RME first)
130
+ })[0];
131
+ if (mostImportantTrend) {
132
+ lines.push(colorize('brightMagenta', 'Performance Distribution (most variable task):'));
133
+ lines.push(colorize('white', mostImportantTrend.task));
134
+ const cv = ((mostImportantTrend.statistics.stdDeviation /
135
+ mostImportantTrend.statistics.mean) *
136
+ 100).toFixed(1);
137
+ lines.push(colorize('dim', ` Variability: ${cv}%`));
138
+ lines.push('');
139
+ // Create distribution buckets
140
+ const values = mostImportantTrend.dataPoints.map((dp) => dp.mean);
141
+ const min = Math.min(...values);
142
+ const max = Math.max(...values);
143
+ const range = max - min;
144
+ const numBuckets = Math.min(5, mostImportantTrend.runs);
145
+ const bucketSize = range / numBuckets;
146
+ const buckets = [];
147
+ for (let i = 0; i < numBuckets; i++) {
148
+ const bucketMin = min + i * bucketSize;
149
+ const bucketMax = min + (i + 1) * bucketSize;
150
+ const count = values.filter((v) => v >= bucketMin &&
151
+ (i === numBuckets - 1 ? v <= bucketMax : v < bucketMax)).length;
152
+ const label = formatTimeRange(bucketMin, bucketMax);
153
+ buckets.push({
154
+ count,
155
+ label,
156
+ max: bucketMax,
157
+ min: bucketMin,
158
+ });
159
+ }
160
+ // Filter out empty buckets for cleaner display
161
+ const nonEmptyBuckets = buckets.filter((b) => b.count > 0);
162
+ const chart = generateBarChart(nonEmptyBuckets, 25);
163
+ for (const line of chart) {
164
+ lines.push(colorize('brightCyan', line));
165
+ }
166
+ lines.push('');
167
+ lines.push(colorize('dim', ` Mean: ${(mostImportantTrend.statistics.mean / NS_PER_MS).toFixed(3)}ms Median: ${(mostImportantTrend.statistics.median / NS_PER_MS).toFixed(3)}ms StdDev: ${(mostImportantTrend.statistics.stdDeviation / NS_PER_MS).toFixed(3)}ms`));
168
+ lines.push('');
169
+ }
170
+ return lines.join('\n');
171
+ }
172
+ /**
173
+ * Format as JSON
174
+ */
175
+ formatJson(data) {
176
+ return JSON.stringify({
177
+ regressions: data.regressions,
178
+ summary: {
179
+ degradingTasks: data.summary.degradingTasks,
180
+ improvingTasks: data.summary.improvingTasks,
181
+ runs: data.runs,
182
+ stableTasks: data.summary.stableTasks,
183
+ timespan: data.timespan,
184
+ totalTasks: data.summary.totalTasks,
185
+ },
186
+ trends: data.trends,
187
+ }, null, 2);
188
+ }
189
+ }
190
+ //# sourceMappingURL=trends.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trends.js","sourceRoot":"","sources":["../../../src/formatters/history/trends.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,wBAAwB,EAAE,MAAM,WAAW,CAAC;AAQrD,OAAO,EAAE,QAAQ,EAAE,4BAA4B;AAC/C,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,2BAA2B;AAEzE;;GAEG;AACH,MAAM,SAAS,GAAG,SAAS,CAAC;AAE5B;;GAEG;AACH,MAAM,SAAS,GAAG,KAAK,CAAC;AAExB;;;GAGG;AACH,MAAM,eAAe,GAAG,CAAC,KAAa,EAAE,KAAa,EAAU,EAAE;IAC/D,0EAA0E;IAC1E,IAAI,KAAK,GAAG,SAAS,EAAE,CAAC;QACtB,MAAM,KAAK,GAAG,KAAK,GAAG,SAAS,CAAC;QAChC,MAAM,KAAK,GAAG,KAAK,GAAG,SAAS,CAAC;QAChC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;IACrD,CAAC;IAED,iCAAiC;IACjC,MAAM,KAAK,GAAG,KAAK,GAAG,SAAS,CAAC;IAChC,MAAM,KAAK,GAAG,KAAK,GAAG,SAAS,CAAC;IAChC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;AACrD,CAAC,CAAC;AAEF;;GAEG;AACH,MAAM,eAAe,GAAG,CAAC,GAAW,EAAU,EAAE,CAC9C,wBAAwB,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC;AAEvC;;GAEG;AACH,MAAM,OAAO,sBAAsB;IACjC;;OAEG;IACH,WAAW,CAAC,IAAkB;QAC5B,MAAM,KAAK,GAAa,EAAE,CAAC;QAE3B,KAAK,CAAC,IAAI,CACR,QAAQ,CACN,eAAe,EACf,QAAQ,CAAC,MAAM,EAAE,yBAAyB,IAAI,CAAC,IAAI,QAAQ,CAAC,CAC7D,CACF,CAAC;QAEF,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC;YAC7C,KAAK,CAAC,IAAI,CACR,QAAQ,CACN,KAAK,EACL,eAAe,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,kBAAkB,EAAE,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,kBAAkB,EAAE,EAAE,CACvG,CACF,CAAC;QACJ,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAEf,qBAAqB;QACrB,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC,CAAC;QAC/C,KAAK,CAAC,IAAI,CACR,KAAK,QAAQ,CAAC,YAAY,EAAE,GAAG,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,cAAc,eAAe,QAAQ,CAAC,WAAW,EAAE,GAAG,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,cAAc,eAAe,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,WAAW,SAAS,CAChN,CAAC;QACF,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAEf,iCAAiC;QACjC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,eAAe,EAAE,2BAA2B,CAAC,CAAC,CAAC;QACnE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAEf,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YACpC,cAAc;YACd,MAAM,SAAS,GACb,SAAS,CAAC,KAAK,KAAK,WAAW;gBAC7B,CAAC,CAAC,QAAQ,CAAC,YAAY,EAAE,GAAG,CAAC;gBAC7B,CAAC,CAAC,SAAS,CAAC,KAAK,KAAK,WAAW;oBAC/B,CAAC,CAAC,QAAQ,CAAC,WAAW,EAAE,GAAG,CAAC;oBAC5B,CAAC,CAAC,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;YAE7B,MAAM,WAAW,GACf,SAAS,CAAC,aAAa,GAAG,CAAC,CAAC;gBAC1B,CAAC,CAAC,YAAY;gBACd,CAAC,CAAC,SAAS,CAAC,aAAa,GAAG,CAAC;oBAC3B,CAAC,CAAC,WAAW;oBACb,CAAC,CAAC,KAAK,CAAC;YAEd,MAAM,UAAU,GAAG,SAAS,CAAC,aAAa,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3D,MAAM,SAAS,GAAG,GAAG,UAAU,GAAG,SAAS,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;YAExE,yEAAyE;YACzE,MAAM,MAAM,GAAG,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;YACzD,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;YAClE,MAAM,SAAS,GAAG,iBAAiB,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;YAC5D,MAAM,cAAc,GAClB,SAAS,CAAC,KAAK,KAAK,WAAW;gBAC7B,CAAC,CAAC,YAAY;gBACd,CAAC,CAAC,SAAS,CAAC,KAAK,KAAK,WAAW;oBAC/B,CAAC,CAAC,WAAW;oBACb,CAAC,CAAC,MAAM,CAAC;YAEf,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;YACnD,MAAM,cAAc,GAAG,QAAQ,CAAC,WAAW,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;YACpE,MAAM,gBAAgB,GAAG,QAAQ,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC;YAE7D,gFAAgF;YAChF,sEAAsE;YACtE,MAAM,MAAM,GAAG,KAAK,SAAS,IAAI,QAAQ,EAAE,CAAC;YAC5C,MAAM,kBAAkB,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;YACnD,MAAM,YAAY,GAAG,EAAE,CAAC;YAExB,IAAI,kBAAkB,GAAG,YAAY,EAAE,CAAC;gBACtC,2CAA2C;gBAC3C,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBACnB,KAAK,CAAC,IAAI,CACR,GAAG,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,cAAc,KAAK,gBAAgB,EAAE,CACpE,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACN,+BAA+B;gBAC/B,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,YAAY,GAAG,kBAAkB,CAAC,CAAC;gBAC/D,MAAM,UAAU,GAAG,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;gBACvC,KAAK,CAAC,IAAI,CACR,GAAG,MAAM,GAAG,UAAU,GAAG,cAAc,KAAK,gBAAgB,EAAE,CAC/D,CAAC;YACJ,CAAC;QACH,CAAC;QAED,6BAA6B;QAE7B,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAEf,0BAA0B;QAC1B,IAAI,IAAI,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAChC,KAAK,CAAC,IAAI,CACR,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC,MAAM,EAAE,uBAAuB,CAAC,CAAC,CACjE,CAAC;YACF,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAEf,KAAK,MAAM,UAAU,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;gBAC1C,KAAK,CAAC,IAAI,CACR,KAAK,QAAQ,CAAC,WAAW,EAAE,GAAG,CAAC,IAAI,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC,IAAI,CAAC,KAAK,QAAQ,CAAC,WAAW,EAAE,GAAG,UAAU,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,UAAU,CAAC,IAAI,QAAQ,CAC9K,CAAC;YACJ,CAAC;YAED,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACjB,CAAC;QAED,sDAAsD;QACtD,IAAI,IAAI,CAAC,wBAAwB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7C,KAAK,CAAC,IAAI,CACR,QAAQ,CACN,cAAc,EACd,QAAQ,CAAC,MAAM,EAAE,8CAA8C,CAAC,CACjE,CACF,CAAC;YACF,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAEf,KAAK,MAAM,UAAU,IAAI,IAAI,CAAC,wBAAwB,EAAE,CAAC;gBACvD,KAAK,CAAC,IAAI,CACR,KAAK,QAAQ,CAAC,cAAc,EAAE,GAAG,CAAC,IAAI,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC,IAAI,CAAC,KAAK,QAAQ,CAAC,cAAc,EAAE,GAAG,UAAU,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,UAAU,CAAC,IAAI,OAAO,UAAU,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,CACtN,CAAC;YACJ,CAAC;YAED,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACjB,CAAC;QAED,6FAA6F;QAC7F,qFAAqF;QACrF,MAAM,kBAAkB,GAAG,IAAI,CAAC,MAAM;aACnC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC;aAC1B,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YACb,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,YAAY,GAAG,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC;YACnE,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,YAAY,GAAG,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC;YACnE,OAAO,IAAI,GAAG,IAAI,CAAC,CAAC,uCAAuC;QAC7D,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAER,IAAI,kBAAkB,EAAE,CAAC;YACvB,KAAK,CAAC,IAAI,CACR,QAAQ,CACN,eAAe,EACf,gDAAgD,CACjD,CACF,CAAC;YACF,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC;YACvD,MAAM,EAAE,GAAG,CACT,CAAC,kBAAkB,CAAC,UAAU,CAAC,YAAY;gBACzC,kBAAkB,CAAC,UAAU,CAAC,IAAI,CAAC;gBACrC,GAAG,CACJ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YACb,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,kBAAkB,EAAE,GAAG,CAAC,CAAC,CAAC;YACrD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAEf,8BAA8B;YAC9B,MAAM,MAAM,GAAG,kBAAkB,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;YAClE,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC;YAChC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC;YAChC,MAAM,KAAK,GAAG,GAAG,GAAG,GAAG,CAAC;YACxB,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,kBAAkB,CAAC,IAAI,CAAC,CAAC;YACxD,MAAM,UAAU,GAAG,KAAK,GAAG,UAAU,CAAC;YAEtC,MAAM,OAAO,GAAyB,EAAE,CAAC;YACzC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,EAAE,CAAC,EAAE,EAAE,CAAC;gBACpC,MAAM,SAAS,GAAG,GAAG,GAAG,CAAC,GAAG,UAAU,CAAC;gBACvC,MAAM,SAAS,GAAG,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,UAAU,CAAC;gBAC7C,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CACzB,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,IAAI,SAAS;oBACd,CAAC,CAAC,KAAK,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAC1D,CAAC,MAAM,CAAC;gBAET,MAAM,KAAK,GAAG,eAAe,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;gBAEpD,OAAO,CAAC,IAAI,CAAC;oBACX,KAAK;oBACL,KAAK;oBACL,GAAG,EAAE,SAAS;oBACd,GAAG,EAAE,SAAS;iBACf,CAAC,CAAC;YACL,CAAC;YAED,+CAA+C;YAC/C,MAAM,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;YAC3D,MAAM,KAAK,GAAG,gBAAgB,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC;YACpD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC,CAAC;YAC3C,CAAC;YAED,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACf,KAAK,CAAC,IAAI,CACR,QAAQ,CACN,KAAK,EACL,WAAW,CAAC,kBAAkB,CAAC,UAAU,CAAC,IAAI,GAAG,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC,kBAAkB,CAAC,UAAU,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC,kBAAkB,CAAC,UAAU,CAAC,YAAY,GAAG,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CACzO,CACF,CAAC;YACF,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACjB,CAAC;QAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED;;OAEG;IACH,UAAU,CAAC,IAAkB;QAC3B,OAAO,IAAI,CAAC,SAAS,CACnB;YACE,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,OAAO,EAAE;gBACP,cAAc,EAAE,IAAI,CAAC,OAAO,CAAC,cAAc;gBAC3C,cAAc,EAAE,IAAI,CAAC,OAAO,CAAC,cAAc;gBAC3C,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,WAAW,EAAE,IAAI,CAAC,OAAO,CAAC,WAAW;gBACrC,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBACvB,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU;aACpC;YACD,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB,EACD,IAAI,EACJ,CAAC,CACF,CAAC;IACJ,CAAC;CACF"}