added totals to Meter and Series + united MeterInbound/VaryingInbound via SeriesInbound
This commit is contained in:
parent
e7e2953d00
commit
04257cff9b
@ -24,7 +24,7 @@ public enum Alignment {
|
|||||||
@NonNull
|
@NonNull
|
||||||
public final BiFunction<ZonedDateTime, Long, ZonedDateTime> plus;
|
public final BiFunction<ZonedDateTime, Long, ZonedDateTime> plus;
|
||||||
|
|
||||||
Alignment(final @NonNull Duration maxDuration, @NonNull final Function<ZonedDateTime, ZonedDateTime> align, @NonNull final BiFunction<ZonedDateTime, Long, ZonedDateTime> plus) {
|
Alignment(@NonNull final Duration maxDuration, @NonNull final Function<@NonNull ZonedDateTime, @NonNull ZonedDateTime> align, @NonNull final BiFunction<@NonNull ZonedDateTime, @NonNull Long, @NonNull ZonedDateTime> plus) {
|
||||||
this.maxDuration = maxDuration;
|
this.maxDuration = maxDuration;
|
||||||
this.align = align;
|
this.align = align;
|
||||||
this.plus = plus;
|
this.plus = plus;
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package de.ph87.data.series;
|
package de.ph87.data.series;
|
||||||
|
|
||||||
|
import de.ph87.data.value.Value;
|
||||||
import de.ph87.data.value.*;
|
import de.ph87.data.value.*;
|
||||||
import jakarta.persistence.*;
|
import jakarta.persistence.*;
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
@ -43,11 +44,36 @@ public class Series {
|
|||||||
@Column(nullable = false)
|
@Column(nullable = false)
|
||||||
private boolean graphAutoscale = false;
|
private boolean graphAutoscale = false;
|
||||||
|
|
||||||
public Series(@NonNull final String name, @NonNull final Unit unit, @NonNull final SeriesType type) {
|
@Column(nullable = false)
|
||||||
|
private double min;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private double max;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private double avg;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private int count;
|
||||||
|
|
||||||
|
public Series(@NonNull final String name, @NonNull final Unit unit, @NonNull final SeriesType type, @NonNull final Value value) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.title = name;
|
this.title = name;
|
||||||
this.unit = unit;
|
this.unit = unit;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
|
|
||||||
|
final double converted = value.as(unit).value;
|
||||||
|
this.min = converted;
|
||||||
|
this.max = converted;
|
||||||
|
this.avg = converted;
|
||||||
|
this.count = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update(@NonNull final Value value) {
|
||||||
|
final double converted = value.as(unit).value;
|
||||||
|
this.min = Math.min(this.min, converted);
|
||||||
|
this.max = Math.max(this.max, converted);
|
||||||
|
this.avg = (this.avg * this.count + converted) / ++this.count;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
26
src/main/java/de/ph87/data/series/SeriesInbound.java
Normal file
26
src/main/java/de/ph87/data/series/SeriesInbound.java
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
package de.ph87.data.series;
|
||||||
|
|
||||||
|
import de.ph87.data.value.Value;
|
||||||
|
import lombok.*;
|
||||||
|
|
||||||
|
import java.time.*;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class SeriesInbound {
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public final String name;
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public final ZonedDateTime date;
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public final Value value;
|
||||||
|
|
||||||
|
public SeriesInbound(@NonNull final String name, @NonNull final ZonedDateTime date, @NonNull final Value value) {
|
||||||
|
this.name = name;
|
||||||
|
this.date = date;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,7 +1,6 @@
|
|||||||
package de.ph87.data.series;
|
package de.ph87.data.series;
|
||||||
|
|
||||||
import de.ph87.data.*;
|
import de.ph87.data.*;
|
||||||
import de.ph87.data.value.*;
|
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
import lombok.extern.slf4j.*;
|
import lombok.extern.slf4j.*;
|
||||||
import org.springframework.stereotype.*;
|
import org.springframework.stereotype.*;
|
||||||
@ -31,35 +30,41 @@ public class SeriesService {
|
|||||||
publish(series, Action.DELETED);
|
publish(series, Action.DELETED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
private Series getById(final long id) {
|
private Series getById(final long id) {
|
||||||
return seriesRepository.findById(id).orElseThrow();
|
return seriesRepository.findById(id).orElseThrow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
public SeriesDto getDtoById(final long id) {
|
public SeriesDto getDtoById(final long id) {
|
||||||
return toDto(getById(id));
|
return toDto(getById(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
private SeriesDto publish(@NonNull final Series series, @NonNull final Action action) {
|
private SeriesDto publish(@NonNull final Series series, @NonNull final Action action) {
|
||||||
final SeriesDto dto = toDto(series);
|
final SeriesDto dto = toDto(series);
|
||||||
log.info("Series {}: {}", action, series);
|
log.info("Series {}: {}", action, series);
|
||||||
return dto;
|
return dto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
private SeriesDto toDto(@NonNull final Series series) {
|
private SeriesDto toDto(@NonNull final Series series) {
|
||||||
return new SeriesDto(series);
|
return new SeriesDto(series);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Series getOrCreate(@NonNull final String name, @NonNull final Unit unit, @NonNull final SeriesType type) {
|
@NonNull
|
||||||
|
public Series getOrCreate(@NonNull final SeriesInbound inbound, @NonNull final SeriesType type) {
|
||||||
final Series series = seriesRepository
|
final Series series = seriesRepository
|
||||||
.findByName(name)
|
.findByName(inbound.getName())
|
||||||
.orElseGet(() -> {
|
.orElseGet(() -> {
|
||||||
final Series fresh = seriesRepository.save(new Series(name, unit, type));
|
final Series fresh = seriesRepository.save(new Series(inbound.name, inbound.value.unit, type, inbound.value));
|
||||||
publish(fresh, Action.CREATED);
|
publish(fresh, Action.CREATED);
|
||||||
return fresh;
|
return fresh;
|
||||||
});
|
});
|
||||||
if (series.getType() != type) {
|
if (series.getType() != type) {
|
||||||
log.warn("Existing Series type does not match requested type: requested={}, series={}", type, series);
|
log.warn("Existing Series type does not match requested type: requested={}, series={}", type, series);
|
||||||
}
|
}
|
||||||
|
series.update(inbound.value);
|
||||||
return series;
|
return series;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package de.ph87.data.series.meter;
|
package de.ph87.data.series.meter;
|
||||||
|
|
||||||
import de.ph87.data.series.*;
|
import de.ph87.data.series.*;
|
||||||
|
import de.ph87.data.value.Value;
|
||||||
import jakarta.persistence.*;
|
import jakarta.persistence.*;
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
|
|
||||||
@ -31,10 +32,26 @@ public class Meter {
|
|||||||
@Column(nullable = false)
|
@Column(nullable = false)
|
||||||
private String number;
|
private String number;
|
||||||
|
|
||||||
public Meter(@NonNull final Series series, @NonNull final ZonedDateTime date, @NonNull final String number) {
|
@Column(nullable = false)
|
||||||
|
private double min;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private double max;
|
||||||
|
|
||||||
|
public Meter(@NonNull final Series series, @NonNull final ZonedDateTime date, @NonNull final String number, @NonNull final Value value) {
|
||||||
this.series = series;
|
this.series = series;
|
||||||
this.date = date;
|
this.date = date;
|
||||||
this.number = number;
|
this.number = number;
|
||||||
|
|
||||||
|
final double converted = value.as(series.getUnit()).value;
|
||||||
|
this.min = converted;
|
||||||
|
this.max = converted;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update(@NonNull final Value value) {
|
||||||
|
final double converted = value.as(series.getUnit()).value;
|
||||||
|
this.min = Math.min(this.min, converted);
|
||||||
|
this.max = Math.max(this.max, converted);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package de.ph87.data.series.meter;
|
package de.ph87.data.series.meter;
|
||||||
|
|
||||||
|
import de.ph87.data.series.*;
|
||||||
import de.ph87.data.value.Value;
|
import de.ph87.data.value.Value;
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
|
|
||||||
@ -7,24 +8,14 @@ import java.time.*;
|
|||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@ToString
|
@ToString
|
||||||
public class MeterInbound {
|
public class MeterInbound extends SeriesInbound {
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public final String seriesName;
|
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
public final String meterNumber;
|
public final String meterNumber;
|
||||||
|
|
||||||
@NonNull
|
public MeterInbound(@NonNull final String name, @NonNull final String meterNumber, @NonNull final ZonedDateTime date, final Value value) {
|
||||||
public final ZonedDateTime date;
|
super(name, date, value);
|
||||||
|
|
||||||
public final Value value;
|
|
||||||
|
|
||||||
public MeterInbound(@NonNull final String seriesName, @NonNull final String meterNumber, @NonNull final ZonedDateTime date, final Value value) {
|
|
||||||
this.seriesName = seriesName;
|
|
||||||
this.meterNumber = meterNumber;
|
this.meterNumber = meterNumber;
|
||||||
this.date = date;
|
|
||||||
this.value = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,34 +40,37 @@ public class MeterService {
|
|||||||
private final MeterYearRepository meterYearRepository;
|
private final MeterYearRepository meterYearRepository;
|
||||||
|
|
||||||
@EventListener(MeterInbound.class)
|
@EventListener(MeterInbound.class)
|
||||||
public void onEvent(@NonNull final MeterInbound event) {
|
public void onEvent(@NonNull final MeterInbound inbound) {
|
||||||
final Meter meter = getOrCreate(event);
|
final Meter meter = getOrCreate(inbound);
|
||||||
|
|
||||||
final MeterValue.Id five = new MeterValue.Id(meter, event.date, Alignment.FIVE);
|
final MeterValue.Id five = new MeterValue.Id(meter, inbound.date, Alignment.FIVE);
|
||||||
meterFiveRepository.findById(five).ifPresentOrElse(existing -> existing.update(event.value), () -> meterFiveRepository.save(new MeterFive(five, event.value)));
|
meterFiveRepository.findById(five).ifPresentOrElse(existing -> existing.update(inbound.value), () -> meterFiveRepository.save(new MeterFive(five, inbound.value)));
|
||||||
|
|
||||||
final MeterValue.Id hour = new MeterValue.Id(meter, event.date, Alignment.HOUR);
|
final MeterValue.Id hour = new MeterValue.Id(meter, inbound.date, Alignment.HOUR);
|
||||||
meterHourRepository.findById(hour).ifPresentOrElse(existing -> existing.update(event.value), () -> meterHourRepository.save(new MeterHour(hour, event.value)));
|
meterHourRepository.findById(hour).ifPresentOrElse(existing -> existing.update(inbound.value), () -> meterHourRepository.save(new MeterHour(hour, inbound.value)));
|
||||||
|
|
||||||
final MeterValue.Id day = new MeterValue.Id(meter, event.date, Alignment.DAY);
|
final MeterValue.Id day = new MeterValue.Id(meter, inbound.date, Alignment.DAY);
|
||||||
meterDayRepository.findById(day).ifPresentOrElse(existing -> existing.update(event.value), () -> meterDayRepository.save(new MeterDay(day, event.value)));
|
meterDayRepository.findById(day).ifPresentOrElse(existing -> existing.update(inbound.value), () -> meterDayRepository.save(new MeterDay(day, inbound.value)));
|
||||||
|
|
||||||
final MeterValue.Id week = new MeterValue.Id(meter, event.date, Alignment.WEEK);
|
final MeterValue.Id week = new MeterValue.Id(meter, inbound.date, Alignment.WEEK);
|
||||||
meterWeekRepository.findById(week).ifPresentOrElse(existing -> existing.update(event.value), () -> meterWeekRepository.save(new MeterWeek(week, event.value)));
|
meterWeekRepository.findById(week).ifPresentOrElse(existing -> existing.update(inbound.value), () -> meterWeekRepository.save(new MeterWeek(week, inbound.value)));
|
||||||
|
|
||||||
final MeterValue.Id month = new MeterValue.Id(meter, event.date, Alignment.MONTH);
|
final MeterValue.Id month = new MeterValue.Id(meter, inbound.date, Alignment.MONTH);
|
||||||
meterMonthRepository.findById(month).ifPresentOrElse(existing -> existing.update(event.value), () -> meterMonthRepository.save(new MeterMonth(month, event.value)));
|
meterMonthRepository.findById(month).ifPresentOrElse(existing -> existing.update(inbound.value), () -> meterMonthRepository.save(new MeterMonth(month, inbound.value)));
|
||||||
|
|
||||||
final MeterValue.Id year = new MeterValue.Id(meter, event.date, Alignment.YEAR);
|
final MeterValue.Id year = new MeterValue.Id(meter, inbound.date, Alignment.YEAR);
|
||||||
meterYearRepository.findById(year).ifPresentOrElse(existing -> existing.update(event.value), () -> meterYearRepository.save(new MeterYear(year, event.value)));
|
meterYearRepository.findById(year).ifPresentOrElse(existing -> existing.update(inbound.value), () -> meterYearRepository.save(new MeterYear(year, inbound.value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private Meter getOrCreate(@NonNull final MeterInbound event) {
|
private Meter getOrCreate(@NonNull final MeterInbound inbound) {
|
||||||
final Series series = seriesService.getOrCreate(event.seriesName, event.value.unit, SeriesType.METER);
|
final Series series = seriesService.getOrCreate(inbound, SeriesType.METER);
|
||||||
return meterRepository.findFirstBySeriesOrderByDateDesc(series)
|
return meterRepository.findFirstBySeriesOrderByDateDesc(series)
|
||||||
.filter(m -> m.getNumber().equals(event.meterNumber))
|
.filter(m -> m.getNumber().equals(inbound.meterNumber))
|
||||||
.orElseGet(() -> meterRepository.save(new Meter(series, event.date, event.meterNumber)));
|
.stream()
|
||||||
|
.peek(existing -> existing.update(inbound.value))
|
||||||
|
.findFirst()
|
||||||
|
.orElseGet(() -> meterRepository.save(new Meter(series, inbound.date, inbound.meterNumber, inbound.value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@ -80,7 +83,7 @@ public class MeterService {
|
|||||||
case MONTH -> meterMonthRepository.findAllByIdMeterSeriesIdAndIdDateGreaterThanEqualAndIdDateLessThanEqualOrderByIdDate(series.id, begin.date, end.date);
|
case MONTH -> meterMonthRepository.findAllByIdMeterSeriesIdAndIdDateGreaterThanEqualAndIdDateLessThanEqualOrderByIdDate(series.id, begin.date, end.date);
|
||||||
case YEAR -> meterYearRepository.findAllByIdMeterSeriesIdAndIdDateGreaterThanEqualAndIdDateLessThanEqualOrderByIdDate(series.id, begin.date, end.date);
|
case YEAR -> meterYearRepository.findAllByIdMeterSeriesIdAndIdDateGreaterThanEqualAndIdDateLessThanEqualOrderByIdDate(series.id, begin.date, end.date);
|
||||||
};
|
};
|
||||||
final List<GraphPoint> points = graphPoints.stream().map(v -> new GraphPoint(v.getId().getDate(), v.getMax() - v.getMin())).collect(Collectors.toCollection(LinkedList::new));
|
final List<GraphPoint> points = graphPoints.stream().map(meterValue -> new GraphPoint(meterValue.getId().getDate(), meterValue.getMax() - meterValue.getMin())).collect(Collectors.toCollection(LinkedList::new));
|
||||||
for (int i = 0; i < points.size() - 1; i++) {
|
for (int i = 0; i < points.size() - 1; i++) {
|
||||||
if (points.get(i).date.compareTo(points.get(i + 1).date) == 0) {
|
if (points.get(i).date.compareTo(points.get(i + 1).date) == 0) {
|
||||||
final GraphPoint first = points.remove(i);
|
final GraphPoint first = points.remove(i);
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package de.ph87.data.series.varying;
|
package de.ph87.data.series.varying;
|
||||||
|
|
||||||
|
import de.ph87.data.series.*;
|
||||||
import de.ph87.data.value.Value;
|
import de.ph87.data.value.Value;
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
|
|
||||||
@ -7,20 +8,10 @@ import java.time.*;
|
|||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@ToString
|
@ToString
|
||||||
public class VaryingInbound {
|
public class VaryingInbound extends SeriesInbound {
|
||||||
|
|
||||||
@NonNull
|
public VaryingInbound(@NonNull final String name, @NonNull final ZonedDateTime date, @NonNull final Value value) {
|
||||||
public final String name;
|
super(name, date, value);
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public final ZonedDateTime date;
|
|
||||||
|
|
||||||
public final Value value;
|
|
||||||
|
|
||||||
public VaryingInbound(@NonNull final String name, @NonNull final ZonedDateTime date, final Value value) {
|
|
||||||
this.name = name;
|
|
||||||
this.date = date;
|
|
||||||
this.value = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,6 +26,8 @@ public class VaryingService {
|
|||||||
|
|
||||||
private final VaryingFiveRepository varyingFiveRepository;
|
private final VaryingFiveRepository varyingFiveRepository;
|
||||||
|
|
||||||
|
private final VaryingHourRepository varyingHourRepository;
|
||||||
|
|
||||||
private final VaryingDayRepository varyingDayRepository;
|
private final VaryingDayRepository varyingDayRepository;
|
||||||
|
|
||||||
private final VaryingWeekRepository varyingWeekRepository;
|
private final VaryingWeekRepository varyingWeekRepository;
|
||||||
@ -34,29 +36,27 @@ public class VaryingService {
|
|||||||
|
|
||||||
private final VaryingYearRepository varyingYearRepository;
|
private final VaryingYearRepository varyingYearRepository;
|
||||||
|
|
||||||
private final VaryingHourRepository varyingHourRepository;
|
|
||||||
|
|
||||||
@EventListener(VaryingInbound.class)
|
@EventListener(VaryingInbound.class)
|
||||||
public void onEvent(@NonNull final VaryingInbound event) {
|
public void onEvent(@NonNull final VaryingInbound inbound) {
|
||||||
final Series series = seriesService.getOrCreate(event.name, event.value.unit, SeriesType.VARYING);
|
final Series series = seriesService.getOrCreate(inbound, SeriesType.VARYING);
|
||||||
|
|
||||||
final Varying.Id five = new Varying.Id(series, event.date, Alignment.FIVE);
|
final Varying.Id five = new Varying.Id(series, inbound.date, Alignment.FIVE);
|
||||||
varyingFiveRepository.findById(five).ifPresentOrElse(existing -> existing.update(event.value), () -> varyingFiveRepository.save(new VaryingFive(five, event.value)));
|
varyingFiveRepository.findById(five).ifPresentOrElse(existing -> existing.update(inbound.value), () -> varyingFiveRepository.save(new VaryingFive(five, inbound.value)));
|
||||||
|
|
||||||
final Varying.Id hour = new Varying.Id(series, event.date, Alignment.HOUR);
|
final Varying.Id hour = new Varying.Id(series, inbound.date, Alignment.HOUR);
|
||||||
varyingHourRepository.findById(hour).ifPresentOrElse(existing -> existing.update(event.value), () -> varyingHourRepository.save(new VaryingHour(hour, event.value)));
|
varyingHourRepository.findById(hour).ifPresentOrElse(existing -> existing.update(inbound.value), () -> varyingHourRepository.save(new VaryingHour(hour, inbound.value)));
|
||||||
|
|
||||||
final Varying.Id day = new Varying.Id(series, event.date, Alignment.DAY);
|
final Varying.Id day = new Varying.Id(series, inbound.date, Alignment.DAY);
|
||||||
varyingDayRepository.findById(day).ifPresentOrElse(existing -> existing.update(event.value), () -> varyingDayRepository.save(new VaryingDay(day, event.value)));
|
varyingDayRepository.findById(day).ifPresentOrElse(existing -> existing.update(inbound.value), () -> varyingDayRepository.save(new VaryingDay(day, inbound.value)));
|
||||||
|
|
||||||
final Varying.Id week = new Varying.Id(series, event.date, Alignment.WEEK);
|
final Varying.Id week = new Varying.Id(series, inbound.date, Alignment.WEEK);
|
||||||
varyingWeekRepository.findById(week).ifPresentOrElse(existing -> existing.update(event.value), () -> varyingWeekRepository.save(new VaryingWeek(week, event.value)));
|
varyingWeekRepository.findById(week).ifPresentOrElse(existing -> existing.update(inbound.value), () -> varyingWeekRepository.save(new VaryingWeek(week, inbound.value)));
|
||||||
|
|
||||||
final Varying.Id month = new Varying.Id(series, event.date, Alignment.MONTH);
|
final Varying.Id month = new Varying.Id(series, inbound.date, Alignment.MONTH);
|
||||||
varyingMonthRepository.findById(month).ifPresentOrElse(existing -> existing.update(event.value), () -> varyingMonthRepository.save(new VaryingMonth(month, event.value)));
|
varyingMonthRepository.findById(month).ifPresentOrElse(existing -> existing.update(inbound.value), () -> varyingMonthRepository.save(new VaryingMonth(month, inbound.value)));
|
||||||
|
|
||||||
final Varying.Id year = new Varying.Id(series, event.date, Alignment.YEAR);
|
final Varying.Id year = new Varying.Id(series, inbound.date, Alignment.YEAR);
|
||||||
varyingYearRepository.findById(year).ifPresentOrElse(existing -> existing.update(event.value), () -> varyingYearRepository.save(new VaryingYear(year, event.value)));
|
varyingYearRepository.findById(year).ifPresentOrElse(existing -> existing.update(inbound.value), () -> varyingYearRepository.save(new VaryingYear(year, inbound.value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user