Neville Ausgetauscht + PDF

This commit is contained in:
Moritz Utcke
2025-01-13 11:09:20 +07:00
parent d084ed506d
commit 01b701c392
13 changed files with 500 additions and 307 deletions

2
.gitignore vendored
View File

@@ -30,3 +30,5 @@ bun.lockb
public/fonts/ public/fonts/
*.Identifier *.Identifier
src/lib/Berechnungen/BedarfsausweisWohnen/18599-Tabellenverfahren-Wohngebaeude-komplett-ocr.pdf

View File

@@ -39,7 +39,7 @@
"flag-icons": "^6.15.0", "flag-icons": "^6.15.0",
"fontkit": "^2.0.4", "fontkit": "^2.0.4",
"js-cookie": "^3.0.5", "js-cookie": "^3.0.5",
"js-interpolate": "^1.3.1", "js-interpolate": "^1.3.2",
"moment": "^2.30.1", "moment": "^2.30.1",
"moment-timezone": "^0.5.46", "moment-timezone": "^0.5.46",
"pdf-lib": "^1.17.1", "pdf-lib": "^1.17.1",

View File

@@ -1,8 +1,8 @@
<script lang="ts"> <script lang="ts">
import { BedarfsausweisWohnenClient, GebaeudeAufnahmeClient } from "#components/Ausweis/types.js"; import { BedarfsausweisWohnenClient, GebaeudeAufnahmeClient } from "#components/Ausweis/types.js";
import { funktionMonatlicherBelastungsgrad } from "#lib/Berechnungen/BedarfsausweisWohnen/funktionMonatlicherBelastungsgrad"; import { funktionMonatlicherBelastungsgrad } from "#lib/Berechnungen/BedarfsausweisWohnen/funktionMonatlicherBelastungsgrad.js";
import { funktionBilanzInnentemperatur } from "#lib/Berechnungen/BedarfsausweisWohnen/funktionBilanzInnentemperatur"; import { funktionBilanzInnentemperatur } from "#lib/Berechnungen/BedarfsausweisWohnen/funktionBilanzInnentemperatur.js";
import { funktionAusnutzungsgrad } from "#lib/Berechnungen/BedarfsausweisWohnen/funktionAusnutzungsgrad"; import { funktionAusnutzungsgrad } from "#lib/Berechnungen/BedarfsausweisWohnen/funktionAusnutzungsgrad.js";
export let ausweis: BedarfsausweisWohnenClient; export let ausweis: BedarfsausweisWohnenClient;
export let gebaeude_aufnahme: GebaeudeAufnahmeClient; export let gebaeude_aufnahme: GebaeudeAufnahmeClient;
@@ -78,7 +78,7 @@
Dezember: 0 Dezember: 0
}; };
let bilanzinnentemperaturen = { let bilanzInnenTemperaturen = {
Januar: 0, Januar: 0,
Februar: 0, Februar: 0,
März: 0, März: 0,
@@ -120,31 +120,34 @@
belastungsgrade.November = funktionMonatlicherBelastungsgrad(heizlast, zeitkonstante, "November"); belastungsgrade.November = funktionMonatlicherBelastungsgrad(heizlast, zeitkonstante, "November");
belastungsgrade.Dezember = funktionMonatlicherBelastungsgrad(heizlast, zeitkonstante, "Dezember"); belastungsgrade.Dezember = funktionMonatlicherBelastungsgrad(heizlast, zeitkonstante, "Dezember");
bilanzinnentemperaturen.Januar = funktionBilanzInnentemperatur(heizlast, zeitkonstante, "Januar"); bilanzInnenTemperaturen.Januar = funktionBilanzInnentemperatur(heizlast, zeitkonstante, "Januar");
bilanzinnentemperaturen.Februar = funktionBilanzInnentemperatur(heizlast, zeitkonstante, "Februar"); bilanzInnenTemperaturen.Februar = funktionBilanzInnentemperatur(heizlast, zeitkonstante, "Februar");
bilanzinnentemperaturen.März = funktionBilanzInnentemperatur(heizlast, zeitkonstante, "März"); bilanzInnenTemperaturen.März = funktionBilanzInnentemperatur(heizlast, zeitkonstante, "März");
bilanzinnentemperaturen.April = funktionBilanzInnentemperatur(heizlast, zeitkonstante, "April"); bilanzInnenTemperaturen.April = funktionBilanzInnentemperatur(heizlast, zeitkonstante, "April");
bilanzinnentemperaturen.Mai = funktionBilanzInnentemperatur(heizlast, zeitkonstante, "Mai"); bilanzInnenTemperaturen.Mai = funktionBilanzInnentemperatur(heizlast, zeitkonstante, "Mai");
bilanzinnentemperaturen.Juni = funktionBilanzInnentemperatur(heizlast, zeitkonstante, "Juni"); bilanzInnenTemperaturen.Juni = funktionBilanzInnentemperatur(heizlast, zeitkonstante, "Juni");
bilanzinnentemperaturen.Juli = funktionBilanzInnentemperatur(heizlast, zeitkonstante, "Juli"); bilanzInnenTemperaturen.Juli = funktionBilanzInnentemperatur(heizlast, zeitkonstante, "Juli");
bilanzinnentemperaturen.August = funktionBilanzInnentemperatur(heizlast, zeitkonstante, "August"); bilanzInnenTemperaturen.August = funktionBilanzInnentemperatur(heizlast, zeitkonstante, "August");
bilanzinnentemperaturen.September = funktionBilanzInnentemperatur(heizlast, zeitkonstante, "September"); bilanzInnenTemperaturen.September = funktionBilanzInnentemperatur(heizlast, zeitkonstante, "September");
bilanzinnentemperaturen.Oktober = funktionBilanzInnentemperatur(heizlast, zeitkonstante, "Oktober"); bilanzInnenTemperaturen.Oktober = funktionBilanzInnentemperatur(heizlast, zeitkonstante, "Oktober");
bilanzinnentemperaturen.November = funktionBilanzInnentemperatur(heizlast, zeitkonstante, "November"); bilanzInnenTemperaturen.November = funktionBilanzInnentemperatur(heizlast, zeitkonstante, "November");
bilanzinnentemperaturen.Dezember = funktionBilanzInnentemperatur(heizlast, zeitkonstante, "Dezember"); bilanzInnenTemperaturen.Dezember = funktionBilanzInnentemperatur(heizlast, zeitkonstante, "Dezember");
waermeSenken.Januar = maximalerWaermestrom * [bilanzinnentemperaturen.Januar - minimaleAussentemperatur] / [innenTemperatur - minimaleAussentemperatur] * belastungsgrade.Januar; console.log(belastungsgrade.Juli, bilanzInnenTemperaturen.Juli);
waermeSenken.Februar = maximalerWaermestrom * [bilanzinnentemperaturen.Februar - minimaleAussentemperatur] / [innenTemperatur - minimaleAussentemperatur] * belastungsgrade.Februar;
waermeSenken.März = maximalerWaermestrom * [bilanzinnentemperaturen.März - minimaleAussentemperatur] / [innenTemperatur - minimaleAussentemperatur] * belastungsgrade.März;
waermeSenken.April = maximalerWaermestrom * [bilanzinnentemperaturen.April - minimaleAussentemperatur] / [innenTemperatur - minimaleAussentemperatur] * belastungsgrade.April; waermeSenken.Januar = maximalerWaermestrom * (bilanzInnenTemperaturen.Januar - minimaleAussentemperatur) / (innenTemperatur - minimaleAussentemperatur) * belastungsgrade.Januar;
waermeSenken.Mai = maximalerWaermestrom * [bilanzinnentemperaturen.Mai - minimaleAussentemperatur] / [innenTemperatur - minimaleAussentemperatur] * belastungsgrade.Mai; waermeSenken.Februar = maximalerWaermestrom * (bilanzInnenTemperaturen.Februar - minimaleAussentemperatur) / (innenTemperatur - minimaleAussentemperatur) * belastungsgrade.Februar;
waermeSenken.Juni = maximalerWaermestrom * [bilanzinnentemperaturen.Juni - minimaleAussentemperatur] / [innenTemperatur - minimaleAussentemperatur] * belastungsgrade.Juni; waermeSenken.März = maximalerWaermestrom * (bilanzInnenTemperaturen.März - minimaleAussentemperatur) / (innenTemperatur - minimaleAussentemperatur) * belastungsgrade.März;
waermeSenken.Juli = maximalerWaermestrom * [bilanzinnentemperaturen.Juli - minimaleAussentemperatur] / [innenTemperatur - minimaleAussentemperatur] * belastungsgrade.Juli; waermeSenken.April = maximalerWaermestrom * (bilanzInnenTemperaturen.April - minimaleAussentemperatur) / (innenTemperatur - minimaleAussentemperatur) * belastungsgrade.April;
waermeSenken.August = maximalerWaermestrom * [bilanzinnentemperaturen.August - minimaleAussentemperatur] / [innenTemperatur - minimaleAussentemperatur] * belastungsgrade.August; waermeSenken.Mai = maximalerWaermestrom * (bilanzInnenTemperaturen.Mai - minimaleAussentemperatur) / (innenTemperatur - minimaleAussentemperatur) * belastungsgrade.Mai;
waermeSenken.September = maximalerWaermestrom * [bilanzinnentemperaturen.September - minimaleAussentemperatur] / [innenTemperatur - minimaleAussentemperatur] * belastungsgrade.September; waermeSenken.Juni = maximalerWaermestrom * (bilanzInnenTemperaturen.Juni - minimaleAussentemperatur) / (innenTemperatur - minimaleAussentemperatur) * belastungsgrade.Juni;
waermeSenken.Oktober = maximalerWaermestrom * [bilanzinnentemperaturen.Oktober - minimaleAussentemperatur] / [innenTemperatur - minimaleAussentemperatur] * belastungsgrade.Oktober; waermeSenken.Juli = maximalerWaermestrom * (bilanzInnenTemperaturen.Juli - minimaleAussentemperatur) / (innenTemperatur - minimaleAussentemperatur) * belastungsgrade.Juli;
waermeSenken.November = maximalerWaermestrom * [bilanzinnentemperaturen.November - minimaleAussentemperatur] / [innenTemperatur - minimaleAussentemperatur] * belastungsgrade.November; waermeSenken.August = maximalerWaermestrom * (bilanzInnenTemperaturen.August - minimaleAussentemperatur) / (innenTemperatur - minimaleAussentemperatur) * belastungsgrade.August;
waermeSenken.Dezember = maximalerWaermestrom * [bilanzinnentemperaturen.Dezember - minimaleAussentemperatur] / [innenTemperatur - minimaleAussentemperatur] * belastungsgrade.Dezember; waermeSenken.September = maximalerWaermestrom * (bilanzInnenTemperaturen.September - minimaleAussentemperatur) / (innenTemperatur - minimaleAussentemperatur) * belastungsgrade.September;
waermeSenken.Oktober = maximalerWaermestrom * (bilanzInnenTemperaturen.Oktober - minimaleAussentemperatur) / (innenTemperatur - minimaleAussentemperatur) * belastungsgrade.Oktober;
waermeSenken.November = maximalerWaermestrom * (bilanzInnenTemperaturen.November - minimaleAussentemperatur) / (innenTemperatur - minimaleAussentemperatur) * belastungsgrade.November;
waermeSenken.Dezember = maximalerWaermestrom * (bilanzInnenTemperaturen.Dezember - minimaleAussentemperatur) / (innenTemperatur - minimaleAussentemperatur) * belastungsgrade.Dezember;
waermequellensenkenverhaeltnisJanuar = waermeQuellen.Januar / waermeSenken.Januar; waermequellensenkenverhaeltnisJanuar = waermeQuellen.Januar / waermeSenken.Januar;
@@ -160,6 +163,9 @@
waermequellensenkenverhaeltnisNovember = waermeQuellen.November / waermeSenken.November; waermequellensenkenverhaeltnisNovember = waermeQuellen.November / waermeSenken.November;
waermequellensenkenverhaeltnisDezember = waermeQuellen.Dezember / waermeSenken.Dezember; waermequellensenkenverhaeltnisDezember = waermeQuellen.Dezember / waermeSenken.Dezember;
console.log(waermequellensenkenverhaeltnisJuli);
ausnutzungsgradJanuar = funktionAusnutzungsgrad(waermequellensenkenverhaeltnisJanuar, zeitkonstante, "alleMonate"); ausnutzungsgradJanuar = funktionAusnutzungsgrad(waermequellensenkenverhaeltnisJanuar, zeitkonstante, "alleMonate");
ausnutzungsgradFebruar = funktionAusnutzungsgrad(waermequellensenkenverhaeltnisFebruar, zeitkonstante, "alleMonate"); ausnutzungsgradFebruar = funktionAusnutzungsgrad(waermequellensenkenverhaeltnisFebruar, zeitkonstante, "alleMonate");
ausnutzungsgradMärz = funktionAusnutzungsgrad(waermequellensenkenverhaeltnisMärz, zeitkonstante, "alleMonate"); ausnutzungsgradMärz = funktionAusnutzungsgrad(waermequellensenkenverhaeltnisMärz, zeitkonstante, "alleMonate");
@@ -225,7 +231,7 @@
<tbody> <tbody>
<tr> <tr>
<td class="border border-gray-300 px-2 py-1 bg-gray-100">31</td> <td class="border border-gray-300 px-2 py-1 bg-gray-100">31</td>
<td class="border border-gray-300 px-2 py-1 bg-blue-100">{Math.round(bilanzinnentemperaturen.Januar*1000)/1000}</td> <td class="border border-gray-300 px-2 py-1 bg-blue-100">{Math.round(bilanzInnenTemperaturen.Januar*1000)/1000}</td>
<td class="border border-gray-300 px-2 py-1 bg-gray-100">1,0</td> <td class="border border-gray-300 px-2 py-1 bg-gray-100">1,0</td>
<td class="border border-gray-300 px-2 py-1 bg-blue-100">{Math.round(belastungsgrade.Januar*1000)/1000} <td class="border border-gray-300 px-2 py-1 bg-blue-100">{Math.round(belastungsgrade.Januar*1000)/1000}
</td> </td>
@@ -240,7 +246,7 @@
</tr> </tr>
<tr> <tr>
<td class="border border-gray-300 px-2 py-1 bg-gray-100">28</td> <td class="border border-gray-300 px-2 py-1 bg-gray-100">28</td>
<td class="border border-gray-300 px-2 py-1 bg-blue-100">{Math.round(bilanzinnentemperaturen.Februar*1000)/1000}</td> <td class="border border-gray-300 px-2 py-1 bg-blue-100">{Math.round(bilanzInnenTemperaturen.Februar*1000)/1000}</td>
<td class="border border-gray-300 px-2 py-1 bg-gray-100">1,9</td> <td class="border border-gray-300 px-2 py-1 bg-gray-100">1,9</td>
<td class="border border-gray-300 px-2 py-1 bg-blue-100">{Math.round(belastungsgrade.Februar*1000)/1000} <td class="border border-gray-300 px-2 py-1 bg-blue-100">{Math.round(belastungsgrade.Februar*1000)/1000}
@@ -256,7 +262,7 @@
</tr> </tr>
<tr> <tr>
<td class="border border-gray-300 px-2 py-1 bg-gray-100">31</td> <td class="border border-gray-300 px-2 py-1 bg-gray-100">31</td>
<td class="border border-gray-300 px-2 py-1 bg-blue-100">{Math.round(bilanzinnentemperaturen.März*1000)/1000}</td> <td class="border border-gray-300 px-2 py-1 bg-blue-100">{Math.round(bilanzInnenTemperaturen.März*1000)/1000}</td>
<td class="border border-gray-300 px-2 py-1 bg-gray-100">4,7</td> <td class="border border-gray-300 px-2 py-1 bg-gray-100">4,7</td>
<td class="border border-gray-300 px-2 py-1 bg-blue-100">{Math.round(belastungsgrade.März*1000)/1000} <td class="border border-gray-300 px-2 py-1 bg-blue-100">{Math.round(belastungsgrade.März*1000)/1000}
@@ -272,7 +278,7 @@
</tr> </tr>
<tr> <tr>
<td class="border border-gray-300 px-2 py-1 bg-gray-100">30</td> <td class="border border-gray-300 px-2 py-1 bg-gray-100">30</td>
<td class="border border-gray-300 px-2 py-1 bg-blue-100">{Math.round(bilanzinnentemperaturen.April*1000)/1000}</td> <td class="border border-gray-300 px-2 py-1 bg-blue-100">{Math.round(bilanzInnenTemperaturen.April*1000)/1000}</td>
<td class="border border-gray-300 px-2 py-1 bg-gray-100">9,2</td> <td class="border border-gray-300 px-2 py-1 bg-gray-100">9,2</td>
<td class="border border-gray-300 px-2 py-1 bg-blue-100">{Math.round(belastungsgrade.April*1000)/1000} <td class="border border-gray-300 px-2 py-1 bg-blue-100">{Math.round(belastungsgrade.April*1000)/1000}
@@ -288,7 +294,7 @@
</tr> </tr>
<tr> <tr>
<td class="border border-gray-300 px-2 py-1 bg-gray-100">31</td> <td class="border border-gray-300 px-2 py-1 bg-gray-100">31</td>
<td class="border border-gray-300 px-2 py-1 bg-blue-100">{Math.round(bilanzinnentemperaturen.Mai*1000)/1000}</td> <td class="border border-gray-300 px-2 py-1 bg-blue-100">{Math.round(bilanzInnenTemperaturen.Mai*1000)/1000}</td>
<td class="border border-gray-300 px-2 py-1 bg-gray-100">14,1</td> <td class="border border-gray-300 px-2 py-1 bg-gray-100">14,1</td>
<td class="border border-gray-300 px-2 py-1 bg-blue-100">{Math.round(belastungsgrade.Mai*1000)/1000} <td class="border border-gray-300 px-2 py-1 bg-blue-100">{Math.round(belastungsgrade.Mai*1000)/1000}
@@ -304,7 +310,7 @@
</tr> </tr>
<tr> <tr>
<td class="border border-gray-300 px-2 py-1 bg-gray-100">30</td> <td class="border border-gray-300 px-2 py-1 bg-gray-100">30</td>
<td class="border border-gray-300 px-2 py-1 bg-blue-100">{Math.round(bilanzinnentemperaturen.Juni*1000)/1000}</td> <td class="border border-gray-300 px-2 py-1 bg-blue-100">{Math.round(bilanzInnenTemperaturen.Juni*1000)/1000}</td>
<td class="border border-gray-300 px-2 py-1 bg-gray-100">16,7</td> <td class="border border-gray-300 px-2 py-1 bg-gray-100">16,7</td>
<td class="border border-gray-300 px-2 py-1 bg-blue-100">{Math.round(belastungsgrade.Juni*1000)/1000} <td class="border border-gray-300 px-2 py-1 bg-blue-100">{Math.round(belastungsgrade.Juni*1000)/1000}
@@ -320,7 +326,7 @@
</tr> </tr>
<tr> <tr>
<td class="border border-gray-300 px-2 py-1 bg-gray-100">31</td> <td class="border border-gray-300 px-2 py-1 bg-gray-100">31</td>
<td class="border border-gray-300 px-2 py-1 bg-blue-100">{Math.round(bilanzinnentemperaturen.Juli*1000)/1000}</td> <td class="border border-gray-300 px-2 py-1 bg-blue-100">{Math.round(bilanzInnenTemperaturen.Juli*1000)/1000}</td>
<td class="border border-gray-300 px-2 py-1 bg-gray-100">19,0</td> <td class="border border-gray-300 px-2 py-1 bg-gray-100">19,0</td>
<td class="border border-gray-300 px-2 py-1 bg-blue-100">{Math.round(belastungsgrade.Juli*1000)/1000} <td class="border border-gray-300 px-2 py-1 bg-blue-100">{Math.round(belastungsgrade.Juli*1000)/1000}
@@ -336,7 +342,7 @@
</tr> </tr>
<tr> <tr>
<td class="border border-gray-300 px-2 py-1 bg-gray-100">31</td> <td class="border border-gray-300 px-2 py-1 bg-gray-100">31</td>
<td class="border border-gray-300 px-2 py-1 bg-blue-100">{Math.round(bilanzinnentemperaturen.August*1000)/1000}</td> <td class="border border-gray-300 px-2 py-1 bg-blue-100">{Math.round(bilanzInnenTemperaturen.August*1000)/1000}</td>
<td class="border border-gray-300 px-2 py-1 bg-gray-100">18,6</td> <td class="border border-gray-300 px-2 py-1 bg-gray-100">18,6</td>
<td class="border border-gray-300 px-2 py-1 bg-blue-100">{Math.round(belastungsgrade.August*1000)/1000} <td class="border border-gray-300 px-2 py-1 bg-blue-100">{Math.round(belastungsgrade.August*1000)/1000}
@@ -352,7 +358,7 @@
</tr> </tr>
<tr> <tr>
<td class="border border-gray-300 px-2 py-1 bg-gray-100">30</td> <td class="border border-gray-300 px-2 py-1 bg-gray-100">30</td>
<td class="border border-gray-300 px-2 py-1 bg-blue-100">{Math.round(bilanzinnentemperaturen.September*1000)/1000}</td> <td class="border border-gray-300 px-2 py-1 bg-blue-100">{Math.round(bilanzInnenTemperaturen.September*1000)/1000}</td>
<td class="border border-gray-300 px-2 py-1 bg-gray-100">14,3</td> <td class="border border-gray-300 px-2 py-1 bg-gray-100">14,3</td>
<td class="border border-gray-300 px-2 py-1 bg-blue-100">{Math.round(belastungsgrade.September*1000)/1000} <td class="border border-gray-300 px-2 py-1 bg-blue-100">{Math.round(belastungsgrade.September*1000)/1000}
@@ -368,7 +374,7 @@
</tr> </tr>
<tr> <tr>
<td class="border border-gray-300 px-2 py-1 bg-gray-100">31</td> <td class="border border-gray-300 px-2 py-1 bg-gray-100">31</td>
<td class="border border-gray-300 px-2 py-1 bg-blue-100">{Math.round(bilanzinnentemperaturen.Oktober*1000)/1000}</td> <td class="border border-gray-300 px-2 py-1 bg-blue-100">{Math.round(bilanzInnenTemperaturen.Oktober*1000)/1000}</td>
<td class="border border-gray-300 px-2 py-1 bg-gray-100">9,4</td> <td class="border border-gray-300 px-2 py-1 bg-gray-100">9,4</td>
<td class="border border-gray-300 px-2 py-1 bg-blue-100">{Math.round(belastungsgrade.Oktober*1000)/1000} <td class="border border-gray-300 px-2 py-1 bg-blue-100">{Math.round(belastungsgrade.Oktober*1000)/1000}
@@ -384,7 +390,7 @@
</tr> </tr>
<tr> <tr>
<td class="border border-gray-300 px-2 py-1 bg-gray-100">30</td> <td class="border border-gray-300 px-2 py-1 bg-gray-100">30</td>
<td class="border border-gray-300 px-2 py-1 bg-blue-100">{Math.round(bilanzinnentemperaturen.November*1000)/1000}</td> <td class="border border-gray-300 px-2 py-1 bg-blue-100">{Math.round(bilanzInnenTemperaturen.November*1000)/1000}</td>
<td class="border border-gray-300 px-2 py-1 bg-gray-100">4,1</td> <td class="border border-gray-300 px-2 py-1 bg-gray-100">4,1</td>
<td class="border border-gray-300 px-2 py-1 bg-blue-100">{Math.round(belastungsgrade.November*1000)/1000} <td class="border border-gray-300 px-2 py-1 bg-blue-100">{Math.round(belastungsgrade.November*1000)/1000}
@@ -400,7 +406,7 @@
</tr> </tr>
<tr> <tr>
<td class="border border-gray-300 px-2 py-1 bg-gray-100">31</td> <td class="border border-gray-300 px-2 py-1 bg-gray-100">31</td>
<td class="border border-gray-300 px-2 py-1 bg-blue-100">{Math.round(bilanzinnentemperaturen.Dezember*1000)/1000}</td> <td class="border border-gray-300 px-2 py-1 bg-blue-100">{Math.round(bilanzInnenTemperaturen.Dezember*1000)/1000}</td>
<td class="border border-gray-300 px-2 py-1 bg-gray-100">0,9</td> <td class="border border-gray-300 px-2 py-1 bg-gray-100">0,9</td>
<td class="border border-gray-300 px-2 py-1 bg-blue-100">{Math.round(belastungsgrade.Dezember*1000)/1000} <td class="border border-gray-300 px-2 py-1 bg-blue-100">{Math.round(belastungsgrade.Dezember*1000)/1000}

View File

@@ -1,80 +1,156 @@
// Funktion zur Berechnung des Ausnutzungsgrades aus Tabelle 18 // Funktion zur Berechnung des Ausnutzungsgrades aus Tabelle 18
import { nevillePolynomialInterpolation } from "js-interpolate"; import { cubicSplineInterpolation, nevillePolynomialInterpolation } from "js-interpolate";
const dataset = { const dataset = {
alleMonate: { alleMonate: {
30: [ 0.999,0.992,0.978,0.956,0.927,0.893,0.856,0.818,0.78,0.742,0.706,0.671,0.638,0.608,0.579,0.553,0.528,0.505 30: [
,0.483,0.463,0.445,0.428,0.411,0.396,0.382,0.369,0.357,0.345,0.334,0.324,0.314,0.305,0.296,0.288,0.28,0.273,0.266, 0.999, 0.992, 0.978, 0.956, 0.927, 0.893, 0.856, 0.818, 0.78, 0.742,
0.259,0.253,0.246,0.22,0.198,0.181,0.166,0.153,0.142,0.133,0.125,0.117,0.111,0.105,0.1], 0.706, 0.671, 0.638, 0.608, 0.579, 0.553, 0.528, 0.505, 0.483,
40: [ 1.0,0.997,0.99,0.975,0.954,0.926,0.892,0.855,0.817,0.778,0.739,0.702,0.667,0.634,0.603,0.574,0.547,0.522 0.463, 0.445, 0.428, 0.411, 0.396, 0.382, 0.369, 0.357, 0.345,
,0.498,0.477,0.457,0.438,0.421,0.405,0.39,0.376,0.363,0.351,0.339,0.329,0.318,0.309,0.3,0.291,0.283,0.276,0.268, 0.334, 0.324, 0.314, 0.305, 0.296, 0.288, 0.28, 0.273, 0.266, 0.259,
0.261,0.255,0.249,0.221,0.199,0.181,0.166,0.154,0.143,0.133,0.125,0.118,0.111,0.105,0.1], 0.253, 0.246, 0.22, 0.198, 0.181, 0.166, 0.153, 0.142, 0.133, 0.125,
50: [ 1.0,0.999,0.995,0.986,0.97,0.948,0.918,0.883,0.845,0.805,0.765,0.726,0.688,0.652,0.619,0.588,0.559,0.533 0.117, 0.111, 0.105, 0.1,
,0.508,0.485,0.464,0.445,0.427,0.41,0.394,0.38,0.366,0.354,0.342,0.331,0.321,0.311,0.301,0.293,0.285,0.277,0.269, ],
0.262,0.256,0.249,0.222,0.2,0.182,0.167,0.154,0.143,0.133,0.125,0.118,0.111,0.105,0.1], 40: [
60: [ 1.0,1.0,0.998,0.992,0.981,0.963,0.937,0.904,0.867,0.826,0.785,0.743,0.704,0.666,0.631,0.598,0.568,0.54 1.0, 0.997, 0.99, 0.975, 0.954, 0.926, 0.892, 0.855, 0.817, 0.778,
,0.514,0.491,0.469,0.449,0.43,0.413,0.397,0.382,0.368,0.355,0.343,0.332,0.322,0.312,0.302,0.293,0.285,0.277,0.27, 0.739, 0.702, 0.667, 0.634, 0.603, 0.574, 0.547, 0.522, 0.498,
0.263,0.256,0.25,0.222,0.2,0.182,0.167,0.154,0.143,0.133,0.125,0.118,0.111,0.105,0.1], 0.477, 0.457, 0.438, 0.421, 0.405, 0.39, 0.376, 0.363, 0.351, 0.339,
70: [ 1.0,1.0,0.999,0.996,0.988,0.973,0.951,0.921,0.884,0.843,0.8,0.757,0.716,0.676,0.639,0.605,0.574,0.545 0.329, 0.318, 0.309, 0.3, 0.291, 0.283, 0.276, 0.268, 0.261, 0.255,
,0.518,0.494,0.472,0.451,0.432,0.414,0.398,0.383,0.369,0.356,0.344,0.333,0.322,0.312,0.303,0.294,0.286,0.278,0.27, 0.249, 0.221, 0.199, 0.181, 0.166, 0.154, 0.143, 0.133, 0.125,
0.263,0.256,0.25,0.222,0.2,0.182,0.167,0.154,0.143,0.133,0.125,0.118,0.111,0.105,0.1], 0.118, 0.111, 0.105, 0.1,
80: [1.0,1.0,0.999,0.998,0.992,0.981,0.962,0.934,0.898,0.857,0.813,0.769,0.725,0.684,0.646,0.61,0.578,0.548 ],
,0.521,0.496,0.473,0.452,0.433,0.415,0.399,0.384,0.37,0.357,0.344,0.333,0.322,0.312,0.303,0.294,0.286,0.278,0.27, 50: [
0.263,0.256,0.25,0.222,0.2,0.182,0.167,0.154,0.143,0.133,0.125,0.118,0.111,0.105,0.1], 1.0, 0.999, 0.995, 0.986, 0.97, 0.948, 0.918, 0.883, 0.845, 0.805,
90: [ 1.0,1.0,1.0,0.999,0.995,0.986,0.97,0.944,0.91,0.869,0.824,0.778,0.733,0.69,0.651,0.614,0.581,0.55 0.765, 0.726, 0.688, 0.652, 0.619, 0.588, 0.559, 0.533, 0.508,
,0.523,0.497,0.474,0.453,0.434,0.416,0.4,0.384,0.37,0.357,0.345,0.333,0.322,0.312,0.303,0.294,0.286,0.278,0.27, 0.485, 0.464, 0.445, 0.427, 0.41, 0.394, 0.38, 0.366, 0.354, 0.342,
0.263,0.256,0.25,0.222,0.2,0.182,0.167,0.154,0.143,0.133,0.125,0.118,0.111,0.105,0.1], 0.331, 0.321, 0.311, 0.301, 0.293, 0.285, 0.277, 0.269, 0.262,
100: [ 1.0,1.0,1.0,0.999,0.997,0.99,0.976,0.953,0.92,0.879,0.833,0.786,0.739,0.695,0.654,0.617,0.583,0.552 0.256, 0.249, 0.222, 0.2, 0.182, 0.167, 0.154, 0.143, 0.133, 0.125,
,0.524,0.498,0.475,0.454,0.434,0.416,0.4,0.384,0.37,0.357,0.345,0.333,0.323,0.312,0.303,0.294,0.286,0.278,0.27, 0.118, 0.111, 0.105, 0.1,
0.263,0.256,0.25,0.222,0.2,0.182,0.167,0.154,0.143,0.133,0.125,0.118,0.111,0.105,0.1], ],
110: [ 1.0,1.0,1.0,0.999,0.998,0.993,0.981,0.96,0.928,0.887,0.841,0.792,0.744,0.699,0.657,0.619,0.584,0.553 60: [
,0.525,0.499,0.475,0.454,0.435,0.417,0.4,0.384,0.37,0.357,0.345,0.333,0.323,0.312,0.303,0.294,0.286,0.278,0.27, 1.0, 1.0, 0.998, 0.992, 0.981, 0.963, 0.937, 0.904, 0.867, 0.826,
0.263,0.256,0.25,0.222,0.2,0.182,0.167,0.154,0.143,0.133,0.125,0.118,0.111,0.105,0.1], 0.785, 0.743, 0.704, 0.666, 0.631, 0.598, 0.568, 0.54, 0.514, 0.491,
120: [ 1.0,1.0,1.0,1.0,0.999,0.995,0.985,0.966,0.935,0.895,0.847,0.798,0.748,0.702,0.659,0.621,0.586,0.554 0.469, 0.449, 0.43, 0.413, 0.397, 0.382, 0.368, 0.355, 0.343, 0.332,
,0.525,0.5,0.476,0.454,0.435,0.417,0.4,0.385,0.37,0.357,0.345,0.333,0.323,0.312,0.303,0.294,0.286,0.278,0.27, 0.322, 0.312, 0.302, 0.293, 0.285, 0.277, 0.27, 0.263, 0.256, 0.25,
0.263,0.256,0.25,0.222,0.2,0.182,0.167,0.154,0.143,0.133,0.125,0.118,0.111,0.105,0.1], 0.222, 0.2, 0.182, 0.167, 0.154, 0.143, 0.133, 0.125, 0.118, 0.111,
130: [ 1.0,1.0,1.0,1.0,0.999,0.996,0.988,0.971,0.942,0.901,0.853,0.802,0.752,0.704,0.661,0.622,0.587,0.554 0.105, 0.1,
,0.526,0.5,0.476,0.454,0.435,0.417,0.4,0.385,0.37,0.357,0.345,0.333,0.323,0.312,0.303,0.294,0.286,0.278,0.27, ],
0.263,0.256,0.25,0.222,0.2,0.182,0.167,0.154,0.143,0.133,0.125,0.118,0.111,0.105,0.1], 70: [
140: [ 1.0,1.0,1.0,1.0,0.999,0.997,0.991,0.975,0.947,0.907,0.858,0.806,0.755,0.706,0.662,0.623,0.587,0.555 1.0, 1.0, 0.999, 0.996, 0.988, 0.973, 0.951, 0.921, 0.884, 0.843,
,0.526,0.5,0.476,0.454,0.435,0.417,0.4,0.385,0.37,0.357,0.345,0.333,0.323,0.312,0.303,0.294,0.286,0.278,0.27, 0.8, 0.757, 0.716, 0.676, 0.639, 0.605, 0.574, 0.545, 0.518, 0.494,
0.263,0.256,0.25,0.222,0.2,0.182,0.167,0.154,0.143,0.133,0.125,0.118,0.111,0.105,0.1], 0.472, 0.451, 0.432, 0.414, 0.398, 0.383, 0.369, 0.356, 0.344,
150: [ 1.0,1.0,1.0,1.0,0.999,0.998,0.992,0.979,0.952,0.912,0.863,0.809,0.757,0.708,0.663,0.623,0.588,0.555 0.333, 0.322, 0.312, 0.303, 0.294, 0.286, 0.278, 0.27, 0.263, 0.256,
,0.526,0.5,0.476,0.454,0.435,0.417,0.4,0.385,0.37,0.357,0.345,0.333,0.323,0.312,0.303,0.294,0.286,0.278,0.27, 0.25, 0.222, 0.2, 0.182, 0.167, 0.154, 0.143, 0.133, 0.125, 0.118,
0.263,0.256,0.25,0.222,0.2,0.182,0.167,0.154,0.143,0.133,0.125,0.118,0.111,0.105,0.1], 0.111, 0.105, 0.1,
],
80: [
1.0, 1.0, 0.999, 0.998, 0.992, 0.981, 0.962, 0.934, 0.898, 0.857,
0.813, 0.769, 0.725, 0.684, 0.646, 0.61, 0.578, 0.548, 0.521, 0.496,
0.473, 0.452, 0.433, 0.415, 0.399, 0.384, 0.37, 0.357, 0.344, 0.333,
0.322, 0.312, 0.303, 0.294, 0.286, 0.278, 0.27, 0.263, 0.256, 0.25,
0.222, 0.2, 0.182, 0.167, 0.154, 0.143, 0.133, 0.125, 0.118, 0.111,
0.105, 0.1,
],
90: [
1.0, 1.0, 1.0, 0.999, 0.995, 0.986, 0.97, 0.944, 0.91, 0.869, 0.824,
0.778, 0.733, 0.69, 0.651, 0.614, 0.581, 0.55, 0.523, 0.497, 0.474,
0.453, 0.434, 0.416, 0.4, 0.384, 0.37, 0.357, 0.345, 0.333, 0.322,
0.312, 0.303, 0.294, 0.286, 0.278, 0.27, 0.263, 0.256, 0.25, 0.222,
0.2, 0.182, 0.167, 0.154, 0.143, 0.133, 0.125, 0.118, 0.111, 0.105,
0.1,
],
100: [
1.0, 1.0, 1.0, 0.999, 0.997, 0.99, 0.976, 0.953, 0.92, 0.879, 0.833,
0.786, 0.739, 0.695, 0.654, 0.617, 0.583, 0.552, 0.524, 0.498,
0.475, 0.454, 0.434, 0.416, 0.4, 0.384, 0.37, 0.357, 0.345, 0.333,
0.323, 0.312, 0.303, 0.294, 0.286, 0.278, 0.27, 0.263, 0.256, 0.25,
0.222, 0.2, 0.182, 0.167, 0.154, 0.143, 0.133, 0.125, 0.118, 0.111,
0.105, 0.1,
],
110: [
1.0, 1.0, 1.0, 0.999, 0.998, 0.993, 0.981, 0.96, 0.928, 0.887,
0.841, 0.792, 0.744, 0.699, 0.657, 0.619, 0.584, 0.553, 0.525,
0.499, 0.475, 0.454, 0.435, 0.417, 0.4, 0.384, 0.37, 0.357, 0.345,
0.333, 0.323, 0.312, 0.303, 0.294, 0.286, 0.278, 0.27, 0.263, 0.256,
0.25, 0.222, 0.2, 0.182, 0.167, 0.154, 0.143, 0.133, 0.125, 0.118,
0.111, 0.105, 0.1,
],
120: [
1.0, 1.0, 1.0, 1.0, 0.999, 0.995, 0.985, 0.966, 0.935, 0.895, 0.847,
0.798, 0.748, 0.702, 0.659, 0.621, 0.586, 0.554, 0.525, 0.5, 0.476,
0.454, 0.435, 0.417, 0.4, 0.385, 0.37, 0.357, 0.345, 0.333, 0.323,
0.312, 0.303, 0.294, 0.286, 0.278, 0.27, 0.263, 0.256, 0.25, 0.222,
0.2, 0.182, 0.167, 0.154, 0.143, 0.133, 0.125, 0.118, 0.111, 0.105,
0.1,
],
130: [
1.0, 1.0, 1.0, 1.0, 0.999, 0.996, 0.988, 0.971, 0.942, 0.901, 0.853,
0.802, 0.752, 0.704, 0.661, 0.622, 0.587, 0.554, 0.526, 0.5, 0.476,
0.454, 0.435, 0.417, 0.4, 0.385, 0.37, 0.357, 0.345, 0.333, 0.323,
0.312, 0.303, 0.294, 0.286, 0.278, 0.27, 0.263, 0.256, 0.25, 0.222,
0.2, 0.182, 0.167, 0.154, 0.143, 0.133, 0.125, 0.118, 0.111, 0.105,
0.1,
],
140: [
1.0, 1.0, 1.0, 1.0, 0.999, 0.997, 0.991, 0.975, 0.947, 0.907, 0.858,
0.806, 0.755, 0.706, 0.662, 0.623, 0.587, 0.555, 0.526, 0.5, 0.476,
0.454, 0.435, 0.417, 0.4, 0.385, 0.37, 0.357, 0.345, 0.333, 0.323,
0.312, 0.303, 0.294, 0.286, 0.278, 0.27, 0.263, 0.256, 0.25, 0.222,
0.2, 0.182, 0.167, 0.154, 0.143, 0.133, 0.125, 0.118, 0.111, 0.105,
0.1,
],
150: [
1.0, 1.0, 1.0, 1.0, 0.999, 0.998, 0.992, 0.979, 0.952, 0.912, 0.863,
0.809, 0.757, 0.708, 0.663, 0.623, 0.588, 0.555, 0.526, 0.5, 0.476,
0.454, 0.435, 0.417, 0.4, 0.385, 0.37, 0.357, 0.345, 0.333, 0.323,
0.312, 0.303, 0.294, 0.286, 0.278, 0.27, 0.263, 0.256, 0.25, 0.222,
0.2, 0.182, 0.167, 0.154, 0.143, 0.133, 0.125, 0.118, 0.111, 0.105,
0.1,
],
},
};
}, const waermeQuellenSenkenVerhaeltnis = [
} 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1, 1.1, 1.2, 1.3, 1.4, 1.5,
1.6, 1.7, 1.8, 1.9, 2, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, 2.9, 3, 3.1,
3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, 4, 4.5, 5, 5.5, 6, 6.5, 7, 7.5, 8,
8.5, 9, 9.5, 10,
];
const waermeQuellenSenkenVerhaeltnis = [0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1,1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8, export function funktionAusnutzungsgrad(
1.9,2,2.1,2.2,2.3,2.4,2.5,2.6,2.7,2.8,2.9,3,3.1,3.2,3.3,3.4,3.5,3.6,3.7,3.8,3.9,4,4.5,5,5.5,6,6.5,7,7.5,8,8.5,9,9.5,10]; waermequellensenkenverhaeltnis: number,
zeitkonstane: number,
monat: keyof typeof dataset
) {
const data = dataset[monat];
export function funktionAusnutzungsgrad(waermequellensenkenverhaeltnis: number, zeitkonstane: number, monat: keyof typeof dataset) { const interpolations: number[] = [];
const data = dataset[monat]
const interpolations: number[] = []
for (const key in data) { for (const key in data) {
const values = data[key as unknown as keyof typeof data] const values = data[key as unknown as keyof typeof data];
const interpolate = nevillePolynomialInterpolation( const interpolated = cubicSplineInterpolation(
values.map((value, i) => ({ x: waermeQuellenSenkenVerhaeltnis[i], y: value })), values.map((value, i) => ({
values.length x: waermeQuellenSenkenVerhaeltnis[i],
) y: value,
})),
waermequellensenkenverhaeltnis
);
interpolations.push(interpolate(waermequellensenkenverhaeltnis))
interpolations.push(interpolated);
} }
const interpolate = nevillePolynomialInterpolation( const interpolated = cubicSplineInterpolation(
interpolations.map((interpolation, i) => { interpolations.map((interpolation, i) => {
return { return {
x: Object.keys(data)[i], x: Object.keys(data)[i],
y: interpolation y: interpolation,
} };
}), }),
interpolations.length zeitkonstane
) );
return interpolate(zeitkonstane) return interpolated;
} }

View File

@@ -1,6 +1,6 @@
// Funktion zur Berechnung der Bilanzinnentemperatur aus Tabelle 8 EFH oder Tabelle 10 MFH // Funktion zur Berechnung der Bilanzinnentemperatur aus Tabelle 8 EFH oder Tabelle 10 MFH
import { nevillePolynomialInterpolation } from "js-interpolate"; import { cubicSplineInterpolation, nevillePolynomialInterpolation } from "js-interpolate";
import { any } from "node_modules/cypress/types/bluebird/index.js"; import { any } from "node_modules/cypress/types/bluebird/index.js";
// aus Eingabeformular // aus Eingabeformular
@@ -149,7 +149,7 @@ const HeizLast = [0, 5, 10, 25, 50, 75, 100, 125, 150];
// jede einzeln interpolieren und dann zwischen den Tabellen interpolieren. // jede einzeln interpolieren und dann zwischen den Tabellen interpolieren.
// Falls wir also den Wert an Stelle Heizlast: 120, Zeitkonstante 100, Monat: // Falls wir also den Wert an Stelle Heizlast: 120, Zeitkonstante 100, Monat:
// Januar haben wollen: // Januar haben wollen:
export function funktionBilanzInnentemperatur(heizlast: number, zeitkonstane: number, monat: keyof typeof dataset) { export function funktionBilanzInnentemperatur(heizlast: number, zeitkonstane: number, monat: keyof typeof dataset): number {
const data = dataset[monat] const data = dataset[monat]
const interpolations: number[] = [] const interpolations: number[] = []
@@ -157,25 +157,23 @@ export function funktionBilanzInnentemperatur(heizlast: number, zeitkonstane: nu
for (const key in data) { for (const key in data) {
const values = data[key as unknown as keyof typeof data] const values = data[key as unknown as keyof typeof data]
const interpolate = nevillePolynomialInterpolation( const interpolated = cubicSplineInterpolation(
values.map((value, i) => ({ x: HeizLast[i], y: value })), values.map((value, i) => ({ x: HeizLast[i], y: value })),
values.length heizlast
) )
interpolations.push(interpolate(heizlast)) interpolations.push(interpolated)
} }
const interpolate = nevillePolynomialInterpolation( const interpolated = cubicSplineInterpolation(
interpolations.map((interpolation, i) => { interpolations.map((interpolation, i) => {
return { return {
x: Object.keys(data)[i], x: Object.keys(data)[i],
y: interpolation y: interpolation
} }
}), }),
interpolations.length zeitkonstane
) )
return interpolate(zeitkonstane) return interpolated
} }
console.log(funktionBilanzInnentemperatur(120, 100, "Januar"))

View File

@@ -1,6 +1,6 @@
// Funktion zur Berechnung des monatlichen Belastungsgrades aus Tabelle 9 EFH und Tabelle 11 MFH // Funktion zur Berechnung des monatlichen Belastungsgrades aus Tabelle 9 EFH und Tabelle 11 MFH
import { nevillePolynomialInterpolation } from "js-interpolate"; import { cubicSplineInterpolation } from "js-interpolate";
let wohneinheiten = 3; let wohneinheiten = 3;
@@ -155,23 +155,23 @@ export function funktionMonatlicherBelastungsgrad(heizlast: number, zeitkonstane
for (const key in data) { for (const key in data) {
const values = data[key as unknown as keyof typeof data] const values = data[key as unknown as keyof typeof data]
const interpolate = nevillePolynomialInterpolation( const interpolated = cubicSplineInterpolation(
values.map((value, i) => ({ x: HeizLast[i], y: value })), values.map((value, i) => ({ x: HeizLast[i], y: value })),
values.length heizlast
) )
interpolations.push(interpolate(heizlast)) interpolations.push(interpolated)
} }
const interpolate = nevillePolynomialInterpolation( const interpolated = cubicSplineInterpolation(
interpolations.map((interpolation, i) => { interpolations.map((interpolation, i) => {
return { return {
x: Object.keys(data)[i], x: Object.keys(data)[i],
y: interpolation y: interpolation
} }
}), }),
interpolations.length zeitkonstane
) )
return interpolate(zeitkonstane) return interpolated
} }

View File

@@ -1,5 +1,6 @@
import { PDFPage } from 'pdf-lib'; import { PDFPage } from 'pdf-lib';
import { PDFElement, Size } from './PDFElement.js'; import { PDFElement, Size } from './PDFElement.js';
import { Margin, Padding } from './Layout.js';
export interface FlexOptions { export interface FlexOptions {
page: PDFPage; page: PDFPage;
@@ -12,6 +13,8 @@ export interface FlexOptions {
align?: 'start' | 'center' | 'end' | 'stretch'; align?: 'start' | 'center' | 'end' | 'stretch';
gap?: number; gap?: number;
children?: PDFElement[]; children?: PDFElement[];
margin?: Margin,
padding?: Padding
} }
export class Flex extends PDFElement { export class Flex extends PDFElement {
@@ -24,7 +27,7 @@ export class Flex extends PDFElement {
private gap: number; private gap: number;
private children: PDFElement[]; private children: PDFElement[];
constructor(options: FlexOptions) { constructor(private options: FlexOptions) {
super(); super();
this.page = options.page; this.page = options.page;
this._width = options.width; this._width = options.width;
@@ -36,6 +39,8 @@ export class Flex extends PDFElement {
this.alignItems = options.align ?? 'start'; this.alignItems = options.align ?? 'start';
this.gap = options.gap ?? 0; this.gap = options.gap ?? 0;
this.children = options.children ?? []; this.children = options.children ?? [];
this.padding = options.padding || { top: 0, left: 0, right: 0, bottom: 0}
this.margin = options.margin || { top: 0, left: 0, right: 0, bottom: 0}
} }
addChild(...children: PDFElement[]): void { addChild(...children: PDFElement[]): void {
@@ -44,7 +49,7 @@ export class Flex extends PDFElement {
get height(): number { get height(): number {
if (typeof this._height === "number") { if (typeof this._height === "number") {
return this._height; return this._height + this.padding.top + this.padding.bottom;
} }
let currentHeight = 0 let currentHeight = 0
@@ -63,7 +68,7 @@ export class Flex extends PDFElement {
} }
} }
return currentHeight; return currentHeight + this.padding.bottom + this.padding.top;
} }
set width(value: Size) { set width(value: Size) {
@@ -71,6 +76,10 @@ export class Flex extends PDFElement {
} }
get width(): number { get width(): number {
return this.innerWidth + this.padding.left + this.padding.right
}
get innerWidth() {
if (typeof this._width === "number") { if (typeof this._width === "number") {
return this._width; return this._width;
} }
@@ -95,7 +104,7 @@ export class Flex extends PDFElement {
} }
draw(page: PDFPage, x: number = this.x, y: number = this.y): void { draw(page: PDFPage, x: number = this.x, y: number = this.y): void {
const childPositions = this.calculateChildPositions(x, y); const childPositions = this.calculateChildPositions(x + this.margin.left + this.padding.left, y - this.margin.top - this.padding.top);
// Draw each child // Draw each child
this.children.forEach((child, i) => { this.children.forEach((child, i) => {
@@ -118,22 +127,62 @@ export class Flex extends PDFElement {
const totalGaps = this.gap * (this.children.length - 1); const totalGaps = this.gap * (this.children.length - 1);
// Justify content
const justifyOffset = this.calculateJustifyOffset(totalChildrenSize, totalGaps);
// Since the origin is at X: 0 Y: page height and everything will be drawn // Since the origin is at X: 0 Y: page height and everything will be drawn
// above the current position we first need to subtract the height of the // above the current position we first need to subtract the height of the
// element from the current Y // element from the current Y
this.children.forEach((child, i) => { this.children.forEach((child, i) => {
const childX = this.direction === 'row' ? currentX : currentX + this.calculateAlignOffset(child.width); const remainingSpace =
const childY = this.direction === 'row' ? currentY - this.calculateAlignOffset(child.height) : currentY; this.direction === 'row' ? this.width - totalChildrenSize - totalGaps : this.height - totalChildrenSize - totalGaps;
let childX = this.direction === 'row' ? currentX : currentX + this.calculateAlignOffset(child.width);
let childY = this.direction === 'row' ? currentY - this.calculateAlignOffset(child.height) : currentY;
if (this.direction === "row") { if (this.direction === "row") {
currentX += child.width + this.gap + justifyOffset; currentX += child.width + this.gap;
switch (this.justifyContent) {
case 'center':
childX += remainingSpace / 2;
break;
case 'end':
childX += remainingSpace;
break;
case 'space-between':
currentX += (this.innerWidth - totalChildrenSize - totalGaps) / (this.children.length - 1);
break;
case 'space-around':
const adjustment = remainingSpace / (this.children.length + 1);
childX += adjustment;
currentX += adjustment;
break;
case 'start':
default:
break;
}
} }
if (this.direction === 'column') { if (this.direction === 'column') {
currentY -= child.height + this.gap; currentY -= child.height + this.gap;
switch (this.justifyContent) {
case 'center':
childY -= remainingSpace / 2;
break;
case 'end':
childY -= remainingSpace;
break;
case 'space-between':
currentY -= (this.innerHeight - totalChildrenSize - totalGaps) / (this.children.length - 1);
break;
case 'space-around':
const adjustment = remainingSpace / (this.children.length + 1);
childY -= adjustment;
currentY -= adjustment;
break;
case 'start':
default:
break;
}
} }
positions.push({ x: childX, y: childY }); positions.push({ x: childX, y: childY });
@@ -142,24 +191,6 @@ export class Flex extends PDFElement {
return positions; return positions;
} }
private calculateJustifyOffset(totalChildrenSize: number, totalGaps: number): number {
const remainingSpace =
this.direction === 'row' ? this.width - totalChildrenSize - totalGaps : this.height - totalChildrenSize - totalGaps;
switch (this.justifyContent) {
case 'center':
return remainingSpace / 2;
case 'end':
return remainingSpace;
case 'space-between':
return totalGaps / (this.children.length - 1) + (this.width - totalChildrenSize) / this.children.length;
case 'space-around':
return remainingSpace / this.children.length;
default:
return 0;
}
}
private calculateAlignOffset(childSize: number): number { private calculateAlignOffset(childSize: number): number {
switch (this.alignItems) { switch (this.alignItems) {
case 'center': case 'center':

View File

@@ -11,16 +11,11 @@ export type Margin = {
export type Padding = Margin; export type Padding = Margin;
export class Layout extends PDFElement { export class Layout extends PDFElement {
private margin: Margin public margin: Margin
public padding: Padding
protected _height: Size = "auto"; protected _height: Size = "auto";
protected _width: Size = "auto"; protected _width: Size = "auto";
private padding: Padding = {
bottom: 0,
left: 0,
right: 0,
top: 0
};
public children: PDFElement[]; public children: PDFElement[];
@@ -31,14 +26,14 @@ export class Layout extends PDFElement {
super() super()
this.children = children this.children = children
this.margin = options?.margin ?? { this.margin = options?.margin || {
bottom: 0, bottom: 0,
left: 0, left: 0,
right: 0, right: 0,
top: 0 top: 0
}; };
this.padding = options?.padding ?? { this.padding = options?.padding || {
bottom: 0, bottom: 0,
left: 0, left: 0,
right: 0, right: 0,
@@ -70,7 +65,7 @@ export class Layout extends PDFElement {
for (const child of this.children) { for (const child of this.children) {
child.draw(page, x + this.margin.left + this.padding.left, currentY); child.draw(page, x + this.margin.left + this.padding.left, currentY);
currentY -= child.height; currentY -= child.height + child.margin.top + child.margin.bottom;
} }
} }

View File

@@ -1,27 +1,38 @@
import { PDFPage } from 'pdf-lib'; import { PDFPage } from "pdf-lib";
import { Margin, Padding } from "./Layout.js";
export type Size = number | "auto"; export type Size = number | "auto";
export abstract class PDFElement { export abstract class PDFElement {
protected _width: Size = 0; protected _height: Size = 0;
protected _width: Size = 0;
public margin: Margin = { top: 0, bottom: 0, left: 0, right: 0 };
public padding: Padding = { top: 0, bottom: 0, left: 0, right: 0 };
get width(): number { get width(): number {
return this._width === "auto" ? 0 : this._width return this.innerWidth + this.padding.left + this.padding.right;
} }
set width(value: Size) { set width(value: Size) {
this._width = value; this._width = value;
} }
protected _height: Size = 0;
get innerWidth() {
return this._width === "auto" ? 0 : this._width;
}
get height(): number { get height(): number {
return this._height === "auto" ? 0 : this._height return this.innerHeight + this.padding.top + this.padding.bottom;
} }
set height(value: Size) { set height(value: Size) {
this._height = value; this._height = value;
} }
abstract draw(page: PDFPage, x: number, y: number): void; get innerHeight() {
return this._height === "auto" ? 0 : this._height;
}
abstract draw(page: PDFPage, x: number, y: number): void;
abstract addChild(...children: PDFElement[]): void; abstract addChild(...children: PDFElement[]): void;
} }

View File

@@ -1,10 +1,14 @@
import { PDFPage, PDFFont, rgb, RGB } from 'pdf-lib'; import { PDFPage, PDFFont, rgb, RGB } from 'pdf-lib';
import { PDFElement, Size } from './PDFElement.js'; import { PDFElement, Size } from './PDFElement.js';
import { Margin, Padding } from './Layout.js';
export interface TextOptions { export interface TextOptions {
font: PDFFont; font: PDFFont;
fontSize?: number; fontSize?: number;
color?: RGB; color?: RGB;
margin?: Margin,
padding?: Padding,
lineHeight?: number
} }
export class Text extends PDFElement { export class Text extends PDFElement {
@@ -12,6 +16,13 @@ export class Text extends PDFElement {
private font: PDFFont; private font: PDFFont;
private fontSize: number; private fontSize: number;
private color: RGB; private color: RGB;
private options: TextOptions
protected _width: number;
protected _height: number;
public padding: Padding
public margin: Margin
constructor(content: string, options: TextOptions) { constructor(content: string, options: TextOptions) {
super(); super();
@@ -20,20 +31,31 @@ export class Text extends PDFElement {
this.fontSize = options.fontSize ?? 12; this.fontSize = options.fontSize ?? 12;
this.color = options.color ?? rgb(0, 0, 0); this.color = options.color ?? rgb(0, 0, 0);
this._width = this.font.widthOfTextAtSize(content, this.fontSize); this._width = this.font.widthOfTextAtSize(content, this.fontSize);
this._height = this.font.heightAtSize(this.fontSize); this._height = options.lineHeight || this.font.heightAtSize(this.fontSize);
this.options = options;
this.margin = this.options.margin || { top: 0, left: 0, right: 0, bottom: 0}
this.padding = this.options.padding || { top: 0, left: 0, right: 0, bottom: 0}
} }
addChild(...children: PDFElement[]): void { addChild(...children: PDFElement[]): void {
throw new Error("Cannot add child element to Text") throw new Error("Cannot add child element to Text")
} }
get height() {
return this._height + this.padding.top + this.padding.bottom;
}
get width() {
return this._width + this.padding.left + this.padding.right;
}
draw(page: PDFPage, x: number, y: number): void { draw(page: PDFPage, x: number, y: number): void {
page.drawText(this.content, { page.drawText(this.content, {
x, x: x + this.margin.left + this.padding.left,
y: y - this.height, y: y - this.height - this.margin.top - this.padding.top,
size: this.fontSize, size: this.fontSize,
font: this.font, font: this.font,
color: this.color, color: this.color
}); });
} }
} }

View File

@@ -4,14 +4,14 @@ import { Checkbox, Flex, Text } from "./index.js"
import { Layout } from "./Layout.js" import { Layout } from "./Layout.js"
import { PDFElement } from "./PDFElement.js" import { PDFElement } from "./PDFElement.js"
export function xml2pdf(xml: string, font: PDFFont) { export function xml2pdf(xml: string, fonts: Record<string, PDFFont> & { "default": PDFFont }) {
const tree = txml.parse(xml) const tree = txml.parse(xml)
const iterateChildren = (children: ReturnType<typeof txml.parse>, parent: PDFElement) => { const iterateChildren = (children: ReturnType<typeof txml.parse>, parent: PDFElement) => {
for (const child of children) { for (const child of children) {
if (typeof child === "string") { if (typeof child === "string") {
// Simple text // Simple text
parent.addChild(new Text(child, { font })) parent.addChild(new Text(child, { font: fonts["default"] }))
} else if (child.tagName === "flex") { } else if (child.tagName === "flex") {
const flexbox = new Flex({ const flexbox = new Flex({
height: parseFloat(child.attributes.height) || "auto", height: parseFloat(child.attributes.height) || "auto",
@@ -19,7 +19,19 @@ export function xml2pdf(xml: string, font: PDFFont) {
align: child.attributes.align, align: child.attributes.align,
direction: child.attributes.direction, direction: child.attributes.direction,
gap: parseFloat(child.attributes.gap) || 0, gap: parseFloat(child.attributes.gap) || 0,
justify: child.attributes.justify justify: child.attributes.justify,
margin: {
bottom: parseFloat(child.attributes.marginBottom) || 0,
left: parseFloat(child.attributes.marginLeft) || 0,
right: parseFloat(child.attributes.marginRight) || 0,
top: parseFloat(child.attributes.marginTop) || 0,
},
padding: {
bottom: parseFloat(child.attributes.paddingBottom) || 0,
left: parseFloat(child.attributes.paddingLeft) || 0,
right: parseFloat(child.attributes.paddingRight) || 0,
top: parseFloat(child.attributes.paddingTop) || 0,
}
}) })
iterateChildren(child.children, flexbox) iterateChildren(child.children, flexbox)
@@ -38,7 +50,18 @@ export function xml2pdf(xml: string, font: PDFFont) {
color = rgb(...colorValue.map((x) => parseInt(x) / 255) as [number, number, number]); color = rgb(...colorValue.map((x) => parseInt(x) / 255) as [number, number, number]);
} }
const text = new Text(child.children[0] || "", { font: child.attributes.hasOwnProperty("bold") ? bold : font, fontSize: parseFloat(child.attributes.size) || 10, color }) const text = new Text(child.children[0] || "", { font: child.attributes.hasOwnProperty("font") ? fonts[child.attributes["font"]] : fonts["default"], lineHeight: parseFloat(child.attributes.lineHeight), fontSize: parseFloat(child.attributes.size) || 10, color, margin: {
bottom: parseFloat(child.attributes.marginBottom) || 0,
left: parseFloat(child.attributes.marginLeft) || 0,
right: parseFloat(child.attributes.marginRight) || 0,
top: parseFloat(child.attributes.marginTop) || 0,
},
padding: {
bottom: parseFloat(child.attributes.paddingBottom) || 0,
left: parseFloat(child.attributes.paddingLeft) || 0,
right: parseFloat(child.attributes.paddingRight) || 0,
top: parseFloat(child.attributes.paddingTop) || 0,
} })
parent.addChild(text) parent.addChild(text)
} else if (child.tagName === "checkbox") { } else if (child.tagName === "checkbox") {
@@ -77,29 +100,41 @@ export function xml2pdf(xml: string, font: PDFFont) {
return layout return layout
} }
const pdf = await PDFDocument.create() // const pdf = await PDFDocument.create()
const page = pdf.addPage() // const page = pdf.addPage()
const font = await pdf.embedFont(StandardFonts.Helvetica) // const font = await pdf.embedFont(StandardFonts.Helvetica)
const bold = await pdf.embedFont(StandardFonts.HelveticaBold) // const bold = await pdf.embedFont(StandardFonts.HelveticaBold)
const layout = xml2pdf(`<layout height="${page.getHeight()}" width="${page.getWidth()}" marginTop="0" marginLeft="0"> // console.log(page.getWidth(), "WIDTH");
<text bold size="40">Hello</text>
<text color="255,0,255" size="24">Hello, how are you?</text>
<flex direction="row" gap="8" align="center">
<checkbox height="100" width="100"></checkbox>
<text>Hello</text>
<layout marginLeft="0">
<text>Hello</text>
<text>Nasya, i love you</text>
</layout>
</flex>
</layout>`, font)
layout.draw(page, 0, page.getHeight())
import { writeFileSync } from "fs" // const layout = xml2pdf(`
import { FixedLengthArray } from "#lib/Berechnungen/BedarfsausweisWohnen/types.js" // <flex direction="column" justify="end" width="${page.getWidth()}" height="${page.getHeight()}">
// <flex direction="row" gap="5" align="center">
// <checkbox width="8" height="8"></checkbox>
// <text size="12">awd1</text>
// </flex>
// <flex direction="row" gap="5" align="center">
// <checkbox width="8" height="8"></checkbox>
// <text size="12">awd2</text>
// </flex>
// <flex direction="row" gap="5" align="center">
// <checkbox width="8" height="8"></checkbox>
// <text size="12">awd3</text>
// </flex>
// <flex direction="row" gap="5" align="center">
// <checkbox width="8" height="8"></checkbox>
// <text size="12">awd4</text>
// </flex>
// </flex>`, {
// "default": font
// })
writeFileSync("./test-pdf.pdf", await pdf.save()) // layout.draw(page, 0, page.getHeight())
// import { writeFileSync } from "fs"
// import { FixedLengthArray } from "#lib/Berechnungen/BedarfsausweisWohnen/types.js"
// writeFileSync("./test-pdf.pdf", await pdf.save())

View File

@@ -3,6 +3,7 @@ import { endEnergieVerbrauchVerbrauchsausweis_2016 } from "#lib/Berechnungen/Ver
import * as fs from "fs" import * as fs from "fs"
import { PDFDocument, rgb, StandardFonts, TextAlignment } from "pdf-lib"; import { PDFDocument, rgb, StandardFonts, TextAlignment } from "pdf-lib";
import { checkbox, flex, text } from "./elements/index.js"; import { checkbox, flex, text } from "./elements/index.js";
import { xml2pdf } from "./elements/xml2pdf.js";
/* -------------------------------- Pdf Tools ------------------------------- */ /* -------------------------------- Pdf Tools ------------------------------- */
@@ -35,123 +36,139 @@ export async function pdfDatenblatt(ausweis: VerbrauchsausweisWohnenClient) {
ort: "Beispielhausen" ort: "Beispielhausen"
}; };
pages[0].drawText(`${benutzer.vorname} ${benutzer.name}`, { const layout = xml2pdf(`<layout height="${pages[0].getHeight()}" width="${pages[0].getWidth()}" marginTop="150" marginLeft="45" marginRight="45">
x: marginX, <text size="12" lineHeight="14">${benutzer.vorname} ${benutzer.name}</text>
y: height - marginY, <text size="12" lineHeight="14">${benutzer.adresse}</text>
font, <text size="12" lineHeight="14">${benutzer.plz} ${benutzer.ort}</text>
size: 12 <flex direction="row" justify="space-between" marginTop="55" width="${pages[0].getWidth() - 90}">
<text size="12" font="bold">Datenblatt Energieausweis</text>
<text size="12">Ausweis ID: ${ausweis.uid}</text>
</flex>
<text size="12" lineHeight="14" font="bold" marginTop="10">Gebäudedaten</text>
<text size="12" lineHeight="14">Adresse: ${ausweis.gebaeude_aufnahme_allgemein.adresse}, ${ausweis.gebaeude_aufnahme_allgemein.plz} ${ausweis.gebaeude_aufnahme_allgemein.ort}</text>
<flex direction="row" justify="space-between" width="${pages[0].getWidth() - 90}" marginTop="25">
<flex direction="row" gap="5" align="center">
<checkbox width="8" height="8"></checkbox>
<text size="12">Neubau</text>
</flex>
<flex direction="row" gap="5" align="center">
<checkbox width="8" height="8"></checkbox>
<text size="12">Vermietung/Verkauf</text>
</flex>
<flex direction="row" gap="5" align="center">
<checkbox width="8" height="8"></checkbox>
<text size="12">Modernisierung</text>
</flex>
<flex direction="row" gap="5" align="center">
<checkbox width="8" height="8"></checkbox>
<text size="12">Sonstiges</text>
</flex>
</flex>
<flex direction="row" marginTop="25" gap="15">
<flex direction="column" width="${(pages[0].getWidth() - 90) / 2 - 7.5}">
<flex direction="row" align="center" justify="space-between" width="${(pages[0].getWidth() - 90) / 2 - 7.5}">
<text size="12" lineHeight="14">Gebäudetyp:</text>
<text size="12" lineHeight="14">${ausweis.gebaeude_aufnahme_allgemein.gebaeudetyp}</text>
</flex>
<flex direction="row" align="center" justify="space-between" width="${(pages[0].getWidth() - 90) / 2 - 7.5}">
<text size="12" lineHeight="14">Wohnfläche:</text>
<text size="12" lineHeight="14">DIN Wohnfläche innen ${ausweis.gebaeude_aufnahme_allgemein.flaeche} m²</text>
</flex>
<flex direction="row" align="center" justify="space-between" width="${(pages[0].getWidth() - 90) / 2 - 7.5}">
<text size="12" lineHeight="14">Leerstand:</text>
<text size="12" lineHeight="14">${ausweis.gebaeude_aufnahme_allgemein.leerstand || 0}%</text>
</flex>
<flex direction="row" align="center" justify="space-between" width="${(pages[0].getWidth() - 90) / 2 - 7.5}">
<text size="12" lineHeight="14">Wohnungen:</text>
<text size="12" lineHeight="14">${ausweis.gebaeude_aufnahme_allgemein.einheiten}</text>
</flex>
</flex>
<flex direction="column" width="${(pages[0].getWidth() - 90) / 2 - 7.5}">
<flex direction="row" align="center" justify="space-between" width="${(pages[0].getWidth() - 90) / 2 - 7.5}">
<text size="12" lineHeight="14">Dachgeschoss:</text>
<text size="12" lineHeight="14">${ausweis.gebaeude_aufnahme_allgemein.dachgeschoss}</text>
</flex>
<flex direction="row" align="center" justify="space-between" width="${(pages[0].getWidth() - 90) / 2 - 7.5}">
<text size="12" lineHeight="14">Keller:</text>
<text size="12" lineHeight="14">${ausweis.gebaeude_aufnahme_allgemein.keller}</text>
</flex>
</flex>
</flex>
</layout>`, {
"default": font,
bold: bold
}) })
pages[0].drawText(benutzer.adresse, { layout.draw(pages[0], 0, pages[0].getHeight())
x: marginX,
y: height - marginY - 15,
font,
size: 12
})
pages[0].drawText(`${benutzer.plz} ${benutzer.ort}`, { // const containerWidth = width - marginX;
x: marginX,
y: height - marginY - 30,
font,
size: 12
})
pages[0].drawText("Datenblatt Energieausweis", { // const layout = flex([
x: marginX, // flex([
y: height - marginY - 100, // checkbox(8, 8), text("Neubau", {
font: bold, // color: rgb(0,0,0),
size: 12, // font,
}) // fontSize: 12
// })
// ], {
// align: "center",
// justify: "center",
// gap: 5,
// height: 12,
// page: pages[0]
// }),
// flex([
// checkbox(8, 8), text("Vermietung/Verkauf", {
// color: rgb(0,0,0),
// font,
// fontSize: 12
// })
// ], {
// align: "center",
// justify: "center",
// gap: 5,
// height: 12,
// page: pages[0]
// }),
// flex([
// checkbox(8, 8), text("Modernisierung", {
// color: rgb(0,0,0),
// font,
// fontSize: 12
// })
// ], {
// align: "center",
// justify: "center",
// gap: 5,
// height: 12,
// page: pages[0]
// }),
// flex([
// checkbox(8, 8), text("Sonstiges", {
// color: rgb(0,0,0),
// font,
// fontSize: 12
// })
// ], {
// align: "center",
// justify: "center",
// gap: 5,
// height: 12,
// page: pages[0]
// })
// ], {
// align: "center",
// justify: "space-between",
// gap: 15,
// x: marginX,
// y: height - marginY - 165,
// height: 12,
// width: containerWidth
// })
let ausweisIDText = `Ausweis ID: ${ausweis.uid}` // layout.draw(pages[0])
pages[0].drawText(ausweisIDText, {
x: width - marginX - font.widthOfTextAtSize(ausweisIDText, 12),
y: height - marginY - 100,
font,
size: 12,
})
pages[0].drawText("Gebäudedaten", {
x: marginX,
y: height - marginY - 125,
font: bold,
size: 12,
})
pages[0].drawText(`Adresse: ${ausweis.gebaeude_aufnahme_allgemein.adresse}, ${ausweis.gebaeude_aufnahme_allgemein.plz} ${ausweis.gebaeude_aufnahme_allgemein.ort}`, {
x: marginX,
y: height - marginY - 140,
font,
size: 12,
})
const containerWidth = width - marginX;
const layout = flex([
flex([
checkbox(8, 8), text("Neubau", {
color: rgb(0,0,0),
font,
fontSize: 12
})
], {
align: "center",
justify: "center",
gap: 5,
height: 12,
page: pages[0]
}),
flex([
checkbox(8, 8), text("Vermietung/Verkauf", {
color: rgb(0,0,0),
font,
fontSize: 12
})
], {
align: "center",
justify: "center",
gap: 5,
height: 12,
page: pages[0]
}),
flex([
checkbox(8, 8), text("Modernisierung", {
color: rgb(0,0,0),
font,
fontSize: 12
})
], {
align: "center",
justify: "center",
gap: 5,
height: 12,
page: pages[0]
}),
flex([
checkbox(8, 8), text("Sonstiges", {
color: rgb(0,0,0),
font,
fontSize: 12
})
], {
align: "center",
justify: "center",
gap: 5,
height: 12,
page: pages[0]
})
], {
align: "center",
justify: "space-between",
gap: 15,
x: marginX,
y: height - marginY - 165,
height: 12,
width: containerWidth
})
layout.draw(pages[0])
// pdf.getForm().flatten() // pdf.getForm().flatten()

Binary file not shown.