@chahidy/plannr 0.1.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.
- package/README.md +84 -0
- package/dist/index.cjs +104 -0
- package/dist/index.d.cts +233 -0
- package/dist/index.d.ts +233 -0
- package/dist/index.js +77 -0
- package/main.js +14 -0
- package/package.json +73 -0
- package/src/api/build-plan-numbers.ts +54 -0
- package/src/domain/block-config.ts +84 -0
- package/src/domain/build-plan-numbers.ts +40 -0
- package/src/domain/floor.ts +63 -0
- package/src/domain/plan-number-parts.ts +35 -0
- package/src/domain/plan-number-type.ts +41 -0
- package/src/domain/plan-type.ts +7 -0
- package/src/domain/plan.ts +11 -0
- package/src/domain/trade.ts +18 -0
- package/src/generators/floors.ts +52 -0
- package/src/generators/plan-generator.ts +46 -0
- package/src/generators/plan-number.ts +33 -0
- package/src/index.ts +34 -0
- package/src/package.json +18 -0
- package/src/rules/plan-rule.ts +7 -0
- package/src/standards/default-tga.ts +9 -0
- package/src/standards/office-standard.ts +6 -0
- package/tsconfig.json +10 -0
- package/tsup.config.ts +8 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// src/generators/floors.ts
|
|
2
|
+
function generateFloors(counts, cfg) {
|
|
3
|
+
const floors = [];
|
|
4
|
+
const ugCount = counts?.ug?.count ?? 0;
|
|
5
|
+
const ugPrefix = cfg?.ug?.prefix ?? counts?.ug?.prefix ?? "UG";
|
|
6
|
+
for (let i = ugCount; i >= 1; i--) {
|
|
7
|
+
floors.push(`${ugPrefix}${i}`);
|
|
8
|
+
}
|
|
9
|
+
const egName = cfg?.eg?.prefix ?? "EG";
|
|
10
|
+
floors.push(egName);
|
|
11
|
+
const ogCount = counts?.og?.count ?? 0;
|
|
12
|
+
const ogPrefix = cfg?.og?.prefix ?? counts?.og?.prefix ?? "OG";
|
|
13
|
+
for (let i = 1; i <= ogCount; i++) {
|
|
14
|
+
floors.push(`${ogPrefix}${i}`);
|
|
15
|
+
}
|
|
16
|
+
if (counts?.dg) {
|
|
17
|
+
const dgName = cfg?.dg?.prefix ?? "DG";
|
|
18
|
+
floors.push(dgName);
|
|
19
|
+
}
|
|
20
|
+
return floors;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// src/generators/plan-number.ts
|
|
24
|
+
function buildPlanNumber(plan, projectNumber, separator = "_", suffix, index) {
|
|
25
|
+
const floor = plan.floor ?? "XX";
|
|
26
|
+
const trade = plan.trade ?? "AR";
|
|
27
|
+
const running = String(plan.runningNumber).padStart(3, "0");
|
|
28
|
+
return `${projectNumber}${separator}${trade}${separator}${plan.type}${separator}${floor}${separator}${running}${separator}${suffix}${separator}${index}`;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// src/api/build-plan-numbers.ts
|
|
32
|
+
function buildPlanNumbers(input) {
|
|
33
|
+
let runningNumber = 1;
|
|
34
|
+
const plans = [];
|
|
35
|
+
for (const block of input.blocks) {
|
|
36
|
+
const floors = generateFloors(input.floorcfg);
|
|
37
|
+
for (const trade of block.trades) {
|
|
38
|
+
for (const type of block.planTypes) {
|
|
39
|
+
if (type === "GR") {
|
|
40
|
+
const perFloor = block.plansPerFloor ?? 1;
|
|
41
|
+
for (const floor of floors) {
|
|
42
|
+
for (let i = 0; i < perFloor; i++) {
|
|
43
|
+
plans.push({
|
|
44
|
+
trade,
|
|
45
|
+
type,
|
|
46
|
+
floor,
|
|
47
|
+
runningNumber: runningNumber++
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
} else if (type === "SC") {
|
|
52
|
+
const count = block.minimumPerTrade ?? 1;
|
|
53
|
+
for (let i = 0; i < count; i++) {
|
|
54
|
+
plans.push({
|
|
55
|
+
trade,
|
|
56
|
+
type,
|
|
57
|
+
floor: void 0,
|
|
58
|
+
runningNumber: runningNumber++
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return plans.map(
|
|
66
|
+
(plan) => buildPlanNumber(
|
|
67
|
+
plan,
|
|
68
|
+
input.projectNumber,
|
|
69
|
+
input.separator ?? "-",
|
|
70
|
+
input.suffix ?? "F",
|
|
71
|
+
input.index ?? "A"
|
|
72
|
+
)
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
export {
|
|
76
|
+
buildPlanNumbers
|
|
77
|
+
};
|
package/main.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { buildPlanNumbers } from "./dist/index.cjs";
|
|
2
|
+
|
|
3
|
+
const plans = buildPlanNumbers({
|
|
4
|
+
projectNumber: "21015",
|
|
5
|
+
floorcfg: { ug: {prefix: "KG", count:2} },
|
|
6
|
+
blocks: [
|
|
7
|
+
{
|
|
8
|
+
trades: ["LUE"],
|
|
9
|
+
planTypes: ["GR"],
|
|
10
|
+
},
|
|
11
|
+
],
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
console.log(plans);
|
package/package.json
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@chahidy/plannr",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"author": "Chahid Yahya",
|
|
6
|
+
"main": "dist/index.cjs",
|
|
7
|
+
"module": "dist/index.js",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"require": "./dist/index.cjs",
|
|
13
|
+
"types": "./dist/index.d.ts"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "tsup"
|
|
18
|
+
},
|
|
19
|
+
"description": "automatischen Generierung von Plannummern",
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"acorn": "^8.15.0",
|
|
22
|
+
"any-promise": "^1.3.0",
|
|
23
|
+
"bundle-require": "^5.1.0",
|
|
24
|
+
"cac": "^6.7.14",
|
|
25
|
+
"chokidar": "^4.0.3",
|
|
26
|
+
"commander": "^4.1.1",
|
|
27
|
+
"confbox": "^0.1.8",
|
|
28
|
+
"consola": "^3.4.2",
|
|
29
|
+
"debug": "^4.4.3",
|
|
30
|
+
"esbuild": "^0.27.2",
|
|
31
|
+
"fdir": "^6.5.0",
|
|
32
|
+
"fix-dts-default-cjs-exports": "^1.0.1",
|
|
33
|
+
"joycon": "^3.1.1",
|
|
34
|
+
"lilconfig": "^3.1.3",
|
|
35
|
+
"lines-and-columns": "^1.2.4",
|
|
36
|
+
"load-tsconfig": "^0.2.5",
|
|
37
|
+
"magic-string": "^0.30.21",
|
|
38
|
+
"mlly": "^1.8.0",
|
|
39
|
+
"ms": "^2.1.3",
|
|
40
|
+
"mz": "^2.7.0",
|
|
41
|
+
"object-assign": "^4.1.1",
|
|
42
|
+
"pathe": "^2.0.3",
|
|
43
|
+
"picocolors": "^1.1.1",
|
|
44
|
+
"picomatch": "^4.0.3",
|
|
45
|
+
"pirates": "^4.0.7",
|
|
46
|
+
"pkg-types": "^1.3.1",
|
|
47
|
+
"postcss-load-config": "^6.0.1",
|
|
48
|
+
"readdirp": "^4.1.2",
|
|
49
|
+
"resolve-from": "^5.0.0",
|
|
50
|
+
"rollup": "^4.54.0",
|
|
51
|
+
"source-map": "^0.7.6",
|
|
52
|
+
"sucrase": "^3.35.1",
|
|
53
|
+
"thenify": "^3.3.1",
|
|
54
|
+
"thenify-all": "^1.6.0",
|
|
55
|
+
"tinyexec": "^0.3.2",
|
|
56
|
+
"tinyglobby": "^0.2.15",
|
|
57
|
+
"tree-kill": "^1.2.2",
|
|
58
|
+
"ts-interface-checker": "^0.1.13",
|
|
59
|
+
"tsup": "^8.5.1",
|
|
60
|
+
"typescript": "^5.9.3",
|
|
61
|
+
"ufo": "^1.6.1"
|
|
62
|
+
},
|
|
63
|
+
"devDependencies": {},
|
|
64
|
+
"repository": {
|
|
65
|
+
"type": "git",
|
|
66
|
+
"url": "git+https://github.com/chahidy/plannr.git"
|
|
67
|
+
},
|
|
68
|
+
"license": "ISC",
|
|
69
|
+
"bugs": {
|
|
70
|
+
"url": "https://github.com/chahidy/plannr/issues"
|
|
71
|
+
},
|
|
72
|
+
"homepage": "https://github.com/chahidy/plannr#readme"
|
|
73
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// api/build-plan-numbers.ts
|
|
2
|
+
import { BuildPlanNumbersInput } from "../domain/build-plan-numbers";
|
|
3
|
+
import { Plan } from "../domain/plan";
|
|
4
|
+
import { generateFloors } from "../generators/floors";
|
|
5
|
+
import { buildPlanNumber } from "../generators/plan-number";
|
|
6
|
+
|
|
7
|
+
export function buildPlanNumbers(input: BuildPlanNumbersInput): string[] {
|
|
8
|
+
let runningNumber = 1;
|
|
9
|
+
const plans: Plan[] = [];
|
|
10
|
+
|
|
11
|
+
for (const block of input.blocks) {
|
|
12
|
+
const floors = generateFloors(input.floorcfg);
|
|
13
|
+
|
|
14
|
+
for (const trade of block.trades) {
|
|
15
|
+
for (const type of block.planTypes) {
|
|
16
|
+
if (type === "GR") {
|
|
17
|
+
const perFloor = block.plansPerFloor ?? 1;
|
|
18
|
+
|
|
19
|
+
for (const floor of floors) {
|
|
20
|
+
for (let i = 0; i < perFloor; i++) {
|
|
21
|
+
plans.push({
|
|
22
|
+
trade,
|
|
23
|
+
type,
|
|
24
|
+
floor,
|
|
25
|
+
runningNumber: runningNumber++,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
} else if (type === "SC") {
|
|
30
|
+
const count = block.minimumPerTrade ?? 1;
|
|
31
|
+
|
|
32
|
+
for (let i = 0; i < count; i++) {
|
|
33
|
+
plans.push({
|
|
34
|
+
trade,
|
|
35
|
+
type,
|
|
36
|
+
floor: undefined,
|
|
37
|
+
runningNumber: runningNumber++,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return plans.map((plan) =>
|
|
46
|
+
buildPlanNumber(
|
|
47
|
+
plan,
|
|
48
|
+
input.projectNumber,
|
|
49
|
+
input.separator ?? "-",
|
|
50
|
+
input.suffix ?? "F",
|
|
51
|
+
input.index ?? "A"
|
|
52
|
+
)
|
|
53
|
+
);
|
|
54
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// domain/block-config.ts
|
|
2
|
+
import { Trade } from "./trade";
|
|
3
|
+
import { PlanType } from "./plan-type";
|
|
4
|
+
/**
|
|
5
|
+
* Konfiguriert einen zusammenhängenden Block von Plänen,
|
|
6
|
+
* der in definierter Reihenfolge generiert wird.
|
|
7
|
+
*
|
|
8
|
+
* Die Reihenfolge der Blocks bestimmt die Reihenfolge
|
|
9
|
+
* der erzeugten Plannummern.
|
|
10
|
+
*/
|
|
11
|
+
export interface PlanBlockConfig {
|
|
12
|
+
/**
|
|
13
|
+
* Gewerke, für die dieser Block gilt.
|
|
14
|
+
*
|
|
15
|
+
* Für jedes Gewerk wird die Block-Logik separat angewendet.
|
|
16
|
+
*
|
|
17
|
+
* @example ["LUE", "HEI", "SAN"]
|
|
18
|
+
*/
|
|
19
|
+
trades: Trade[];
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Planarten, die in diesem Block erzeugt werden.
|
|
23
|
+
*
|
|
24
|
+
* - `GR` = Grundriss
|
|
25
|
+
* - `SC` = Schema / Strangschema
|
|
26
|
+
*
|
|
27
|
+
* @example ["GR"]
|
|
28
|
+
*/
|
|
29
|
+
planTypes: PlanType[];
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Gibt an, ob die Pläne geschossbezogen erzeugt werden.
|
|
33
|
+
*
|
|
34
|
+
* - Relevant für Grundrisse (`GR`)
|
|
35
|
+
* - Wird ignoriert bei Schemata (`SC`)
|
|
36
|
+
*
|
|
37
|
+
* @default true bei GR, false bei SC
|
|
38
|
+
*
|
|
39
|
+
* ⚠️ Empfehlung:
|
|
40
|
+
* In der Regel nicht manuell setzen,
|
|
41
|
+
* sondern über `planTypes` steuern.
|
|
42
|
+
*
|
|
43
|
+
* * @deprecated Wird implizit über `plansPerFloor` gesteuert.
|
|
44
|
+
*
|
|
45
|
+
*/
|
|
46
|
+
perFloor?: boolean;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Anzahl der Grundrisspläne pro Geschoss und Gewerk.
|
|
50
|
+
*
|
|
51
|
+
* - Standard: 1
|
|
52
|
+
* - Beispiel: 2 → zwei Grundrisse pro Geschoss
|
|
53
|
+
*
|
|
54
|
+
* Wird **nur angewendet**, wenn `planTypes` `GR` enthält.
|
|
55
|
+
*
|
|
56
|
+
* @example 1
|
|
57
|
+
*/
|
|
58
|
+
plansPerFloor?: number;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Minimale Anzahl von Plänen pro Gewerk.
|
|
62
|
+
*
|
|
63
|
+
* - Standard: 1
|
|
64
|
+
* - Typischer Anwendungsfall: Strangschemata (`SC`)
|
|
65
|
+
*
|
|
66
|
+
* Wird **nur angewendet**, wenn `planTypes` `SC` enthält.
|
|
67
|
+
*
|
|
68
|
+
* @example 3
|
|
69
|
+
*/
|
|
70
|
+
minimumPerTrade?: number;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Optionale Reihenfolge der Geschosse für diesen Block.
|
|
74
|
+
*
|
|
75
|
+
* Ermöglicht z. B.:
|
|
76
|
+
* - erst EG, dann OGs
|
|
77
|
+
* - Sonderreihenfolgen für bestimmte Planarten
|
|
78
|
+
*
|
|
79
|
+
* Enthält nur Geschossnamen, die in `FloorConfig` existieren.
|
|
80
|
+
*
|
|
81
|
+
* @example ["EG", "1OG", "2OG"]
|
|
82
|
+
*/
|
|
83
|
+
floorOrder?: string[];
|
|
84
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { PlanBlockConfig } from "./block-config";
|
|
2
|
+
import { FloorConfig } from "./floor";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Erzeugt Plannummern auf Basis von Blöcken, Geschossen und Projektparametern.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* buildPlanNumbers({
|
|
10
|
+
* projectNumber: "21015",
|
|
11
|
+
* floorcfg: { eg: "EG", ogPrefix: "OG" },
|
|
12
|
+
* blocks: [
|
|
13
|
+
* { trades: ["LUE"], planTypes: ["GR"], plansPerFloor: 1 },
|
|
14
|
+
* { trades: ["HEI"], planTypes: ["SC"], minimumPerTrade: 2 }
|
|
15
|
+
* ]
|
|
16
|
+
* })
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export interface BuildPlanNumbersInput {
|
|
20
|
+
/**
|
|
21
|
+
* Vereinfachte Angabe:
|
|
22
|
+
* Gesamtanzahl Geschosse (inkl. EG).
|
|
23
|
+
*
|
|
24
|
+
* ⚠️ Wird ignoriert, wenn `floorCounts` gesetzt ist.
|
|
25
|
+
*/
|
|
26
|
+
floors?: number;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Erweiterte Geschossdefinition.
|
|
30
|
+
*
|
|
31
|
+
* Überschreibt die automatische Geschossermittlung.
|
|
32
|
+
*/
|
|
33
|
+
floorCounts?: FloorConfig;
|
|
34
|
+
floorcfg?: FloorConfig;
|
|
35
|
+
blocks: PlanBlockConfig[];
|
|
36
|
+
projectNumber: string;
|
|
37
|
+
separator?: string;
|
|
38
|
+
suffix?: string;
|
|
39
|
+
index?: string;
|
|
40
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Basis-Floors (feste Namen)
|
|
3
|
+
*/
|
|
4
|
+
type BaseFloor = "UG" | "EG" | "1OG" | "2OG" | "3OG" | "DG";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Floor mit optionalem Index/Suffix
|
|
8
|
+
* - z.B. UG1, OG2, EG1, DG1
|
|
9
|
+
*/
|
|
10
|
+
export type Floor<I extends string = `${number}`> =
|
|
11
|
+
| BaseFloor
|
|
12
|
+
| `${BaseFloor}${I}`;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* FloorCode = Array von Floors
|
|
16
|
+
*/
|
|
17
|
+
export type FloorCode = Floor[];
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Konfiguration der Geschossbezeichnungen.
|
|
21
|
+
*
|
|
22
|
+
* Ermöglicht unterschiedliche Bürostandards:
|
|
23
|
+
* - UG vs. -01
|
|
24
|
+
* - OG1 vs. 1OG
|
|
25
|
+
* - optionales Dachgeschoss
|
|
26
|
+
*/
|
|
27
|
+
export interface FloorConfig {
|
|
28
|
+
/**
|
|
29
|
+
* Untergeschoss-Bezeichnung (z. B. "UG" oder "-01").
|
|
30
|
+
*/
|
|
31
|
+
ug?: {
|
|
32
|
+
prefix?: Floor;
|
|
33
|
+
count: number;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Erdgeschoss-Bezeichnung (z. B. "EG").
|
|
38
|
+
*/
|
|
39
|
+
eg?: {
|
|
40
|
+
prefix?: Floor;
|
|
41
|
+
count: number;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Präfix für Obergeschosse.
|
|
46
|
+
*
|
|
47
|
+
* Beispiel:
|
|
48
|
+
* - Prefix: "OG"
|
|
49
|
+
* - Ergebnis: OG1, OG2, OG3, ...
|
|
50
|
+
*/
|
|
51
|
+
og?: {
|
|
52
|
+
prefix?: Floor;
|
|
53
|
+
count: number;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Dachgeschoss-Bezeichnung (z. B. "DG").
|
|
58
|
+
*/
|
|
59
|
+
dg?: {
|
|
60
|
+
prefix?: Floor;
|
|
61
|
+
count: number;
|
|
62
|
+
};
|
|
63
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Floor } from "./floor";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Projektnummer (z. B. "21015")
|
|
5
|
+
*/
|
|
6
|
+
export type ProjectNumber = string;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Geschosskennzeichen (z. B. "EG", "1OG", "UG", "DG")
|
|
10
|
+
*/
|
|
11
|
+
export type FloorCode = Floor[];
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Laufende Plannummer innerhalb eines Projekts
|
|
15
|
+
* (z. B. "001", "002", ...)
|
|
16
|
+
*/
|
|
17
|
+
export type RunningNumber = string;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Planstatus / Freigabestatus
|
|
21
|
+
* (z. B. "F", "A", "P")
|
|
22
|
+
*/
|
|
23
|
+
export type PlanStatus = string;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Index / Revisionskennzeichen
|
|
27
|
+
* (z. B. "a", "b", "c")
|
|
28
|
+
*/
|
|
29
|
+
export type PlanIndex = string;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Trennzeichen zwischen Plannummernblöcken
|
|
33
|
+
* (z. B. "-", "_")
|
|
34
|
+
*/
|
|
35
|
+
export type Separator = string;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { Trade } from "./trade";
|
|
2
|
+
import type { PlanType } from "./plan-type";
|
|
3
|
+
import type {
|
|
4
|
+
ProjectNumber,
|
|
5
|
+
RunningNumber,
|
|
6
|
+
PlanStatus,
|
|
7
|
+
PlanIndex,
|
|
8
|
+
Separator,
|
|
9
|
+
} from "./plan-number-parts";
|
|
10
|
+
import { Floor } from "./floor";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Template Literal Type für eine Plannummer.
|
|
14
|
+
*
|
|
15
|
+
* Aufbau:
|
|
16
|
+
* Projekt → Gewerk → Planart → Geschoss → laufende Nummer → Status → Index
|
|
17
|
+
*/
|
|
18
|
+
export type Plannummer<
|
|
19
|
+
Sep extends Separator,
|
|
20
|
+
PN extends ProjectNumber,
|
|
21
|
+
G extends Trade,
|
|
22
|
+
T extends PlanType,
|
|
23
|
+
F extends Floor,
|
|
24
|
+
N extends RunningNumber,
|
|
25
|
+
S extends PlanStatus,
|
|
26
|
+
I extends PlanIndex
|
|
27
|
+
> = `${PN}${Sep}${G}${Sep}${T}${Sep}${F}${Sep}${N}${Sep}${S}${Sep}${I}`;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Standard-Plannummer, wie sie von der API zurückgegeben wird.
|
|
31
|
+
*/
|
|
32
|
+
export type DefaultPlannummer = Plannummer<
|
|
33
|
+
"-",
|
|
34
|
+
ProjectNumber,
|
|
35
|
+
Trade,
|
|
36
|
+
PlanType,
|
|
37
|
+
Floor,
|
|
38
|
+
RunningNumber,
|
|
39
|
+
PlanStatus,
|
|
40
|
+
PlanIndex
|
|
41
|
+
>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Trade } from "./trade";
|
|
2
|
+
import { PlanType } from "./plan-type";
|
|
3
|
+
import { FloorCode } from "./plan-number-parts";
|
|
4
|
+
import { Floor } from "./floor";
|
|
5
|
+
|
|
6
|
+
export interface Plan {
|
|
7
|
+
trade: Trade;
|
|
8
|
+
type: PlanType;
|
|
9
|
+
floor?: Floor;
|
|
10
|
+
runningNumber: number;
|
|
11
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Technische Gewerke (TGA).
|
|
3
|
+
*
|
|
4
|
+
* LUE - Lüftung
|
|
5
|
+
*
|
|
6
|
+
* HZ - Heizung
|
|
7
|
+
*
|
|
8
|
+
* SAN - Sanitär
|
|
9
|
+
*
|
|
10
|
+
* EL - Elektro
|
|
11
|
+
*
|
|
12
|
+
* TR - Tragwerk
|
|
13
|
+
*
|
|
14
|
+
* AR - Architektur
|
|
15
|
+
*
|
|
16
|
+
* HLS - Heizung/Lüftung/Sanitär
|
|
17
|
+
*/
|
|
18
|
+
export type Trade = "LUE" | "HZ" | "SAN" | "EL" | "TR" | "AR" | "HLS";
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// generators/floors.ts
|
|
2
|
+
import { Floor, FloorConfig } from "../domain/floor";
|
|
3
|
+
import { FloorCode } from "../domain/plan-number-parts";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Generiert alle Geschosse basierend auf FloorConfig und optionaler Zählung.
|
|
7
|
+
* Unterstützt UG, EG, OGs, DG.
|
|
8
|
+
*
|
|
9
|
+
* @param counts - optionale Anzahl und Präfix pro Geschoss
|
|
10
|
+
* @param cfg - FloorConfig mit individuellen Bezeichnungen/Präfixen
|
|
11
|
+
* @returns Floor[] - Liste aller Geschosse
|
|
12
|
+
*/
|
|
13
|
+
export function generateFloors(
|
|
14
|
+
counts?: FloorConfig,
|
|
15
|
+
cfg?: FloorConfig
|
|
16
|
+
): Floor[] {
|
|
17
|
+
const floors: Floor[] = [];
|
|
18
|
+
|
|
19
|
+
// -------------------
|
|
20
|
+
// Untergeschosse (UG)
|
|
21
|
+
// -------------------
|
|
22
|
+
const ugCount = counts?.ug?.count ?? 0;
|
|
23
|
+
const ugPrefix = cfg?.ug?.prefix ?? counts?.ug?.prefix ?? "UG";
|
|
24
|
+
for (let i = ugCount; i >= 1; i--) {
|
|
25
|
+
floors.push(`${ugPrefix}${i}` as Floor<`${number}`>);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// -------------------
|
|
29
|
+
// Erdgeschoss (EG)
|
|
30
|
+
// -------------------
|
|
31
|
+
const egName = cfg?.eg?.prefix ?? "EG";
|
|
32
|
+
floors.push(egName as Floor<`${number}`>);
|
|
33
|
+
|
|
34
|
+
// -------------------
|
|
35
|
+
// Obergeschosse (OG)
|
|
36
|
+
// -------------------
|
|
37
|
+
const ogCount = counts?.og?.count ?? 0;
|
|
38
|
+
const ogPrefix = cfg?.og?.prefix ?? counts?.og?.prefix ?? "OG";
|
|
39
|
+
for (let i = 1; i <= ogCount; i++) {
|
|
40
|
+
floors.push(`${ogPrefix}${i}` as Floor<`${number}`>);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// -------------------
|
|
44
|
+
// Dachgeschoss (DG)
|
|
45
|
+
// -------------------
|
|
46
|
+
if (counts?.dg) {
|
|
47
|
+
const dgName = cfg?.dg?.prefix ?? "DG";
|
|
48
|
+
floors.push(dgName as Floor<`${number}`>);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return floors;
|
|
52
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// src/generators/plan-generator.ts
|
|
2
|
+
import { Trade } from "../domain/trade";
|
|
3
|
+
import { OfficeStandard } from "../standards/office-standard";
|
|
4
|
+
import { Plan } from "../domain/plan";
|
|
5
|
+
|
|
6
|
+
export function generatePlans(
|
|
7
|
+
trades: Trade[],
|
|
8
|
+
floors: string[],
|
|
9
|
+
standard: OfficeStandard
|
|
10
|
+
): Plan[] {
|
|
11
|
+
let runningNumber = 1;
|
|
12
|
+
const plans: Plan[] = [];
|
|
13
|
+
|
|
14
|
+
for (const trade of trades) {
|
|
15
|
+
for (const rule of standard.planRules) {
|
|
16
|
+
if (rule.perFloor) {
|
|
17
|
+
for (const floor of floors) {
|
|
18
|
+
plans.push({
|
|
19
|
+
trade,
|
|
20
|
+
type: rule.type,
|
|
21
|
+
floor,
|
|
22
|
+
runningNumber: runningNumber++,
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
} else {
|
|
26
|
+
// Strangschemata / minimumPerTrade
|
|
27
|
+
const existingCount = plans.filter(
|
|
28
|
+
(p) => p.trade === trade && p.type === rule.type
|
|
29
|
+
).length;
|
|
30
|
+
const needed = rule.minimumPerTrade
|
|
31
|
+
? Math.max(rule.minimumPerTrade - existingCount, 0)
|
|
32
|
+
: 0;
|
|
33
|
+
|
|
34
|
+
for (let i = 0; i < needed; i++) {
|
|
35
|
+
plans.push({
|
|
36
|
+
trade,
|
|
37
|
+
type: rule.type,
|
|
38
|
+
runningNumber: runningNumber++,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return plans;
|
|
46
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// generators/plan-number.ts
|
|
2
|
+
import { Plan } from "../domain/plan";
|
|
3
|
+
import { Trade } from "../domain/trade";
|
|
4
|
+
import { PlanType } from "../domain/plan-type";
|
|
5
|
+
import { Plannummer } from "../domain/plan-number-type";
|
|
6
|
+
|
|
7
|
+
export function buildPlanNumber<
|
|
8
|
+
P extends string,
|
|
9
|
+
Suf extends string = "F",
|
|
10
|
+
I extends string = "A"
|
|
11
|
+
>(
|
|
12
|
+
plan: Plan,
|
|
13
|
+
projectNumber: P,
|
|
14
|
+
separator: string = "_",
|
|
15
|
+
suffix: Suf,
|
|
16
|
+
index: I
|
|
17
|
+
): Plannummer<typeof separator, P, Trade, PlanType, string, string, Suf, I> {
|
|
18
|
+
const floor = plan.floor ?? "XX";
|
|
19
|
+
const trade = plan.trade ?? "AR";
|
|
20
|
+
const running = String(plan.runningNumber).padStart(3, "0");
|
|
21
|
+
|
|
22
|
+
// TypeScript prüft hier den Typ via Template Literal Type
|
|
23
|
+
return `${projectNumber}${separator}${trade}${separator}${plan.type}${separator}${floor}${separator}${running}${separator}${suffix}${separator}${index}` as Plannummer<
|
|
24
|
+
typeof separator,
|
|
25
|
+
P,
|
|
26
|
+
Trade,
|
|
27
|
+
PlanType,
|
|
28
|
+
string,
|
|
29
|
+
string,
|
|
30
|
+
Suf,
|
|
31
|
+
I
|
|
32
|
+
>;
|
|
33
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plannummern-Generator für Bau- und TGA-Projekte.
|
|
3
|
+
*
|
|
4
|
+
* Dieses Paket ermöglicht die strukturierte Erzeugung von
|
|
5
|
+
* Plannummern auf Basis von:
|
|
6
|
+
* - Gewerken (Trades)
|
|
7
|
+
* - Planarten (Grundriss / Schema)
|
|
8
|
+
* - Geschossen
|
|
9
|
+
* - frei konfigurierbaren Bürostandards
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* import { buildPlanNumbers } from "@dein-name/plannummern";
|
|
14
|
+
*
|
|
15
|
+
* const plans = buildPlanNumbers({
|
|
16
|
+
* projectNumber: "21015",
|
|
17
|
+
* floorcfg: { eg: "EG", ogPrefix: "OG" },
|
|
18
|
+
* blocks: [
|
|
19
|
+
* { trades: ["LUE"], planTypes: ["GR"], plansPerFloor: 1 },
|
|
20
|
+
* { trades: ["HEI","SAN"], planTypes: ["SC"], minimumPerTrade: 2 }
|
|
21
|
+
* ]
|
|
22
|
+
* });
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export { buildPlanNumbers } from "./api/build-plan-numbers";
|
|
26
|
+
// zentrale Domänen-Typen
|
|
27
|
+
export type { Trade } from "./domain/trade";
|
|
28
|
+
export type { PlanType } from "./domain/plan-type";
|
|
29
|
+
export type { FloorConfig } from "./domain/floor";
|
|
30
|
+
export type { PlanBlockConfig } from "./domain/block-config";
|
|
31
|
+
|
|
32
|
+
// Template Literal Type
|
|
33
|
+
export type { DefaultPlannummer } from "./domain/plan-number-type";
|
|
34
|
+
export type { BuildPlanNumbersInput } from "./domain/build-plan-numbers";
|