diff --git a/src/main/angular/src/app/location/detail/location-detail.ts b/src/main/angular/src/app/location/detail/location-detail.ts
index 7e7d492..085f0eb 100644
--- a/src/main/angular/src/app/location/detail/location-detail.ts
+++ b/src/main/angular/src/app/location/detail/location-detail.ts
@@ -1,4 +1,4 @@
-import {Component, OnDestroy, OnInit, ViewChild} from '@angular/core';
+import {Component, OnDestroy, OnInit} from '@angular/core';
import {LocationService} from '../location-service';
import {ActivatedRoute} from '@angular/router';
import {Location} from '../Location';
@@ -11,6 +11,7 @@ import {SeriesType} from '../../series/SeriesType';
import {Subscription, timer} from 'rxjs';
import {SeriesHistory} from './history/series-history';
import {Interval} from '../../series/Interval';
+import {MenuService} from '../../menu-service';
function yesterday(now: any) {
const yesterday = new Date(now.getTime());
@@ -31,9 +32,6 @@ function yesterday(now: any) {
})
export class LocationDetail implements OnInit, OnDestroy {
- @ViewChild("today")
- protected today!: SeriesHistory;
-
protected readonly Interval = Interval;
protected location: Location | null = null;
@@ -50,13 +48,17 @@ export class LocationDetail implements OnInit, OnDestroy {
readonly locationService: LocationService,
readonly seriesService: SeriesService,
readonly activatedRoute: ActivatedRoute,
+ readonly menuService: MenuService,
) {
//
}
ngOnInit(): void {
this.activatedRoute.params.subscribe(params => {
- this.locationService.getById(params['id'], location => this.location = location);
+ this.locationService.getById(params['id'], location => {
+ this.location = location;
+ this.menuService.title = this.location.name;
+ });
});
this.seriesService.findAll(list => this.series = list);
this.subs.push(this.seriesService.subscribe(this.updateSeries));
@@ -67,6 +69,7 @@ export class LocationDetail implements OnInit, OnDestroy {
}
ngOnDestroy(): void {
+ this.menuService.title = "";
this.subs.forEach(sub => sub.unsubscribe());
}
@@ -83,7 +86,6 @@ export class LocationDetail implements OnInit, OnDestroy {
} else {
this.series.push(fresh);
}
- this.today.updateSeries(fresh);
};
protected readonly filterEnergy = (): Series[] => {
diff --git a/src/main/angular/src/app/location/list/location-list.ts b/src/main/angular/src/app/location/list/location-list.ts
index c1dfcea..c84b987 100644
--- a/src/main/angular/src/app/location/list/location-list.ts
+++ b/src/main/angular/src/app/location/list/location-list.ts
@@ -1,7 +1,8 @@
-import {Component, OnInit} from '@angular/core';
+import {Component, OnDestroy, OnInit} from '@angular/core';
import {LocationService} from '../location-service';
import {Location} from '../Location';
import {RouterLink} from '@angular/router';
+import {MenuService} from '../../menu-service';
@Component({
selector: 'app-location-list',
@@ -11,18 +12,24 @@ import {RouterLink} from '@angular/router';
templateUrl: './location-list.html',
styleUrl: './location-list.less',
})
-export class LocationList implements OnInit {
+export class LocationList implements OnInit, OnDestroy {
protected list: Location[] = [];
constructor(
readonly locationService: LocationService,
+ readonly menuService: MenuService,
) {
//
}
ngOnInit(): void {
this.locationService.findAll(list => this.list = list);
+ this.menuService.title = "Orte";
+ }
+
+ ngOnDestroy(): void {
+ this.menuService.title = "";
}
}
diff --git a/src/main/angular/src/app/menu-service.ts b/src/main/angular/src/app/menu-service.ts
new file mode 100644
index 0000000..7b59bda
--- /dev/null
+++ b/src/main/angular/src/app/menu-service.ts
@@ -0,0 +1,10 @@
+import {Injectable} from '@angular/core';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class MenuService {
+
+ title: string = "";
+
+}
diff --git a/src/main/angular/src/app/point/PointSeries.ts b/src/main/angular/src/app/point/PointSeries.ts
index 9d56fbe..6438121 100644
--- a/src/main/angular/src/app/point/PointSeries.ts
+++ b/src/main/angular/src/app/point/PointSeries.ts
@@ -3,13 +3,11 @@ import {validateList, validateNumber} from "../common";
export class PointSeries {
- readonly valueString: string;
-
constructor(
readonly series: Series,
readonly points: number[][],
) {
- this.valueString = series.getValueString(points.length === 0 ? null : points[0][1]);
+ //
}
static fromJson(json: any): PointSeries {
diff --git a/src/main/angular/src/app/series/Series.ts b/src/main/angular/src/app/series/Series.ts
index d96443f..f4e0bc1 100644
--- a/src/main/angular/src/app/series/Series.ts
+++ b/src/main/angular/src/app/series/Series.ts
@@ -1,48 +1,36 @@
import {or, validateDate, validateEnum, validateNumber, validateString} from "../common";
import {SeriesType} from './SeriesType';
-import {formatNumber} from '@angular/common';
+import {Value} from './Value';
export class Series {
- readonly valueString: string;
+ readonly value: Value | null = null;
constructor(
readonly id: number,
readonly name: string,
- readonly decimals: number,
+ readonly precision: number,
readonly seconds: number,
- readonly value: number | null,
- readonly last: Date | null,
- readonly unit: string,
readonly type: SeriesType,
+ value: number | null,
+ readonly unit: string,
+ readonly last: Date | null,
) {
- this.valueString = this.getValueString(value);
- }
-
- getValueString(value: number | null | undefined): string {
- return (value === null || value === undefined ? '-' : formatNumber(value, "de-DE", `0.${this.decimals}-${this.decimals}`)) + ' ' + this.unit;
+ this.value = Value.of(this, value, last);
}
static fromJson(json: any): Series {
return new Series(
validateNumber(json.id),
validateString(json.name),
- validateNumber(json.decimals),
+ validateNumber(json.precision),
validateNumber(json.seconds),
- or(json.value, validateNumber, null),
- or(json.last, validateDate, null),
- validateString(json.unit),
validateEnum(json.type, SeriesType),
+ or(json.value, validateNumber, null),
+ validateString(json.unit),
+ or(json.last, validateDate, null),
);
}
- isOld(now: Date): boolean {
- if (this.last === null) {
- return true;
- }
- const ageSeconds = (now.getTime() - this.last.getTime()) / 1000;
- return ageSeconds > this.seconds * 2.1;
- }
-
}
diff --git a/src/main/angular/src/app/series/Value.ts b/src/main/angular/src/app/series/Value.ts
new file mode 100644
index 0000000..c0bd367
--- /dev/null
+++ b/src/main/angular/src/app/series/Value.ts
@@ -0,0 +1,89 @@
+import {formatNumber} from '@angular/common';
+import {PointResponse} from '../point/PointResponse';
+import {Series} from './Series';
+
+export class Value {
+
+ constructor(
+ readonly value: number,
+ readonly precision: number,
+ readonly seconds: number,
+ readonly unit: string,
+ readonly date: Date,
+ ) {
+ //
+ }
+
+ toValueString(zeroToDash: boolean, now_ageCheckToDash: Date | null): string {
+ if (this.value === null || this.value === undefined) {
+ return "[???]";
+ }
+ if (this.value === 0) {
+ return zeroToDash ? "-" : `0 ${this.unit}`;
+ }
+ if (now_ageCheckToDash !== null) {
+ const ageSeconds = (now_ageCheckToDash.getTime() - this.date.getTime()) / 1000;
+ if (ageSeconds > this.seconds * 2.1) {
+ return `--- ${this.unit}`
+ }
+ }
+
+ const scale = Math.floor(Math.log10(this.value));
+ const rest = scale - this.precision + 1;
+ if (isNaN(rest)) {
+ console.log(this);
+ }
+ if (rest >= 0) {
+ return `${Math.round(this.value)} ${this.unit}`;
+ }
+ return formatNumber(this.value, "de-DE", `0.${-rest}-${-rest}`) + ' ' + this.unit;
+ }
+
+ plus(other: Value | null | undefined): Value | null {
+ return this.operateSameUnit("plus", other, (a, b) => a + b);
+ }
+
+ minus(other: Value | null | undefined): Value | null {
+ return this.operateSameUnit("minus", other, (a, b) => a - b);
+ }
+
+ operateSameUnit(operationName: string, other: Value | null | undefined, operation: (a: number, b: number) => number): Value | null {
+ if (!other) {
+ return null;
+ }
+ if (this.unit !== other.unit) {
+ throw new Error(`Operation '${operationName} needs units to be the same: this=${this}, other=${other}`);
+ }
+ const decimals = Math.max(this.precision, other.precision);
+ const seconds = Math.max(this.seconds, other.seconds);
+ const date = this.date.getTime() < other.date.getTime() ? this.date : other.date;
+ return new Value(operation(this.value, other.value), decimals, seconds, this.unit, date);
+ }
+
+ static of(series: Series, value: number | null | undefined, date: Date | null | undefined): Value | null {
+ if (value === null || value === undefined) {
+ return null;
+ }
+ if (date === null || date === undefined) {
+ throw new Error("When 'value' is set, 'last' must be set too, but isn't!")
+ }
+ return new Value(value, series.precision, series.seconds, series.unit, date);
+ }
+
+ static ofPoint(response: PointResponse, seriesIndex: number, pointIndex: number, valueIndex: number): Value | null {
+ const series = response.series[seriesIndex];
+ if (!series) {
+ return null;
+ }
+
+ const point = series.points[pointIndex];
+ if (!point) {
+ return null;
+ }
+
+ const date = new Date(point[0] * 1000);
+ const value = point[valueIndex];
+ return Value.of(series.series, value, date);
+ }
+
+}
diff --git a/src/main/angular/src/app/series/select/series-select.html b/src/main/angular/src/app/series/select/series-select.html
index f5e896d..8ed6faa 100644
--- a/src/main/angular/src/app/series/select/series-select.html
+++ b/src/main/angular/src/app/series/select/series-select.html
@@ -8,12 +8,7 @@
@for (series of series; track series.id) {
}
diff --git a/src/main/angular/src/colors.less b/src/main/angular/src/colors.less
new file mode 100644
index 0000000..350e7fb
--- /dev/null
+++ b/src/main/angular/src/colors.less
@@ -0,0 +1,25 @@
+@empty: gray;
+@purchase: red;
+@deliver: magenta;
+@produce: #0095ff;
+@consume: #ff8800;
+
+.purchase {
+ color: @purchase;
+}
+
+.deliver {
+ color: @deliver;
+}
+
+.produce {
+ color: @produce;
+}
+
+.consume {
+ color: @consume;
+}
+
+.empty {
+ color: @empty !important;
+}
diff --git a/src/main/angular/src/styles.less b/src/main/angular/src/styles.less
index 313a070..e8cf5cc 100644
--- a/src/main/angular/src/styles.less
+++ b/src/main/angular/src/styles.less
@@ -32,10 +32,10 @@ div {
> .SectionHeading {
display: flex;
+ color: dimgray;
margin-top: -1.25em;
> .SectionHeadingText {
- font-weight: bold;
background-color: white;
}
}
@@ -45,7 +45,9 @@ div {
overflow: visible;
> .SectionHeading {
+ color: dimgray;
> .SectionHeadingText {
+ font-size: 70%;
font-style: italic;
}
}
@@ -65,10 +67,10 @@ div {
> .SectionHeading {
display: flex;
+ color: dimgray;
margin-top: -1.25em;
> .SectionHeadingText {
- font-weight: bold;
background-color: white;
}
}
@@ -81,14 +83,17 @@ div {
.Section4 {
flex: 1;
- text-align: center;
> .SectionHeadingText {
- font-weight: bold;
+ text-align: right;
+ font-size: 70%;
+ color: dimgray;
+ font-style: italic;
background-color: white;
}
> .SectionBody {
+ text-align: right;
}
}
diff --git a/src/main/java/de/ph87/data/series/Series.java b/src/main/java/de/ph87/data/series/Series.java
index d44ff4a..f30cd00 100644
--- a/src/main/java/de/ph87/data/series/Series.java
+++ b/src/main/java/de/ph87/data/series/Series.java
@@ -42,7 +42,7 @@ public class Series {
@Setter
@Column(nullable = false)
- private int decimals = 1;
+ private int precision = 2;
@Column
@Nullable
@@ -66,10 +66,10 @@ public class Series {
@Enumerated(EnumType.STRING)
private SeriesType type = SeriesType.VARYING;
- public Series(@NonNull final String name, @NonNull final String unit, final int decimals, final int seconds, @NonNull final SeriesType type) {
+ public Series(@NonNull final String name, @NonNull final String unit, final int precision, final int seconds, @NonNull final SeriesType type) {
this.name = name;
this.unit = unit;
- this.decimals = decimals;
+ this.precision = precision;
this.seconds = seconds;
this.type = type;
}
diff --git a/src/main/java/de/ph87/data/series/SeriesController.java b/src/main/java/de/ph87/data/series/SeriesController.java
index 6a49ee9..bcaf290 100644
--- a/src/main/java/de/ph87/data/series/SeriesController.java
+++ b/src/main/java/de/ph87/data/series/SeriesController.java
@@ -42,7 +42,7 @@ public class SeriesController {
@NonNull
@PostMapping("{id}/decimals")
public SeriesDto decimals(@PathVariable final long id, @RequestBody final int decimals) {
- return seriesService.modify(id, series -> series.setDecimals(decimals));
+ return seriesService.modify(id, series -> series.setPrecision(decimals));
}
@NonNull
diff --git a/src/main/java/de/ph87/data/series/SeriesDto.java b/src/main/java/de/ph87/data/series/SeriesDto.java
index c38de70..494e9cc 100644
--- a/src/main/java/de/ph87/data/series/SeriesDto.java
+++ b/src/main/java/de/ph87/data/series/SeriesDto.java
@@ -19,7 +19,7 @@ public class SeriesDto implements IWebsocketMessage {
@NonNull
public final String unit;
- public final int decimals;
+ public final int precision;
@Nullable
public final ZonedDateTime first;
@@ -40,7 +40,7 @@ public class SeriesDto implements IWebsocketMessage {
this.version = series.getVersion();
this.name = series.getName();
this.unit = series.getUnit();
- this.decimals = series.getDecimals();
+ this.precision = series.getPrecision();
this.first = series.getFirst();
this.last = series.getLast();
this.value = series.getValue();