Enrich operating periods with raw activity details
This commit is contained in:
parent
94767bc161
commit
14a6f8d42e
|
|
@ -1,6 +1,7 @@
|
|||
package at.procon.eventhub.esperpoc.dto;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.List;
|
||||
|
||||
public record OperatingPeriodDto(
|
||||
long operatingPeriodNo,
|
||||
|
|
@ -8,11 +9,14 @@ public record OperatingPeriodDto(
|
|||
OffsetDateTime endedAt,
|
||||
long durationSeconds,
|
||||
String closedBy,
|
||||
List<ActivityIntervalDto> rawActivities,
|
||||
long breakRestSeconds,
|
||||
long drivingSeconds,
|
||||
long workSeconds,
|
||||
long availabilitySeconds,
|
||||
long unknownSeconds,
|
||||
int intervalCount,
|
||||
ShiftDrivingEvaluationDto drivingTimeInterruptionEvaluation,
|
||||
boolean clippedToRequestedPeriod
|
||||
) {
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package at.procon.eventhub.esperpoc.service;
|
|||
|
||||
import at.procon.eventhub.config.EventHubProperties;
|
||||
import at.procon.eventhub.esperpoc.dto.ActivityIntervalDto;
|
||||
import at.procon.eventhub.esperpoc.dto.DrivingInterruptionDto;
|
||||
import at.procon.eventhub.esperpoc.dto.EsperOperatingPeriodRequest;
|
||||
import at.procon.eventhub.esperpoc.dto.EsperOperatingPeriodResultDto;
|
||||
import at.procon.eventhub.esperpoc.dto.EsperUnknownTreatmentMode;
|
||||
|
|
@ -9,6 +10,7 @@ import at.procon.eventhub.esperpoc.dto.NonDrivingIntervalDto;
|
|||
import at.procon.eventhub.esperpoc.dto.OperatingPeriodActivityIntervalDto;
|
||||
import at.procon.eventhub.esperpoc.dto.OperatingPeriodDto;
|
||||
import at.procon.eventhub.esperpoc.dto.RawActivityEventDto;
|
||||
import at.procon.eventhub.esperpoc.dto.ShiftDrivingEvaluationDto;
|
||||
import at.procon.eventhub.esperpoc.persistence.EsperPocActivityRepository;
|
||||
import java.time.Duration;
|
||||
import java.time.OffsetDateTime;
|
||||
|
|
@ -140,8 +142,11 @@ public class EsperOperatingPeriodEvaluationService {
|
|||
List<OperatingPeriodDto> operatingPeriods = buildOperatingPeriods(
|
||||
evaluation.closedPeriods(),
|
||||
periodizedIntervals,
|
||||
clipKnownActivities(resolvedKnownLoadedIntervals, requestedFrom, requestedTo),
|
||||
requestedFrom,
|
||||
requestedTo
|
||||
requestedTo,
|
||||
mergeGapTolerance,
|
||||
significantDrivingThreshold
|
||||
);
|
||||
long totalElapsedMs = elapsedMillis(startedNanos);
|
||||
|
||||
|
|
@ -366,8 +371,11 @@ public class EsperOperatingPeriodEvaluationService {
|
|||
private List<OperatingPeriodDto> buildOperatingPeriods(
|
||||
List<EsperClosedOperatingPeriod> closedPeriods,
|
||||
List<OperatingPeriodActivityIntervalDto> clippedPeriodizedIntervals,
|
||||
List<ActivityIntervalDto> clippedKnownActivities,
|
||||
OffsetDateTime requestedFrom,
|
||||
OffsetDateTime requestedTo
|
||||
OffsetDateTime requestedTo,
|
||||
Duration mergeGapTolerance,
|
||||
Duration significantDrivingThreshold
|
||||
) {
|
||||
Map<Long, List<OperatingPeriodActivityIntervalDto>> intervalsByPeriod = new LinkedHashMap<>();
|
||||
for (OperatingPeriodActivityIntervalDto interval : clippedPeriodizedIntervals) {
|
||||
|
|
@ -384,6 +392,16 @@ public class EsperOperatingPeriodEvaluationService {
|
|||
continue;
|
||||
}
|
||||
List<OperatingPeriodActivityIntervalDto> intervals = intervalsByPeriod.getOrDefault(closedPeriod.operatingPeriodNo(), List.of());
|
||||
List<ActivityIntervalDto> rawActivities = clipKnownActivitiesToPeriod(clippedKnownActivities, start, end);
|
||||
long breakRestSeconds = rawActivities.stream()
|
||||
.filter(activity -> "BREAK_REST".equals(activity.activityType()))
|
||||
.mapToLong(ActivityIntervalDto::durationSeconds)
|
||||
.sum();
|
||||
ShiftDrivingEvaluationDto drivingEvaluation = evaluateSignificantDrivingWithEsper(
|
||||
rawActivities,
|
||||
mergeGapTolerance,
|
||||
significantDrivingThreshold
|
||||
);
|
||||
long drivingSeconds = sumActivitySeconds(intervals, "DRIVE");
|
||||
long workSeconds = sumActivitySeconds(intervals, "WORK");
|
||||
long availabilitySeconds = sumActivitySeconds(intervals, "AVAILABILITY");
|
||||
|
|
@ -394,11 +412,14 @@ public class EsperOperatingPeriodEvaluationService {
|
|||
end,
|
||||
Duration.between(start, end).getSeconds(),
|
||||
closedPeriod.closedBy(),
|
||||
rawActivities,
|
||||
breakRestSeconds,
|
||||
drivingSeconds,
|
||||
workSeconds,
|
||||
availabilitySeconds,
|
||||
unknownSeconds,
|
||||
intervals.size(),
|
||||
drivingEvaluation,
|
||||
!start.equals(closedPeriod.startedAt()) || !end.equals(closedPeriod.endedAt())
|
||||
));
|
||||
}
|
||||
|
|
@ -433,6 +454,38 @@ public class EsperOperatingPeriodEvaluationService {
|
|||
.toList();
|
||||
}
|
||||
|
||||
private List<ActivityIntervalDto> clipKnownActivities(
|
||||
List<ActivityIntervalDto> activities,
|
||||
OffsetDateTime requestedFrom,
|
||||
OffsetDateTime requestedTo
|
||||
) {
|
||||
return clipKnownActivitiesToPeriod(activities, requestedFrom, requestedTo);
|
||||
}
|
||||
|
||||
private List<ActivityIntervalDto> clipKnownActivitiesToPeriod(
|
||||
List<ActivityIntervalDto> activities,
|
||||
OffsetDateTime periodFrom,
|
||||
OffsetDateTime periodTo
|
||||
) {
|
||||
return activities.stream()
|
||||
.map(activity -> {
|
||||
OffsetDateTime start = max(activity.startedAt(), periodFrom);
|
||||
OffsetDateTime end = min(activity.endedAt(), periodTo);
|
||||
if (!end.isAfter(start)) {
|
||||
return null;
|
||||
}
|
||||
boolean clipped = activity.clippedToRequestedPeriod()
|
||||
|| !start.equals(activity.startedAt())
|
||||
|| !end.equals(activity.endedAt());
|
||||
return activity.withTime(start, end, clipped);
|
||||
})
|
||||
.filter(Objects::nonNull)
|
||||
.sorted(Comparator.comparing(ActivityIntervalDto::startedAt)
|
||||
.thenComparing(ActivityIntervalDto::endedAt)
|
||||
.thenComparing(ActivityIntervalDto::activityType, Comparator.nullsLast(String::compareTo)))
|
||||
.toList();
|
||||
}
|
||||
|
||||
private List<NonDrivingIntervalDto> clipNonDrivingIntervals(
|
||||
List<NonDrivingIntervalDto> intervals,
|
||||
OffsetDateTime requestedFrom,
|
||||
|
|
@ -558,6 +611,66 @@ public class EsperOperatingPeriodEvaluationService {
|
|||
.toList();
|
||||
}
|
||||
|
||||
private ShiftDrivingEvaluationDto evaluateSignificantDrivingWithEsper(
|
||||
List<ActivityIntervalDto> rawActivities,
|
||||
Duration mergeGapTolerance,
|
||||
Duration significantDrivingThreshold
|
||||
) {
|
||||
if (rawActivities.isEmpty()) {
|
||||
return new ShiftDrivingEvaluationDto(
|
||||
(int) significantDrivingThreshold.toMinutes(),
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
List.of()
|
||||
);
|
||||
}
|
||||
List<ActivityIntervalDto> mergedActivities = activityEngine.mergeConsecutiveIdenticalActivities(
|
||||
rawActivities,
|
||||
mergeGapTolerance
|
||||
);
|
||||
List<ActivityIntervalDto> significantDrivingPeriods = mergedActivities.stream()
|
||||
.filter(activity -> "DRIVE".equals(activity.activityType()))
|
||||
.filter(activity -> activity.durationSeconds() > significantDrivingThreshold.getSeconds())
|
||||
.sorted(Comparator.comparing(ActivityIntervalDto::startedAt))
|
||||
.toList();
|
||||
if (significantDrivingPeriods.isEmpty()) {
|
||||
return new ShiftDrivingEvaluationDto(
|
||||
(int) significantDrivingThreshold.toMinutes(),
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
List.of()
|
||||
);
|
||||
}
|
||||
List<DrivingInterruptionDto> interruptions = new ArrayList<>();
|
||||
for (int index = 1; index < significantDrivingPeriods.size(); index++) {
|
||||
ActivityIntervalDto previous = significantDrivingPeriods.get(index - 1);
|
||||
ActivityIntervalDto next = significantDrivingPeriods.get(index);
|
||||
if (next.startedAt().isAfter(previous.endedAt())) {
|
||||
interruptions.add(new DrivingInterruptionDto(
|
||||
previous.endedAt(),
|
||||
next.startedAt(),
|
||||
Duration.between(previous.endedAt(), next.startedAt()).getSeconds(),
|
||||
previous.sourceRowId(),
|
||||
next.sourceRowId()
|
||||
));
|
||||
}
|
||||
}
|
||||
ActivityIntervalDto first = significantDrivingPeriods.get(0);
|
||||
ActivityIntervalDto last = significantDrivingPeriods.get(significantDrivingPeriods.size() - 1);
|
||||
return new ShiftDrivingEvaluationDto(
|
||||
(int) significantDrivingThreshold.toMinutes(),
|
||||
first.startedAt(),
|
||||
last.endedAt(),
|
||||
first,
|
||||
last,
|
||||
interruptions
|
||||
);
|
||||
}
|
||||
|
||||
private int resolveOperatingSplitIdleHours(EsperOperatingPeriodRequest request) {
|
||||
if (request.operatingSplitIdleHours() != null) {
|
||||
return request.operatingSplitIdleHours();
|
||||
|
|
|
|||
Loading…
Reference in New Issue