diff --git a/src/app/chart/statistics/statistics.component.html b/src/app/chart/statistics/statistics.component.html index 8c40f48..7ad4328 100644 --- a/src/app/chart/statistics/statistics.component.html +++ b/src/app/chart/statistics/statistics.component.html @@ -1,11 +1,29 @@ -
-
- Laagste: {{ format(statistics.min) }} -
-
- Hoogste: {{ format(statistics.max) }} -
-
- Gemiddelde: {{ format(statistics.avg) }} -
+
+ + + + + + +
+ Min: {{ format(statistics.min) }} + + Max: {{ format(statistics.max) }} + + Gem.: {{ format(statistics.avg) }} +
+ + + + + + + +
+ Min: {{ format(statistics.min) }} + + Max: {{ format(statistics.max) }} + + Gem.: {{ format(statistics.avg) }} +
diff --git a/src/app/chart/statistics/statistics.component.ts b/src/app/chart/statistics/statistics.component.ts index 25e53cb..d7148b6 100644 --- a/src/app/chart/statistics/statistics.component.ts +++ b/src/app/chart/statistics/statistics.component.ts @@ -15,11 +15,6 @@ export class StatisticsComponent { @Input() public decimalFormat: string; - @Input() - public valuePrefix = ''; - @Input() - public valuePostfix = ''; - @Input() public additionalClasses = ''; @@ -29,6 +24,9 @@ export class StatisticsComponent { if (value === undefined || value === null || isNaN(value)) { return '-'; } - return this.valuePrefix + this.decimalPipe.transform(value, this.decimalFormat) + this.valuePostfix; + let formatted = this.statistics.prefix ? this.statistics.prefix : ''; + formatted = formatted + this.decimalPipe.transform(value, this.decimalFormat); + formatted = this.statistics.postfix ? formatted + this.statistics.postfix : formatted; + return formatted } } diff --git a/src/app/energie-verbruik/energie-verbruik-base-chart.service.ts b/src/app/energie-verbruik/energie-verbruik-base-chart.service.ts index 0e8781d..65bb762 100644 --- a/src/app/energie-verbruik/energie-verbruik-base-chart.service.ts +++ b/src/app/energie-verbruik/energie-verbruik-base-chart.service.ts @@ -6,6 +6,8 @@ import startsWith from 'lodash-es/startsWith'; import capitalize from 'lodash-es/capitalize'; import {DecimalPipe} from '@angular/common'; import {ChartService} from '../chart/chart.service'; +import {VerbruikKostenOverzicht} from './verbruikKostenOverzicht'; +import {Statistics} from '../statistics'; const dataColors: {[key: string]: string} = { 'stroomVerbruikDal': '#4575b3', @@ -58,11 +60,14 @@ export abstract class AbstractEnergieVerbruikHistorieService extends ChartServic public formatWithUnitLabel(verbruiksoort: string, energieSoorten: string[], value: number) { const withoutUnitLabel = this.formatWithoutUnitLabel(verbruiksoort, value); - if (verbruiksoort === 'verbruik') { - return withoutUnitLabel + ' ' + this.getVerbruikLabel(energieSoorten[0]); - } else if (verbruiksoort === 'kosten') { - return '\u20AC ' + withoutUnitLabel; - } + + const prefix = verbruiksoort === 'kosten' ? this.getVerbruikSoortPrefix(verbruiksoort) : ''; + const postfix = verbruiksoort === 'verbruik' ? this.getEnergiesoortPostfix(energieSoorten[0]) : ''; + + let formatted = prefix ? prefix + ' ' : ''; + formatted = formatted + withoutUnitLabel; + formatted = postfix ? formatted + ' ' + postfix : formatted; + return formatted; } protected getTooltipContent(c3, data, titleFormatter, _valueFormatter, color, verbruiksoort: string, energiesoorten: string[]) { @@ -111,13 +116,21 @@ export abstract class AbstractEnergieVerbruikHistorieService extends ChartServic } // noinspection JSMethodCanBeStatic - private getVerbruikLabel(energiesoort: string) { + public getEnergiesoortPostfix(energiesoort: string) { if (energiesoort === 'stroom') { return 'kWh'; } else if (energiesoort === 'gas') { return 'm\u00B3'; } else { - return '?'; + return null; + } + } + + public getVerbruikSoortPrefix(verbruiksoort: string) { + if (verbruiksoort === 'kosten') { + return '\u20AC'; + } else { + return null; } } @@ -154,4 +167,137 @@ export abstract class AbstractEnergieVerbruikHistorieService extends ChartServic } return newEnergiesoorten; } + + public getStatistics(verbruiksoort: string, energiesoorten: string[], verbruiken: VerbruikKostenOverzicht[]): Statistics { + return { + avg: this.getAvg(verbruiksoort, energiesoorten, verbruiken), + min: this.getMin(verbruiksoort, energiesoorten, verbruiken), + max: this.getMax(verbruiksoort, energiesoorten, verbruiken), + prefix: verbruiksoort === 'kosten' ? this.getVerbruikSoortPrefix(verbruiksoort) + ' ' : '', + postfix: verbruiksoort === 'verbruik' ? ' ' + this.getEnergiesoortPostfix(energiesoorten[0]) : '' + }; + } + + protected getAvg(verbruiksoort: string, energiesoorten: string[], verbruiken: VerbruikKostenOverzicht[]): number { + const numberOfNonEmptyVerbruiken = this.getNonEmptyValues(verbruiken, verbruiksoort, energiesoorten).length; + if (numberOfNonEmptyVerbruiken === 0) { + return null; + } + return this.getSum(verbruiksoort, energiesoorten, verbruiken) / numberOfNonEmptyVerbruiken; + } + + protected getMin(verbruiksoort: string, energiesoorten: string[], verbruiken: VerbruikKostenOverzicht[]): number { + let nonEmptyValues = this.getNonEmptyValues(verbruiken, verbruiksoort, energiesoorten); + if (nonEmptyValues.length === 0) { + return null; + } + if (verbruiksoort === 'verbruik') { + return this.getMinVerbruik(energiesoorten, verbruiken); + } else if (verbruiksoort === 'kosten') { + return this.getMinKosten(energiesoorten, verbruiken); + } + return null; + } + + private getMinVerbruik(energiesoorten: string[], verbruiken: VerbruikKostenOverzicht[]) { + if (energiesoorten[0] === 'gas') { + return Math.min(...verbruiken.filter(value => value.gasVerbruik > 0) + .map(value => value.gasVerbruik)); + } else { + return Math.min(...verbruiken.filter(value => (value.stroomVerbruikDal + value.stroomVerbruikNormaal) > 0) + .map(value => value.stroomVerbruikDal + value.stroomVerbruikNormaal)); + } + } + + private getMinKosten(energiesoorten: string[], verbruiken: VerbruikKostenOverzicht[]) { + if (energiesoorten.length === 2) { + return Math.min(...verbruiken.map(value => value.gasKosten + value.stroomKostenDal + value.stroomKostenNormaal)); + } else if (energiesoorten[0] === 'gas') { + return Math.min(...verbruiken.map(value => value.gasKosten)); + } else { + return Math.min(...verbruiken.map(value => value.stroomKostenDal + value.stroomKostenNormaal)); + } + } + + protected getMax(verbruiksoort: string, energiesoorten: string[], verbruiken: VerbruikKostenOverzicht[]): number { + let nonEmptyValues = this.getNonEmptyValues(verbruiken, verbruiksoort, energiesoorten); + if (nonEmptyValues.length === 0) { + return null; + } + if (verbruiksoort === 'verbruik') { + return this.getMaxVerbruik(energiesoorten, verbruiken); + } else if (verbruiksoort === 'kosten') { + return this.getMaxKosten(energiesoorten, verbruiken); + } + return null; + } + + private getMaxVerbruik(energiesoorten: string[], verbruiken: VerbruikKostenOverzicht[]) { + if (energiesoorten[0] === 'gas') { + return Math.max(...verbruiken.filter(value => value.gasVerbruik > 0) + .map(value => value.gasVerbruik)); + } else { + return Math.max(...verbruiken.filter(value => (value.stroomVerbruikDal + value.stroomVerbruikNormaal) > 0) + .map(value => value.stroomVerbruikDal + value.stroomVerbruikNormaal)); + } + } + + private getMaxKosten(energiesoorten: string[], verbruiken: VerbruikKostenOverzicht[]) { + if (energiesoorten.length === 2) { + return Math.max(...verbruiken.map(value => value.gasKosten + value.stroomKostenDal + value.stroomKostenNormaal)); + } else if (energiesoorten[0] === 'gas') { + return Math.max(...verbruiken.map(value => value.gasKosten)); + } else { + return Math.max(...verbruiken.map(value => value.stroomKostenDal + value.stroomKostenNormaal)); + } + } + + private getValue(verbruiksoort: string, energiesoorten: string[], verbruik: VerbruikKostenOverzicht): number { + if (verbruiksoort === 'verbruik') { + return this.getVerbruikValue(energiesoorten, verbruik); + } else if (verbruiksoort === 'kosten') { + return this.getKostenValue(energiesoorten, verbruik); + } + } + + private getVerbruikValue(energiesoorten: string[], verbruik: VerbruikKostenOverzicht) { + if (energiesoorten[0] === 'gas') { + return verbruik.gasVerbruik; + } else { + return this.allNull([verbruik.stroomVerbruikDal, verbruik.stroomVerbruikNormaal]) + ? null : verbruik.stroomVerbruikDal + verbruik.stroomVerbruikNormaal; + } + } + + private getKostenValue(energiesoorten: string[], verbruik: VerbruikKostenOverzicht) { + if (energiesoorten.length === 2) { + return this.allNull([verbruik.stroomKostenDal, verbruik.stroomKostenNormaal, verbruik.gasKosten]) + ? null : verbruik.stroomKostenDal + verbruik.stroomKostenNormaal + verbruik.gasKosten; + } else if (energiesoorten[0] === 'gas') { + return verbruik.gasKosten; + } else { + return this.allNull([verbruik.stroomKostenDal, verbruik.stroomKostenNormaal]) + ? null : verbruik.stroomKostenDal + verbruik.stroomKostenNormaal; + } + } + + private getSum(verbruiksoort: string, energiesoorten: string[], verbruiken: VerbruikKostenOverzicht[]): number { + const values = this.getNonEmptyValues(verbruiken, verbruiksoort, energiesoorten); + if (values.length === 0) { + return null; + } + return values.reduce((accumulator, current) => { + return accumulator + current; + }, 0); + } + + private getNonEmptyValues(verbruiken: VerbruikKostenOverzicht[], verbruiksoort: string, energiesoorten: string[]) { + return verbruiken + .map(verbruik => this.getValue(verbruiksoort, energiesoorten, verbruik)) + .filter(value => value !== null); + } + + private allNull(values: any[]): boolean { + return values.filter(value => value === null).length === values.length; + } } diff --git a/src/app/energie-verbruik/energie-verbruik-dag-historie.service.ts b/src/app/energie-verbruik/energie-verbruik-dag-historie.service.ts index b014ee5..ed4cb4d 100644 --- a/src/app/energie-verbruik/energie-verbruik-dag-historie.service.ts +++ b/src/app/energie-verbruik/energie-verbruik-dag-historie.service.ts @@ -95,12 +95,12 @@ export class EnergieVerbruikDagHistorieService extends AbstractEnergieVerbruikHi return this.formatDate(verbruikOpDag.dag); } + public getDayjs(_selectedDate: Dayjs, verbruikOpDag: VerbruikOpDag): Dayjs { + return dayjs(verbruikOpDag.dag); + } + // noinspection JSMethodCanBeStatic private formatDate(date: any): string { return capitalize(dayjs(date).format('ddd DD-MM')); } - - public getDayjs(_selectedDate: Dayjs, verbruikOpDag: VerbruikOpDag): Dayjs { - return dayjs(verbruikOpDag.dag); - } } diff --git a/src/app/energie-verbruik/energie-verbruik-historie.service.ts b/src/app/energie-verbruik/energie-verbruik-historie.service.ts index e0a5d24..a97530e 100644 --- a/src/app/energie-verbruik/energie-verbruik-historie.service.ts +++ b/src/app/energie-verbruik/energie-verbruik-historie.service.ts @@ -6,6 +6,10 @@ export interface EnergieVerbruikHistorieService { getVerbruiken(selectedDate: Dayjs): Observable; + getStatistics(verbruiksoort: string, + energiesoorten: string[], + verbruiken: T[]); + getEmptyChartConfig(): ChartConfiguration; getChartConfig(selectedDate: Dayjs, diff --git a/src/app/energie-verbruik/energie-verbruik-maand-historie.service.ts b/src/app/energie-verbruik/energie-verbruik-maand-historie.service.ts index 8a9c7c5..cee7cda 100644 --- a/src/app/energie-verbruik/energie-verbruik-maand-historie.service.ts +++ b/src/app/energie-verbruik/energie-verbruik-maand-historie.service.ts @@ -77,3 +77,4 @@ export class EnergieVerbruikMaandHistorieService extends AbstractEnergieVerbruik return dayjs(year + '-' + month + '-' + day); } } + diff --git a/src/app/energie-verbruik/energie-verbruik-uur-historie.service.ts b/src/app/energie-verbruik/energie-verbruik-uur-historie.service.ts index 7f4188a..1f53678 100644 --- a/src/app/energie-verbruik/energie-verbruik-uur-historie.service.ts +++ b/src/app/energie-verbruik/energie-verbruik-uur-historie.service.ts @@ -60,11 +60,11 @@ export class EnergieVerbruikUurHistorieService extends AbstractEnergieVerbruikHi return this.formatUur(verbruikInUur.uur); } - private formatUur(uur: number): string { - return `${this.decimalPipe.transform(uur, '2.0-0')}:00 - ${this.decimalPipe.transform(uur + 1, '2.0-0')}:00`; - } - public getDayjs(selectedDate: Dayjs, _verbruikInUur: VerbruikInUur): Dayjs { return selectedDate.clone(); } + + private formatUur(uur: number): string { + return `${this.decimalPipe.transform(uur, '2.0-0')}:00 - ${this.decimalPipe.transform(uur + 1, '2.0-0')}:00`; + } } diff --git a/src/app/energie-verbruik/energie-verbruik.component.html b/src/app/energie-verbruik/energie-verbruik.component.html index 808b5d0..26de1b3 100644 --- a/src/app/energie-verbruik/energie-verbruik.component.html +++ b/src/app/energie-verbruik/energie-verbruik.component.html @@ -1,128 +1,142 @@ -
-
 
+
+
+
 
-
- +
-
- -
+ +
- -
-
- -
-
- + +
+
+ +
+
+ +
-
- -
-
- -
-
- + +
+
+ +
+
+ +
-
- -
-
- -
-
- -
-
- + +
+
+ +
+
+ +
+
+ +
+
+ +
-
- -
-
- -
- + +
+ +
-
-
-
- -
+
+
+ +
-
-
-
- - +
+
+
+
+ - - + + - - - - + + + + - -
Gas Stroom Totaal
{{ getFormattedDate(verbruik) }}{{ getFormattedValue(verbruik, 'gas') }}{{ getFormattedValue(verbruik, 'stroom') }}{{ getFormattedTotalCosts(verbruik) }}{{ getFormattedDate(verbruik) }}{{ getFormattedValue(verbruik, 'gas') }}{{ getFormattedValue(verbruik, 'stroom') }}{{ getFormattedTotalCosts(verbruik) }}
+ + +
-
+ +
+
+
 
+
+ + +
+
+
+ diff --git a/src/app/energie-verbruik/energie-verbruik.component.ts b/src/app/energie-verbruik/energie-verbruik.component.ts index abcee7a..0010681 100644 --- a/src/app/energie-verbruik/energie-verbruik.component.ts +++ b/src/app/energie-verbruik/energie-verbruik.component.ts @@ -13,6 +13,7 @@ import {VerbruikKostenOverzicht} from './verbruikKostenOverzicht'; import {NgxSpinnerService} from 'ngx-spinner'; import dayjs, {Dayjs} from 'dayjs'; import {faFireFlameCurved, faPlugCircleBolt} from '@fortawesome/free-solid-svg-icons'; +import {Statistics} from '../statistics'; const periodeToDateNavigatorModeMapping: Map = new Map([ @@ -34,13 +35,15 @@ export class EnergieVerbruikComponent implements OnInit { public showChart = false; public showTable = false; - public dateNavigatorMode: string; public selectedDate: Dayjs = dayjs(); + public dateNavigatorMode: string; public verbruiksoort = ''; public energiesoorten: string[] = []; - public periode = ''; + public statistics: Statistics; + public periode = ''; private chart: ChartAPI; + public verbruiken: any[] = []; private energieVerbruikHistorieService: EnergieVerbruikHistorieService; @@ -109,6 +112,8 @@ export class EnergieVerbruikComponent implements OnInit { private loadData(verbruiken: any[]) { this.verbruiken = verbruiken; + this.statistics = this.energieVerbruikHistorieService.getStatistics(this.verbruiksoort, this.energiesoorten, this.verbruiken); + if (this.showChart) { this.loadDataIntoChart(); } else if (this.showTable) { @@ -121,11 +126,9 @@ export class EnergieVerbruikComponent implements OnInit { } private loadDataIntoChart(): void { - const chartConfiguration: ChartConfiguration = this.energieVerbruikHistorieService.getChartConfig(this.selectedDate, - this.verbruiksoort, - this.energiesoorten, - this.verbruiken, - (date: Dayjs) => this.navigateToDetails(date)); + const chartConfiguration: ChartConfiguration = this.energieVerbruikHistorieService.getChartConfig( + this.selectedDate, this.verbruiksoort, this.energiesoorten, this.verbruiken, + (date: Dayjs) => this.navigateToDetails(date)); this.loadChartConfiguration(chartConfiguration); } @@ -176,7 +179,7 @@ export class EnergieVerbruikComponent implements OnInit { } public determineChartOrTable() { - const autoChartOrTableThreshold = 500; + const autoChartOrTableThreshold = 576; // Corresponds with Bootstrap SM if (window.innerWidth >= autoChartOrTableThreshold) { this.doShowChart(); } else { @@ -241,4 +244,8 @@ export class EnergieVerbruikComponent implements OnInit { } return ''; } + + public getDecimalFormat(): string { + return '1.3-3'; + } } diff --git a/src/app/energie-verbruik/energie-verbuik-component.scss b/src/app/energie-verbruik/energie-verbuik-component.scss index d347928..3f74688 100644 --- a/src/app/energie-verbruik/energie-verbuik-component.scss +++ b/src/app/energie-verbruik/energie-verbuik-component.scss @@ -1,3 +1,24 @@ +@import "node_modules/bootstrap/scss/functions"; +@import "node_modules/bootstrap/scss/variables"; +@import "node_modules/bootstrap/scss/mixins/_breakpoints"; + .electricity-gas-toggle-button { width: 8em; } + +// Style the statistics row so that the with is the same as the graph/table area. +// So that the the background color of the two elements "match". +.statistics-row { + margin-right: 0; + margin-left: 0; +} +@include media-breakpoint-up(lg) { + .statistics-row { + margin-left: 2px; + } +} + +.sticky-footer { + position: sticky; + bottom: 0; +} diff --git a/src/app/klimaat/klimaat-historie/klimaat-historie-component.scss b/src/app/klimaat/klimaat-historie/klimaat-historie-component.scss new file mode 100644 index 0000000..4352f43 --- /dev/null +++ b/src/app/klimaat/klimaat-historie/klimaat-historie-component.scss @@ -0,0 +1,15 @@ +@import "node_modules/bootstrap/scss/functions"; +@import "node_modules/bootstrap/scss/variables"; +@import "node_modules/bootstrap/scss/mixins/_breakpoints"; + +// Style the statistics row so that the with is the same as the graph/table area. +// So that the the background color of the two elements "match". +.statistics-row { + margin-right: 0; + margin-left: 0; +} +@include media-breakpoint-up(lg) { + .statistics-row { + margin-left: 2px; + } +} diff --git a/src/app/klimaat/klimaat-historie/klimaat-historie.component.html b/src/app/klimaat/klimaat-historie/klimaat-historie.component.html index d2c5f71..958b91d 100644 --- a/src/app/klimaat/klimaat-historie/klimaat-historie.component.html +++ b/src/app/klimaat/klimaat-historie/klimaat-historie.component.html @@ -69,9 +69,9 @@
-
-
 
+
+
 
- +
diff --git a/src/app/klimaat/klimaat-historie/klimaat-historie.component.ts b/src/app/klimaat/klimaat-historie/klimaat-historie.component.ts index 84586ca..eef5f85 100644 --- a/src/app/klimaat/klimaat-historie/klimaat-historie.component.ts +++ b/src/app/klimaat/klimaat-historie/klimaat-historie.component.ts @@ -25,7 +25,8 @@ import {faDroplet, faThermometerHalf} from '@fortawesome/free-solid-svg-icons'; @Component({ selector: 'home-klimaat-historie', - templateUrl: './klimaat-historie.component.html' + templateUrl: './klimaat-historie.component.html', + styleUrls: ['./klimaat-historie-component.scss'] }) export class KlimaatHistorieComponent implements OnInit { faDroplet = faDroplet; @@ -324,7 +325,12 @@ export class KlimaatHistorieComponent implements OnInit { private getStatistics(klimaats: Klimaat[]): Statistics { const values: number[] = filter(map(klimaats, this.sensorType), (value: number) => value !== null && value > 0); - return new Statistics(min(values), max(values), mean(values)); + return { + min: min(values), + max: max(values), + avg: mean(values), + postfix: this.getValuePostFix(this.sensorType) + }; } // noinspection JSMethodCanBeStatic diff --git a/src/app/opgenomen-vermogen/opgenomen-vermogen.component.ts b/src/app/opgenomen-vermogen/opgenomen-vermogen.component.ts index b22f8d1..36de271 100644 --- a/src/app/opgenomen-vermogen/opgenomen-vermogen.component.ts +++ b/src/app/opgenomen-vermogen/opgenomen-vermogen.component.ts @@ -179,7 +179,11 @@ export class OpgenomenVermogenComponent implements OnInit { // noinspection JSMethodCanBeStatic private getStatistics(opgenomenVermogens: OpgenomenVermogen[]): Statistics { const watts: number[] = filter(map(opgenomenVermogens, 'watt'), (watt: number) => watt !== null && watt > 0); - return new Statistics(min(watts), max(watts), mean(watts)); + return { + min: min(watts), + max: max(watts), + avg: mean(watts) + }; } public periodLengthChanged(): void { diff --git a/src/app/statistics.ts b/src/app/statistics.ts index 7d92790..9f3e55e 100644 --- a/src/app/statistics.ts +++ b/src/app/statistics.ts @@ -1,7 +1,7 @@ -export class Statistics { - - constructor(public min: number, - public max: number, - public avg: number) { - } +export interface Statistics { + min: number; + max: number; + avg: number, + prefix?: string, + postfix?: string }