import assert from "node:assert/strict"; import { describe, it } from "node:test"; import { calculateDistributionBoardLoads } from "../src/domain/calculations/distribution-board-load-calculation.js"; const board = ( id: string, simultaneityFactor: number, feedingDistributionBoardId: string | null = null, feedingCircuitId: string | null = null ) => ({ id, name: id, boardNumber: id.toUpperCase(), simultaneityFactor, feedingDistributionBoardId, feedingCircuitId, }); describe("distribution-board load calculation", () => { it("rolls recursive demand into the selected feeder circuit exactly once", () => { const result = calculateDistributionBoardLoads({ boards: [ board("nshv", 0.8), board("uv1", 0.5, "nshv", "nshv-out"), board("uv2", 0.25, "uv1", "uv1-out"), ], circuits: [ { id: "nshv-out", distributionBoardId: "nshv", rows: [{ activePowerKw: 2, cosPhi: 1 }] }, { id: "uv1-out", distributionBoardId: "uv1", rows: [{ activePowerKw: 4, cosPhi: 0.8 }] }, { id: "uv2-load", distributionBoardId: "uv2", rows: [{ activePowerKw: 8, cosPhi: 0.8 }] }, ], }); assert.deepEqual(result.boards.get("uv2"), { distributionBoardId: "uv2", activePowerBeforeSimultaneityKw: 8, apparentPowerBeforeSimultaneityKva: 10, demandActivePowerKw: 2, demandApparentPowerKva: 2.5, cosPhi: 0.8, }); assert.equal(result.circuits.get("uv1-out")?.activePowerKw, 6); assert.equal(result.boards.get("uv1")?.demandActivePowerKw, 3); assert.equal(result.circuits.get("nshv-out")?.activePowerKw, 5); assert.equal(result.boards.get("nshv")?.demandActivePowerKw, 4); assert.equal(result.circuits.get("nshv-out")?.downstreamBoards.length, 1); }); it("combines apparent power for multiple child boards on one circuit", () => { const result = calculateDistributionBoardLoads({ boards: [board("main", 1), board("a", 1, "main", "out"), board("b", 1, "main", "out")], circuits: [ { id: "out", distributionBoardId: "main", rows: [] }, { id: "a-load", distributionBoardId: "a", rows: [{ activePowerKw: 2, cosPhi: 0.5 }] }, { id: "b-load", distributionBoardId: "b", rows: [{ activePowerKw: 2, cosPhi: 1 }] }, ], }); const feeder = result.circuits.get("out")!; assert.equal(feeder.activePowerKw, 4); assert.equal(feeder.apparentPowerKva, 6); assert.equal(feeder.cosPhi, 2 / 3); assert.deepEqual(feeder.downstreamBoards.map((entry) => entry.distributionBoardId), ["a", "b"]); }); it("keeps a board-only hierarchy relation out of load rollup", () => { const result = calculateDistributionBoardLoads({ boards: [board("main", 1), board("child", 1, "main", null)], circuits: [ { id: "main-load", distributionBoardId: "main", rows: [{ activePowerKw: 1, cosPhi: 1 }] }, { id: "child-load", distributionBoardId: "child", rows: [{ activePowerKw: 5, cosPhi: 1 }] }, ], }); assert.equal(result.boards.get("main")?.demandActivePowerKw, 1); assert.equal(result.boards.get("child")?.demandActivePowerKw, 5); }); it("rejects cycles defensively", () => { assert.throws( () => calculateDistributionBoardLoads({ boards: [board("a", 1, "b", "b-out"), board("b", 1, "a", "a-out")], circuits: [ { id: "a-out", distributionBoardId: "a", rows: [] }, { id: "b-out", distributionBoardId: "b", rows: [] }, ], }), /cycle/ ); }); });