leistungsbilanz-ts/scripts/verify-revit-reference-xlsx.ts

162 lines
4.8 KiB
TypeScript

import assert from "node:assert/strict";
import { createHash } from "node:crypto";
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
import { dirname, resolve } from "node:path";
import ExcelJS from "exceljs";
import {
createDefaultExternalXlsxTransportConfiguration,
type ExternalXlsxScalar,
} from "../src/external-model/xlsx/external-xlsx-contracts.js";
import {
createExternalXlsxReturn,
parseExternalXlsx,
} from "../src/external-model/xlsx/external-xlsx-transport.js";
async function main() {
const inputPath = resolve(
process.argv[2] ?? "docs/spec/kbp-Stromkreis.xlsx"
);
const outputPath = resolve(
process.argv[3] ?? "data/revit-reference/kbp-Stromkreis-R2-Rueckgabe.xlsx"
);
assert.notEqual(
inputPath,
outputPath,
"Eingabe- und Ausgabedatei müssen verschieden sein."
);
const source = readFileSync(inputPath);
const configuration = createDefaultExternalXlsxTransportConfiguration();
const document = await parseExternalXlsx({
fileName: inputPath,
bytes: source,
configuration,
});
const objectRows = document.rows.filter((row) => row.classification === "object");
const suspectRows = document.rows.filter(
(row) => row.classification === "suspect-object"
);
const worksharingIdColumn = document.columns.find(
(column) => column.header === configuration.columns.worksharingId
)?.columnNumber;
assert.ok(worksharingIdColumn, "Worksharing-ID-Spalte wurde nicht aufgelöst.");
assert.equal(objectRows.length, 487, "Es werden 487 Objektzeilen erwartet.");
assert.equal(suspectRows.length, 0, "Es werden keine verdächtigen Zeilen erwartet.");
assert.equal(
document.columns.filter((column) => column.comment !== null).length,
14,
"Es werden 14 Kopfzeilenkommentare erwartet."
);
assert.equal(
document.issues.filter((issue) => issue.code === "duplicate-ifc-guid").length,
0,
"Die Musterdatei darf keine exakten IfcGUID-Duplikate enthalten."
);
const testValues = [
{
circuitCombined: "UV_R2_TEST-2F1",
electricalPowerW: 111,
voltageV: 230,
currentA: 0.48,
},
{
circuitCombined: "UV_R2_TEST-2F2",
electricalPowerW: 222,
voltageV: 230,
currentA: 0.97,
},
{
circuitCombined: "UV_R2_TEST-3F1",
electricalPowerW: 333,
voltageV: 400,
currentA: 0.48,
},
] satisfies Record<string, ExternalXlsxScalar>[];
const updates = testValues.map((values, index) => {
const value = objectRows[index]?.cells[worksharingIdColumn - 1]?.value;
if (typeof value !== "string") {
throw new Error("Worksharing-ID muss Text sein.");
}
return { worksharingId: value, values };
});
const result = await createExternalXlsxReturn({
fileName: inputPath,
bytes: source,
configuration,
updates,
});
assert.equal(result.exportedObjectCount, 487);
mkdirSync(dirname(outputPath), { recursive: true });
writeFileSync(outputPath, result.bytes);
const outputDocument = await parseExternalXlsx({
fileName: outputPath,
bytes: result.bytes,
configuration,
});
assert.equal(
outputDocument.rows.filter((row) => row.classification === "object").length,
487
);
assert.equal(
outputDocument.rows.some((row) => row.classification !== "object"),
false,
"Die Rückgabedatei darf keine Summen- oder Hinweiszeilen enthalten."
);
assert.equal(outputDocument.sheetName, document.sheetName);
assert.deepEqual(
outputDocument.columns,
document.columns,
"Kopfzeilen, Kommentare und Spaltenbreiten müssen erhalten bleiben."
);
assert.deepEqual(
outputDocument.rows.slice(updates.length).map((row) => row.cells),
objectRows.slice(updates.length).map((row) => row.cells),
"Nicht geänderte Objektzellen müssen Wert, Typ und Zahlenformat behalten."
);
const outputWorkbook = new ExcelJS.Workbook();
await outputWorkbook.xlsx.load(result.bytes as never);
const commentedCells: string[] = [];
outputWorkbook.worksheets[0].eachRow({ includeEmpty: true }, (row) => {
row.eachCell({ includeEmpty: true }, (cell) => {
if (cell.note !== undefined) commentedCells.push(cell.address);
});
});
assert.equal(
commentedCells.length,
14,
"Nur die 14 Kopfzellen dürfen Kommentare enthalten."
);
assert.equal(
commentedCells.every((address) => address.endsWith("1")),
true,
"Datenzellen dürfen keine Kommentare enthalten."
);
process.stdout.write(
`${JSON.stringify(
{
input: inputPath,
output: outputPath,
inputBytes: source.length,
outputBytes: result.bytes.length,
inputSha256: createHash("sha256").update(source).digest("hex"),
outputSha256: createHash("sha256").update(result.bytes).digest("hex"),
sheetName: document.sheetName,
objectCount: objectRows.length,
headerCommentCount: document.columns.filter(
(column) => column.comment !== null
).length,
exactDuplicateIfcGuidCount: 0,
changedObjectCount: updates.length,
},
null,
2
)}\n`
);
}
void main();