API Optimierungen

This commit is contained in:
Moritz Utcke
2023-05-06 23:02:54 +04:00
parent bc3878e645
commit 9619bf29f3
14 changed files with 396 additions and 31 deletions

View File

@@ -23,14 +23,15 @@
"cookiejs": "^2.1.2",
"express": "^4.18.2",
"jwt-simple": "^0.5.6",
"katex": "^0.16.7",
"knex": "^2.4.2",
"moment": "^2.29.4",
"pg": "^8.10.0",
"svelte": "^3.54.0",
"svelte-preprocess": "^5.0.1",
"tailwindcss": "^3.0.24",
"uuid": "^9.0.0",
"zod": "^3.21.4",
"svelte-preprocess": "^5.0.1"
"zod": "^3.21.4"
},
"devDependencies": {
"@types/uuid": "^9.0.1",

View File

@@ -1,18 +1,297 @@
<script lang="ts">
import HorizontalDots from "./Icons/HorizontalDots.svelte";
import type { Verbrauchsausweis } from "src/lib/Ausweis/Verbrauchsausweis";
import Katex from "./Katex.svelte";
import moment from "moment";
import Cross from "./Icons/Cross.svelte";
export let id: string;
export let strasse: string = "";
export let plz: string = "";
export let stadt: string = "";
interface Service {
name: string;
url: string;
}
export let ausweis: Verbrauchsausweis;
export let services: Service[];
export let hidden: boolean;
export let i: number;
let left: string = "";
$: {
if (i == 0 || i % 3 == 0) {
left = "0";
} else if (i % 2 == 0) {
left = "-50%";
} else {
left = "-100%";
}
}
$: energieverbrauchDaten = [
moment(ausweis.energieverbrauch_zeitraum),
moment(ausweis.energieverbrauch_zeitraum).add("1", "year"),
moment(ausweis.energieverbrauch_zeitraum).add("2", "years"),
moment(ausweis.energieverbrauch_zeitraum).add("3", "years"),
];
let showDropdown: boolean = false;
</script>
<div class="rounded-lg bg-white shadow-sm border px-4 py-1">
<div class="flex flex-row justify-between items-center">
<h3>{strasse}, {plz} {stadt}</h3>
<button class="cursor-pointer">
<HorizontalDots width={20} height={20}></HorizontalDots>
<div class="rounded-lg bg-white shadow-sm border px-4 py-1 relative">
<div class="flex flex-row justify-between items-center cursor-pointer">
<h3>
{ausweis.objekt_strasse}, {ausweis.objekt_plz}
{ausweis.objekt_ort}
</h3>
<button
class="cursor-pointer relative hover:bg-gray-100 rounded-lg p-1"
on:click={() => {
showDropdown = !showDropdown;
}}
>
<HorizontalDots width={20} height={20} />
<div
class="absolute right-0 top-full w-[150px] border shadow-md rounded-lg bg-white z-50"
hidden={!showDropdown}
>
<button
class="cursor-pointer hover:bg-gray-100 w-full p-1"
on:click={() => {
hidden = !hidden;
}}>Berechnung</button
>
<button
class="cursor-pointer hover:bg-gray-100 w-full p-1"
on:click={() => {}}>Gebäudeansicht</button
>
<button
class="cursor-pointer hover:bg-gray-100 w-full p-1"
on:click={() => {}}>Ausweis Ansehen</button
>
</div>
</button>
</div>
<a href="/ausweis/{id}/cad">Gebäudeansicht</a>
<a href="/ausweis/{ausweis.uid}/cad">Gebäudeansicht</a>
<div
class="absolute top-[calc(100%+16px)] left-0 w-[200%] rounded-lg z-50 bg-white border p-2"
style="left: {left};"
{hidden}
>
<div class="flex flex-row justify-between">
<h4 class="px-2 py-1 bg-violet-50 rounded-lg">
Datenprüfung Verbrauchsausweis - ID {ausweis.id} - {ausweis.objekt_strasse},
{ausweis.objekt_plz}
{ausweis.objekt_ort}
</h4>
<Cross
on:click={() => (hidden = true)}
className="p-1 hover:bg-gray-100 cursor-pointer w-[25px] h-[25px] rounded-lg"
/>
</div>
<h5>Abschnitt A,B,C,D und E</h5>
<div class="grid grid-cols-4 gap-4">
<div class="border rounded-lg p-1">
<table>
<tr>
<td>AL</td><td>:</td>
<td>{ausweis.ausstellgrund}</td>
</tr>
<tr>
<td>BH</td><td>:</td>
<td>{ausweis.baujahr_anlage}</td>
</tr>
<tr>
<td>BG</td><td>:</td>
<td>{ausweis.baujahr_gebaeude}</td>
</tr>
<tr>
<td>AW</td><td>:</td>
<td>{ausweis.anzahl_einheiten}</td>
</tr>
<tr>
<td>ST</td><td>:</td>
<td>{ausweis.objekt_saniert}</td>
</tr>
</table>
</div>
<div class="border rounded-lg p-1">
<table>
<tr>
<td>WF</td><td>:</td>
<td>{ausweis.wohnflaeche}</td>
</tr>
<tr>
<td>F</td><td>:</td>
<td>{ausweis.baujahr_anlage}</td>
</tr>
<tr>
<td>AN</td><td>:</td>
<td>{ausweis.baujahr_gebaeude}</td>
</tr>
<tr>
<td>KB</td><td>:</td>
<td>{ausweis.keller_beheizt}</td>
</tr>
<tr>
<td>DB</td><td>:</td>
<td>{ausweis.dachgeschoss}</td>
</tr>
</table>
</div>
<div class="border rounded-lg p-1">
<table>
<tr>
<td>WWE</td><td>:</td>
<td>{ausweis.warmwasser_enthalten}</td>
</tr>
<tr>
<td>WWA</td><td>:</td>
<td>{ausweis.anteil_warmwasser_1}</td>
</tr>
<tr>
<td>WWAZH</td><td>:</td>
<td>{ausweis.anteil_warmwasser_2}</td>
</tr>
<tr>
<td>AEVS</td><td>:</td>
<td />
</tr>
<tr>
<td>SSWW</td><td>:</td>
<td>{ausweis.dachgeschoss}</td>
</tr>
</table>
</div>
<div class="border rounded-lg p-1">
<table>
<tr>
<td>GT</td><td>:</td>
<td>{ausweis.objekt_gebaeudeteil}</td>
</tr>
<tr>
<td>GTL</td><td>:</td>
<td />
</tr>
<tr>
<td>L</td><td>:</td>
<td>{ausweis.lueftungskonzept}</td>
</tr>
<tr>
<td>AK</td><td>:</td>
<td />
</tr>
<tr>
<td>LS</td><td>:</td>
<td>{ausweis.leerstand}</td>
</tr>
</table>
</div>
</div>
<div class="border rounded-lg p-1 gap-2 grid grid-cols-4 justify-between">
<table>
<tr>
<td>{energieverbrauchDaten[0].format("MMMM YYYY")}</td>
</tr>
<tr>
<td
>{energieverbrauchDaten[0].format("MM.YYYY")} - {energieverbrauchDaten[1].format(
"MM.YYYY"
)}</td
>
</tr>
<tr>
<td
>{energieverbrauchDaten[1].format("MM.YYYY")} - {energieverbrauchDaten[2].format(
"MM.YYYY"
)}</td
>
</tr>
<tr>
<td
>{energieverbrauchDaten[2].format("MM.YYYY")} - {energieverbrauchDaten[3].format(
"MM.YYYY"
)}</td
>
</tr>
<tr>
<td>Faktoren Hi / PF / COE</td>
</tr>
</table>
<table>
<tr>
<td>Primäre Heizquelle (1)</td>
</tr>
<tr>
<td
>{ausweis.energieverbrauch_1_heizquelle_1}
{ausweis.energietraeger_einheit_heizquelle_1}
{ausweis.energietraeger_1}</td
>
</tr>
<tr>
<td
>{ausweis.energieverbrauch_2_heizquelle_1}
{ausweis.energietraeger_einheit_heizquelle_1}
{ausweis.energietraeger_1}</td
>
</tr>
<tr>
<td
>{ausweis.energieverbrauch_3_heizquelle_1}
{ausweis.energietraeger_einheit_heizquelle_1}
{ausweis.energietraeger_1}</td
>
</tr>
<tr>
<td>10 / 1.1 / 2.5</td>
</tr>
</table>
<table>
<tr>
<td>Sekundäre Heizquelle (2)</td>
</tr>
<tr>
<td
>{ausweis.energieverbrauch_1_heizquelle_2}
{ausweis.energietraeger_einheit_heizquelle_2}
{ausweis.energietraeger_2}</td
>
</tr>
<tr>
<td
>{ausweis.energieverbrauch_2_heizquelle_2}
{ausweis.energietraeger_einheit_heizquelle_2}
{ausweis.energietraeger_2}</td
>
</tr>
<tr>
<td
>{ausweis.energieverbrauch_3_heizquelle_2}
{ausweis.energietraeger_einheit_heizquelle_2}
{ausweis.energietraeger_2}</td
>
</tr>
<tr>
<td>10 / 1.1 / 2.5</td>
</tr>
</table>
<table>
<tr>
<td>Klimafaktoren</td>
</tr>
<tr>
<td>1.12</td>
</tr>
<tr>
<td>1.15</td>
</tr>
<tr>
<td>1.12</td>
</tr>
<tr>
<td>-</td>
</tr>
</table>
</div>
</div>
</div>

View File

@@ -0,0 +1,23 @@
<script lang="ts">
export let width: number = 15;
export let height: number = 15;
export let fill: string = "currentColor";
export let className: string;
</script>
<svg
width={width}
height={height}
class={className}
viewBox="0 0 15 15"
fill="none"
xmlns="http://www.w3.org/2000/svg"
on:click
{...$$restProps}
><path
d="M12.8536 2.85355C13.0488 2.65829 13.0488 2.34171 12.8536 2.14645C12.6583 1.95118 12.3417 1.95118 12.1464 2.14645L7.5 6.79289L2.85355 2.14645C2.65829 1.95118 2.34171 1.95118 2.14645 2.14645C1.95118 2.34171 1.95118 2.65829 2.14645 2.85355L6.79289 7.5L2.14645 12.1464C1.95118 12.3417 1.95118 12.6583 2.14645 12.8536C2.34171 13.0488 2.65829 13.0488 2.85355 12.8536L7.5 8.20711L12.1464 12.8536C12.3417 13.0488 12.6583 13.0488 12.8536 12.8536C13.0488 12.6583 13.0488 12.3417 12.8536 12.1464L8.20711 7.5L12.8536 2.85355Z"
fill={fill}
fill-rule="evenodd"
clip-rule="evenodd"
/></svg
>

View File

@@ -11,6 +11,8 @@
viewBox="0 0 15 15"
fill="none"
xmlns="http://www.w3.org/2000/svg"
on:click
{...$$restProps}
><path
d="M7.07926 0.222253C7.31275 -0.007434 7.6873 -0.007434 7.92079 0.222253L14.6708 6.86227C14.907 7.09465 14.9101 7.47453 14.6778 7.71076C14.4454 7.947 14.0655 7.95012 13.8293 7.71773L13 6.90201V12.5C13 12.7761 12.7762 13 12.5 13H2.50002C2.22388 13 2.00002 12.7761 2.00002 12.5V6.90201L1.17079 7.71773C0.934558 7.95012 0.554672 7.947 0.32229 7.71076C0.0899079 7.47453 0.0930283 7.09465 0.32926 6.86227L7.07926 0.222253ZM7.50002 1.49163L12 5.91831V12H10V8.49999C10 8.22385 9.77617 7.99999 9.50002 7.99999H6.50002C6.22388 7.99999 6.00002 8.22385 6.00002 8.49999V12H3.00002V5.91831L7.50002 1.49163ZM7.00002 12H9.00002V8.99999H7.00002V12Z"
fill={fill}

View File

@@ -0,0 +1,19 @@
<script lang="ts">
import katex from "katex";
export let math: string;
export let displayMode: boolean = false;
const options = {
displayMode: displayMode,
throwOnError: false
}
let katexString: any;
$: katexString = katex.renderToString(math, options)
</script>
<svelte:head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/katex.min.css" integrity="sha384-AfEj0r4/OFrOo5t7NnNe46zW/tFgW6x/bCJG8FqQCEo3+Aro6EYUG4+cU+KJWu/X" crossorigin="anonymous">
</svelte:head>
{@html katexString}

View File

@@ -1,4 +1,5 @@
import { getKlimafaktorenClient } from "../Klimafaktoren";
import { getHeizwertfaktorClient } from "../server/Heizwertfaktor";
export enum AusweisType {
VERBRAUCHSAUSWEIS,
@@ -16,6 +17,40 @@ export enum Lueftungskonzept {
export type Ausweisart = "VA" | "BA" | "VANW";
export type Ausstellgrund = "Vermietung" | "Neubau" | "Verkauf" | "Modernisierung" | "Sonstiges";
class BitChecker {
public value: number;
constructor(number: number) {
this.value = number;
}
public isSet(bitIndex: number): boolean {
const bitMask = 1 << bitIndex;
return (this.value & bitMask) !== 0;
}
public set(index: number): number {
if (!this.isSet(index)) {
this.value += 2 ** index;
}
return this.value;
}
public off(index: number) {
if (this.isSet(index)) {
this.value -= 2 ** index;
}
return this.value;
}
public valueOf(): number {
return this.value;
}
}
export class Verbrauchsausweis {
public ausweisart: Ausweisart = "VA";
public id: number = 0;
@@ -35,8 +70,7 @@ export class Verbrauchsausweis {
public erstellungsdatum: Date = new Date();
public ausstellgrund: Ausstellgrund = "Vermietung";
public energieverbrauch_zeitraum_monat: number = 0;
public energieverbrauch_zeitraum_jahr: number = 0;
public energieverbrauch_zeitraum: Date = new Date();
public energieverbrauch_1_heizquelle_1: number = 0;
public energieverbrauch_2_heizquelle_1: number = 0;
public energieverbrauch_3_heizquelle_1: number = 0;
@@ -52,7 +86,7 @@ export class Verbrauchsausweis {
public anteil_warmwasser_1: number = 0;
public anteil_warmwasser_2: number = 0;
public public_id: string = "";
public uid: string = "";
public wohnflaeche: number = 0;
public keller_beheizt: boolean = false;
@@ -66,7 +100,7 @@ export class Verbrauchsausweis {
public versorgungssysteme: number = 0;
public fenster_dach: number = 0;
public energiequelle_2_nutzung: number = 0;
public energiequelle_2_nutzung: BitChecker = new BitChecker(0);
public daemmung: number = 0;
public energetische_nutzfläche: number = 0;
@@ -160,7 +194,7 @@ export class Verbrauchsausweis {
];
if (this.energietraeger_1 && this.energietraeger_einheit_heizquelle_1) {
[umrechnungsfaktor, primaerfaktor, heizwertfaktor, coe] =
getHeizwertfaktor(
await getHeizwertfaktorClient(
this.energietraeger_1,
this.energietraeger_einheit_heizquelle_1
);
@@ -168,7 +202,7 @@ export class Verbrauchsausweis {
if (this.energietraeger_2 && this.energietraeger_einheit_heizquelle_2) {
[umrechnungsfaktor_1, primaerfaktor_1, heizwertfaktor_1, coe_1] =
getHeizwertfaktor(
await getHeizwertfaktorClient(
this.energietraeger_2,
this.energietraeger_einheit_heizquelle_2
);
@@ -215,7 +249,7 @@ export class Verbrauchsausweis {
durchschnittsKlimafaktor;
}
if (energiequelle_2_nutzung[3]) {
if (this.energiequelle_2_nutzung.isSet(3)) {
kuehlungsZuschlag = 6 * this.energetische_nutzfläche * 3;
}

View File

@@ -1,5 +1,5 @@
export class Ausweis {
public static fromPublicId(public_id: string) {
public static fromUID(uid: string) {
}

View File

@@ -1,5 +1,5 @@
import moment from "moment";
import { memoize } from "./Memization";
import { memoize } from "./Memoization";
export const getKlimafaktorenClient = memoize<Promise<number[]>>(async (date: Date, zip: string) => {
const response = await fetch(`/api/klimafaktoren?date=${moment(date).format("YYYY-MM-DD")}&zip=${zip}`);

View File

@@ -10,7 +10,7 @@ export class User {
* @param uid Die unique/public id des gesuchten Benutzers.
* @returns {UserType | null} Die Daten des Nutzers oder null falls dieser nicht gefunden werden kann.
*/
public static async fromPublicId(uid: string): Promise<UserType | null> {
public static async fromUID(uid: string): Promise<UserType | null> {
if (!uid || typeof uid !== "string") {
return null;
}

View File

@@ -0,0 +1,5 @@
import { memoize } from "../Memoization";
export const getHeizwertfaktorClient = memoize<Promise<[number, number, number, number]>>(async function() {
return [1,1,1,1];
})

View File

@@ -0,0 +1,3 @@
export async function getKlimafaktorenServer(date: Date, zip: string) {
};

View File

@@ -14,7 +14,7 @@ export const get: APIRoute = async ({ request }) => {
return MissingPropertyError(["uid"]);
}
const user = User.fromPublicId(body.uid);
const user = User.fromUID(body.uid);
if (!user) {
return MissingEntityError("user");

View File

@@ -4,6 +4,7 @@ import { decodeToken } from "../../lib/JsonWebToken";
import { User } from "../../lib/User";
import UserLayout from "~/layouts/UserLayout.astro";
import AusweisCard from "~/components/AusweisCard.svelte";
import { Verbrauchsausweis } from "src/lib/Ausweis/Verbrauchsausweis";
const token = Astro.cookies.get("token").value;
const expires = Astro.cookies.get("expires").number();
@@ -16,7 +17,7 @@ if (!token || now > expires) {
}
const parsed = decodeToken(token);
const user = await User.fromPublicId(parsed.uid);
const user = await User.fromUID(parsed.uid);
if (!user) {
Astro.cookies.delete("token");
@@ -30,11 +31,9 @@ if (!user) {
<h1>Willkommen zurück <b>{user.email}</b></h1>
<h2>Ihre Ausweise</h2>
<div class="overflow-x-auto grid grid-flow-row grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4">
<AusweisCard strasse="Götheborgstraße 12" plz="21030" stadt="Hamburg"></AusweisCard>
<AusweisCard strasse="Götheborgstraße 12" plz="21030" stadt="Hamburg"></AusweisCard>
<AusweisCard strasse="Götheborgstraße 12" plz="21030" stadt="Hamburg"></AusweisCard>
<AusweisCard strasse="Götheborgstraße 12" plz="21030" stadt="Hamburg"></AusweisCard>
<AusweisCard strasse="Götheborgstraße 12" plz="21030" stadt="Hamburg"></AusweisCard>
<div class="grid grid-flow-row grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-4">
<AusweisCard client:load hidden={true} i={0} ausweis={new Verbrauchsausweis()}></AusweisCard>
<AusweisCard client:load hidden={true} i={1} ausweis={new Verbrauchsausweis()}></AusweisCard>
<AusweisCard client:load hidden={true} i={2} ausweis={new Verbrauchsausweis()}></AusweisCard>
</div>
</UserLayout>