Skip to content

Commit a6e9e5f

Browse files
authored
DAVE-760 Spitzenstunde Auswertung Messstelle (#401)
1 parent ff048bc commit a6e9e5f

File tree

8 files changed

+530
-41
lines changed

8 files changed

+530
-41
lines changed

src/main/java/de/muenchen/dave/domain/dtos/laden/messwerte/BelastungsplanMessquerschnitteDTO.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
package de.muenchen.dave.domain.dtos.laden.messwerte;
22

3+
import com.fasterxml.jackson.annotation.JsonFormat;
4+
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
5+
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
6+
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
7+
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
38
import java.io.Serializable;
49
import java.math.BigDecimal;
510
import java.time.LocalTime;
@@ -8,16 +13,34 @@
813

914
@Data
1015
public class BelastungsplanMessquerschnitteDTO implements Serializable {
16+
1117
private List<LadeBelastungsplanMessquerschnittDataDTO> ladeBelastungsplanMessquerschnittDataDTOList;
18+
1219
private String strassenname;
20+
1321
private String mstId;
22+
1423
private Integer stadtbezirkNummer;
24+
1525
private Integer totalKfz;
26+
1627
private Integer totalSv;
28+
1729
private Integer totalGv;
30+
1831
private Integer totalRad;
32+
1933
private BigDecimal totalPercentSv;
34+
2035
private BigDecimal totalPercentGv;
36+
37+
@JsonDeserialize(using = LocalTimeDeserializer.class)
38+
@JsonSerialize(using = LocalTimeSerializer.class)
39+
@JsonFormat(pattern = "HH:mm")
2140
private LocalTime startUhrzeitSpitzenstunde;
41+
42+
@JsonDeserialize(using = LocalTimeDeserializer.class)
43+
@JsonSerialize(using = LocalTimeSerializer.class)
44+
@JsonFormat(pattern = "HH:mm")
2245
private LocalTime endeUhrzeitSpitzenstunde;
2346
}

src/main/java/de/muenchen/dave/services/messstelle/BelastungsplanService.java

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
import de.muenchen.dave.domain.dtos.messstelle.MessstelleOptionsDTO;
66
import de.muenchen.dave.domain.dtos.messstelle.ReadMessquerschnittDTO;
77
import de.muenchen.dave.domain.dtos.messstelle.ReadMessstelleInfoDTO;
8+
import de.muenchen.dave.domain.enums.Zeitauswahl;
89
import de.muenchen.dave.geodateneai.gen.model.IntervalDto;
10+
import de.muenchen.dave.util.OptionsUtil;
911
import de.muenchen.dave.util.messstelle.MesswerteBaseUtil;
1012
import java.math.BigDecimal;
1113
import java.math.RoundingMode;
@@ -35,7 +37,7 @@ protected static String getStrassennameFromMessquerschnitt(final ReadMessstelleI
3537

3638
public BelastungsplanMessquerschnitteDTO ladeBelastungsplan(
3739
final List<IntervalDto> intervals,
38-
final List<IntervalDto> totalSumOfAllMessquerschnitte,
40+
final List<IntervalDto> totalSumForEachMessquerschnitt,
3941
final String messstelleId,
4042
final MessstelleOptionsDTO options) {
4143

@@ -47,7 +49,7 @@ public BelastungsplanMessquerschnitteDTO ladeBelastungsplan(
4749
belastungsplanMessquerschnitte.setStadtbezirkNummer(messstelle.getStadtbezirkNummer());
4850
belastungsplanMessquerschnitte.setStrassenname(getStrassennameFromMessquerschnitt(messstelle));
4951

50-
final var messquerschnitte = totalSumOfAllMessquerschnitte
52+
final var messquerschnitte = totalSumForEachMessquerschnitt
5153
.stream()
5254
.map(sumOfMessquerschnitt -> {
5355
final LadeBelastungsplanMessquerschnittDataDTO messquerschnitt = new LadeBelastungsplanMessquerschnittDataDTO();
@@ -95,25 +97,25 @@ public BelastungsplanMessquerschnitteDTO ladeBelastungsplan(
9597
}
9698
belastungsplanMessquerschnitte.setLadeBelastungsplanMessquerschnittDataDTOList(sortedMessquerschnitte);
9799

98-
final Integer totalSumKfz = totalSumOfAllMessquerschnitte
100+
final Integer totalSumKfz = totalSumForEachMessquerschnitt
99101
.stream()
100102
.mapToInt(interval -> ObjectUtils.defaultIfNull(interval.getSummeKraftfahrzeugverkehr(), BigDecimal.ZERO).intValue())
101103
.sum();
102104
belastungsplanMessquerschnitte.setTotalKfz(roundNumberToHundredIfNeeded(totalSumKfz, options));
103105

104-
final Integer totalSumSv = totalSumOfAllMessquerschnitte
106+
final Integer totalSumSv = totalSumForEachMessquerschnitt
105107
.stream()
106108
.mapToInt(interval -> ObjectUtils.defaultIfNull(interval.getSummeSchwerverkehr(), BigDecimal.ZERO).intValue())
107109
.sum();
108110
belastungsplanMessquerschnitte.setTotalSv(roundNumberToHundredIfNeeded(totalSumSv, options));
109111

110-
final Integer totalSumGv = totalSumOfAllMessquerschnitte
112+
final Integer totalSumGv = totalSumForEachMessquerschnitt
111113
.stream()
112114
.mapToInt(interval -> ObjectUtils.defaultIfNull(interval.getSummeGueterverkehr(), BigDecimal.ZERO).intValue())
113115
.sum();
114116
belastungsplanMessquerschnitte.setTotalGv(roundNumberToHundredIfNeeded(totalSumGv, options));
115117

116-
final Integer totalSumRad = totalSumOfAllMessquerschnitte
118+
final Integer totalSumRad = totalSumForEachMessquerschnitt
117119
.stream()
118120
.mapToInt(interval -> ObjectUtils.defaultIfNull(interval.getAnzahlRad(), BigDecimal.ZERO).intValue())
119121
.sum();
@@ -125,8 +127,8 @@ public BelastungsplanMessquerschnitteDTO ladeBelastungsplan(
125127
final var totalPercentageSv = calcPercentage(totalSumSv, totalSum);
126128
belastungsplanMessquerschnitte.setTotalPercentSv(totalPercentageSv);
127129

128-
if (options.getMessquerschnittIds().size() == 1) {
129-
final var isKfzStelle = Objects.equals(options.getZeitauswahl(), "Spitzenstunde KFZ");
130+
if (OptionsUtil.isZeitauswahlSpitzenstunde(options.getZeitauswahl())) {
131+
final var isKfzStelle = Objects.equals(options.getZeitauswahl(), Zeitauswahl.SPITZENSTUNDE_KFZ.getCapitalizedName());
130132
final var spitzenstunde = spitzenstundeService.calculateSpitzenstundeAndAddBlockSpecificDataToResult(
131133
options.getZeitblock(),
132134
intervals,

src/main/java/de/muenchen/dave/services/messstelle/MesswerteService.java

Lines changed: 64 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,11 @@
1515
import de.muenchen.dave.util.OptionsUtil;
1616
import de.muenchen.dave.util.messstelle.MesswerteBaseUtil;
1717
import java.time.LocalDate;
18+
import java.time.LocalDateTime;
19+
import java.time.LocalTime;
1820
import java.util.Collections;
1921
import java.util.List;
22+
import java.util.Objects;
2023
import java.util.Set;
2124
import lombok.AllArgsConstructor;
2225
import lombok.extern.slf4j.Slf4j;
@@ -31,7 +34,8 @@
3134
@AllArgsConstructor
3235
public class MesswerteService {
3336

34-
private static final String ERROR_MESSAGE = "Beim Laden der AverageMeasurementValuesPerIntervalResponse ist ein Fehler aufgetreten";
37+
private static final String ERROR_MESSAGE = "Beim Laden der Messwerte ist ein Fehler aufgetreten";
38+
3539
private final MessstelleService messstelleService;
3640
private final MesswerteApi messwerteApi;
3741
private final GanglinieService ganglinieService;
@@ -51,31 +55,54 @@ public class MesswerteService {
5155
public LadeProcessedMesswerteDTO ladeMesswerte(final String messstelleId, final MessstelleOptionsDTO options) {
5256
log.debug("#ladeMesswerte {}", messstelleId);
5357

54-
final IntervalResponseDto response = this.ladeMesswerteIntervalle(options, messstelleService.getMessquerschnittIdsByMessstelleId(messstelleId));
58+
final var response = this.ladeMesswerteIntervalle(options, messstelleService.getMessquerschnittIdsByMessstelleId(messstelleId));
5559
final var isKfzMessstelle = messstelleService.isKfzMessstelle(messstelleId);
5660
final List<IntervalDto> intervals;
61+
final List<IntervalDto> sumOfIntervalsForEachMessquerschnitt;
5762

5863
if (OptionsUtil.isZeitauswahlSpitzenstunde(options.getZeitauswahl())) {
5964
// Extrahieren der Intervalle welche die Spitzenstunde ausmachen.
6065
intervals = spitzenstundeService.getIntervalsOfSpitzenstunde(
61-
ListUtils.emptyIfNull(response.getMeanOfMqIdForEachIntervalByMesstag()),
66+
ListUtils.emptyIfNull(response.getMeanOfSummedUpMessquerschnitteForEachIntervalOverMesstage()),
6267
isKfzMessstelle,
6368
options.getIntervall());
69+
70+
// Summieren der Intervalle je Messquerschnitt welche die Spitzenstunde ausmachen.
71+
final var uhrzeitVon = getEarliestUhrzeitVonOfIntervals(intervals);
72+
final var uhrzeitBis = getLatestUhrzeitBisOfIntervals(intervals);
73+
74+
sumOfIntervalsForEachMessquerschnitt = ListUtils.emptyIfNull(response.getMeanForEachIntervalAndEachMessquerschnittOverMesstage())
75+
.stream()
76+
.map(intervalsForMqId -> ListUtils.emptyIfNull(intervalsForMqId.getIntervals())
77+
.stream()
78+
.filter(interval -> isTimeToCompareEqualOrAfterStarttimeAndBeforeEndTime(
79+
interval.getDatumUhrzeitVon().toLocalTime(),
80+
uhrzeitVon,
81+
uhrzeitBis))
82+
.reduce(
83+
new IntervalDto(),
84+
MesswerteBaseUtil::sumIntervalsAndAdaptDatumUhrzeitVonAndBisAndReturnNewInterval))
85+
.toList();
6486
} else {
65-
intervals = ListUtils.emptyIfNull(response.getMeanOfMqIdForEachIntervalByMesstag());
66-
}
87+
intervals = ListUtils.emptyIfNull(response.getMeanOfSummedUpMessquerschnitteForEachIntervalOverMesstage());
6788

68-
final var meanPerMessquerschnitt = ListUtils.emptyIfNull(response.getMeanOfIntervalsForEachMqIdByMesstag())
69-
.stream()
70-
.flatMap(intervalsForMqId -> ListUtils.emptyIfNull(intervalsForMqId.getMeanOfIntervalsByMesstag()).stream())
71-
.toList();
89+
sumOfIntervalsForEachMessquerschnitt = ListUtils.emptyIfNull(response.getMeanOfSummedUpDailyIntervalsForEachMessquerschnittOverMesstage())
90+
.stream()
91+
.flatMap(intervalsForMqId -> ListUtils.emptyIfNull(intervalsForMqId.getIntervals()).stream())
92+
.toList();
93+
}
7294

95+
// Aufbereiten der Daten für die entsprechenden Auswertungen
7396
final var processedZaehldaten = new LadeProcessedMesswerteDTO();
7497
processedZaehldaten.setZaehldatenStepline(ganglinieService.ladeGanglinie(intervals, options.getFahrzeuge()));
7598
processedZaehldaten.setZaehldatenHeatmap(heatmapService.ladeHeatmap(intervals, options));
7699
processedZaehldaten.setZaehldatenTable(listenausgabeService.ladeListenausgabe(intervals, isKfzMessstelle, options));
77-
processedZaehldaten
78-
.setBelastungsplanMessquerschnitte(belastungsplanService.ladeBelastungsplan(intervals, meanPerMessquerschnitt, messstelleId, options));
100+
processedZaehldaten.setBelastungsplanMessquerschnitte(
101+
belastungsplanService.ladeBelastungsplan(intervals,
102+
sumOfIntervalsForEachMessquerschnitt,
103+
messstelleId,
104+
options));
105+
79106
if (CollectionUtils.isNotEmpty(intervals)) {
80107
processedZaehldaten.setTagesTyp(TagesTyp.getByIntervallTyp(intervals.getFirst().getTagesTyp()));
81108
}
@@ -163,4 +190,30 @@ public TagesaggregatResponseDto ladeMeanOfTagesaggregatePerMq(final TagesTyp tag
163190
return response.getBody();
164191
}
165192

193+
protected static boolean isTimeToCompareEqualOrAfterStarttimeAndBeforeEndTime(
194+
final LocalTime timeToCompare,
195+
final LocalTime startTime,
196+
final LocalTime endTime) {
197+
return (timeToCompare.equals(startTime) || timeToCompare.isAfter(startTime)) &&
198+
!(timeToCompare.equals(endTime) || timeToCompare.isAfter(endTime));
199+
}
200+
201+
protected static LocalTime getEarliestUhrzeitVonOfIntervals(final List<IntervalDto> intervals) {
202+
return intervals.stream()
203+
.map(IntervalDto::getDatumUhrzeitVon)
204+
.filter(Objects::nonNull)
205+
.map(LocalDateTime::toLocalTime)
206+
.min(LocalTime::compareTo)
207+
.orElse(null);
208+
}
209+
210+
protected static LocalTime getLatestUhrzeitBisOfIntervals(final List<IntervalDto> intervals) {
211+
return intervals.stream()
212+
.map(IntervalDto::getDatumUhrzeitBis)
213+
.filter(Objects::nonNull)
214+
.map(LocalDateTime::toLocalTime)
215+
.max(LocalTime::compareTo)
216+
.orElse(null);
217+
}
218+
166219
}

src/main/java/de/muenchen/dave/util/messstelle/MesswerteBaseUtil.java

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,11 @@
66
import java.math.BigDecimal;
77
import java.math.RoundingMode;
88
import java.time.LocalDate;
9+
import java.time.LocalDateTime;
910
import java.time.LocalTime;
11+
import java.util.Comparator;
1012
import java.util.List;
13+
import java.util.stream.Stream;
1114
import lombok.AccessLevel;
1215
import lombok.NoArgsConstructor;
1316
import org.apache.commons.collections4.CollectionUtils;
@@ -85,4 +88,82 @@ public static double calculateAnteilProzent(final Integer dividend, final Intege
8588
.scaleByPowerOfTen(2)
8689
.doubleValue();
8790
}
91+
92+
/**
93+
* Die Methode summiert die in den Parameter gegebenen Intervalle.
94+
* <p>
95+
* Der Messquerschnitt und der Tagestyp für den summierten Interval
96+
* wird aus dem zweiten Interval entnommen.
97+
* <p>
98+
* Das Attribut {@link IntervalDto#getDatumUhrzeitVon()} des summierten Intervalls wird auf das
99+
* kleinere gleichlautende Attribut der im Parameter gegebenen Intervalle gesetzt.
100+
* <p>
101+
* Das Attribut {@link IntervalDto#getDatumUhrzeitBis()} des summierten Intervalls wird auf das
102+
* größere gleichlautende Attribut der im Parameter gegebenen Intervalle gesetzt.
103+
*
104+
* @param interval1 zum Summieren
105+
* @param interval2 zum Summieren
106+
* @return einen neuen Interval mit den summierten Werten
107+
*/
108+
public static IntervalDto sumIntervalsAndAdaptDatumUhrzeitVonAndBisAndReturnNewInterval(
109+
final IntervalDto interval1,
110+
final IntervalDto interval2) {
111+
final var interval = sumCountingValuesOfIntervalsAndReturnNewInterval(interval1, interval2);
112+
interval.setMqId(interval2.getMqId());
113+
interval.setTagesTyp(interval2.getTagesTyp());
114+
final var intervalVon = getMin(interval1.getDatumUhrzeitVon(), interval2.getDatumUhrzeitVon());
115+
interval.setDatumUhrzeitVon(intervalVon);
116+
final var intervalBis = getMax(interval1.getDatumUhrzeitBis(), interval2.getDatumUhrzeitBis());
117+
interval.setDatumUhrzeitBis(intervalBis);
118+
return interval;
119+
}
120+
121+
public static IntervalDto sumCountingValuesOfIntervalsAndReturnNewInterval(
122+
final IntervalDto interval1,
123+
final IntervalDto interval2) {
124+
return sumCountingValuesOfAggregatesAndReturnNewTagesaggregatModelForMesswerte(interval1, interval2);
125+
}
126+
127+
private static IntervalDto sumCountingValuesOfAggregatesAndReturnNewTagesaggregatModelForMesswerte(
128+
final IntervalDto interval1,
129+
final IntervalDto interval2) {
130+
final var interval = new IntervalDto();
131+
interval.setAnzahlLfw(sumValuesIfAnyNotNullOrReturnNull(interval1.getAnzahlLfw(), interval2.getAnzahlLfw()));
132+
interval.setAnzahlKrad(sumValuesIfAnyNotNullOrReturnNull(interval1.getAnzahlKrad(), interval2.getAnzahlKrad()));
133+
interval.setAnzahlLkw(sumValuesIfAnyNotNullOrReturnNull(interval1.getAnzahlLkw(), interval2.getAnzahlLkw()));
134+
interval.setAnzahlBus(sumValuesIfAnyNotNullOrReturnNull(interval1.getAnzahlBus(), interval2.getAnzahlBus()));
135+
interval.setAnzahlRad(sumValuesIfAnyNotNullOrReturnNull(interval1.getAnzahlRad(), interval2.getAnzahlRad()));
136+
interval.setSummeAllePkw(sumValuesIfAnyNotNullOrReturnNull(interval1.getSummeAllePkw(), interval2.getSummeAllePkw()));
137+
interval.setSummeLastzug(sumValuesIfAnyNotNullOrReturnNull(interval1.getSummeLastzug(), interval2.getSummeLastzug()));
138+
interval.setSummeGueterverkehr(sumValuesIfAnyNotNullOrReturnNull(interval1.getSummeGueterverkehr(), interval2.getSummeGueterverkehr()));
139+
interval.setSummeSchwerverkehr(sumValuesIfAnyNotNullOrReturnNull(interval1.getSummeSchwerverkehr(), interval2.getSummeSchwerverkehr()));
140+
interval.setSummeKraftfahrzeugverkehr(
141+
sumValuesIfAnyNotNullOrReturnNull(interval1.getSummeKraftfahrzeugverkehr(), interval2.getSummeKraftfahrzeugverkehr()));
142+
return interval;
143+
}
144+
145+
public static BigDecimal sumValuesIfAnyNotNullOrReturnNull(final BigDecimal... values) {
146+
BigDecimal summedValue = null;
147+
if (ObjectUtils.anyNotNull(values)) {
148+
summedValue = Stream.of(values)
149+
.reduce(BigDecimal.ZERO,
150+
(value1, value2) -> ObjectUtils.defaultIfNull(value1, BigDecimal.ZERO).add(ObjectUtils.defaultIfNull(value2, BigDecimal.ZERO)));
151+
}
152+
return summedValue;
153+
}
154+
155+
static LocalDateTime getMin(final LocalDateTime dateTime1, final LocalDateTime dateTime2) {
156+
return Stream.of(dateTime1, dateTime2)
157+
.filter(ObjectUtils::isNotEmpty)
158+
.min(Comparator.naturalOrder())
159+
.orElse(null);
160+
}
161+
162+
static LocalDateTime getMax(final LocalDateTime dateTime1, final LocalDateTime dateTime2) {
163+
return Stream.of(dateTime1, dateTime2)
164+
.filter(ObjectUtils::isNotEmpty)
165+
.max(Comparator.naturalOrder())
166+
.orElse(null);
167+
}
168+
88169
}

0 commit comments

Comments
 (0)