Compare commits
2 Commits
59b9ad5241
...
df09c65b2b
| Author | SHA1 | Date | |
|---|---|---|---|
| df09c65b2b | |||
| e2738716be |
50
src/main/angular/src/app/Unit.ts
Normal file
50
src/main/angular/src/app/Unit.ts
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import {formatNumber} from "@angular/common";
|
||||||
|
|
||||||
|
export const PREFIXES_POSITIVE: string[] = ['', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y', 'R', 'Q'];
|
||||||
|
export const PREFIXES_NEGATIVE: string[] = ['', 'm', 'µ', 'n', 'p', 'f', 'a', 'z', 'y', 'r', 'q'];
|
||||||
|
|
||||||
|
export function applyPrefixUnit(value: number, unit: string, divisor: number, prefix: string, digits: number, locale: string) {
|
||||||
|
if (isNaN(value) || isNaN(divisor) || divisor === 0) {
|
||||||
|
return '-';
|
||||||
|
}
|
||||||
|
const format = '0.' + digits + '-' + digits;
|
||||||
|
return formatNumber(value / divisor, locale, format) + ' ' + prefix + unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Unit {
|
||||||
|
|
||||||
|
private _divisor: number = 1;
|
||||||
|
|
||||||
|
private _prefix: string = "";
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
readonly unit: string,
|
||||||
|
readonly locale: string,
|
||||||
|
) {
|
||||||
|
// -
|
||||||
|
}
|
||||||
|
|
||||||
|
get divisor(): number {
|
||||||
|
return this._divisor;
|
||||||
|
}
|
||||||
|
|
||||||
|
get prefix(): string {
|
||||||
|
return this._prefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
public update(value: number) {
|
||||||
|
const prefixGroup = Math.floor(Math.floor(Math.log10(value)) / 3);
|
||||||
|
if (prefixGroup <= 0) {
|
||||||
|
this._prefix = PREFIXES_NEGATIVE[-prefixGroup];
|
||||||
|
} else {
|
||||||
|
this._prefix = PREFIXES_POSITIVE[prefixGroup];
|
||||||
|
}
|
||||||
|
const exponentFromGroup = prefixGroup * 3;
|
||||||
|
this._divisor = Math.pow(10, exponentFromGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
applyPrefixUnit(value: number): string {
|
||||||
|
return applyPrefixUnit(value, this.unit, this.divisor, this.prefix, 2, this.locale);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,8 +1,17 @@
|
|||||||
import {ApplicationConfig, provideZoneChangeDetection} from '@angular/core';
|
import {ApplicationConfig, LOCALE_ID, provideZoneChangeDetection} from '@angular/core';
|
||||||
import {provideRouter} from '@angular/router';
|
import {provideRouter} from '@angular/router';
|
||||||
|
|
||||||
import {routes} from './app.routes';
|
import {routes} from './app.routes';
|
||||||
|
import {registerLocaleData} from "@angular/common";
|
||||||
|
import localeDe from '@angular/common/locales/de';
|
||||||
|
import localeDeExtra from '@angular/common/locales/extra/de';
|
||||||
|
|
||||||
|
registerLocaleData(localeDe, 'de-DE', localeDeExtra);
|
||||||
|
|
||||||
export const appConfig: ApplicationConfig = {
|
export const appConfig: ApplicationConfig = {
|
||||||
providers: [provideZoneChangeDetection({eventCoalescing: true}), provideRouter(routes)]
|
providers: [
|
||||||
|
{provide: LOCALE_ID, useValue: 'de-DE'},
|
||||||
|
provideZoneChangeDetection({eventCoalescing: true}),
|
||||||
|
provideRouter(routes),
|
||||||
|
]
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
import {Routes} from '@angular/router';
|
import {Routes} from '@angular/router';
|
||||||
import {SolarComponent} from './solar/solar.component';
|
import {SolarSystemComponent} from './solar-system/solar-system.component';
|
||||||
import {VoltageDropComponent} from "./voltage-drop/voltage-drop.component";
|
import {VoltageDropComponent} from "./voltage-drop/voltage-drop.component";
|
||||||
|
|
||||||
export const routes: Routes = [
|
export const routes: Routes = [
|
||||||
{path: 'Solar', component: SolarComponent},
|
{path: 'Solar', component: SolarSystemComponent},
|
||||||
{path: 'VoltageDrop', component: VoltageDropComponent},
|
{path: 'VoltageDrop', component: VoltageDropComponent},
|
||||||
{path: '**', redirectTo: '/Solar'},
|
{path: '**', redirectTo: '/Solar'},
|
||||||
];
|
];
|
||||||
|
|||||||
43
src/main/angular/src/app/solar-system/SOLAR_SYSTEM.ts
Normal file
43
src/main/angular/src/app/solar-system/SOLAR_SYSTEM.ts
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import {SolarSystemBody} from "./SolarSystemBody";
|
||||||
|
|
||||||
|
export const SUN = new SolarSystemBody('Sonne', 1392700000, 0, 1.989e33, []);
|
||||||
|
|
||||||
|
export const MERCURY = new SolarSystemBody('Merkur', 4879400, 57.9, 3.285e26, []);
|
||||||
|
|
||||||
|
export const VENUS = new SolarSystemBody('Venus', 12104000, 108.2, 4.867e27, []);
|
||||||
|
|
||||||
|
export const EARTH = new SolarSystemBody('Erde', 12742000, 149.6, 5.972e27, [
|
||||||
|
new SolarSystemBody('Mond', 3474800, 0, 7.342e25, [])
|
||||||
|
]);
|
||||||
|
|
||||||
|
export const MARS = new SolarSystemBody('Mars', 6779000, 228, 6.39e26, [
|
||||||
|
new SolarSystemBody('Phobos', 22533, 0, 1.0659e19, []),
|
||||||
|
new SolarSystemBody('Deimos', 12400, 0, 1.4762e18, [])
|
||||||
|
]);
|
||||||
|
|
||||||
|
export const JUPITER = new SolarSystemBody('Jupiter', 139820000, 778.5, 1.898e30, [
|
||||||
|
new SolarSystemBody('Io', 3643000, 0, 8.932e25, []),
|
||||||
|
new SolarSystemBody('Europa', 3121600, 0, 4.799e25, []),
|
||||||
|
new SolarSystemBody('Ganymede', 5262400, 0, 1.4819e26, []),
|
||||||
|
new SolarSystemBody('Callisto', 4820600, 0, 1.0759e26, [])
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
export const SATURN = new SolarSystemBody('Saturn', 116460000, 1432, 5.683e29, [
|
||||||
|
new SolarSystemBody('Titan', 5149460, 0, 1.3452e26, []),
|
||||||
|
new SolarSystemBody('Enceladus', 504200, 0, 1.08e23, [])
|
||||||
|
]);
|
||||||
|
|
||||||
|
export const URANUS = new SolarSystemBody('Uranus', 50724000, 2867, 8.681e28, [
|
||||||
|
new SolarSystemBody('Miranda', 471600, 0, 6.59e22, []),
|
||||||
|
new SolarSystemBody('Ariel', 1157800, 0, 1.35e24, []),
|
||||||
|
new SolarSystemBody('Umbriel', 1169400, 0, 1.17e24, []),
|
||||||
|
new SolarSystemBody('Titania', 1576800, 0, 3.42e24, []),
|
||||||
|
new SolarSystemBody('Oberon', 1522800, 0, 3.01e24, [])
|
||||||
|
]);
|
||||||
|
|
||||||
|
export const NEPTUNE = new SolarSystemBody('Neptun', 49244000, 4515, 1.024e29, [
|
||||||
|
new SolarSystemBody('Triton', 2706800, 0, 2.14e25, [])
|
||||||
|
]);
|
||||||
|
|
||||||
|
export const BODIES: SolarSystemBody[] = [SUN, MERCURY, VENUS, EARTH, MARS, JUPITER, SATURN, URANUS, NEPTUNE];
|
||||||
21
src/main/angular/src/app/solar-system/SolarSystemBody.ts
Normal file
21
src/main/angular/src/app/solar-system/SolarSystemBody.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
export class SolarSystemBody {
|
||||||
|
|
||||||
|
readonly realDistanceMeters: number;
|
||||||
|
|
||||||
|
modelMeters: number;
|
||||||
|
|
||||||
|
modelDistance: number;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
readonly name: string,
|
||||||
|
readonly realMeters: number,
|
||||||
|
realDistanceMioKm: number,
|
||||||
|
readonly massKg: number,
|
||||||
|
readonly moons: SolarSystemBody[],
|
||||||
|
) {
|
||||||
|
this.realDistanceMeters = realDistanceMioKm * 1000 * 1000 * 1000;
|
||||||
|
this.modelMeters = realMeters;
|
||||||
|
this.modelDistance = realDistanceMioKm;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -9,23 +9,25 @@
|
|||||||
<div class="tileContent">
|
<div class="tileContent">
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="name">Name</td>
|
<th>Name</th>
|
||||||
<td class="real">Realität</td>
|
<th>Realität</th>
|
||||||
<td class="model" colspan="2">Skaliert</td>
|
<th>Skaliert</th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr *ngFor="let mass of masses">
|
<tr *ngFor="let mass of BODIES">
|
||||||
<td class="name">{{ mass.name }}</td>
|
<td class="name">{{ mass.name }}</td>
|
||||||
<td class="real">{{ doPrefix(mass.realMeters, 'm', 1000, 'k', 0) }}</td>
|
<td class="real">{{ applyPrefixUnit(mass.realMeters, 'm', 1000, 'k', 0, locale) }}</td>
|
||||||
<td class="model" colspan="2">{{ unit(mass.modelMeters, 'm') }}</td>
|
<td class="model">{{ diameterUnit.applyPrefixUnit(mass.modelMeters) }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
</table>
|
||||||
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<th>
|
<th>
|
||||||
<select [(ngModel)]="pivot">
|
<select [(ngModel)]="pivot" (ngModelChange)="update()">
|
||||||
<option *ngFor="let mass of masses" [ngValue]="mass">{{ mass.name }}</option>
|
<option *ngFor="let mass of BODIES" [ngValue]="mass">{{ mass.name }}</option>
|
||||||
</select>
|
</select>
|
||||||
</th>
|
</th>
|
||||||
<td colspan="2">
|
<td>
|
||||||
<input type="number" [(ngModel)]="pivot.modelMeters" (ngModelChange)="ngOnInit()">
|
<input type="number" [(ngModel)]="pivot.modelMeters" (ngModelChange)="update()">
|
||||||
</td>
|
</td>
|
||||||
<td class="unit">
|
<td class="unit">
|
||||||
m
|
m
|
||||||
@ -12,14 +12,17 @@ td {
|
|||||||
.name {
|
.name {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
width: 33.33%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.real {
|
.real {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
|
width: 33.33%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.model {
|
.model {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
|
width: 33.33%;
|
||||||
}
|
}
|
||||||
|
|
||||||
input {
|
input {
|
||||||
@ -0,0 +1,46 @@
|
|||||||
|
import {Component, Inject, LOCALE_ID, OnInit} from '@angular/core';
|
||||||
|
import {DecimalPipe, NgForOf} from "@angular/common";
|
||||||
|
import {FormsModule} from "@angular/forms";
|
||||||
|
import {SolarSystemBody} from "./SolarSystemBody";
|
||||||
|
import {BODIES, JUPITER} from "./SOLAR_SYSTEM";
|
||||||
|
import {applyPrefixUnit, Unit} from "../Unit";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-solar-system',
|
||||||
|
standalone: true,
|
||||||
|
imports: [
|
||||||
|
NgForOf,
|
||||||
|
DecimalPipe,
|
||||||
|
FormsModule,
|
||||||
|
],
|
||||||
|
templateUrl: './solar-system.component.html',
|
||||||
|
styleUrl: './solar-system.component.less'
|
||||||
|
})
|
||||||
|
export class SolarSystemComponent implements OnInit {
|
||||||
|
|
||||||
|
protected readonly applyPrefixUnit = applyPrefixUnit;
|
||||||
|
|
||||||
|
protected readonly BODIES = BODIES;
|
||||||
|
|
||||||
|
protected pivot: SolarSystemBody = JUPITER;
|
||||||
|
|
||||||
|
protected diameterUnit: Unit;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
@Inject(LOCALE_ID) readonly locale: string,
|
||||||
|
) {
|
||||||
|
this.diameterUnit = new Unit('m', this.locale);
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.pivot.modelMeters = 0.18;
|
||||||
|
this.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected update() {
|
||||||
|
const scale = this.pivot.modelMeters / this.pivot.realMeters;
|
||||||
|
BODIES.filter(m => m != this.pivot).forEach(m => m.modelMeters = scale * m.realMeters);
|
||||||
|
this.diameterUnit.update(this.pivot.modelMeters);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,15 +0,0 @@
|
|||||||
export class Mass {
|
|
||||||
|
|
||||||
modelMeters: number;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
readonly name: string,
|
|
||||||
readonly realMeters: number,
|
|
||||||
readonly massKg: number,
|
|
||||||
readonly moons: Mass[],
|
|
||||||
modeMeters?: number,
|
|
||||||
) {
|
|
||||||
this.modelMeters = modeMeters || realMeters;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,90 +0,0 @@
|
|||||||
import {Component, OnInit} from '@angular/core';
|
|
||||||
import {DecimalPipe, NgForOf} from "@angular/common";
|
|
||||||
import {FormsModule} from "@angular/forms";
|
|
||||||
import {Mass} from "./Mass";
|
|
||||||
|
|
||||||
const PREFIXES_POSITIVE: string[] = ['', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y', 'R', 'Q'];
|
|
||||||
|
|
||||||
const PREFIXES_NEGATIVE: string[] = ['', 'm', 'µ', 'n', 'p', 'f', 'a', 'z', 'y', 'r', 'q'];
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'app-solar',
|
|
||||||
standalone: true,
|
|
||||||
imports: [
|
|
||||||
NgForOf,
|
|
||||||
DecimalPipe,
|
|
||||||
FormsModule
|
|
||||||
],
|
|
||||||
templateUrl: './solar.component.html',
|
|
||||||
styleUrl: './solar.component.less'
|
|
||||||
})
|
|
||||||
export class SolarComponent implements OnInit {
|
|
||||||
|
|
||||||
protected readonly jupiter = new Mass('Jupiter', 139820000, 1.898e30, [
|
|
||||||
new Mass('Io', 3643000, 8.932e25, []),
|
|
||||||
new Mass('Europa', 3121600, 4.799e25, []),
|
|
||||||
new Mass('Ganymede', 5262400, 1.4819e26, []),
|
|
||||||
new Mass('Callisto', 4820600, 1.0759e26, [])
|
|
||||||
], 0.18);
|
|
||||||
|
|
||||||
protected masses: Mass[] = [
|
|
||||||
new Mass('Sonne', 1392700000, 1.989e33, []),
|
|
||||||
new Mass('Merkur', 4879400, 3.285e26, []),
|
|
||||||
new Mass('Venus', 12104000, 4.867e27, []),
|
|
||||||
new Mass('Erde', 12742000, 5.972e27, [
|
|
||||||
new Mass('Mond', 3474800, 7.342e25, [])
|
|
||||||
]),
|
|
||||||
new Mass('Mars', 6779000, 6.39e26, [
|
|
||||||
new Mass('Phobos', 22533, 1.0659e19, []),
|
|
||||||
new Mass('Deimos', 12400, 1.4762e18, [])
|
|
||||||
]),
|
|
||||||
this.jupiter,
|
|
||||||
new Mass('Saturn', 116460000, 5.683e29, [
|
|
||||||
new Mass('Titan', 5149460, 1.3452e26, []),
|
|
||||||
new Mass('Enceladus', 504200, 1.08e23, [])
|
|
||||||
]),
|
|
||||||
new Mass('Uranus', 50724000, 8.681e28, [
|
|
||||||
new Mass('Miranda', 471600, 6.59e22, []),
|
|
||||||
new Mass('Ariel', 1157800, 1.35e24, []),
|
|
||||||
new Mass('Umbriel', 1169400, 1.17e24, []),
|
|
||||||
new Mass('Titania', 1576800, 3.42e24, []),
|
|
||||||
new Mass('Oberon', 1522800, 3.01e24, [])
|
|
||||||
]),
|
|
||||||
new Mass('Neptun', 49244000, 1.024e29, [
|
|
||||||
new Mass('Triton', 2706800, 2.14e25, [])
|
|
||||||
])
|
|
||||||
];
|
|
||||||
|
|
||||||
protected pivot: Mass = this.jupiter;
|
|
||||||
|
|
||||||
protected divisor: number = 1;
|
|
||||||
|
|
||||||
protected prefix = "";
|
|
||||||
|
|
||||||
ngOnInit() {
|
|
||||||
const scale = this.pivot.modelMeters / this.pivot.realMeters;
|
|
||||||
this.masses.filter(m => m != this.pivot).forEach(m => m.modelMeters = scale * m.realMeters);
|
|
||||||
this.updatePrefix();
|
|
||||||
}
|
|
||||||
|
|
||||||
private updatePrefix() {
|
|
||||||
const exponent = Math.floor(Math.log10(this.jupiter.modelMeters));
|
|
||||||
const prefixGroup = Math.floor(exponent / 3);
|
|
||||||
if (prefixGroup <= 0) {
|
|
||||||
this.prefix = PREFIXES_NEGATIVE[-prefixGroup];
|
|
||||||
} else {
|
|
||||||
this.prefix = PREFIXES_POSITIVE[prefixGroup];
|
|
||||||
}
|
|
||||||
const exponentFromGroup = prefixGroup * 3;
|
|
||||||
this.divisor = Math.pow(10, exponentFromGroup);
|
|
||||||
}
|
|
||||||
|
|
||||||
unit(value: number, unit: string) {
|
|
||||||
return this.doPrefix(value, unit, this.divisor, this.prefix, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
doPrefix(value: number, unit: string, divisor: number, prefix: string, digits: number) {
|
|
||||||
return (value / divisor).toFixed(digits) + ' ' + prefix + unit;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
<div class="value">
|
|
||||||
<div class="label">{{title}}</div>
|
|
||||||
<div class="input">
|
|
||||||
<input disabled type="number" [value]="round(value, places)">
|
|
||||||
<div class="unit">{{unit}}</div>
|
|
||||||
</div>
|
|
||||||
<div class="input" *ngIf="percentDivisor !== undefined">
|
|
||||||
<input *ngIf="value !== undefined" disabled type="number" [class.tooHigh]="percentMax !== undefined && value / percentDivisor > percentMax" [value]="formatPercent()">
|
|
||||||
<div class="unit">%</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@ -1,44 +0,0 @@
|
|||||||
.value {
|
|
||||||
clear: both;
|
|
||||||
|
|
||||||
.label {
|
|
||||||
padding: 1vmin 0 0.5vmin 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input {
|
|
||||||
clear: both;
|
|
||||||
float: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type=number] {
|
|
||||||
float: left;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
input.tooHigh {
|
|
||||||
background-color: red;
|
|
||||||
}
|
|
||||||
|
|
||||||
.unit {
|
|
||||||
padding-left: 0.5vmin;
|
|
||||||
}
|
|
||||||
|
|
||||||
.shortcuts {
|
|
||||||
clear: both;
|
|
||||||
|
|
||||||
.shortcut {
|
|
||||||
float: left;
|
|
||||||
font-size: 90%;
|
|
||||||
padding: 0.2vmin 0.7vmin;
|
|
||||||
margin: 0.5vmin;
|
|
||||||
border-radius: 0.5vmin;
|
|
||||||
background-color: lightgray;
|
|
||||||
}
|
|
||||||
|
|
||||||
.shortcutSelected {
|
|
||||||
background-color: lightgreen;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,65 +0,0 @@
|
|||||||
import {Component, Input, OnInit} from '@angular/core';
|
|
||||||
import {NgIf} from "@angular/common";
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'app-value',
|
|
||||||
templateUrl: './value.component.html',
|
|
||||||
standalone: true,
|
|
||||||
imports: [
|
|
||||||
NgIf
|
|
||||||
],
|
|
||||||
styleUrls: ['./value.component.less']
|
|
||||||
})
|
|
||||||
export class ValueComponent implements OnInit {
|
|
||||||
|
|
||||||
@Input()
|
|
||||||
title!: string;
|
|
||||||
|
|
||||||
@Input()
|
|
||||||
unit!: string;
|
|
||||||
|
|
||||||
@Input()
|
|
||||||
value?: number;
|
|
||||||
|
|
||||||
@Input()
|
|
||||||
places?: number;
|
|
||||||
|
|
||||||
@Input()
|
|
||||||
percentDivisor?: number;
|
|
||||||
|
|
||||||
@Input()
|
|
||||||
percentPlaces?: number;
|
|
||||||
|
|
||||||
@Input()
|
|
||||||
percentMax?: number;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnInit(): void {
|
|
||||||
}
|
|
||||||
|
|
||||||
round(value: number | undefined, places: number | undefined): number | undefined {
|
|
||||||
if (value === undefined || places === undefined) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
const divisor = Math.pow(10, places);
|
|
||||||
return Math.round(value * divisor) / divisor;
|
|
||||||
}
|
|
||||||
|
|
||||||
formatPercent(): number | undefined {
|
|
||||||
if (this.value === undefined || this.percentDivisor === undefined || this.percentPlaces === undefined) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
return this.round(this.value / this.percentDivisor * 100, this.percentPlaces)
|
|
||||||
}
|
|
||||||
|
|
||||||
defined() {
|
|
||||||
for (let argument of arguments) {
|
|
||||||
if (argument === undefined || argument === null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -7,69 +7,69 @@
|
|||||||
Vorgaben
|
Vorgaben
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="tileContent">
|
<div class="tileContent" id="VoltageDropInputs">
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="label">Spannung</td>
|
<td class="label">Spannung</td>
|
||||||
<td class="input"><input type="number" [(ngModel)]="values.voltage" (ngModelChange)="update()"></td>
|
<td class="input"><input type="number" [(ngModel)]="input.voltage" (ngModelChange)="update()"></td>
|
||||||
<td class="unit">V</td>
|
<td class="unit"> V</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="3" class="shortcuts">
|
<td colspan="3" class="shortcuts">
|
||||||
<ng-container *ngFor="let v of voltages">
|
<ng-container *ngFor="let v of SHORTCUTS_VOLTAGE">
|
||||||
<div class="shortcut" [class.shortcutSelected]="values.voltage===v" (click)="values.voltage=v; update()">{{ v }}</div>
|
<div class="shortcut" [class.shortcutSelected]="inRange(input.voltage, v, 0.1)" (click)="input.voltage=v; update()">{{ v }}</div>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td class="label">Leistung</td>
|
<td class="label">Leistung</td>
|
||||||
<td class="input"><input type="number" [(ngModel)]="values.power" (ngModelChange)="update()"></td>
|
<td class="input"><input type="number" [(ngModel)]="input.power" (ngModelChange)="update()"></td>
|
||||||
<td class="unit">kW</td>
|
<td class="unit"> kW</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="3" class="shortcuts">
|
<td colspan="3" class="shortcuts">
|
||||||
<ng-container *ngFor="let c of powers">
|
<ng-container *ngFor="let c of SHORTCUTS_POWER">
|
||||||
<div class="shortcut" [class.shortcutSelected]="values.power===c" (click)="values.power=c; update()">{{ c }}</div>
|
<div class="shortcut" [class.shortcutSelected]="inRange(input.power, c, 0.1)" (click)="input.power=c; update()">{{ c }}</div>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td class="label">Querschnitt</td>
|
<td class="label">Querschnitt</td>
|
||||||
<td class="input"><input type="number" [(ngModel)]="values.crossSection" (ngModelChange)="update()"></td>
|
<td class="input"><input type="number" [(ngModel)]="input.crossSection" (ngModelChange)="update()"></td>
|
||||||
<td class="unit">mm²</td>
|
<td class="unit"> mm²</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="3" class="shortcuts">
|
<td colspan="3" class="shortcuts">
|
||||||
<ng-container *ngFor="let c of crossSections">
|
<ng-container *ngFor="let c of SHORTCUTS_CROSS_SECTION">
|
||||||
<div class="shortcut" [class.shortcutSelected]="values.crossSection===c" (click)="values.crossSection=c; update()">{{ c }}</div>
|
<div class="shortcut" [class.shortcutSelected]="inRange(input.crossSection, c, 0.1)" (click)="input.crossSection=c; update()">{{ c }}</div>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td class="label">Länge (1-fach)</td>
|
<td class="label">Länge (einfacher Weg)</td>
|
||||||
<td class="input"><input type="number" [(ngModel)]="values.length" (ngModelChange)="update()"></td>
|
<td class="input"><input type="number" [(ngModel)]="input.length" (ngModelChange)="update()"></td>
|
||||||
<td class="unit">m</td>
|
<td class="unit"> m</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="3" class="shortcuts">
|
<td colspan="3" class="shortcuts">
|
||||||
<ng-container *ngFor="let l of lengths">
|
<ng-container *ngFor="let l of SHORTCUTS_LENGTH">
|
||||||
<div class="shortcut" [class.shortcutSelected]="values.length===l" (click)="values.length=l; update()">{{ l }}</div>
|
<div class="shortcut" [class.shortcutSelected]="inRange(input.length, l, 0.1)" (click)="input.length=l; update()">{{ l }}</div>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td class="label">Spezifischer Widerstand</td>
|
<td class="label">Spezifischer Widerstand</td>
|
||||||
<td class="input"><input type="number" [(ngModel)]="values.resistanceSpecific" (ngModelChange)="update()"></td>
|
<td class="input"><input type="number" [(ngModel)]="input.resistanceSpecific" (ngModelChange)="update()"></td>
|
||||||
<td class="unit">Ω*m</td>
|
<td class="unit"> Ω*m</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="3" class="shortcuts">
|
<td colspan="3" class="shortcuts">
|
||||||
<ng-container *ngFor="let r of resistances">
|
<ng-container *ngFor="let r of SHORTCUTS_RESISTANCE">
|
||||||
<div class="shortcut" [class.shortcutSelected]="values.resistanceSpecific===r.value" (click)="values.resistanceSpecific=r.value; update()">{{ r.name }}</div>
|
<div class="shortcut" [class.shortcutSelected]="inRange(input.resistanceSpecific, r.value, 0.0005)" (click)="input.resistanceSpecific = r.value; update()">{{ r.name }}</div>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -86,15 +86,83 @@
|
|||||||
Ergebnisse
|
Ergebnisse
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="tileContent">
|
<div class="tileContent" id="VoltageDropResults">
|
||||||
<app-value title="Spannungsverlust" unit="V" [value]="voltageDrop2Way" [places]="1" [percentDivisor]="values.voltage" [percentPlaces]="2" [percentMax]="0.03"></app-value>
|
|
||||||
<app-value title="Verlustleistung" unit="W" [value]="powerLoss2Way" [places]="0"></app-value>
|
<div class="group" [class.groupAlarm]="(voltageDropPercent || 0) > 3">
|
||||||
<app-value title="Verfügbare Spannung" unit="V" [value]="voltageDropLoad" [places]="1" [percentDivisor]="values.voltage" [percentPlaces]="2"></app-value>
|
<div class="header">Spannungsverlust:</div>
|
||||||
<app-value title="Verfügbare Leistung" unit="W" [value]="powerLoad" [places]="0" [percentDivisor]="values.power * 1000" [percentPlaces]="2"></app-value>
|
<div class="valueUnit">
|
||||||
<app-value title="Strom" unit="A" [value]="current" [places]="1"></app-value>
|
<div class="value">{{ voltageDrop2Way?.toFixed(1) }}</div>
|
||||||
<app-value title="Leitungwiderstand" unit="Ω" [value]="resistance2Way" [places]="3"></app-value>
|
<div class="unit"> V</div>
|
||||||
<app-value title="Lastwiderstand" unit="Ω" [value]="resistanceLoad" [places]="3"></app-value>
|
</div>
|
||||||
<app-value title="Gesamtwiderstand" unit="Ω" [value]="resistanceTotal" [places]="3"></app-value>
|
<div class="valueUnit">
|
||||||
|
<div class="value">{{ voltageDropPercent?.toFixed(2) }}</div>
|
||||||
|
<div class="unit"> %</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="group">
|
||||||
|
<div class="header">Verlustleistung:</div>
|
||||||
|
<div class="valueUnit">
|
||||||
|
<div class="value">{{ powerLoss2Way?.toFixed(0) }}</div>
|
||||||
|
<div class="unit"> W</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="group">
|
||||||
|
<div class="header">Verfügbare Spannung:</div>
|
||||||
|
<div class="valueUnit">
|
||||||
|
<div class="value">{{ voltageDropLoad?.toFixed(1) }}</div>
|
||||||
|
<div class="unit"> V</div>
|
||||||
|
</div>
|
||||||
|
<div class="valueUnit">
|
||||||
|
<div class="value">{{ voltageDropLoadPercent?.toFixed(2) }}</div>
|
||||||
|
<div class="unit"> %</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="group">
|
||||||
|
<div class="header">Verfügbare Leistung:</div>
|
||||||
|
<div class="valueUnit">
|
||||||
|
<div class="value">{{ powerLoad?.toFixed(0) }}</div>
|
||||||
|
<div class="unit"> W</div>
|
||||||
|
</div>
|
||||||
|
<div class="valueUnit">
|
||||||
|
<div class="value">{{ powerLoadPercent?.toFixed(2) }}</div>
|
||||||
|
<div class="unit"> %</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="group">
|
||||||
|
<div class="header">Strom:</div>
|
||||||
|
<div class="valueUnit">
|
||||||
|
<div class="value">{{ current?.toFixed(1) }}</div>
|
||||||
|
<div class="unit"> A</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="group">
|
||||||
|
<div class="header">Leitungwiderstand:</div>
|
||||||
|
<div class="valueUnit">
|
||||||
|
<div class="value">{{ resistance2Way?.toFixed(3) }}</div>
|
||||||
|
<div class="unit"> Ω</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="group">
|
||||||
|
<div class="header">Lastwiderstand:</div>
|
||||||
|
<div class="valueUnit">
|
||||||
|
<div class="value">{{ resistanceLoad?.toFixed(3) }}</div>
|
||||||
|
<div class="unit"> Ω</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="group">
|
||||||
|
<div class="header">Gesamtwiderstand:</div>
|
||||||
|
<div class="valueUnit">
|
||||||
|
<div class="value">{{ resistanceTotal?.toFixed(3) }}</div>
|
||||||
|
<div class="unit"> Ω</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,28 +1,73 @@
|
|||||||
@import "../../tile.less";
|
@import "../../tile.less";
|
||||||
|
|
||||||
.label {
|
#VoltageDropInputs {
|
||||||
|
|
||||||
}
|
.label {
|
||||||
|
width: 12em;
|
||||||
|
}
|
||||||
|
|
||||||
.input {
|
.input {
|
||||||
|
input {
|
||||||
|
width: 100%;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
.unit {
|
||||||
|
width: 3em;
|
||||||
|
}
|
||||||
|
|
||||||
.unit {
|
.shortcuts {
|
||||||
|
padding-top: calc(@space / 2);
|
||||||
|
padding-bottom: calc(@space * 2);
|
||||||
|
|
||||||
}
|
.shortcut {
|
||||||
|
float: left;
|
||||||
|
font-size: 80%;
|
||||||
|
padding: calc(@space / 2) @space;
|
||||||
|
margin-right: calc(@space / 2);
|
||||||
|
background-color: lightskyblue;
|
||||||
|
border-radius: @space;
|
||||||
|
}
|
||||||
|
|
||||||
.shortcuts {
|
.shortcutSelected {
|
||||||
padding-top: calc(@space / 2);
|
color: white;
|
||||||
padding-bottom: calc(@space * 2);
|
background-color: dodgerblue;
|
||||||
|
}
|
||||||
|
|
||||||
.shortcut {
|
}
|
||||||
float: left;
|
|
||||||
font-size: 80%;
|
}
|
||||||
padding: calc(@space / 2) @space;
|
|
||||||
margin-right: calc(@space / 2);
|
#VoltageDropResults {
|
||||||
background-color: lightskyblue;
|
|
||||||
border-radius: @space;
|
.group {
|
||||||
|
margin-bottom: calc(2 * @space);
|
||||||
|
|
||||||
|
.header {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.valueUnit {
|
||||||
|
float: right;
|
||||||
|
clear: right;
|
||||||
|
|
||||||
|
.value {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.unit {
|
||||||
|
float: left;
|
||||||
|
width: 1.5em;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.groupAlarm {
|
||||||
|
color: red;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
import { Component } from '@angular/core';
|
import {Component} from '@angular/core';
|
||||||
import {FormsModule} from "@angular/forms";
|
import {FormsModule} from "@angular/forms";
|
||||||
import {ValueComponent} from "./value/value.component";
|
|
||||||
import {NgForOf} from "@angular/common";
|
import {NgForOf} from "@angular/common";
|
||||||
|
|
||||||
class Resistance {
|
class Resistance {
|
||||||
@ -33,7 +32,6 @@ class Values {
|
|||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [
|
imports: [
|
||||||
FormsModule,
|
FormsModule,
|
||||||
ValueComponent,
|
|
||||||
NgForOf
|
NgForOf
|
||||||
],
|
],
|
||||||
templateUrl: './voltage-drop.component.html',
|
templateUrl: './voltage-drop.component.html',
|
||||||
@ -41,37 +39,27 @@ class Values {
|
|||||||
})
|
})
|
||||||
export class VoltageDropComponent {
|
export class VoltageDropComponent {
|
||||||
|
|
||||||
readonly lengths: number[] = [10, 15, 20, 30, 40, 50, 75, 100];
|
readonly SHORTCUTS_LENGTH: number[] = [10, 15, 20, 30, 40, 50, 75, 100];
|
||||||
|
|
||||||
readonly voltages: number[] = [5, 12, 24, 36, 230, 400];
|
readonly SHORTCUTS_VOLTAGE: number[] = [5, 12, 24, 36, 230, 400];
|
||||||
|
|
||||||
readonly powers: number[] = [0.5, 1, 2, 3.68, 5, 7.5, 10, 15, 20, 25, 30];
|
readonly SHORTCUTS_POWER: number[] = [0.5, 1, 2, 3.68, 5, 7.5, 10, 15, 20, 25, 30];
|
||||||
|
|
||||||
readonly crossSections: number[] = [0.75, 1.5, 2.5, 4, 6, 10, 16, 25, 35, 50];
|
readonly SHORTCUTS_CROSS_SECTION: number[] = [0.75, 1.5, 2.5, 4, 6, 10, 16, 25, 35, 50];
|
||||||
|
|
||||||
readonly resistances: Resistance[] = [
|
readonly SHORTCUTS_RESISTANCE: Resistance[] = [
|
||||||
{name: 'Silber', value: 0.015},
|
{name: 'Silber', value: 0.015},
|
||||||
{name: 'Kupfer', value: 0.017},
|
{name: 'Kupfer', value: 0.017},
|
||||||
{name: 'Aluminium', value: 0.0278},
|
{name: 'Aluminium', value: 0.0278},
|
||||||
];
|
];
|
||||||
|
|
||||||
readonly testSet: Values = {
|
readonly input: Values = {
|
||||||
length: this.lengths[4],
|
length: this.SHORTCUTS_LENGTH[4],
|
||||||
voltage: this.voltages[4],
|
voltage: this.SHORTCUTS_VOLTAGE[4],
|
||||||
power: this.powers[3],
|
power: this.SHORTCUTS_POWER[3],
|
||||||
crossSection: this.crossSections[3],
|
crossSection: this.SHORTCUTS_CROSS_SECTION[3],
|
||||||
resistanceSpecific: this.resistances[1].value,
|
resistanceSpecific: this.SHORTCUTS_RESISTANCE[1].value,
|
||||||
}
|
};
|
||||||
|
|
||||||
readonly testSet2: Values = {
|
|
||||||
length: 100,
|
|
||||||
voltage: 230,
|
|
||||||
power: 2.5,
|
|
||||||
crossSection: 1.5,
|
|
||||||
resistanceSpecific: this.resistances[1].value,
|
|
||||||
}
|
|
||||||
|
|
||||||
readonly values: Values = this.testSet;
|
|
||||||
|
|
||||||
resistance2Way?: number;
|
resistance2Way?: number;
|
||||||
|
|
||||||
@ -83,12 +71,18 @@ export class VoltageDropComponent {
|
|||||||
|
|
||||||
voltageDrop2Way?: number;
|
voltageDrop2Way?: number;
|
||||||
|
|
||||||
|
voltageDropPercent?: number;
|
||||||
|
|
||||||
powerLoss2Way?: number;
|
powerLoss2Way?: number;
|
||||||
|
|
||||||
voltageDropLoad?: number;
|
voltageDropLoad?: number;
|
||||||
|
|
||||||
|
voltageDropLoadPercent?: number;
|
||||||
|
|
||||||
powerLoad?: number;
|
powerLoad?: number;
|
||||||
|
|
||||||
|
powerLoadPercent?: number;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,25 +91,35 @@ export class VoltageDropComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
update() {
|
update() {
|
||||||
if (!this.values || !this.values.resistanceSpecific || !this.values.length || !this.values.crossSection || !this.values.power || !this.values.voltage) {
|
if (!this.input || !this.input.resistanceSpecific || !this.input.length || !this.input.crossSection || !this.input.power || !this.input.voltage) {
|
||||||
this.resistance2Way = undefined;
|
this.resistance2Way = undefined;
|
||||||
this.resistanceLoad = undefined;
|
this.resistanceLoad = undefined;
|
||||||
this.resistanceTotal = undefined;
|
this.resistanceTotal = undefined;
|
||||||
this.current = undefined;
|
this.current = undefined;
|
||||||
this.voltageDrop2Way = undefined;
|
this.voltageDrop2Way = undefined;
|
||||||
|
this.voltageDropPercent = undefined;
|
||||||
this.powerLoss2Way = undefined;
|
this.powerLoss2Way = undefined;
|
||||||
this.voltageDropLoad = undefined;
|
this.voltageDropLoad = undefined;
|
||||||
|
this.voltageDropLoadPercent = undefined;
|
||||||
this.powerLoad = undefined;
|
this.powerLoad = undefined;
|
||||||
|
this.powerLoadPercent = undefined;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.resistance2Way = (this.values.resistanceSpecific * this.values.length / this.values.crossSection) * 2;
|
this.resistance2Way = (this.input.resistanceSpecific * this.input.length / this.input.crossSection) * 2;
|
||||||
this.resistanceLoad = (this.values.voltage * this.values.voltage) / (this.values.power * 1000);
|
this.resistanceLoad = (this.input.voltage * this.input.voltage) / (this.input.power * 1000);
|
||||||
this.resistanceTotal = this.resistance2Way + this.resistanceLoad;
|
this.resistanceTotal = this.resistance2Way + this.resistanceLoad;
|
||||||
this.current = this.values.voltage / this.resistanceTotal;
|
this.current = this.input.voltage / this.resistanceTotal;
|
||||||
this.voltageDrop2Way = this.resistance2Way * this.current;
|
this.voltageDrop2Way = this.resistance2Way * this.current;
|
||||||
|
this.voltageDropPercent = 100 * this.voltageDrop2Way / this.input.voltage;
|
||||||
this.powerLoss2Way = this.voltageDrop2Way * this.current;
|
this.powerLoss2Way = this.voltageDrop2Way * this.current;
|
||||||
this.voltageDropLoad = this.resistanceLoad * this.current;
|
this.voltageDropLoad = this.resistanceLoad * this.current;
|
||||||
|
this.voltageDropLoadPercent = 100 * this.voltageDropLoad / this.input.voltage;
|
||||||
this.powerLoad = this.voltageDropLoad * this.current;
|
this.powerLoad = this.voltageDropLoad * this.current;
|
||||||
|
this.powerLoadPercent = 100 * this.powerLoad / (this.input.power * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
inRange(value: number, wanted: number, delta: number) {
|
||||||
|
return Math.abs(wanted - value) <= Math.abs(delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="de">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>Patrix Tools</title>
|
<title>Patrix Tools</title>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user