172 lines
4.1 KiB
TypeScript
172 lines
4.1 KiB
TypeScript
import {
|
|
circuitGroupCategoryNumbers,
|
|
type CircuitGroupCategory,
|
|
} from "../../shared/constants/circuit-group.js";
|
|
|
|
export type GroupedEquipmentIdentifierKind =
|
|
| "group_upstream_protection"
|
|
| "group_rcd"
|
|
| "circuit";
|
|
|
|
export interface ParsedGroupedEquipmentIdentifier {
|
|
category: CircuitGroupCategory;
|
|
groupNumber: number;
|
|
kind: GroupedEquipmentIdentifierKind;
|
|
circuitNumber: number | null;
|
|
}
|
|
|
|
const categoryByNumber: Record<string, CircuitGroupCategory> = {
|
|
"1": "lighting",
|
|
"2": "single_phase",
|
|
"3": "three_phase",
|
|
};
|
|
|
|
function requirePositiveInteger(value: number, fieldName: string): void {
|
|
if (!Number.isInteger(value) || value < 1) {
|
|
throw new RangeError(`${fieldName} must be a positive integer`);
|
|
}
|
|
}
|
|
|
|
function getGroupStem(
|
|
category: CircuitGroupCategory,
|
|
functionLetter: "F" | "Q",
|
|
groupNumber: number
|
|
): string {
|
|
requirePositiveInteger(groupNumber, "groupNumber");
|
|
return `-${circuitGroupCategoryNumbers[category]}${functionLetter}${groupNumber}`;
|
|
}
|
|
|
|
export function formatCircuitGroupPrefix(
|
|
category: CircuitGroupCategory,
|
|
groupNumber: number
|
|
) {
|
|
return `${getGroupStem(category, "F", groupNumber)}.`;
|
|
}
|
|
|
|
export function formatGroupUpstreamProtectionIdentifier(
|
|
category: CircuitGroupCategory,
|
|
groupNumber: number
|
|
): string {
|
|
return `${getGroupStem(category, "F", groupNumber)}.0`;
|
|
}
|
|
|
|
export function formatGroupRcdIdentifier(
|
|
category: CircuitGroupCategory,
|
|
groupNumber: number
|
|
): string {
|
|
return `${getGroupStem(category, "Q", groupNumber)}.0`;
|
|
}
|
|
|
|
export function formatGroupedCircuitIdentifier(
|
|
category: CircuitGroupCategory,
|
|
groupNumber: number,
|
|
circuitNumber: number
|
|
): string {
|
|
requirePositiveInteger(circuitNumber, "circuitNumber");
|
|
return `${getGroupStem(category, "F", groupNumber)}.${circuitNumber}`;
|
|
}
|
|
|
|
export function parseGroupedEquipmentIdentifier(
|
|
equipmentIdentifier: string
|
|
): ParsedGroupedEquipmentIdentifier | null {
|
|
const match = /^-(1|2|3)(F|Q)([1-9]\d*)\.(0|[1-9]\d*)$/.exec(
|
|
equipmentIdentifier
|
|
);
|
|
if (!match) {
|
|
return null;
|
|
}
|
|
|
|
const [, categoryNumber, functionLetter, groupNumberValue, suffixValue] =
|
|
match;
|
|
const category = categoryByNumber[categoryNumber];
|
|
const groupNumber = Number(groupNumberValue);
|
|
const suffix = Number(suffixValue);
|
|
|
|
if (functionLetter === "Q") {
|
|
return suffix === 0
|
|
? {
|
|
category,
|
|
groupNumber,
|
|
kind: "group_rcd",
|
|
circuitNumber: null,
|
|
}
|
|
: null;
|
|
}
|
|
|
|
if (suffix === 0) {
|
|
return {
|
|
category,
|
|
groupNumber,
|
|
kind: "group_upstream_protection",
|
|
circuitNumber: null,
|
|
};
|
|
}
|
|
|
|
return {
|
|
category,
|
|
groupNumber,
|
|
kind: "circuit",
|
|
circuitNumber: suffix,
|
|
};
|
|
}
|
|
|
|
export function getNextGroupedCircuitNumber(
|
|
category: CircuitGroupCategory,
|
|
groupNumber: number,
|
|
equipmentIdentifiers: Iterable<string>
|
|
): number {
|
|
requirePositiveInteger(groupNumber, "groupNumber");
|
|
let highestCircuitNumber = 0;
|
|
|
|
for (const equipmentIdentifier of equipmentIdentifiers) {
|
|
const parsed = parseGroupedEquipmentIdentifier(equipmentIdentifier);
|
|
if (
|
|
parsed?.kind === "circuit" &&
|
|
parsed.category === category &&
|
|
parsed.groupNumber === groupNumber &&
|
|
parsed.circuitNumber !== null
|
|
) {
|
|
highestCircuitNumber = Math.max(
|
|
highestCircuitNumber,
|
|
parsed.circuitNumber
|
|
);
|
|
}
|
|
}
|
|
|
|
return highestCircuitNumber + 1;
|
|
}
|
|
|
|
export function getNextGroupedCircuitIdentifier(
|
|
category: CircuitGroupCategory,
|
|
groupNumber: number,
|
|
equipmentIdentifiers: Iterable<string>
|
|
): string {
|
|
return formatGroupedCircuitIdentifier(
|
|
category,
|
|
groupNumber,
|
|
getNextGroupedCircuitNumber(
|
|
category,
|
|
groupNumber,
|
|
equipmentIdentifiers
|
|
)
|
|
);
|
|
}
|
|
|
|
export function getNextCircuitGroupNumber(
|
|
category: CircuitGroupCategory,
|
|
groups: Iterable<{
|
|
category: CircuitGroupCategory;
|
|
groupNumber: number;
|
|
}>
|
|
): number {
|
|
let highestGroupNumber = 0;
|
|
|
|
for (const group of groups) {
|
|
if (group.category === category) {
|
|
requirePositiveInteger(group.groupNumber, "groupNumber");
|
|
highestGroupNumber = Math.max(highestGroupNumber, group.groupNumber);
|
|
}
|
|
}
|
|
|
|
return highestGroupNumber + 1;
|
|
}
|