geotechcli 0.4.0 → 0.4.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.
- package/dist/commands/ai.d.ts.map +1 -1
- package/dist/commands/ai.js +281 -50
- package/dist/commands/ai.js.map +1 -1
- package/dist/commands/settlement.d.ts.map +1 -1
- package/dist/commands/settlement.js +4 -0
- package/dist/commands/settlement.js.map +1 -1
- package/dist/commands/viz.d.ts +3 -0
- package/dist/commands/viz.d.ts.map +1 -0
- package/dist/commands/viz.js +131 -0
- package/dist/commands/viz.js.map +1 -0
- package/dist/index.js +8 -2
- package/dist/index.js.map +1 -1
- package/dist/ui/terminal.d.ts +0 -1
- package/dist/ui/terminal.d.ts.map +1 -1
- package/dist/ui/terminal.js +36 -70
- package/dist/ui/terminal.js.map +1 -1
- package/dist/util/vision-output.d.ts +5 -0
- package/dist/util/vision-output.d.ts.map +1 -1
- package/dist/util/vision-output.js +25 -0
- package/dist/util/vision-output.js.map +1 -1
- package/dist/util/viz.d.ts +31 -0
- package/dist/util/viz.d.ts.map +1 -0
- package/dist/util/viz.js +320 -0
- package/dist/util/viz.js.map +1 -0
- package/package.json +7 -5
package/dist/ui/terminal.js
CHANGED
|
@@ -1,94 +1,70 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import * as asciichart from 'asciichart';
|
|
3
3
|
import { GEOTECHCLI_VERSION } from '@geotechcli/core';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
function stripAnsi(value) {
|
|
5
|
+
return value.replace(/\x1b\[[0-9;]*m/g, '');
|
|
6
|
+
}
|
|
7
|
+
function pad(value, width) {
|
|
8
|
+
const visible = stripAnsi(value).length;
|
|
9
|
+
return `${value}${' '.repeat(Math.max(0, width - visible))}`;
|
|
10
|
+
}
|
|
7
11
|
export function banner() {
|
|
8
|
-
const c = chalk.bold.cyan;
|
|
9
|
-
const w = chalk.bold.white;
|
|
10
|
-
const g = chalk.gray;
|
|
11
|
-
console.log('');
|
|
12
|
-
console.log(c(' ██████╗ ███████╗ ██████╗ ████████╗███████╗ ██████╗██╗ ██╗ ██████╗██╗ ██╗'));
|
|
13
|
-
console.log(c(' ██╔════╝ ██╔════╝██╔═══██╗╚══██╔══╝██╔════╝██╔════╝██║ ██║██╔════╝██║ ██║'));
|
|
14
|
-
console.log(w(' ██║ ███╗█████╗ ██║ ██║ ██║ █████╗ ██║ ███████║██║ ██║ ██║'));
|
|
15
|
-
console.log(w(' ██║ ██║██╔══╝ ██║ ██║ ██║ ██╔══╝ ██║ ██╔══██║██║ ██║ ██║'));
|
|
16
|
-
console.log(c(' ╚██████╔╝███████╗╚██████╔╝ ██║ ███████╗╚██████╗██║ ██║╚██████╗███████╗██║'));
|
|
17
|
-
console.log(c(' ╚═════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚══════╝ ╚═════╝╚═╝ ╚═╝ ╚═════╝╚══════╝╚═╝'));
|
|
18
12
|
console.log('');
|
|
19
|
-
console.log(
|
|
20
|
-
|
|
21
|
-
|
|
13
|
+
console.log(chalk.bold.cyan(' ██████╗ ███████╗ ██████╗ ████████╗███████╗ ██████╗██╗ ██╗ ██████╗██╗ ██╗'));
|
|
14
|
+
console.log(chalk.bold.cyan(' ██╔════╝ ██╔════╝██╔═══██╗╚══██╔══╝██╔════╝██╔════╝██║ ██║██╔════╝██║ ██║'));
|
|
15
|
+
console.log(chalk.bold.white(' ██║ ███╗█████╗ ██║ ██║ ██║ █████╗ ██║ ███████║██║ ██║ ██║'));
|
|
16
|
+
console.log(chalk.bold.white(' ██║ ██║██╔══╝ ██║ ██║ ██║ ██╔══╝ ██║ ██╔══██║██║ ██║ ██║'));
|
|
17
|
+
console.log(chalk.bold.cyan(' ╚██████╔╝███████╗╚██████╔╝ ██║ ███████╗╚██████╗██║ ██║╚██████╗███████╗██║'));
|
|
18
|
+
console.log(chalk.bold.cyan(' ╚═════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚══════╝ ╚═════╝╚═╝ ╚═╝ ╚═════╝╚══════╝╚═╝'));
|
|
19
|
+
console.log(chalk.gray(` v${GEOTECHCLI_VERSION} | AI-native geotechnical engineering | https://beta.geotechcli.com`));
|
|
22
20
|
console.log('');
|
|
23
21
|
}
|
|
24
22
|
export function heading(text) {
|
|
25
23
|
console.log('');
|
|
26
24
|
console.log(chalk.bold.white(` ${text}`));
|
|
27
|
-
console.log(chalk.gray(
|
|
25
|
+
console.log(chalk.gray(` ${'-'.repeat(Math.min(text.length + 4, 60))}`));
|
|
28
26
|
}
|
|
29
27
|
export function success(text) {
|
|
30
|
-
console.log(chalk.green(
|
|
28
|
+
console.log(chalk.green(` OK ${text}`));
|
|
31
29
|
}
|
|
32
30
|
export function warn(text) {
|
|
33
|
-
console.log(chalk.yellow(
|
|
31
|
+
console.log(chalk.yellow(` WARN ${text}`));
|
|
34
32
|
}
|
|
35
33
|
export function error(text) {
|
|
36
|
-
console.log(chalk.red(
|
|
34
|
+
console.log(chalk.red(` ERR ${text}`));
|
|
37
35
|
}
|
|
38
36
|
export function info(text) {
|
|
39
|
-
console.log(chalk.blue(
|
|
37
|
+
console.log(chalk.blue(` INFO ${text}`));
|
|
40
38
|
}
|
|
41
39
|
export function dim(text) {
|
|
42
40
|
console.log(chalk.gray(` ${text}`));
|
|
43
41
|
}
|
|
44
42
|
export function keyValue(key, value) {
|
|
45
43
|
console.log(chalk.gray(' ') +
|
|
46
|
-
chalk.white.bold(key
|
|
44
|
+
chalk.white.bold(pad(key, 28)) +
|
|
47
45
|
chalk.cyan(String(value)));
|
|
48
46
|
}
|
|
49
|
-
// ---------------------------------------------------------------------------
|
|
50
|
-
// Tables
|
|
51
|
-
// ---------------------------------------------------------------------------
|
|
52
47
|
export function renderTable(headers, rows) {
|
|
53
|
-
|
|
54
|
-
const
|
|
55
|
-
const
|
|
56
|
-
const
|
|
57
|
-
const
|
|
58
|
-
const
|
|
59
|
-
return
|
|
60
|
-
};
|
|
61
|
-
const colorCell = (s) => {
|
|
62
|
-
if (s === 'SEVERE' || s === 'HIGH')
|
|
63
|
-
return chalk.red.bold(s);
|
|
64
|
-
if (s === 'MODERATE')
|
|
65
|
-
return chalk.yellow(s);
|
|
66
|
-
if (s === 'LOW')
|
|
67
|
-
return chalk.green(s);
|
|
68
|
-
return s;
|
|
69
|
-
};
|
|
70
|
-
const topBorder = chalk.gray(' ┌' + colWidths.map((w) => '─'.repeat(w)).join('┬') + '┐');
|
|
71
|
-
const midBorder = chalk.gray(' ├' + colWidths.map((w) => '─'.repeat(w)).join('┼') + '┤');
|
|
72
|
-
const botBorder = chalk.gray(' └' + colWidths.map((w) => '─'.repeat(w)).join('┴') + '┘');
|
|
73
|
-
const formatRow = (cells, isHeader = false) => {
|
|
74
|
-
const formatted = cells.map((c, i) => {
|
|
75
|
-
const display = isHeader ? chalk.cyan.bold(c) : colorCell(c);
|
|
76
|
-
return pad(display, colWidths[i]);
|
|
77
|
-
});
|
|
78
|
-
return chalk.gray(' │') + formatted.join(chalk.gray('│')) + chalk.gray('│');
|
|
48
|
+
const stringRows = rows.map((row) => row.map((cell) => String(cell)));
|
|
49
|
+
const allRows = [headers, ...stringRows];
|
|
50
|
+
const colWidths = headers.map((_, columnIndex) => Math.max(...allRows.map((row) => stripAnsi(row[columnIndex] ?? '').length)) + 2);
|
|
51
|
+
const makeBorder = (left, mid, right) => chalk.gray(` ${left}${colWidths.map((width) => '-'.repeat(width + 2)).join(mid)}${right}`);
|
|
52
|
+
const formatCell = (value, columnIndex, isHeader = false) => {
|
|
53
|
+
const display = isHeader ? chalk.cyan.bold(value) : value;
|
|
54
|
+
return ` ${pad(display, colWidths[columnIndex])} `;
|
|
79
55
|
};
|
|
56
|
+
const formatRow = (cells, isHeader = false) => chalk.gray(' |') +
|
|
57
|
+
cells.map((cell, index) => formatCell(cell, index, isHeader)).join(chalk.gray('|')) +
|
|
58
|
+
chalk.gray('|');
|
|
80
59
|
console.log('');
|
|
81
|
-
console.log(
|
|
60
|
+
console.log(makeBorder('+', '+', '+'));
|
|
82
61
|
console.log(formatRow(headers, true));
|
|
83
|
-
console.log(
|
|
84
|
-
for (const row of
|
|
85
|
-
console.log(formatRow(row
|
|
62
|
+
console.log(makeBorder('+', '+', '+'));
|
|
63
|
+
for (const row of stringRows) {
|
|
64
|
+
console.log(formatRow(row));
|
|
86
65
|
}
|
|
87
|
-
console.log(
|
|
66
|
+
console.log(makeBorder('+', '+', '+'));
|
|
88
67
|
}
|
|
89
|
-
// ---------------------------------------------------------------------------
|
|
90
|
-
// Charts (ASCII line chart for --plot)
|
|
91
|
-
// ---------------------------------------------------------------------------
|
|
92
68
|
export function renderChart(data, options) {
|
|
93
69
|
const height = options?.height ?? 12;
|
|
94
70
|
console.log('');
|
|
@@ -123,16 +99,10 @@ export function renderMultiChart(series, labels, options) {
|
|
|
123
99
|
format: (x) => x.toFixed(1).padStart(8),
|
|
124
100
|
});
|
|
125
101
|
console.log(chart);
|
|
126
|
-
|
|
127
|
-
const legend = labels
|
|
128
|
-
.map((l, i) => chalk.hex(i === 0 ? '#00ffff' : i === 1 ? '#ffff00' : i === 2 ? '#ff0000' : '#00ff00')(`■ ${l}`))
|
|
129
|
-
.join(' ');
|
|
102
|
+
const legend = labels.map((label, index) => `${index + 1}:${label}`).join(' ');
|
|
130
103
|
console.log(` ${legend}`);
|
|
131
104
|
console.log('');
|
|
132
105
|
}
|
|
133
|
-
// ---------------------------------------------------------------------------
|
|
134
|
-
// Steps (verbose output)
|
|
135
|
-
// ---------------------------------------------------------------------------
|
|
136
106
|
export function renderSteps(steps, verbose) {
|
|
137
107
|
if (!verbose)
|
|
138
108
|
return;
|
|
@@ -142,11 +112,7 @@ export function renderSteps(steps, verbose) {
|
|
|
142
112
|
console.log(chalk.gray(` ${step}`));
|
|
143
113
|
}
|
|
144
114
|
}
|
|
145
|
-
// ---------------------------------------------------------------------------
|
|
146
|
-
// JSON output
|
|
147
|
-
// ---------------------------------------------------------------------------
|
|
148
115
|
export function renderJSON(data) {
|
|
149
|
-
// Security: strip any apiKey/api_key/token fields before output
|
|
150
116
|
const sanitized = JSON.parse(JSON.stringify(data, (key, value) => {
|
|
151
117
|
if (/api.?key|token|secret|password/i.test(key)) {
|
|
152
118
|
if (typeof value === 'boolean' || typeof value === 'number' || value == null) {
|
package/dist/ui/terminal.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"terminal.js","sourceRoot":"","sources":["../../src/ui/terminal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,UAAU,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAEtD,
|
|
1
|
+
{"version":3,"file":"terminal.js","sourceRoot":"","sources":["../../src/ui/terminal.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,6 +10,10 @@ export interface VisionInput {
|
|
|
10
10
|
ext: string;
|
|
11
11
|
kind: VisionFileKind;
|
|
12
12
|
}
|
|
13
|
+
export interface VisionPdfPageInput extends VisionInput {
|
|
14
|
+
pageNumber: number;
|
|
15
|
+
totalPages: number;
|
|
16
|
+
}
|
|
13
17
|
export interface HostedBetaVisionRequestDetails {
|
|
14
18
|
prompt: string;
|
|
15
19
|
systemPrompt: string;
|
|
@@ -21,6 +25,7 @@ export interface HostedBetaVisionRequestDetails {
|
|
|
21
25
|
jsonMode?: boolean;
|
|
22
26
|
}
|
|
23
27
|
export declare function readVisionInput(filePath: string): VisionInput;
|
|
28
|
+
export declare function readVisionPdfPageInputs(filePath: string): Promise<VisionPdfPageInput[]>;
|
|
24
29
|
export declare function estimateHostedBetaVisionBodyBytes(details: HostedBetaVisionRequestDetails): number;
|
|
25
30
|
export declare function resolveStructuredOutputTarget(options: {
|
|
26
31
|
outputPath?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vision-output.d.ts","sourceRoot":"","sources":["../../src/util/vision-output.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"vision-output.d.ts","sourceRoot":"","sources":["../../src/util/vision-output.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,+BAA+B,QAAkB,CAAC;AAE/D,eAAO,MAAM,8BAA8B,QACyB,CAAC;AAWrE,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,KAAK,GAAG,SAAS,CAAC;AACzD,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,CAAC;AAE3D,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,cAAc,CAAC;CACtB;AAED,MAAM,WAAW,kBAAmB,SAAQ,WAAW;IACrD,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,8BAA8B;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,CAa7D;AAED,wBAAsB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC,CA0B7F;AAED,wBAAgB,iCAAiC,CAAC,OAAO,EAAE,8BAA8B,GAAG,MAAM,CA8BjG;AAaD,wBAAgB,6BAA6B,CAAC,OAAO,EAAE;IACrD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;CACzB,GAAG;IACF,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,oBAAoB,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAqDA;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEpD"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { readFileSync } from 'node:fs';
|
|
2
2
|
import { extname } from 'node:path';
|
|
3
|
+
import { PDFDocument } from 'pdf-lib';
|
|
3
4
|
export const HOSTED_BETA_REQUEST_LIMIT_BYTES = 8 * 1024 * 1024;
|
|
4
5
|
const HOSTED_BETA_REQUEST_MARGIN_BYTES = 32 * 1024;
|
|
5
6
|
export const HOSTED_BETA_REQUEST_SAFE_BYTES = HOSTED_BETA_REQUEST_LIMIT_BYTES - HOSTED_BETA_REQUEST_MARGIN_BYTES;
|
|
@@ -24,6 +25,30 @@ export function readVisionInput(filePath) {
|
|
|
24
25
|
kind,
|
|
25
26
|
};
|
|
26
27
|
}
|
|
28
|
+
export async function readVisionPdfPageInputs(filePath) {
|
|
29
|
+
const buffer = readFileSync(filePath);
|
|
30
|
+
const source = await PDFDocument.load(buffer, { ignoreEncryption: true });
|
|
31
|
+
const totalPages = source.getPageCount();
|
|
32
|
+
const pageInputs = [];
|
|
33
|
+
for (let index = 0; index < totalPages; index++) {
|
|
34
|
+
const pageDoc = await PDFDocument.create();
|
|
35
|
+
const [copiedPage] = await pageDoc.copyPages(source, [index]);
|
|
36
|
+
pageDoc.addPage(copiedPage);
|
|
37
|
+
const pageBytes = await pageDoc.save();
|
|
38
|
+
const pageBuffer = Buffer.from(pageBytes);
|
|
39
|
+
pageInputs.push({
|
|
40
|
+
base64: pageBuffer.toString('base64'),
|
|
41
|
+
mimeType: 'application/pdf',
|
|
42
|
+
fileBytes: pageBuffer.length,
|
|
43
|
+
filePath,
|
|
44
|
+
ext: 'pdf',
|
|
45
|
+
kind: 'pdf',
|
|
46
|
+
pageNumber: index + 1,
|
|
47
|
+
totalPages,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
return pageInputs;
|
|
51
|
+
}
|
|
27
52
|
export function estimateHostedBetaVisionBodyBytes(details) {
|
|
28
53
|
const body = {
|
|
29
54
|
messages: [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vision-output.js","sourceRoot":"","sources":["../../src/util/vision-output.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"vision-output.js","sourceRoot":"","sources":["../../src/util/vision-output.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export interface ChartSpec {
|
|
2
|
+
id: string;
|
|
3
|
+
title: string;
|
|
4
|
+
xLabel: string;
|
|
5
|
+
yLabel: string;
|
|
6
|
+
xValues: number[];
|
|
7
|
+
series: number[][];
|
|
8
|
+
labels: string[];
|
|
9
|
+
note?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface VisualizationSource {
|
|
12
|
+
sourceType: 'json' | 'csv' | 'xlsx';
|
|
13
|
+
sourceName: string;
|
|
14
|
+
charts: ChartSpec[];
|
|
15
|
+
}
|
|
16
|
+
interface TableChartOptions {
|
|
17
|
+
sourceName: string;
|
|
18
|
+
titlePrefix?: string;
|
|
19
|
+
xColumn?: string;
|
|
20
|
+
yColumns?: string[];
|
|
21
|
+
}
|
|
22
|
+
type TableRow = Record<string, string | number | boolean | null>;
|
|
23
|
+
export declare function buildChartsFromTable(rows: TableRow[], options: TableChartOptions): ChartSpec[];
|
|
24
|
+
export declare function buildChartsFromJson(data: unknown, sourceName: string): ChartSpec[];
|
|
25
|
+
export declare function loadVisualizationSource(filePath: string, options?: {
|
|
26
|
+
sheetName?: string;
|
|
27
|
+
xColumn?: string;
|
|
28
|
+
yColumns?: string[];
|
|
29
|
+
}): Promise<VisualizationSource>;
|
|
30
|
+
export {};
|
|
31
|
+
//# sourceMappingURL=viz.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"viz.d.ts","sourceRoot":"","sources":["../../src/util/viz.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC;IACnB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,GAAG,KAAK,GAAG,MAAM,CAAC;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,SAAS,EAAE,CAAC;CACrB;AAED,UAAU,iBAAiB;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,KAAK,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC,CAAC;AAmJjE,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,iBAAiB,GAAG,SAAS,EAAE,CA0E9F;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,GAAG,SAAS,EAAE,CAuGlF;AAED,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,GACtE,OAAO,CAAC,mBAAmB,CAAC,CAqD9B"}
|
package/dist/util/viz.js
ADDED
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { basename, extname } from 'node:path';
|
|
3
|
+
import ExcelJS from 'exceljs';
|
|
4
|
+
function isRecord(value) {
|
|
5
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
6
|
+
}
|
|
7
|
+
function slugify(value) {
|
|
8
|
+
return value
|
|
9
|
+
.toLowerCase()
|
|
10
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
11
|
+
.replace(/^-+|-+$/g, '')
|
|
12
|
+
.slice(0, 80);
|
|
13
|
+
}
|
|
14
|
+
function humanizeKey(value) {
|
|
15
|
+
return value
|
|
16
|
+
.replace(/([a-z])([A-Z])/g, '$1 $2')
|
|
17
|
+
.replace(/[_-]+/g, ' ')
|
|
18
|
+
.replace(/\s+/g, ' ')
|
|
19
|
+
.trim()
|
|
20
|
+
.replace(/^./, (match) => match.toUpperCase());
|
|
21
|
+
}
|
|
22
|
+
function toFiniteNumber(value) {
|
|
23
|
+
if (typeof value === 'number' && Number.isFinite(value)) {
|
|
24
|
+
return value;
|
|
25
|
+
}
|
|
26
|
+
if (typeof value === 'string') {
|
|
27
|
+
const normalized = value.trim().replace(/,/g, '');
|
|
28
|
+
if (normalized.length === 0) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
const parsed = Number(normalized);
|
|
32
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
33
|
+
}
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
function parseCsvLine(line) {
|
|
37
|
+
const cells = [];
|
|
38
|
+
let current = '';
|
|
39
|
+
let inQuotes = false;
|
|
40
|
+
for (let index = 0; index < line.length; index += 1) {
|
|
41
|
+
const char = line[index];
|
|
42
|
+
if (char === '"') {
|
|
43
|
+
if (inQuotes && line[index + 1] === '"') {
|
|
44
|
+
current += '"';
|
|
45
|
+
index += 1;
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
inQuotes = !inQuotes;
|
|
49
|
+
}
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
if (char === ',' && !inQuotes) {
|
|
53
|
+
cells.push(current);
|
|
54
|
+
current = '';
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
current += char;
|
|
58
|
+
}
|
|
59
|
+
cells.push(current);
|
|
60
|
+
return cells.map((cell) => cell.trim());
|
|
61
|
+
}
|
|
62
|
+
function rowsFromCsv(content) {
|
|
63
|
+
const lines = content
|
|
64
|
+
.split(/\r?\n/)
|
|
65
|
+
.map((line) => line.trim())
|
|
66
|
+
.filter((line) => line.length > 0);
|
|
67
|
+
if (lines.length < 2) {
|
|
68
|
+
return [];
|
|
69
|
+
}
|
|
70
|
+
const headers = parseCsvLine(lines[0]);
|
|
71
|
+
return lines.slice(1).map((line) => {
|
|
72
|
+
const cells = parseCsvLine(line);
|
|
73
|
+
const row = {};
|
|
74
|
+
for (let index = 0; index < headers.length; index += 1) {
|
|
75
|
+
row[headers[index]] = cells[index] ?? '';
|
|
76
|
+
}
|
|
77
|
+
return row;
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
function rowsFromWorksheet(worksheet) {
|
|
81
|
+
const rows = [];
|
|
82
|
+
let headers = [];
|
|
83
|
+
worksheet.eachRow((row, rowNumber) => {
|
|
84
|
+
const values = Array.isArray(row.values) ? row.values.slice(1) : [];
|
|
85
|
+
if (rowNumber === 1) {
|
|
86
|
+
headers = values.map((value, index) => String(value ?? `Column ${index + 1}`).trim());
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
const record = {};
|
|
90
|
+
headers.forEach((header, index) => {
|
|
91
|
+
const value = values[index];
|
|
92
|
+
if (value instanceof Date) {
|
|
93
|
+
record[header] = value.toISOString();
|
|
94
|
+
}
|
|
95
|
+
else if (typeof value === 'object' && value && 'text' in value) {
|
|
96
|
+
record[header] = String(value.text ?? '');
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
record[header] = (value ?? '');
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
if (Object.values(record).some((value) => String(value ?? '').trim().length > 0)) {
|
|
103
|
+
rows.push(record);
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
return rows;
|
|
107
|
+
}
|
|
108
|
+
function inferNumericColumns(rows) {
|
|
109
|
+
if (rows.length === 0) {
|
|
110
|
+
return [];
|
|
111
|
+
}
|
|
112
|
+
const headers = Object.keys(rows[0]);
|
|
113
|
+
return headers.filter((header) => {
|
|
114
|
+
let numericCount = 0;
|
|
115
|
+
let nonEmptyCount = 0;
|
|
116
|
+
for (const row of rows) {
|
|
117
|
+
const raw = row[header];
|
|
118
|
+
if (raw == null || String(raw).trim() === '') {
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
nonEmptyCount += 1;
|
|
122
|
+
if (toFiniteNumber(raw) !== null) {
|
|
123
|
+
numericCount += 1;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return nonEmptyCount > 0 && numericCount === nonEmptyCount;
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
export function buildChartsFromTable(rows, options) {
|
|
130
|
+
if (rows.length === 0) {
|
|
131
|
+
return [];
|
|
132
|
+
}
|
|
133
|
+
const numericColumns = inferNumericColumns(rows);
|
|
134
|
+
if (numericColumns.length === 0) {
|
|
135
|
+
return [];
|
|
136
|
+
}
|
|
137
|
+
const xColumn = options.xColumn && numericColumns.includes(options.xColumn)
|
|
138
|
+
? options.xColumn
|
|
139
|
+
: numericColumns[0];
|
|
140
|
+
const yColumns = (options.yColumns?.length
|
|
141
|
+
? options.yColumns.filter((column) => numericColumns.includes(column) && column !== xColumn)
|
|
142
|
+
: numericColumns.filter((column) => column !== xColumn));
|
|
143
|
+
if (yColumns.length === 0) {
|
|
144
|
+
return [];
|
|
145
|
+
}
|
|
146
|
+
const normalizedRows = rows
|
|
147
|
+
.map((row, index) => {
|
|
148
|
+
const xValue = xColumn ? toFiniteNumber(row[xColumn]) : index + 1;
|
|
149
|
+
if (xValue === null) {
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
const mapped = { __rowIndex: index + 1 };
|
|
153
|
+
for (const key of Object.keys(row)) {
|
|
154
|
+
mapped[key] = row[key];
|
|
155
|
+
}
|
|
156
|
+
mapped.__x = xValue;
|
|
157
|
+
return mapped;
|
|
158
|
+
})
|
|
159
|
+
.filter((row) => row !== null)
|
|
160
|
+
.sort((left, right) => Number(left.__x) - Number(right.__x));
|
|
161
|
+
const xValues = normalizedRows.map((row) => Number(row.__x));
|
|
162
|
+
const charts = [];
|
|
163
|
+
const titlePrefix = options.titlePrefix ?? options.sourceName;
|
|
164
|
+
const combinedSeries = yColumns
|
|
165
|
+
.slice(0, 4)
|
|
166
|
+
.map((column) => normalizedRows.map((row) => toFiniteNumber(row[column]) ?? 0));
|
|
167
|
+
if (combinedSeries.length > 1) {
|
|
168
|
+
charts.push({
|
|
169
|
+
id: slugify(`${options.sourceName}-${xColumn}-overview`),
|
|
170
|
+
title: `${titlePrefix}: ${yColumns.slice(0, 4).map(humanizeKey).join(', ')} vs ${humanizeKey(xColumn)}`,
|
|
171
|
+
xLabel: humanizeKey(xColumn),
|
|
172
|
+
yLabel: 'Value',
|
|
173
|
+
xValues,
|
|
174
|
+
series: combinedSeries,
|
|
175
|
+
labels: yColumns.slice(0, 4).map(humanizeKey),
|
|
176
|
+
note: `Combined chart from ${normalizedRows.length} samples`,
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
for (const column of yColumns) {
|
|
180
|
+
const series = normalizedRows.map((row) => toFiniteNumber(row[column]) ?? 0);
|
|
181
|
+
charts.push({
|
|
182
|
+
id: slugify(`${options.sourceName}-${xColumn}-${column}`),
|
|
183
|
+
title: `${titlePrefix}: ${humanizeKey(column)} vs ${humanizeKey(xColumn)}`,
|
|
184
|
+
xLabel: humanizeKey(xColumn),
|
|
185
|
+
yLabel: humanizeKey(column),
|
|
186
|
+
xValues,
|
|
187
|
+
series: [series],
|
|
188
|
+
labels: [humanizeKey(column)],
|
|
189
|
+
note: `Samples: ${normalizedRows.length}`,
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
return charts;
|
|
193
|
+
}
|
|
194
|
+
export function buildChartsFromJson(data, sourceName) {
|
|
195
|
+
const charts = [];
|
|
196
|
+
if (!isRecord(data)) {
|
|
197
|
+
if (Array.isArray(data) && data.every((item) => isRecord(item))) {
|
|
198
|
+
return buildChartsFromTable(data, { sourceName });
|
|
199
|
+
}
|
|
200
|
+
return charts;
|
|
201
|
+
}
|
|
202
|
+
if (Array.isArray(data.timeSettlement) && data.timeSettlement.every((item) => isRecord(item))) {
|
|
203
|
+
const transformedRows = data.timeSettlement.map((item) => ({
|
|
204
|
+
timeYears: toFiniteNumber(item.timeYears) ?? 0,
|
|
205
|
+
settlement: toFiniteNumber(item.settlement) ?? 0,
|
|
206
|
+
consolidationPercent: Math.round((toFiniteNumber(item.consolidation) ?? 0) * 1000) / 10,
|
|
207
|
+
}));
|
|
208
|
+
charts.push(...buildChartsFromTable(transformedRows, {
|
|
209
|
+
sourceName: `${sourceName}-time-settlement`,
|
|
210
|
+
titlePrefix: 'Consolidation time curve',
|
|
211
|
+
xColumn: 'timeYears',
|
|
212
|
+
yColumns: ['settlement', 'consolidationPercent'],
|
|
213
|
+
}));
|
|
214
|
+
}
|
|
215
|
+
if (Array.isArray(data.profile) && data.profile.every((item) => isRecord(item))) {
|
|
216
|
+
charts.push(...buildChartsFromTable(data.profile, {
|
|
217
|
+
sourceName: `${sourceName}-profile`,
|
|
218
|
+
titlePrefix: 'Settlement profile',
|
|
219
|
+
xColumn: 'x',
|
|
220
|
+
yColumns: ['settlement'],
|
|
221
|
+
}));
|
|
222
|
+
}
|
|
223
|
+
if (Array.isArray(data.layers) && data.layers.every((item) => isRecord(item))) {
|
|
224
|
+
const layerRows = data.layers;
|
|
225
|
+
const firstLayer = layerRows[0];
|
|
226
|
+
if ('CSR' in firstLayer && 'CRR' in firstLayer && 'factorOfSafety' in firstLayer && 'depth' in firstLayer) {
|
|
227
|
+
charts.push(...buildChartsFromTable(layerRows, {
|
|
228
|
+
sourceName: `${sourceName}-liquefaction`,
|
|
229
|
+
titlePrefix: 'Liquefaction depth plots',
|
|
230
|
+
xColumn: 'depth',
|
|
231
|
+
yColumns: ['factorOfSafety', 'CSR', 'CRR', 'N160cs'],
|
|
232
|
+
}));
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
if (Array.isArray(data.shaftFrictionPerLayer) && data.shaftFrictionPerLayer.every((item) => isRecord(item))) {
|
|
236
|
+
const rows = data.shaftFrictionPerLayer.map((item, index, items) => {
|
|
237
|
+
const cumulative = items
|
|
238
|
+
.slice(0, index + 1)
|
|
239
|
+
.reduce((total, entry) => total + (toFiniteNumber(entry.shaftResistance) ?? 0), 0);
|
|
240
|
+
return {
|
|
241
|
+
depth: toFiniteNumber(item.depth) ?? 0,
|
|
242
|
+
unitShaftFriction: toFiniteNumber(item.unitShaftFriction) ?? 0,
|
|
243
|
+
shaftResistance: toFiniteNumber(item.shaftResistance) ?? 0,
|
|
244
|
+
cumulativeShaftResistance: Math.round(cumulative * 100) / 100,
|
|
245
|
+
};
|
|
246
|
+
});
|
|
247
|
+
charts.push(...buildChartsFromTable(rows, {
|
|
248
|
+
sourceName: `${sourceName}-pile`,
|
|
249
|
+
titlePrefix: 'Pile capacity profile',
|
|
250
|
+
xColumn: 'depth',
|
|
251
|
+
yColumns: ['unitShaftFriction', 'shaftResistance', 'cumulativeShaftResistance'],
|
|
252
|
+
}));
|
|
253
|
+
}
|
|
254
|
+
if (Array.isArray(data.sliceResults) && data.sliceResults.every((item) => isRecord(item))) {
|
|
255
|
+
charts.push(...buildChartsFromTable(data.sliceResults, {
|
|
256
|
+
sourceName: `${sourceName}-slope`,
|
|
257
|
+
titlePrefix: 'Slope slice plots',
|
|
258
|
+
xColumn: 'sliceNumber',
|
|
259
|
+
yColumns: ['shearStrength', 'normalForce', 'weight', 'baseAngle'],
|
|
260
|
+
}));
|
|
261
|
+
}
|
|
262
|
+
if (charts.length > 0) {
|
|
263
|
+
return charts;
|
|
264
|
+
}
|
|
265
|
+
for (const [key, value] of Object.entries(data)) {
|
|
266
|
+
if (Array.isArray(value) && value.every((item) => isRecord(item))) {
|
|
267
|
+
charts.push(...buildChartsFromTable(value, {
|
|
268
|
+
sourceName: `${sourceName}-${key}`,
|
|
269
|
+
titlePrefix: humanizeKey(key),
|
|
270
|
+
}));
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
return charts;
|
|
274
|
+
}
|
|
275
|
+
export async function loadVisualizationSource(filePath, options) {
|
|
276
|
+
const extension = extname(filePath).toLowerCase();
|
|
277
|
+
const sourceName = basename(filePath, extension);
|
|
278
|
+
if (extension === '.json') {
|
|
279
|
+
const parsed = JSON.parse(readFileSync(filePath, 'utf-8'));
|
|
280
|
+
return {
|
|
281
|
+
sourceType: 'json',
|
|
282
|
+
sourceName,
|
|
283
|
+
charts: buildChartsFromJson(parsed, sourceName),
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
if (extension === '.csv') {
|
|
287
|
+
return {
|
|
288
|
+
sourceType: 'csv',
|
|
289
|
+
sourceName,
|
|
290
|
+
charts: buildChartsFromTable(rowsFromCsv(readFileSync(filePath, 'utf-8')), {
|
|
291
|
+
sourceName,
|
|
292
|
+
xColumn: options?.xColumn,
|
|
293
|
+
yColumns: options?.yColumns,
|
|
294
|
+
}),
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
if (extension === '.xlsx') {
|
|
298
|
+
const workbook = new ExcelJS.Workbook();
|
|
299
|
+
await workbook.xlsx.readFile(filePath);
|
|
300
|
+
const worksheets = options?.sheetName
|
|
301
|
+
? workbook.worksheets.filter((sheet) => sheet.name === options.sheetName)
|
|
302
|
+
: workbook.worksheets;
|
|
303
|
+
if (worksheets.length === 0) {
|
|
304
|
+
throw new Error(`Sheet "${options?.sheetName}" not found in ${filePath}.`);
|
|
305
|
+
}
|
|
306
|
+
const charts = worksheets.flatMap((worksheet) => buildChartsFromTable(rowsFromWorksheet(worksheet), {
|
|
307
|
+
sourceName: `${sourceName}-${worksheet.name}`,
|
|
308
|
+
titlePrefix: `${worksheet.name} sheet`,
|
|
309
|
+
xColumn: options?.xColumn,
|
|
310
|
+
yColumns: options?.yColumns,
|
|
311
|
+
}));
|
|
312
|
+
return {
|
|
313
|
+
sourceType: 'xlsx',
|
|
314
|
+
sourceName,
|
|
315
|
+
charts,
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
throw new Error(`Unsupported visualization source: ${filePath}. Use .json, .csv, or .xlsx.`);
|
|
319
|
+
}
|
|
320
|
+
//# sourceMappingURL=viz.js.map
|