Add in-vehicle trip Esper projection
This commit is contained in:
parent
9b86d13001
commit
33e9cb62c3
|
|
@ -5,6 +5,7 @@ import at.procon.eventhub.tachographfilesession.model.TachographEsperDailyWeekly
|
||||||
import at.procon.eventhub.tachographfilesession.model.TachographEsperDrivingInterruptionIntervalEvent;
|
import at.procon.eventhub.tachographfilesession.model.TachographEsperDrivingInterruptionIntervalEvent;
|
||||||
import at.procon.eventhub.tachographfilesession.model.TachographEsperPotentialHomeOvernightStayIntervalEvent;
|
import at.procon.eventhub.tachographfilesession.model.TachographEsperPotentialHomeOvernightStayIntervalEvent;
|
||||||
import at.procon.eventhub.tachographfilesession.model.TachographEsperPotentialInVehicleOvernightStayIntervalEvent;
|
import at.procon.eventhub.tachographfilesession.model.TachographEsperPotentialInVehicleOvernightStayIntervalEvent;
|
||||||
|
import at.procon.eventhub.tachographfilesession.model.TachographEsperPotentialInVehicleTripIntervalEvent;
|
||||||
import at.procon.eventhub.tachographfilesession.model.TachographEsperVehicleUsageIntervalEvent;
|
import at.procon.eventhub.tachographfilesession.model.TachographEsperVehicleUsageIntervalEvent;
|
||||||
import at.procon.eventhub.tachographfilesession.model.TachographEsperVuCardAbsentIntervalEvent;
|
import at.procon.eventhub.tachographfilesession.model.TachographEsperVuCardAbsentIntervalEvent;
|
||||||
import java.time.OffsetDateTime;
|
import java.time.OffsetDateTime;
|
||||||
|
|
@ -28,6 +29,7 @@ public record TachographEsperDriverProcessingResultDto(
|
||||||
int unclassifiedDailyWeeklyRestCandidateCoverageIntervalCount,
|
int unclassifiedDailyWeeklyRestCandidateCoverageIntervalCount,
|
||||||
int potentialHomeOvernightStayIntervalCount,
|
int potentialHomeOvernightStayIntervalCount,
|
||||||
int potentialInVehicleOvernightStayIntervalCount,
|
int potentialInVehicleOvernightStayIntervalCount,
|
||||||
|
int potentialInVehicleTripIntervalCount,
|
||||||
int vehicleUsageIntervalCount,
|
int vehicleUsageIntervalCount,
|
||||||
int vuCardAbsentIntervalCount,
|
int vuCardAbsentIntervalCount,
|
||||||
List<TachographEsperActivityIntervalEvent> activityIntervals,
|
List<TachographEsperActivityIntervalEvent> activityIntervals,
|
||||||
|
|
@ -39,6 +41,7 @@ public record TachographEsperDriverProcessingResultDto(
|
||||||
List<TachographEsperDailyWeeklyRestCandidateCoverageIntervalEvent> unclassifiedDailyWeeklyRestCandidateCoverageIntervals,
|
List<TachographEsperDailyWeeklyRestCandidateCoverageIntervalEvent> unclassifiedDailyWeeklyRestCandidateCoverageIntervals,
|
||||||
List<TachographEsperPotentialHomeOvernightStayIntervalEvent> potentialHomeOvernightStayIntervals,
|
List<TachographEsperPotentialHomeOvernightStayIntervalEvent> potentialHomeOvernightStayIntervals,
|
||||||
List<TachographEsperPotentialInVehicleOvernightStayIntervalEvent> potentialInVehicleOvernightStayIntervals,
|
List<TachographEsperPotentialInVehicleOvernightStayIntervalEvent> potentialInVehicleOvernightStayIntervals,
|
||||||
|
List<TachographEsperPotentialInVehicleTripIntervalEvent> potentialInVehicleTripIntervals,
|
||||||
List<TachographEsperVehicleUsageIntervalEvent> vehicleUsageIntervals,
|
List<TachographEsperVehicleUsageIntervalEvent> vehicleUsageIntervals,
|
||||||
List<TachographEsperVuCardAbsentIntervalEvent> vuCardAbsentIntervals,
|
List<TachographEsperVuCardAbsentIntervalEvent> vuCardAbsentIntervals,
|
||||||
List<String> notes
|
List<String> notes
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ public record TachographEsperDrivingDerivedProjectionBundle(
|
||||||
List<TachographEsperDrivingInterruptionIntervalEvent> drivingInterruptionVehicleChangeIntervals,
|
List<TachographEsperDrivingInterruptionIntervalEvent> drivingInterruptionVehicleChangeIntervals,
|
||||||
List<TachographEsperVuCardAbsentIntervalEvent> vuCardAbsentIntervals,
|
List<TachographEsperVuCardAbsentIntervalEvent> vuCardAbsentIntervals,
|
||||||
List<TachographEsperPotentialHomeOvernightStayIntervalEvent> potentialHomeOvernightStayIntervals,
|
List<TachographEsperPotentialHomeOvernightStayIntervalEvent> potentialHomeOvernightStayIntervals,
|
||||||
List<TachographEsperPotentialInVehicleOvernightStayIntervalEvent> potentialInVehicleOvernightStayIntervals
|
List<TachographEsperPotentialInVehicleOvernightStayIntervalEvent> potentialInVehicleOvernightStayIntervals,
|
||||||
|
List<TachographEsperPotentialInVehicleTripIntervalEvent> potentialInVehicleTripIntervals
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,8 @@ public record TachographEsperPotentialHomeOvernightStayIntervalEvent(
|
||||||
OffsetDateTime startedAt,
|
OffsetDateTime startedAt,
|
||||||
OffsetDateTime endedAt,
|
OffsetDateTime endedAt,
|
||||||
long durationSeconds,
|
long durationSeconds,
|
||||||
|
long cardPresentDurationSeconds,
|
||||||
|
double cardPresentCoveragePercent,
|
||||||
long unknownDurationSeconds,
|
long unknownDurationSeconds,
|
||||||
double unknownCoveragePercent,
|
double unknownCoveragePercent,
|
||||||
String previousDrivingSourceIntervalId,
|
String previousDrivingSourceIntervalId,
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,8 @@ public record TachographEsperPotentialInVehicleOvernightStayIntervalEvent(
|
||||||
long durationSeconds,
|
long durationSeconds,
|
||||||
long cardPresentDurationSeconds,
|
long cardPresentDurationSeconds,
|
||||||
double cardPresentCoveragePercent,
|
double cardPresentCoveragePercent,
|
||||||
|
long unknownDurationSeconds,
|
||||||
|
double unknownCoveragePercent,
|
||||||
String previousDrivingSourceIntervalId,
|
String previousDrivingSourceIntervalId,
|
||||||
String nextDrivingSourceIntervalId,
|
String nextDrivingSourceIntervalId,
|
||||||
String previousRegistrationKey,
|
String previousRegistrationKey,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
package at.procon.eventhub.tachographfilesession.model;
|
||||||
|
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public record TachographEsperPotentialInVehicleTripIntervalEvent(
|
||||||
|
UUID sessionId,
|
||||||
|
String driverKey,
|
||||||
|
OffsetDateTime startedAt,
|
||||||
|
OffsetDateTime endedAt,
|
||||||
|
long durationSeconds,
|
||||||
|
String registrationKey,
|
||||||
|
String vehicleKey,
|
||||||
|
int containedPotentialInVehicleOvernightStayIntervalCount,
|
||||||
|
long containedPotentialInVehicleOvernightStayDurationSeconds,
|
||||||
|
long containedCardPresentDurationSeconds,
|
||||||
|
long containedUnknownDurationSeconds,
|
||||||
|
OffsetDateTime firstPotentialInVehicleOvernightStayStartedAt,
|
||||||
|
OffsetDateTime lastPotentialInVehicleOvernightStayEndedAt,
|
||||||
|
String firstPreviousDrivingSourceIntervalId,
|
||||||
|
String lastNextDrivingSourceIntervalId,
|
||||||
|
List<TachographEsperPotentialInVehicleOvernightStayIntervalEvent> potentialInVehicleOvernightStayIntervals
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
@ -997,6 +997,8 @@ public class DriverTimelineBuilder {
|
||||||
(OffsetDateTime) event.get("startedAt"),
|
(OffsetDateTime) event.get("startedAt"),
|
||||||
(OffsetDateTime) event.get("endedAt"),
|
(OffsetDateTime) event.get("endedAt"),
|
||||||
(Long) event.get("durationSeconds"),
|
(Long) event.get("durationSeconds"),
|
||||||
|
0L,
|
||||||
|
0.0d,
|
||||||
(Long) event.get("unknownDurationSeconds"),
|
(Long) event.get("unknownDurationSeconds"),
|
||||||
(Double) event.get("unknownCoveragePercent"),
|
(Double) event.get("unknownCoveragePercent"),
|
||||||
(String) event.get("previousDrivingSourceIntervalId"),
|
(String) event.get("previousDrivingSourceIntervalId"),
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ import at.procon.eventhub.tachographfilesession.model.TachographEsperDrivingDeri
|
||||||
import at.procon.eventhub.tachographfilesession.model.TachographEsperDrivingInterruptionIntervalEvent;
|
import at.procon.eventhub.tachographfilesession.model.TachographEsperDrivingInterruptionIntervalEvent;
|
||||||
import at.procon.eventhub.tachographfilesession.model.TachographEsperPotentialHomeOvernightStayIntervalEvent;
|
import at.procon.eventhub.tachographfilesession.model.TachographEsperPotentialHomeOvernightStayIntervalEvent;
|
||||||
import at.procon.eventhub.tachographfilesession.model.TachographEsperPotentialInVehicleOvernightStayIntervalEvent;
|
import at.procon.eventhub.tachographfilesession.model.TachographEsperPotentialInVehicleOvernightStayIntervalEvent;
|
||||||
|
import at.procon.eventhub.tachographfilesession.model.TachographEsperPotentialInVehicleTripIntervalEvent;
|
||||||
import at.procon.eventhub.tachographfilesession.model.TachographEsperVuCardAbsentIntervalEvent;
|
import at.procon.eventhub.tachographfilesession.model.TachographEsperVuCardAbsentIntervalEvent;
|
||||||
import at.procon.eventhub.tachographfilesession.model.TachographFileSession;
|
import at.procon.eventhub.tachographfilesession.model.TachographFileSession;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
@ -108,6 +109,7 @@ public class DriverTimelineReusableProjectionBuilder {
|
||||||
List<TachographEsperVuCardAbsentIntervalEvent> vuCardAbsentIntervals = new ArrayList<>();
|
List<TachographEsperVuCardAbsentIntervalEvent> vuCardAbsentIntervals = new ArrayList<>();
|
||||||
List<TachographEsperPotentialHomeOvernightStayIntervalEvent> potentialHomeOvernightStayIntervals = new ArrayList<>();
|
List<TachographEsperPotentialHomeOvernightStayIntervalEvent> potentialHomeOvernightStayIntervals = new ArrayList<>();
|
||||||
List<TachographEsperPotentialInVehicleOvernightStayIntervalEvent> potentialInVehicleOvernightStayIntervals = new ArrayList<>();
|
List<TachographEsperPotentialInVehicleOvernightStayIntervalEvent> potentialInVehicleOvernightStayIntervals = new ArrayList<>();
|
||||||
|
List<TachographEsperPotentialInVehicleTripIntervalEvent> potentialInVehicleTripIntervals = new ArrayList<>();
|
||||||
|
|
||||||
executeWithRuntime(
|
executeWithRuntime(
|
||||||
configuration -> {
|
configuration -> {
|
||||||
|
|
@ -129,7 +131,8 @@ public class DriverTimelineReusableProjectionBuilder {
|
||||||
"drivingInterruptionVehicleChangeIntervals", newData -> collectDrivingInterruptionIntervalEvents(newData, drivingInterruptionVehicleChangeIntervals),
|
"drivingInterruptionVehicleChangeIntervals", newData -> collectDrivingInterruptionIntervalEvents(newData, drivingInterruptionVehicleChangeIntervals),
|
||||||
"vuCardAbsentIntervals", newData -> collectVuCardAbsentIntervalEvents(newData, vuCardAbsentIntervals),
|
"vuCardAbsentIntervals", newData -> collectVuCardAbsentIntervalEvents(newData, vuCardAbsentIntervals),
|
||||||
"potentialHomeOvernightStayIntervals", newData -> collectPotentialHomeOvernightStayIntervalEvents(newData, potentialHomeOvernightStayIntervals),
|
"potentialHomeOvernightStayIntervals", newData -> collectPotentialHomeOvernightStayIntervalEvents(newData, potentialHomeOvernightStayIntervals),
|
||||||
"potentialInVehicleOvernightStayIntervals", newData -> collectPotentialInVehicleOvernightStayIntervalEvents(newData, potentialInVehicleOvernightStayIntervals)
|
"potentialInVehicleOvernightStayIntervals", newData -> collectPotentialInVehicleOvernightStayIntervalEvents(newData, potentialInVehicleOvernightStayIntervals),
|
||||||
|
"potentialInVehicleTripIntervals", newData -> collectPotentialInVehicleTripIntervalEvents(newData, potentialInVehicleTripIntervals)
|
||||||
),
|
),
|
||||||
runtime -> {
|
runtime -> {
|
||||||
if (vehicleUsageIntervals != null) {
|
if (vehicleUsageIntervals != null) {
|
||||||
|
|
@ -159,7 +162,8 @@ public class DriverTimelineReusableProjectionBuilder {
|
||||||
sortDrivingInterruptionIntervals(drivingInterruptionVehicleChangeIntervals),
|
sortDrivingInterruptionIntervals(drivingInterruptionVehicleChangeIntervals),
|
||||||
sortVuCardAbsentIntervals(vuCardAbsentIntervals),
|
sortVuCardAbsentIntervals(vuCardAbsentIntervals),
|
||||||
sortPotentialHomeOvernightStayIntervals(potentialHomeOvernightStayIntervals),
|
sortPotentialHomeOvernightStayIntervals(potentialHomeOvernightStayIntervals),
|
||||||
sortPotentialInVehicleOvernightStayIntervals(potentialInVehicleOvernightStayIntervals)
|
sortPotentialInVehicleOvernightStayIntervals(potentialInVehicleOvernightStayIntervals),
|
||||||
|
sortPotentialInVehicleTripIntervals(potentialInVehicleTripIntervals)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -172,6 +176,7 @@ public class DriverTimelineReusableProjectionBuilder {
|
||||||
List.of(),
|
List.of(),
|
||||||
List.of(),
|
List.of(),
|
||||||
List.of(),
|
List.of(),
|
||||||
|
List.of(),
|
||||||
List.of()
|
List.of()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -424,6 +429,8 @@ public class DriverTimelineReusableProjectionBuilder {
|
||||||
OffsetDateTime.ofInstant(Instant.ofEpochSecond(startedAtEpochSecond), ZoneOffset.UTC),
|
OffsetDateTime.ofInstant(Instant.ofEpochSecond(startedAtEpochSecond), ZoneOffset.UTC),
|
||||||
OffsetDateTime.ofInstant(Instant.ofEpochSecond(endedAtEpochSecond), ZoneOffset.UTC),
|
OffsetDateTime.ofInstant(Instant.ofEpochSecond(endedAtEpochSecond), ZoneOffset.UTC),
|
||||||
(Long) event.get("durationSeconds"),
|
(Long) event.get("durationSeconds"),
|
||||||
|
(Long) event.get("cardPresentDurationSeconds"),
|
||||||
|
(Double) event.get("cardPresentCoveragePercent"),
|
||||||
(Long) event.get("unknownDurationSeconds"),
|
(Long) event.get("unknownDurationSeconds"),
|
||||||
(Double) event.get("unknownCoveragePercent"),
|
(Double) event.get("unknownCoveragePercent"),
|
||||||
(String) event.get("previousDrivingSourceIntervalId"),
|
(String) event.get("previousDrivingSourceIntervalId"),
|
||||||
|
|
@ -454,6 +461,8 @@ public class DriverTimelineReusableProjectionBuilder {
|
||||||
(Long) event.get("durationSeconds"),
|
(Long) event.get("durationSeconds"),
|
||||||
(Long) event.get("cardPresentDurationSeconds"),
|
(Long) event.get("cardPresentDurationSeconds"),
|
||||||
(Double) event.get("cardPresentCoveragePercent"),
|
(Double) event.get("cardPresentCoveragePercent"),
|
||||||
|
(Long) event.get("unknownDurationSeconds"),
|
||||||
|
(Double) event.get("unknownCoveragePercent"),
|
||||||
(String) event.get("previousDrivingSourceIntervalId"),
|
(String) event.get("previousDrivingSourceIntervalId"),
|
||||||
(String) event.get("nextDrivingSourceIntervalId"),
|
(String) event.get("nextDrivingSourceIntervalId"),
|
||||||
(String) event.get("previousRegistrationKey"),
|
(String) event.get("previousRegistrationKey"),
|
||||||
|
|
@ -464,6 +473,37 @@ public class DriverTimelineReusableProjectionBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void collectPotentialInVehicleTripIntervalEvents(
|
||||||
|
EventBean[] newData,
|
||||||
|
List<TachographEsperPotentialInVehicleTripIntervalEvent> target
|
||||||
|
) {
|
||||||
|
if (newData == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (EventBean event : newData) {
|
||||||
|
long startedAtEpochSecond = (Long) event.get("startedAtEpochSecond");
|
||||||
|
long endedAtEpochSecond = (Long) event.get("endedAtEpochSecond");
|
||||||
|
target.add(new TachographEsperPotentialInVehicleTripIntervalEvent(
|
||||||
|
(UUID) event.get("sessionId"),
|
||||||
|
(String) event.get("driverKey"),
|
||||||
|
OffsetDateTime.ofInstant(Instant.ofEpochSecond(startedAtEpochSecond), ZoneOffset.UTC),
|
||||||
|
OffsetDateTime.ofInstant(Instant.ofEpochSecond(endedAtEpochSecond), ZoneOffset.UTC),
|
||||||
|
(Long) event.get("durationSeconds"),
|
||||||
|
(String) event.get("registrationKey"),
|
||||||
|
(String) event.get("vehicleKey"),
|
||||||
|
(Integer) event.get("containedPotentialInVehicleOvernightStayIntervalCount"),
|
||||||
|
(Long) event.get("containedPotentialInVehicleOvernightStayDurationSeconds"),
|
||||||
|
(Long) event.get("containedCardPresentDurationSeconds"),
|
||||||
|
(Long) event.get("containedUnknownDurationSeconds"),
|
||||||
|
OffsetDateTime.ofInstant(Instant.ofEpochSecond((Long) event.get("firstPotentialInVehicleOvernightStayStartedAtEpochSecond")), ZoneOffset.UTC),
|
||||||
|
OffsetDateTime.ofInstant(Instant.ofEpochSecond((Long) event.get("lastPotentialInVehicleOvernightStayEndedAtEpochSecond")), ZoneOffset.UTC),
|
||||||
|
(String) event.get("firstPreviousDrivingSourceIntervalId"),
|
||||||
|
(String) event.get("lastNextDrivingSourceIntervalId"),
|
||||||
|
List.of()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private List<TachographEsperDrivingInterruptionIntervalEvent> sortDrivingInterruptionIntervals(
|
private List<TachographEsperDrivingInterruptionIntervalEvent> sortDrivingInterruptionIntervals(
|
||||||
List<TachographEsperDrivingInterruptionIntervalEvent> intervals
|
List<TachographEsperDrivingInterruptionIntervalEvent> intervals
|
||||||
) {
|
) {
|
||||||
|
|
@ -509,6 +549,15 @@ public class DriverTimelineReusableProjectionBuilder {
|
||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<TachographEsperPotentialInVehicleTripIntervalEvent> sortPotentialInVehicleTripIntervals(
|
||||||
|
List<TachographEsperPotentialInVehicleTripIntervalEvent> intervals
|
||||||
|
) {
|
||||||
|
return intervals.stream()
|
||||||
|
.sorted(Comparator.comparing(TachographEsperPotentialInVehicleTripIntervalEvent::startedAt)
|
||||||
|
.thenComparing(TachographEsperPotentialInVehicleTripIntervalEvent::endedAt))
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
private String renderDrivingDerivedProjectionBundleEpl(int significantDrivingMinutes, int minimumRestPeriodMinutes) {
|
private String renderDrivingDerivedProjectionBundleEpl(int significantDrivingMinutes, int minimumRestPeriodMinutes) {
|
||||||
return DRIVING_DERIVED_PROJECTION_BUNDLE_EPL_TEMPLATE
|
return DRIVING_DERIVED_PROJECTION_BUNDLE_EPL_TEMPLATE
|
||||||
.replace(
|
.replace(
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ import at.procon.eventhub.tachographfilesession.model.TachographEsperDrivingInte
|
||||||
import at.procon.eventhub.tachographfilesession.model.TachographFileSession;
|
import at.procon.eventhub.tachographfilesession.model.TachographFileSession;
|
||||||
import at.procon.eventhub.tachographfilesession.model.TachographEsperPotentialHomeOvernightStayIntervalEvent;
|
import at.procon.eventhub.tachographfilesession.model.TachographEsperPotentialHomeOvernightStayIntervalEvent;
|
||||||
import at.procon.eventhub.tachographfilesession.model.TachographEsperPotentialInVehicleOvernightStayIntervalEvent;
|
import at.procon.eventhub.tachographfilesession.model.TachographEsperPotentialInVehicleOvernightStayIntervalEvent;
|
||||||
|
import at.procon.eventhub.tachographfilesession.model.TachographEsperPotentialInVehicleTripIntervalEvent;
|
||||||
import at.procon.eventhub.tachographfilesession.model.TachographEsperVehicleUsageIntervalEvent;
|
import at.procon.eventhub.tachographfilesession.model.TachographEsperVehicleUsageIntervalEvent;
|
||||||
import at.procon.eventhub.tachographfilesession.model.TachographEsperVuCardAbsentIntervalEvent;
|
import at.procon.eventhub.tachographfilesession.model.TachographEsperVuCardAbsentIntervalEvent;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
|
@ -202,17 +203,18 @@ public class TachographFileSessionProcessingService {
|
||||||
requestedFrom,
|
requestedFrom,
|
||||||
requestedTo
|
requestedTo
|
||||||
);
|
);
|
||||||
|
List<TachographEsperVehicleUsageIntervalEvent> rawVehicleUsageIntervals =
|
||||||
|
driverTimelineBuilder.buildEsperVehicleUsageIntervalEvents(timeline);
|
||||||
List<TachographEsperVuCardAbsentIntervalEvent> rawVuCardAbsentIntervals =
|
List<TachographEsperVuCardAbsentIntervalEvent> rawVuCardAbsentIntervals =
|
||||||
derivedProjectionBundle.vuCardAbsentIntervals();
|
derivedProjectionBundle.vuCardAbsentIntervals();
|
||||||
List<TachographEsperPotentialHomeOvernightStayIntervalEvent> potentialHomeOvernightStayIntervals =
|
List<TachographEsperPotentialHomeOvernightStayIntervalEvent> potentialHomeOvernightStayIntervals =
|
||||||
clipEsperPotentialHomeOvernightStayIntervalEvents(
|
clipEsperPotentialHomeOvernightStayIntervalEvents(
|
||||||
derivedProjectionBundle.potentialHomeOvernightStayIntervals(),
|
derivedProjectionBundle.potentialHomeOvernightStayIntervals(),
|
||||||
rawVuCardAbsentIntervals,
|
rawVuCardAbsentIntervals,
|
||||||
|
rawVehicleUsageIntervals,
|
||||||
requestedFrom,
|
requestedFrom,
|
||||||
requestedTo
|
requestedTo
|
||||||
);
|
);
|
||||||
List<TachographEsperVehicleUsageIntervalEvent> rawVehicleUsageIntervals =
|
|
||||||
driverTimelineBuilder.buildEsperVehicleUsageIntervalEvents(timeline);
|
|
||||||
List<TachographEsperDailyWeeklyRestCandidateCoverageIntervalEvent> dailyWeeklyRestCandidateCoverageIntervals =
|
List<TachographEsperDailyWeeklyRestCandidateCoverageIntervalEvent> dailyWeeklyRestCandidateCoverageIntervals =
|
||||||
clipEsperDailyWeeklyRestCandidateCoverageIntervalEvents(
|
clipEsperDailyWeeklyRestCandidateCoverageIntervalEvents(
|
||||||
derivedProjectionBundle.dailyWeeklyRestCandidateCoverageIntervals(),
|
derivedProjectionBundle.dailyWeeklyRestCandidateCoverageIntervals(),
|
||||||
|
|
@ -232,10 +234,18 @@ public class TachographFileSessionProcessingService {
|
||||||
List<TachographEsperPotentialInVehicleOvernightStayIntervalEvent> potentialInVehicleOvernightStayIntervals =
|
List<TachographEsperPotentialInVehicleOvernightStayIntervalEvent> potentialInVehicleOvernightStayIntervals =
|
||||||
clipEsperPotentialInVehicleOvernightStayIntervalEvents(
|
clipEsperPotentialInVehicleOvernightStayIntervalEvents(
|
||||||
derivedProjectionBundle.potentialInVehicleOvernightStayIntervals(),
|
derivedProjectionBundle.potentialInVehicleOvernightStayIntervals(),
|
||||||
|
rawVuCardAbsentIntervals,
|
||||||
rawVehicleUsageIntervals,
|
rawVehicleUsageIntervals,
|
||||||
requestedFrom,
|
requestedFrom,
|
||||||
requestedTo
|
requestedTo
|
||||||
);
|
);
|
||||||
|
List<TachographEsperPotentialInVehicleTripIntervalEvent> potentialInVehicleTripIntervals =
|
||||||
|
clipEsperPotentialInVehicleTripIntervalEvents(
|
||||||
|
derivedProjectionBundle.potentialInVehicleTripIntervals(),
|
||||||
|
potentialInVehicleOvernightStayIntervals,
|
||||||
|
requestedFrom,
|
||||||
|
requestedTo
|
||||||
|
);
|
||||||
List<TachographEsperVehicleUsageIntervalEvent> vehicleUsageIntervals = clipEsperVehicleUsageIntervalEvents(
|
List<TachographEsperVehicleUsageIntervalEvent> vehicleUsageIntervals = clipEsperVehicleUsageIntervalEvents(
|
||||||
rawVehicleUsageIntervals,
|
rawVehicleUsageIntervals,
|
||||||
requestedFrom,
|
requestedFrom,
|
||||||
|
|
@ -264,10 +274,11 @@ public class TachographFileSessionProcessingService {
|
||||||
unclassifiedDailyWeeklyRestCandidateCoverageIntervals.size(),
|
unclassifiedDailyWeeklyRestCandidateCoverageIntervals.size(),
|
||||||
potentialHomeOvernightStayIntervals.size(),
|
potentialHomeOvernightStayIntervals.size(),
|
||||||
potentialInVehicleOvernightStayIntervals.size(),
|
potentialInVehicleOvernightStayIntervals.size(),
|
||||||
|
potentialInVehicleTripIntervals.size(),
|
||||||
vehicleUsageIntervals.size(),
|
vehicleUsageIntervals.size(),
|
||||||
vuCardAbsentIntervals.size(),
|
vuCardAbsentIntervals.size(),
|
||||||
activityIntervals,
|
List.of()/*activityIntervals*/,
|
||||||
drivingIntervals,
|
List.of()/*drivingIntervals*/,
|
||||||
drivingInterruptionIntervals,
|
drivingInterruptionIntervals,
|
||||||
drivingInterruptionVehicleChangeIntervals,
|
drivingInterruptionVehicleChangeIntervals,
|
||||||
dailyWeeklyRestCandidateIntervals,
|
dailyWeeklyRestCandidateIntervals,
|
||||||
|
|
@ -275,6 +286,7 @@ public class TachographFileSessionProcessingService {
|
||||||
unclassifiedDailyWeeklyRestCandidateCoverageIntervals,
|
unclassifiedDailyWeeklyRestCandidateCoverageIntervals,
|
||||||
potentialHomeOvernightStayIntervals,
|
potentialHomeOvernightStayIntervals,
|
||||||
potentialInVehicleOvernightStayIntervals,
|
potentialInVehicleOvernightStayIntervals,
|
||||||
|
potentialInVehicleTripIntervals,
|
||||||
vehicleUsageIntervals,
|
vehicleUsageIntervals,
|
||||||
vuCardAbsentIntervals,
|
vuCardAbsentIntervals,
|
||||||
esperProjectionNotes()
|
esperProjectionNotes()
|
||||||
|
|
@ -510,53 +522,6 @@ public class TachographFileSessionProcessingService {
|
||||||
private List<TachographEsperPotentialHomeOvernightStayIntervalEvent> clipEsperPotentialHomeOvernightStayIntervalEvents(
|
private List<TachographEsperPotentialHomeOvernightStayIntervalEvent> clipEsperPotentialHomeOvernightStayIntervalEvents(
|
||||||
List<TachographEsperPotentialHomeOvernightStayIntervalEvent> intervals,
|
List<TachographEsperPotentialHomeOvernightStayIntervalEvent> intervals,
|
||||||
List<TachographEsperVuCardAbsentIntervalEvent> rawVuCardAbsentIntervals,
|
List<TachographEsperVuCardAbsentIntervalEvent> rawVuCardAbsentIntervals,
|
||||||
OffsetDateTime requestedFrom,
|
|
||||||
OffsetDateTime requestedTo
|
|
||||||
) {
|
|
||||||
if (requestedFrom == null || requestedTo == null) {
|
|
||||||
return List.of();
|
|
||||||
}
|
|
||||||
return intervals.stream()
|
|
||||||
.map(interval -> {
|
|
||||||
OffsetDateTime start = max(interval.startedAt(), requestedFrom);
|
|
||||||
OffsetDateTime end = min(interval.endedAt(), requestedTo);
|
|
||||||
if (!end.isAfter(start)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
long durationSeconds = Duration.between(start, end).getSeconds();
|
|
||||||
long unknownDurationSeconds = overlapSeconds(
|
|
||||||
start,
|
|
||||||
end,
|
|
||||||
rawVuCardAbsentIntervals,
|
|
||||||
interval.driverKey()
|
|
||||||
);
|
|
||||||
double unknownCoveragePercent = durationSeconds == 0L
|
|
||||||
? 0.0d
|
|
||||||
: (unknownDurationSeconds * 100.0d) / durationSeconds;
|
|
||||||
return new TachographEsperPotentialHomeOvernightStayIntervalEvent(
|
|
||||||
interval.sessionId(),
|
|
||||||
interval.driverKey(),
|
|
||||||
start,
|
|
||||||
end,
|
|
||||||
durationSeconds,
|
|
||||||
unknownDurationSeconds,
|
|
||||||
unknownCoveragePercent,
|
|
||||||
interval.previousDrivingSourceIntervalId(),
|
|
||||||
interval.nextDrivingSourceIntervalId(),
|
|
||||||
interval.previousRegistrationKey(),
|
|
||||||
interval.nextRegistrationKey(),
|
|
||||||
interval.previousVehicleKey(),
|
|
||||||
interval.nextVehicleKey()
|
|
||||||
);
|
|
||||||
})
|
|
||||||
.filter(Objects::nonNull)
|
|
||||||
.sorted(Comparator.comparing(TachographEsperPotentialHomeOvernightStayIntervalEvent::startedAt)
|
|
||||||
.thenComparing(TachographEsperPotentialHomeOvernightStayIntervalEvent::endedAt))
|
|
||||||
.toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<TachographEsperPotentialInVehicleOvernightStayIntervalEvent> clipEsperPotentialInVehicleOvernightStayIntervalEvents(
|
|
||||||
List<TachographEsperPotentialInVehicleOvernightStayIntervalEvent> intervals,
|
|
||||||
List<TachographEsperVehicleUsageIntervalEvent> rawVehicleUsageIntervals,
|
List<TachographEsperVehicleUsageIntervalEvent> rawVehicleUsageIntervals,
|
||||||
OffsetDateTime requestedFrom,
|
OffsetDateTime requestedFrom,
|
||||||
OffsetDateTime requestedTo
|
OffsetDateTime requestedTo
|
||||||
|
|
@ -577,11 +542,81 @@ public class TachographFileSessionProcessingService {
|
||||||
end,
|
end,
|
||||||
rawVehicleUsageIntervals,
|
rawVehicleUsageIntervals,
|
||||||
interval.driverKey(),
|
interval.driverKey(),
|
||||||
interval.previousRegistrationKey()
|
null
|
||||||
);
|
);
|
||||||
double cardPresentCoveragePercent = durationSeconds == 0L
|
double cardPresentCoveragePercent = durationSeconds == 0L
|
||||||
? 0.0d
|
? 0.0d
|
||||||
: (cardPresentDurationSeconds * 100.0d) / durationSeconds;
|
: (cardPresentDurationSeconds * 100.0d) / durationSeconds;
|
||||||
|
long unknownDurationSeconds = overlapSeconds(
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
rawVuCardAbsentIntervals,
|
||||||
|
interval.driverKey()
|
||||||
|
);
|
||||||
|
double unknownCoveragePercent = durationSeconds == 0L
|
||||||
|
? 0.0d
|
||||||
|
: (unknownDurationSeconds * 100.0d) / durationSeconds;
|
||||||
|
return new TachographEsperPotentialHomeOvernightStayIntervalEvent(
|
||||||
|
interval.sessionId(),
|
||||||
|
interval.driverKey(),
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
durationSeconds,
|
||||||
|
cardPresentDurationSeconds,
|
||||||
|
cardPresentCoveragePercent,
|
||||||
|
unknownDurationSeconds,
|
||||||
|
unknownCoveragePercent,
|
||||||
|
interval.previousDrivingSourceIntervalId(),
|
||||||
|
interval.nextDrivingSourceIntervalId(),
|
||||||
|
interval.previousRegistrationKey(),
|
||||||
|
interval.nextRegistrationKey(),
|
||||||
|
interval.previousVehicleKey(),
|
||||||
|
interval.nextVehicleKey()
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.sorted(Comparator.comparing(TachographEsperPotentialHomeOvernightStayIntervalEvent::startedAt)
|
||||||
|
.thenComparing(TachographEsperPotentialHomeOvernightStayIntervalEvent::endedAt))
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<TachographEsperPotentialInVehicleOvernightStayIntervalEvent> clipEsperPotentialInVehicleOvernightStayIntervalEvents(
|
||||||
|
List<TachographEsperPotentialInVehicleOvernightStayIntervalEvent> intervals,
|
||||||
|
List<TachographEsperVuCardAbsentIntervalEvent> rawVuCardAbsentIntervals,
|
||||||
|
List<TachographEsperVehicleUsageIntervalEvent> rawVehicleUsageIntervals,
|
||||||
|
OffsetDateTime requestedFrom,
|
||||||
|
OffsetDateTime requestedTo
|
||||||
|
) {
|
||||||
|
if (requestedFrom == null || requestedTo == null) {
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
return intervals.stream()
|
||||||
|
.map(interval -> {
|
||||||
|
OffsetDateTime start = max(interval.startedAt(), requestedFrom);
|
||||||
|
OffsetDateTime end = min(interval.endedAt(), requestedTo);
|
||||||
|
if (!end.isAfter(start)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
long durationSeconds = Duration.between(start, end).getSeconds();
|
||||||
|
long cardPresentDurationSeconds = overlapVehicleUsageSeconds(
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
rawVehicleUsageIntervals,
|
||||||
|
interval.driverKey(),
|
||||||
|
null
|
||||||
|
);
|
||||||
|
double cardPresentCoveragePercent = durationSeconds == 0L
|
||||||
|
? 0.0d
|
||||||
|
: (cardPresentDurationSeconds * 100.0d) / durationSeconds;
|
||||||
|
long unknownDurationSeconds = overlapSeconds(
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
rawVuCardAbsentIntervals,
|
||||||
|
interval.driverKey()
|
||||||
|
);
|
||||||
|
double unknownCoveragePercent = durationSeconds == 0L
|
||||||
|
? 0.0d
|
||||||
|
: (unknownDurationSeconds * 100.0d) / durationSeconds;
|
||||||
return new TachographEsperPotentialInVehicleOvernightStayIntervalEvent(
|
return new TachographEsperPotentialInVehicleOvernightStayIntervalEvent(
|
||||||
interval.sessionId(),
|
interval.sessionId(),
|
||||||
interval.driverKey(),
|
interval.driverKey(),
|
||||||
|
|
@ -590,6 +625,8 @@ public class TachographFileSessionProcessingService {
|
||||||
durationSeconds,
|
durationSeconds,
|
||||||
cardPresentDurationSeconds,
|
cardPresentDurationSeconds,
|
||||||
cardPresentCoveragePercent,
|
cardPresentCoveragePercent,
|
||||||
|
unknownDurationSeconds,
|
||||||
|
unknownCoveragePercent,
|
||||||
interval.previousDrivingSourceIntervalId(),
|
interval.previousDrivingSourceIntervalId(),
|
||||||
interval.nextDrivingSourceIntervalId(),
|
interval.nextDrivingSourceIntervalId(),
|
||||||
interval.previousRegistrationKey(),
|
interval.previousRegistrationKey(),
|
||||||
|
|
@ -604,6 +641,98 @@ public class TachographFileSessionProcessingService {
|
||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<TachographEsperPotentialInVehicleTripIntervalEvent> clipEsperPotentialInVehicleTripIntervalEvents(
|
||||||
|
List<TachographEsperPotentialInVehicleTripIntervalEvent> intervals,
|
||||||
|
List<TachographEsperPotentialInVehicleOvernightStayIntervalEvent> potentialInVehicleOvernightStayIntervals,
|
||||||
|
OffsetDateTime requestedFrom,
|
||||||
|
OffsetDateTime requestedTo
|
||||||
|
) {
|
||||||
|
if (requestedFrom == null || requestedTo == null) {
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
if (intervals == null || intervals.isEmpty()
|
||||||
|
|| potentialInVehicleOvernightStayIntervals == null || potentialInVehicleOvernightStayIntervals.isEmpty()) {
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
return intervals.stream()
|
||||||
|
.map(interval -> {
|
||||||
|
OffsetDateTime start = max(interval.startedAt(), requestedFrom);
|
||||||
|
OffsetDateTime end = min(interval.endedAt(), requestedTo);
|
||||||
|
if (!end.isAfter(start)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
List<TachographEsperPotentialInVehicleOvernightStayIntervalEvent> containedIntervals =
|
||||||
|
potentialInVehicleOvernightStayIntervals.stream()
|
||||||
|
.filter(candidate -> tripContainsPotentialInterval(
|
||||||
|
interval.driverKey(),
|
||||||
|
interval.registrationKey(),
|
||||||
|
interval.vehicleKey(),
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
candidate
|
||||||
|
))
|
||||||
|
.sorted(Comparator.comparing(TachographEsperPotentialInVehicleOvernightStayIntervalEvent::startedAt)
|
||||||
|
.thenComparing(TachographEsperPotentialInVehicleOvernightStayIntervalEvent::endedAt))
|
||||||
|
.toList();
|
||||||
|
if (containedIntervals.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
TachographEsperPotentialInVehicleOvernightStayIntervalEvent first = containedIntervals.get(0);
|
||||||
|
TachographEsperPotentialInVehicleOvernightStayIntervalEvent last =
|
||||||
|
containedIntervals.get(containedIntervals.size() - 1);
|
||||||
|
return new TachographEsperPotentialInVehicleTripIntervalEvent(
|
||||||
|
interval.sessionId(),
|
||||||
|
interval.driverKey(),
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
Duration.between(start, end).getSeconds(),
|
||||||
|
interval.registrationKey(),
|
||||||
|
interval.vehicleKey(),
|
||||||
|
containedIntervals.size(),
|
||||||
|
containedIntervals.stream()
|
||||||
|
.mapToLong(TachographEsperPotentialInVehicleOvernightStayIntervalEvent::durationSeconds)
|
||||||
|
.sum(),
|
||||||
|
containedIntervals.stream()
|
||||||
|
.mapToLong(TachographEsperPotentialInVehicleOvernightStayIntervalEvent::cardPresentDurationSeconds)
|
||||||
|
.sum(),
|
||||||
|
containedIntervals.stream()
|
||||||
|
.mapToLong(TachographEsperPotentialInVehicleOvernightStayIntervalEvent::unknownDurationSeconds)
|
||||||
|
.sum(),
|
||||||
|
first.startedAt(),
|
||||||
|
last.endedAt(),
|
||||||
|
first.previousDrivingSourceIntervalId(),
|
||||||
|
last.nextDrivingSourceIntervalId(),
|
||||||
|
containedIntervals
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.sorted(Comparator.comparing(TachographEsperPotentialInVehicleTripIntervalEvent::startedAt)
|
||||||
|
.thenComparing(TachographEsperPotentialInVehicleTripIntervalEvent::endedAt))
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean tripContainsPotentialInterval(
|
||||||
|
String driverKey,
|
||||||
|
String registrationKey,
|
||||||
|
String vehicleKey,
|
||||||
|
OffsetDateTime tripStartedAt,
|
||||||
|
OffsetDateTime tripEndedAt,
|
||||||
|
TachographEsperPotentialInVehicleOvernightStayIntervalEvent candidate
|
||||||
|
) {
|
||||||
|
if (!Objects.equals(driverKey, candidate.driverKey())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!Objects.equals(registrationKey, candidate.previousRegistrationKey())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (vehicleKey != null && candidate.previousVehicleKey() != null
|
||||||
|
&& !Objects.equals(vehicleKey, candidate.previousVehicleKey())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return !candidate.startedAt().isBefore(tripStartedAt)
|
||||||
|
&& !candidate.endedAt().isAfter(tripEndedAt);
|
||||||
|
}
|
||||||
|
|
||||||
private List<ResolvedActivityInterval> synthesizeUnknownGaps(
|
private List<ResolvedActivityInterval> synthesizeUnknownGaps(
|
||||||
List<ResolvedActivityInterval> knownIntervals,
|
List<ResolvedActivityInterval> knownIntervals,
|
||||||
Duration gapDetectionTolerance
|
Duration gapDetectionTolerance
|
||||||
|
|
@ -1174,6 +1303,7 @@ public class TachographFileSessionProcessingService {
|
||||||
"Unclassified daily/weekly rest candidate coverage intervals are the rest candidates that are neither potential home overnight stays nor potential in-vehicle overnight stays.",
|
"Unclassified daily/weekly rest candidate coverage intervals are the rest candidates that are neither potential home overnight stays nor potential in-vehicle overnight stays.",
|
||||||
"Potential home overnight stay intervals are vehicle-change daily/weekly rest candidate coverage intervals where VU card-absent overlap covers at least 95% of the candidate interval.",
|
"Potential home overnight stay intervals are vehicle-change daily/weekly rest candidate coverage intervals where VU card-absent overlap covers at least 95% of the candidate interval.",
|
||||||
"Potential in-vehicle overnight stay intervals are no-change daily/weekly rest candidate coverage intervals where card-present overlap covers the candidate rest period.",
|
"Potential in-vehicle overnight stay intervals are no-change daily/weekly rest candidate coverage intervals where card-present overlap covers the candidate rest period.",
|
||||||
|
"Potential in-vehicle trip intervals span from the end of the coverage interval before a same-vehicle in-vehicle-overnight sequence to the start of the first coverage interval after that sequence.",
|
||||||
"VU card-absent intervals are gaps between consecutive normalized vehicle-usage intervals for the same driver.",
|
"VU card-absent intervals are gaps between consecutive normalized vehicle-usage intervals for the same driver.",
|
||||||
"occurredFrom and occurredTo clip the returned interval projections to the requested UTC time window.",
|
"occurredFrom and occurredTo clip the returned interval projections to the requested UTC time window.",
|
||||||
"Vehicle-usage intervals clear clipped odometer endpoints because boundary odometer values cannot be recomputed safely from the source interval."
|
"Vehicle-usage intervals clear clipped odometer endpoints because boundary odometer values cannot be recomputed safely from the source interval."
|
||||||
|
|
|
||||||
|
|
@ -137,6 +137,8 @@ create schema PotentialHomeOvernightStayInterval(
|
||||||
startedAtEpochSecond long,
|
startedAtEpochSecond long,
|
||||||
endedAtEpochSecond long,
|
endedAtEpochSecond long,
|
||||||
durationSeconds long,
|
durationSeconds long,
|
||||||
|
cardPresentDurationSeconds long,
|
||||||
|
cardPresentCoveragePercent double,
|
||||||
unknownDurationSeconds long,
|
unknownDurationSeconds long,
|
||||||
unknownCoveragePercent double,
|
unknownCoveragePercent double,
|
||||||
previousDrivingSourceIntervalId string,
|
previousDrivingSourceIntervalId string,
|
||||||
|
|
@ -155,6 +157,8 @@ create schema PotentialInVehicleOvernightStayInterval(
|
||||||
durationSeconds long,
|
durationSeconds long,
|
||||||
cardPresentDurationSeconds long,
|
cardPresentDurationSeconds long,
|
||||||
cardPresentCoveragePercent double,
|
cardPresentCoveragePercent double,
|
||||||
|
unknownDurationSeconds long,
|
||||||
|
unknownCoveragePercent double,
|
||||||
previousDrivingSourceIntervalId string,
|
previousDrivingSourceIntervalId string,
|
||||||
nextDrivingSourceIntervalId string,
|
nextDrivingSourceIntervalId string,
|
||||||
previousRegistrationKey string,
|
previousRegistrationKey string,
|
||||||
|
|
@ -181,6 +185,44 @@ create schema UnclassifiedDailyWeeklyRestCandidateCoverageInterval(
|
||||||
nextVehicleKey string
|
nextVehicleKey string
|
||||||
);
|
);
|
||||||
|
|
||||||
|
create schema PotentialInVehicleTripState(
|
||||||
|
sessionId java.util.UUID,
|
||||||
|
driverKey string,
|
||||||
|
tripStartedAtEpochSecond long,
|
||||||
|
registrationKey string,
|
||||||
|
vehicleKey string,
|
||||||
|
containedPotentialInVehicleOvernightStayIntervalCount int,
|
||||||
|
containedPotentialInVehicleOvernightStayDurationSeconds long,
|
||||||
|
containedCardPresentDurationSeconds long,
|
||||||
|
containedUnknownDurationSeconds long,
|
||||||
|
firstPotentialInVehicleOvernightStayStartedAtEpochSecond long,
|
||||||
|
lastPotentialInVehicleOvernightStayEndedAtEpochSecond long,
|
||||||
|
firstPreviousDrivingSourceIntervalId string,
|
||||||
|
lastNextDrivingSourceIntervalId string
|
||||||
|
);
|
||||||
|
|
||||||
|
create schema PotentialInVehicleTripInterval(
|
||||||
|
sessionId java.util.UUID,
|
||||||
|
driverKey string,
|
||||||
|
startedAtEpochSecond long,
|
||||||
|
endedAtEpochSecond long,
|
||||||
|
durationSeconds long,
|
||||||
|
registrationKey string,
|
||||||
|
vehicleKey string,
|
||||||
|
containedPotentialInVehicleOvernightStayIntervalCount int,
|
||||||
|
containedPotentialInVehicleOvernightStayDurationSeconds long,
|
||||||
|
containedCardPresentDurationSeconds long,
|
||||||
|
containedUnknownDurationSeconds long,
|
||||||
|
firstPotentialInVehicleOvernightStayStartedAtEpochSecond long,
|
||||||
|
lastPotentialInVehicleOvernightStayEndedAtEpochSecond long,
|
||||||
|
firstPreviousDrivingSourceIntervalId string,
|
||||||
|
lastNextDrivingSourceIntervalId string
|
||||||
|
);
|
||||||
|
|
||||||
|
create window PreviousRestCandidateCoverageInterval#unique(driverKey) as DailyWeeklyRestCandidateCoverageInterval;
|
||||||
|
|
||||||
|
create window OpenPotentialInVehicleTripState#unique(driverKey) as PotentialInVehicleTripState;
|
||||||
|
|
||||||
insert into SignificantDrivingInterval
|
insert into SignificantDrivingInterval
|
||||||
select
|
select
|
||||||
sessionId,
|
sessionId,
|
||||||
|
|
@ -435,6 +477,8 @@ select
|
||||||
c.startedAtEpochSecond as startedAtEpochSecond,
|
c.startedAtEpochSecond as startedAtEpochSecond,
|
||||||
c.endedAtEpochSecond as endedAtEpochSecond,
|
c.endedAtEpochSecond as endedAtEpochSecond,
|
||||||
c.durationSeconds as durationSeconds,
|
c.durationSeconds as durationSeconds,
|
||||||
|
c.cardPresentDurationSeconds as cardPresentDurationSeconds,
|
||||||
|
c.cardPresentCoveragePercent as cardPresentCoveragePercent,
|
||||||
c.unknownDurationSeconds as unknownDurationSeconds,
|
c.unknownDurationSeconds as unknownDurationSeconds,
|
||||||
c.unknownCoveragePercent as unknownCoveragePercent,
|
c.unknownCoveragePercent as unknownCoveragePercent,
|
||||||
c.previousDrivingSourceIntervalId as previousDrivingSourceIntervalId,
|
c.previousDrivingSourceIntervalId as previousDrivingSourceIntervalId,
|
||||||
|
|
@ -458,6 +502,8 @@ select
|
||||||
c.durationSeconds as durationSeconds,
|
c.durationSeconds as durationSeconds,
|
||||||
c.cardPresentDurationSeconds as cardPresentDurationSeconds,
|
c.cardPresentDurationSeconds as cardPresentDurationSeconds,
|
||||||
c.cardPresentCoveragePercent as cardPresentCoveragePercent,
|
c.cardPresentCoveragePercent as cardPresentCoveragePercent,
|
||||||
|
c.unknownDurationSeconds as unknownDurationSeconds,
|
||||||
|
c.unknownCoveragePercent as unknownCoveragePercent,
|
||||||
c.previousDrivingSourceIntervalId as previousDrivingSourceIntervalId,
|
c.previousDrivingSourceIntervalId as previousDrivingSourceIntervalId,
|
||||||
c.nextDrivingSourceIntervalId as nextDrivingSourceIntervalId,
|
c.nextDrivingSourceIntervalId as nextDrivingSourceIntervalId,
|
||||||
c.previousRegistrationKey as previousRegistrationKey,
|
c.previousRegistrationKey as previousRegistrationKey,
|
||||||
|
|
@ -501,6 +547,130 @@ where not (
|
||||||
and c.cardPresentDurationSeconds >= c.durationSeconds
|
and c.cardPresentDurationSeconds >= c.durationSeconds
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@Priority(40)
|
||||||
|
on DailyWeeklyRestCandidateCoverageInterval as c
|
||||||
|
insert into PotentialInVehicleTripInterval
|
||||||
|
select
|
||||||
|
s.sessionId as sessionId,
|
||||||
|
s.driverKey as driverKey,
|
||||||
|
s.tripStartedAtEpochSecond as startedAtEpochSecond,
|
||||||
|
c.startedAtEpochSecond as endedAtEpochSecond,
|
||||||
|
c.startedAtEpochSecond - s.tripStartedAtEpochSecond as durationSeconds,
|
||||||
|
s.registrationKey as registrationKey,
|
||||||
|
s.vehicleKey as vehicleKey,
|
||||||
|
s.containedPotentialInVehicleOvernightStayIntervalCount as containedPotentialInVehicleOvernightStayIntervalCount,
|
||||||
|
s.containedPotentialInVehicleOvernightStayDurationSeconds as containedPotentialInVehicleOvernightStayDurationSeconds,
|
||||||
|
s.containedCardPresentDurationSeconds as containedCardPresentDurationSeconds,
|
||||||
|
s.containedUnknownDurationSeconds as containedUnknownDurationSeconds,
|
||||||
|
s.firstPotentialInVehicleOvernightStayStartedAtEpochSecond as firstPotentialInVehicleOvernightStayStartedAtEpochSecond,
|
||||||
|
s.lastPotentialInVehicleOvernightStayEndedAtEpochSecond as lastPotentialInVehicleOvernightStayEndedAtEpochSecond,
|
||||||
|
s.firstPreviousDrivingSourceIntervalId as firstPreviousDrivingSourceIntervalId,
|
||||||
|
s.lastNextDrivingSourceIntervalId as lastNextDrivingSourceIntervalId
|
||||||
|
from OpenPotentialInVehicleTripState as s
|
||||||
|
where s.driverKey = c.driverKey
|
||||||
|
and c.startedAtEpochSecond > s.tripStartedAtEpochSecond
|
||||||
|
and (
|
||||||
|
not (
|
||||||
|
c.previousRegistrationKey is not null
|
||||||
|
and c.nextRegistrationKey is not null
|
||||||
|
and c.previousRegistrationKey = c.nextRegistrationKey
|
||||||
|
and c.cardPresentDurationSeconds >= c.durationSeconds
|
||||||
|
)
|
||||||
|
or s.registrationKey != c.previousRegistrationKey
|
||||||
|
or (
|
||||||
|
s.vehicleKey is not null
|
||||||
|
and c.previousVehicleKey is not null
|
||||||
|
and s.vehicleKey != c.previousVehicleKey
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
@Priority(35)
|
||||||
|
on DailyWeeklyRestCandidateCoverageInterval as c
|
||||||
|
delete from OpenPotentialInVehicleTripState as s
|
||||||
|
where s.driverKey = c.driverKey
|
||||||
|
and not (
|
||||||
|
c.previousRegistrationKey is not null
|
||||||
|
and c.nextRegistrationKey is not null
|
||||||
|
and c.previousRegistrationKey = c.nextRegistrationKey
|
||||||
|
and c.cardPresentDurationSeconds >= c.durationSeconds
|
||||||
|
);
|
||||||
|
|
||||||
|
@Priority(30)
|
||||||
|
on DailyWeeklyRestCandidateCoverageInterval as c
|
||||||
|
insert into OpenPotentialInVehicleTripState
|
||||||
|
select
|
||||||
|
s.sessionId as sessionId,
|
||||||
|
s.driverKey as driverKey,
|
||||||
|
s.tripStartedAtEpochSecond as tripStartedAtEpochSecond,
|
||||||
|
s.registrationKey as registrationKey,
|
||||||
|
s.vehicleKey as vehicleKey,
|
||||||
|
s.containedPotentialInVehicleOvernightStayIntervalCount + 1 as containedPotentialInVehicleOvernightStayIntervalCount,
|
||||||
|
s.containedPotentialInVehicleOvernightStayDurationSeconds + c.durationSeconds as containedPotentialInVehicleOvernightStayDurationSeconds,
|
||||||
|
s.containedCardPresentDurationSeconds + c.cardPresentDurationSeconds as containedCardPresentDurationSeconds,
|
||||||
|
s.containedUnknownDurationSeconds + c.unknownDurationSeconds as containedUnknownDurationSeconds,
|
||||||
|
s.firstPotentialInVehicleOvernightStayStartedAtEpochSecond as firstPotentialInVehicleOvernightStayStartedAtEpochSecond,
|
||||||
|
c.endedAtEpochSecond as lastPotentialInVehicleOvernightStayEndedAtEpochSecond,
|
||||||
|
s.firstPreviousDrivingSourceIntervalId as firstPreviousDrivingSourceIntervalId,
|
||||||
|
c.nextDrivingSourceIntervalId as lastNextDrivingSourceIntervalId
|
||||||
|
from OpenPotentialInVehicleTripState as s
|
||||||
|
where s.driverKey = c.driverKey
|
||||||
|
and c.previousRegistrationKey is not null
|
||||||
|
and c.nextRegistrationKey is not null
|
||||||
|
and c.previousRegistrationKey = c.nextRegistrationKey
|
||||||
|
and c.cardPresentDurationSeconds >= c.durationSeconds
|
||||||
|
and s.registrationKey = c.previousRegistrationKey
|
||||||
|
and (
|
||||||
|
s.vehicleKey is null
|
||||||
|
or c.previousVehicleKey is null
|
||||||
|
or s.vehicleKey = c.previousVehicleKey
|
||||||
|
);
|
||||||
|
|
||||||
|
@Priority(20)
|
||||||
|
on DailyWeeklyRestCandidateCoverageInterval as c
|
||||||
|
insert into OpenPotentialInVehicleTripState
|
||||||
|
select
|
||||||
|
c.sessionId as sessionId,
|
||||||
|
c.driverKey as driverKey,
|
||||||
|
priorCoverage.endedAtEpochSecond as tripStartedAtEpochSecond,
|
||||||
|
c.previousRegistrationKey as registrationKey,
|
||||||
|
case
|
||||||
|
when c.previousVehicleKey is not null then c.previousVehicleKey
|
||||||
|
else c.nextVehicleKey
|
||||||
|
end as vehicleKey,
|
||||||
|
1 as containedPotentialInVehicleOvernightStayIntervalCount,
|
||||||
|
c.durationSeconds as containedPotentialInVehicleOvernightStayDurationSeconds,
|
||||||
|
c.cardPresentDurationSeconds as containedCardPresentDurationSeconds,
|
||||||
|
c.unknownDurationSeconds as containedUnknownDurationSeconds,
|
||||||
|
c.startedAtEpochSecond as firstPotentialInVehicleOvernightStayStartedAtEpochSecond,
|
||||||
|
c.endedAtEpochSecond as lastPotentialInVehicleOvernightStayEndedAtEpochSecond,
|
||||||
|
c.previousDrivingSourceIntervalId as firstPreviousDrivingSourceIntervalId,
|
||||||
|
c.nextDrivingSourceIntervalId as lastNextDrivingSourceIntervalId
|
||||||
|
from PreviousRestCandidateCoverageInterval as priorCoverage
|
||||||
|
where priorCoverage.driverKey = c.driverKey
|
||||||
|
and c.previousRegistrationKey is not null
|
||||||
|
and c.nextRegistrationKey is not null
|
||||||
|
and c.previousRegistrationKey = c.nextRegistrationKey
|
||||||
|
and c.cardPresentDurationSeconds >= c.durationSeconds
|
||||||
|
and not exists (
|
||||||
|
select * from OpenPotentialInVehicleTripState as s
|
||||||
|
where s.driverKey = c.driverKey
|
||||||
|
and s.registrationKey = c.previousRegistrationKey
|
||||||
|
and (
|
||||||
|
s.vehicleKey is null
|
||||||
|
or c.previousVehicleKey is null
|
||||||
|
or s.vehicleKey = c.previousVehicleKey
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
@Priority(10)
|
||||||
|
on DailyWeeklyRestCandidateCoverageInterval
|
||||||
|
delete from PreviousRestCandidateCoverageInterval;
|
||||||
|
|
||||||
|
@Priority(5)
|
||||||
|
on DailyWeeklyRestCandidateCoverageInterval as current
|
||||||
|
insert into PreviousRestCandidateCoverageInterval
|
||||||
|
select *;
|
||||||
|
|
||||||
@name('drivingInterruptionIntervals')
|
@name('drivingInterruptionIntervals')
|
||||||
select * from DrivingInterruptionInterval;
|
select * from DrivingInterruptionInterval;
|
||||||
|
|
||||||
|
|
@ -522,5 +692,8 @@ select * from PotentialHomeOvernightStayInterval;
|
||||||
@name('potentialInVehicleOvernightStayIntervals')
|
@name('potentialInVehicleOvernightStayIntervals')
|
||||||
select * from PotentialInVehicleOvernightStayInterval;
|
select * from PotentialInVehicleOvernightStayInterval;
|
||||||
|
|
||||||
|
@name('potentialInVehicleTripIntervals')
|
||||||
|
select * from PotentialInVehicleTripInterval;
|
||||||
|
|
||||||
@name('unclassifiedDailyWeeklyRestCandidateCoverageIntervals')
|
@name('unclassifiedDailyWeeklyRestCandidateCoverageIntervals')
|
||||||
select * from UnclassifiedDailyWeeklyRestCandidateCoverageInterval;
|
select * from UnclassifiedDailyWeeklyRestCandidateCoverageInterval;
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ import at.procon.eventhub.tachographfilesession.model.TachographEsperActivityInt
|
||||||
import at.procon.eventhub.tachographfilesession.model.TachographEsperDailyWeeklyRestCandidateCoverageIntervalEvent;
|
import at.procon.eventhub.tachographfilesession.model.TachographEsperDailyWeeklyRestCandidateCoverageIntervalEvent;
|
||||||
import at.procon.eventhub.tachographfilesession.model.TachographEsperDrivingInterruptionIntervalEvent;
|
import at.procon.eventhub.tachographfilesession.model.TachographEsperDrivingInterruptionIntervalEvent;
|
||||||
import at.procon.eventhub.tachographfilesession.model.TachographEsperPotentialHomeOvernightStayIntervalEvent;
|
import at.procon.eventhub.tachographfilesession.model.TachographEsperPotentialHomeOvernightStayIntervalEvent;
|
||||||
|
import at.procon.eventhub.tachographfilesession.model.TachographEsperPotentialInVehicleTripIntervalEvent;
|
||||||
import at.procon.eventhub.tachographfilesession.model.TachographEsperVehicleUsageIntervalEvent;
|
import at.procon.eventhub.tachographfilesession.model.TachographEsperVehicleUsageIntervalEvent;
|
||||||
import at.procon.eventhub.tachographfilesession.model.TachographEsperVuCardAbsentIntervalEvent;
|
import at.procon.eventhub.tachographfilesession.model.TachographEsperVuCardAbsentIntervalEvent;
|
||||||
import at.procon.eventhub.tachographfilesession.service.TachographFileSessionProcessingService;
|
import at.procon.eventhub.tachographfilesession.service.TachographFileSessionProcessingService;
|
||||||
|
|
@ -89,6 +90,7 @@ class TachographFileSessionControllerTest {
|
||||||
0,
|
0,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
|
0,
|
||||||
2,
|
2,
|
||||||
1,
|
1,
|
||||||
List.of(new TachographEsperActivityIntervalEvent(
|
List.of(new TachographEsperActivityIntervalEvent(
|
||||||
|
|
@ -192,6 +194,8 @@ class TachographFileSessionControllerTest {
|
||||||
OffsetDateTime.parse("2026-05-12T10:00:00Z"),
|
OffsetDateTime.parse("2026-05-12T10:00:00Z"),
|
||||||
OffsetDateTime.parse("2026-05-12T22:00:00Z"),
|
OffsetDateTime.parse("2026-05-12T22:00:00Z"),
|
||||||
43_200L,
|
43_200L,
|
||||||
|
0L,
|
||||||
|
0.0d,
|
||||||
43_200L,
|
43_200L,
|
||||||
100.0d,
|
100.0d,
|
||||||
"ACT-2",
|
"ACT-2",
|
||||||
|
|
@ -202,6 +206,7 @@ class TachographFileSessionControllerTest {
|
||||||
"VIN-2"
|
"VIN-2"
|
||||||
)),
|
)),
|
||||||
List.of(),
|
List.of(),
|
||||||
|
List.<TachographEsperPotentialInVehicleTripIntervalEvent>of(),
|
||||||
List.of(new TachographEsperVehicleUsageIntervalEvent(
|
List.of(new TachographEsperVehicleUsageIntervalEvent(
|
||||||
sessionId,
|
sessionId,
|
||||||
"12:123",
|
"12:123",
|
||||||
|
|
@ -300,6 +305,7 @@ class TachographFileSessionControllerTest {
|
||||||
.andExpect(jsonPath("$.unclassifiedDailyWeeklyRestCandidateCoverageIntervalCount").value(0))
|
.andExpect(jsonPath("$.unclassifiedDailyWeeklyRestCandidateCoverageIntervalCount").value(0))
|
||||||
.andExpect(jsonPath("$.potentialHomeOvernightStayIntervalCount").value(1))
|
.andExpect(jsonPath("$.potentialHomeOvernightStayIntervalCount").value(1))
|
||||||
.andExpect(jsonPath("$.potentialInVehicleOvernightStayIntervalCount").value(0))
|
.andExpect(jsonPath("$.potentialInVehicleOvernightStayIntervalCount").value(0))
|
||||||
|
.andExpect(jsonPath("$.potentialInVehicleTripIntervalCount").value(0))
|
||||||
.andExpect(jsonPath("$.vuCardAbsentIntervalCount").value(1))
|
.andExpect(jsonPath("$.vuCardAbsentIntervalCount").value(1))
|
||||||
.andExpect(jsonPath("$.drivingInterruptionIntervals[0].previousRegistrationKey").value("12:REG-1"))
|
.andExpect(jsonPath("$.drivingInterruptionIntervals[0].previousRegistrationKey").value("12:REG-1"))
|
||||||
.andExpect(jsonPath("$.drivingInterruptionIntervals[0].nextRegistrationKey").value("12:REG-2"))
|
.andExpect(jsonPath("$.drivingInterruptionIntervals[0].nextRegistrationKey").value("12:REG-2"))
|
||||||
|
|
|
||||||
|
|
@ -104,6 +104,7 @@ class TachographFileSessionProcessingServiceTest {
|
||||||
assertThat(result.unclassifiedDailyWeeklyRestCandidateCoverageIntervalCount()).isEqualTo(0);
|
assertThat(result.unclassifiedDailyWeeklyRestCandidateCoverageIntervalCount()).isEqualTo(0);
|
||||||
assertThat(result.potentialHomeOvernightStayIntervalCount()).isEqualTo(0);
|
assertThat(result.potentialHomeOvernightStayIntervalCount()).isEqualTo(0);
|
||||||
assertThat(result.potentialInVehicleOvernightStayIntervalCount()).isEqualTo(0);
|
assertThat(result.potentialInVehicleOvernightStayIntervalCount()).isEqualTo(0);
|
||||||
|
assertThat(result.potentialInVehicleTripIntervalCount()).isEqualTo(0);
|
||||||
assertThat(result.vehicleUsageIntervalCount()).isEqualTo(2);
|
assertThat(result.vehicleUsageIntervalCount()).isEqualTo(2);
|
||||||
assertThat(result.vuCardAbsentIntervalCount()).isEqualTo(1);
|
assertThat(result.vuCardAbsentIntervalCount()).isEqualTo(1);
|
||||||
assertThat(result.vuCardAbsentIntervals().get(0).startedAt()).isEqualTo(OffsetDateTime.parse("2026-05-01T11:00:01Z"));
|
assertThat(result.vuCardAbsentIntervals().get(0).startedAt()).isEqualTo(OffsetDateTime.parse("2026-05-01T11:00:01Z"));
|
||||||
|
|
@ -201,6 +202,7 @@ class TachographFileSessionProcessingServiceTest {
|
||||||
assertThat(result.unclassifiedDailyWeeklyRestCandidateCoverageIntervalCount()).isEqualTo(0);
|
assertThat(result.unclassifiedDailyWeeklyRestCandidateCoverageIntervalCount()).isEqualTo(0);
|
||||||
assertThat(result.potentialHomeOvernightStayIntervalCount()).isEqualTo(0);
|
assertThat(result.potentialHomeOvernightStayIntervalCount()).isEqualTo(0);
|
||||||
assertThat(result.potentialInVehicleOvernightStayIntervalCount()).isEqualTo(0);
|
assertThat(result.potentialInVehicleOvernightStayIntervalCount()).isEqualTo(0);
|
||||||
|
assertThat(result.potentialInVehicleTripIntervalCount()).isEqualTo(0);
|
||||||
assertThat(result.drivingInterruptionIntervals().get(0).startedAt()).isEqualTo(OffsetDateTime.parse("2026-05-01T09:00:00Z"));
|
assertThat(result.drivingInterruptionIntervals().get(0).startedAt()).isEqualTo(OffsetDateTime.parse("2026-05-01T09:00:00Z"));
|
||||||
assertThat(result.drivingInterruptionIntervals().get(0).endedAt()).isEqualTo(OffsetDateTime.parse("2026-05-01T10:00:00Z"));
|
assertThat(result.drivingInterruptionIntervals().get(0).endedAt()).isEqualTo(OffsetDateTime.parse("2026-05-01T10:00:00Z"));
|
||||||
assertThat(result.drivingInterruptionIntervals().get(0).previousRegistrationKey()).isEqualTo("12:REG-1");
|
assertThat(result.drivingInterruptionIntervals().get(0).previousRegistrationKey()).isEqualTo("12:REG-1");
|
||||||
|
|
@ -300,6 +302,7 @@ class TachographFileSessionProcessingServiceTest {
|
||||||
assertThat(result.dailyWeeklyRestCandidateCoverageIntervalCount()).isEqualTo(0);
|
assertThat(result.dailyWeeklyRestCandidateCoverageIntervalCount()).isEqualTo(0);
|
||||||
assertThat(result.unclassifiedDailyWeeklyRestCandidateCoverageIntervalCount()).isEqualTo(0);
|
assertThat(result.unclassifiedDailyWeeklyRestCandidateCoverageIntervalCount()).isEqualTo(0);
|
||||||
assertThat(result.potentialInVehicleOvernightStayIntervalCount()).isEqualTo(0);
|
assertThat(result.potentialInVehicleOvernightStayIntervalCount()).isEqualTo(0);
|
||||||
|
assertThat(result.potentialInVehicleTripIntervalCount()).isEqualTo(0);
|
||||||
assertThat(result.vehicleUsageIntervalCount()).isEqualTo(2);
|
assertThat(result.vehicleUsageIntervalCount()).isEqualTo(2);
|
||||||
assertThat(result.vuCardAbsentIntervalCount()).isEqualTo(1);
|
assertThat(result.vuCardAbsentIntervalCount()).isEqualTo(1);
|
||||||
}
|
}
|
||||||
|
|
@ -397,8 +400,11 @@ class TachographFileSessionProcessingServiceTest {
|
||||||
assertThat(result.drivingInterruptionVehicleChangeIntervals().get(0).nextRegistrationKey()).isEqualTo("12:REG-2");
|
assertThat(result.drivingInterruptionVehicleChangeIntervals().get(0).nextRegistrationKey()).isEqualTo("12:REG-2");
|
||||||
assertThat(result.potentialHomeOvernightStayIntervalCount()).isEqualTo(1);
|
assertThat(result.potentialHomeOvernightStayIntervalCount()).isEqualTo(1);
|
||||||
assertThat(result.potentialInVehicleOvernightStayIntervalCount()).isEqualTo(0);
|
assertThat(result.potentialInVehicleOvernightStayIntervalCount()).isEqualTo(0);
|
||||||
|
assertThat(result.potentialInVehicleTripIntervalCount()).isEqualTo(0);
|
||||||
assertThat(result.potentialHomeOvernightStayIntervals().get(0).startedAt()).isEqualTo(OffsetDateTime.parse("2026-05-01T11:00:00Z"));
|
assertThat(result.potentialHomeOvernightStayIntervals().get(0).startedAt()).isEqualTo(OffsetDateTime.parse("2026-05-01T11:00:00Z"));
|
||||||
assertThat(result.potentialHomeOvernightStayIntervals().get(0).endedAt()).isEqualTo(OffsetDateTime.parse("2026-05-01T23:00:00Z"));
|
assertThat(result.potentialHomeOvernightStayIntervals().get(0).endedAt()).isEqualTo(OffsetDateTime.parse("2026-05-01T23:00:00Z"));
|
||||||
|
assertThat(result.potentialHomeOvernightStayIntervals().get(0).cardPresentDurationSeconds()).isEqualTo(0L);
|
||||||
|
assertThat(result.potentialHomeOvernightStayIntervals().get(0).cardPresentCoveragePercent()).isEqualTo(0.0d);
|
||||||
assertThat(result.potentialHomeOvernightStayIntervals().get(0).unknownDurationSeconds()).isEqualTo(43_200L);
|
assertThat(result.potentialHomeOvernightStayIntervals().get(0).unknownDurationSeconds()).isEqualTo(43_200L);
|
||||||
assertThat(result.potentialHomeOvernightStayIntervals().get(0).unknownCoveragePercent()).isEqualTo(100.0d);
|
assertThat(result.potentialHomeOvernightStayIntervals().get(0).unknownCoveragePercent()).isEqualTo(100.0d);
|
||||||
}
|
}
|
||||||
|
|
@ -476,6 +482,7 @@ class TachographFileSessionProcessingServiceTest {
|
||||||
assertThat(result.drivingInterruptionVehicleChangeIntervalCount()).isEqualTo(0);
|
assertThat(result.drivingInterruptionVehicleChangeIntervalCount()).isEqualTo(0);
|
||||||
assertThat(result.potentialHomeOvernightStayIntervalCount()).isEqualTo(0);
|
assertThat(result.potentialHomeOvernightStayIntervalCount()).isEqualTo(0);
|
||||||
assertThat(result.potentialInVehicleOvernightStayIntervalCount()).isEqualTo(1);
|
assertThat(result.potentialInVehicleOvernightStayIntervalCount()).isEqualTo(1);
|
||||||
|
assertThat(result.potentialInVehicleTripIntervalCount()).isEqualTo(0);
|
||||||
assertThat(result.dailyWeeklyRestCandidateCoverageIntervals().get(0).cardPresentDurationSeconds()).isEqualTo(50_400L);
|
assertThat(result.dailyWeeklyRestCandidateCoverageIntervals().get(0).cardPresentDurationSeconds()).isEqualTo(50_400L);
|
||||||
assertThat(result.dailyWeeklyRestCandidateCoverageIntervals().get(0).cardPresentCoveragePercent()).isEqualTo(100.0d);
|
assertThat(result.dailyWeeklyRestCandidateCoverageIntervals().get(0).cardPresentCoveragePercent()).isEqualTo(100.0d);
|
||||||
assertThat(result.dailyWeeklyRestCandidateCoverageIntervals().get(0).unknownDurationSeconds()).isEqualTo(0L);
|
assertThat(result.dailyWeeklyRestCandidateCoverageIntervals().get(0).unknownDurationSeconds()).isEqualTo(0L);
|
||||||
|
|
@ -483,6 +490,8 @@ class TachographFileSessionProcessingServiceTest {
|
||||||
assertThat(result.potentialInVehicleOvernightStayIntervals().get(0).endedAt()).isEqualTo(OffsetDateTime.parse("2026-05-02T00:00:00Z"));
|
assertThat(result.potentialInVehicleOvernightStayIntervals().get(0).endedAt()).isEqualTo(OffsetDateTime.parse("2026-05-02T00:00:00Z"));
|
||||||
assertThat(result.potentialInVehicleOvernightStayIntervals().get(0).cardPresentDurationSeconds()).isEqualTo(50_400L);
|
assertThat(result.potentialInVehicleOvernightStayIntervals().get(0).cardPresentDurationSeconds()).isEqualTo(50_400L);
|
||||||
assertThat(result.potentialInVehicleOvernightStayIntervals().get(0).cardPresentCoveragePercent()).isEqualTo(100.0d);
|
assertThat(result.potentialInVehicleOvernightStayIntervals().get(0).cardPresentCoveragePercent()).isEqualTo(100.0d);
|
||||||
|
assertThat(result.potentialInVehicleOvernightStayIntervals().get(0).unknownDurationSeconds()).isEqualTo(0L);
|
||||||
|
assertThat(result.potentialInVehicleOvernightStayIntervals().get(0).unknownCoveragePercent()).isEqualTo(0.0d);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -565,6 +574,7 @@ class TachographFileSessionProcessingServiceTest {
|
||||||
assertThat(result.dailyWeeklyRestCandidateCoverageIntervalCount()).isEqualTo(1);
|
assertThat(result.dailyWeeklyRestCandidateCoverageIntervalCount()).isEqualTo(1);
|
||||||
assertThat(result.potentialHomeOvernightStayIntervalCount()).isEqualTo(0);
|
assertThat(result.potentialHomeOvernightStayIntervalCount()).isEqualTo(0);
|
||||||
assertThat(result.potentialInVehicleOvernightStayIntervalCount()).isEqualTo(0);
|
assertThat(result.potentialInVehicleOvernightStayIntervalCount()).isEqualTo(0);
|
||||||
|
assertThat(result.potentialInVehicleTripIntervalCount()).isEqualTo(0);
|
||||||
assertThat(result.unclassifiedDailyWeeklyRestCandidateCoverageIntervalCount()).isEqualTo(1);
|
assertThat(result.unclassifiedDailyWeeklyRestCandidateCoverageIntervalCount()).isEqualTo(1);
|
||||||
assertThat(result.unclassifiedDailyWeeklyRestCandidateCoverageIntervals().get(0).startedAt())
|
assertThat(result.unclassifiedDailyWeeklyRestCandidateCoverageIntervals().get(0).startedAt())
|
||||||
.isEqualTo(OffsetDateTime.parse("2026-05-01T10:00:00Z"));
|
.isEqualTo(OffsetDateTime.parse("2026-05-01T10:00:00Z"));
|
||||||
|
|
@ -576,6 +586,80 @@ class TachographFileSessionProcessingServiceTest {
|
||||||
.isLessThan(95.0d);
|
.isLessThan(95.0d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void returnsPotentialInVehicleTripIntervalsForSameVehicleOvernightSequenceBoundedByCoverageIntervals() {
|
||||||
|
EventHubProperties properties = new EventHubProperties();
|
||||||
|
TachographFileSessionRepository repository = new InMemoryTachographFileSessionRepository(properties);
|
||||||
|
DriverTimelineBuilder driverTimelineBuilder = new DriverTimelineBuilder();
|
||||||
|
TachographFileSessionProcessingService service = new TachographFileSessionProcessingService(
|
||||||
|
repository,
|
||||||
|
driverTimelineBuilder,
|
||||||
|
new DriverTimelineReusableProjectionBuilder(driverTimelineBuilder),
|
||||||
|
new EventBackedDriverTimelineBuilder(
|
||||||
|
new IntervalBackedDriverTimelineEventBuilder(
|
||||||
|
driverTimelineBuilder,
|
||||||
|
new DriverKeyFactory(),
|
||||||
|
new VehicleKeyFactory(),
|
||||||
|
new EventDetailsFactory(new ObjectMapper())
|
||||||
|
)
|
||||||
|
),
|
||||||
|
properties
|
||||||
|
);
|
||||||
|
|
||||||
|
DriverExtractionSession driver = new DriverExtractionSession(
|
||||||
|
"12:123",
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
List.of(),
|
||||||
|
List.of(),
|
||||||
|
List.of(
|
||||||
|
new ExtractedCardVehicleUsageInterval("CVU-0", OffsetDateTime.parse("2026-05-01T08:00:00Z"), OffsetDateTime.parse("2026-05-01T09:00:00Z"), 100L, 150L, "12:REG-0", "VIN-0", "vu-0"),
|
||||||
|
new ExtractedCardVehicleUsageInterval("CVU-1", OffsetDateTime.parse("2026-05-01T22:00:00Z"), OffsetDateTime.parse("2026-05-04T02:00:00Z"), 200L, 400L, "12:REG-1", "VIN-1", "vu-1"),
|
||||||
|
new ExtractedCardVehicleUsageInterval("CVU-2", OffsetDateTime.parse("2026-05-05T00:00:00Z"), OffsetDateTime.parse("2026-05-05T02:00:00Z"), 401L, 430L, "12:REG-2", "VIN-2", "vu-2")
|
||||||
|
),
|
||||||
|
List.of(
|
||||||
|
new ExtractedCardActivityInterval("ACT-0", OffsetDateTime.parse("2026-05-01T08:00:00Z"), OffsetDateTime.parse("2026-05-01T09:00:00Z"), "DRIVE", "DRIVER", "INSERTED", "SINGLE", "12:REG-0", "VIN-0", "a"),
|
||||||
|
new ExtractedCardActivityInterval("ACT-1", OffsetDateTime.parse("2026-05-01T22:00:00Z"), OffsetDateTime.parse("2026-05-02T00:00:00Z"), "DRIVE", "DRIVER", "INSERTED", "SINGLE", "12:REG-1", "VIN-1", "b"),
|
||||||
|
new ExtractedCardActivityInterval("ACT-2", OffsetDateTime.parse("2026-05-02T20:00:00Z"), OffsetDateTime.parse("2026-05-02T22:00:00Z"), "DRIVE", "DRIVER", "INSERTED", "SINGLE", "12:REG-1", "VIN-1", "c"),
|
||||||
|
new ExtractedCardActivityInterval("ACT-3", OffsetDateTime.parse("2026-05-03T20:00:00Z"), OffsetDateTime.parse("2026-05-03T22:00:00Z"), "DRIVE", "DRIVER", "INSERTED", "SINGLE", "12:REG-1", "VIN-1", "d"),
|
||||||
|
new ExtractedCardActivityInterval("ACT-4", OffsetDateTime.parse("2026-05-05T00:00:00Z"), OffsetDateTime.parse("2026-05-05T02:00:00Z"), "DRIVE", "DRIVER", "INSERTED", "SINGLE", "12:REG-2", "VIN-2", "e")
|
||||||
|
),
|
||||||
|
List.of(),
|
||||||
|
List.of()
|
||||||
|
);
|
||||||
|
TachographFileSession session = new TachographFileSession(
|
||||||
|
UUID.randomUUID(),
|
||||||
|
new TachographFileSessionMetadata("default", "legalrequirements-drivercard", "sample", "sample.ddd", "a", 5, "42", "b", true, null),
|
||||||
|
Map.of(driver.driverKey(), driver),
|
||||||
|
new ExtractionStats(1, 5, 3, 1, 1, 0),
|
||||||
|
List.of(),
|
||||||
|
Instant.now(),
|
||||||
|
Instant.now().plus(4, ChronoUnit.HOURS)
|
||||||
|
);
|
||||||
|
repository.save(session);
|
||||||
|
|
||||||
|
TachographEsperDriverProcessingResultDto result = service.getEsperDriverProcessingResults(
|
||||||
|
session.sessionId(),
|
||||||
|
driver.driverKey(),
|
||||||
|
new TachographEsperEventsProcessingRequest(
|
||||||
|
OffsetDateTime.parse("2026-05-01T10:00:00Z"),
|
||||||
|
OffsetDateTime.parse("2026-05-05T00:00:00Z"),
|
||||||
|
3,
|
||||||
|
720
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
assertThat(result.potentialInVehicleOvernightStayIntervalCount()).isEqualTo(2);
|
||||||
|
assertThat(result.potentialInVehicleTripIntervalCount()).isEqualTo(1);
|
||||||
|
assertThat(result.potentialInVehicleTripIntervals().get(0).startedAt())
|
||||||
|
.isEqualTo(OffsetDateTime.parse("2026-05-01T22:00:00Z"));
|
||||||
|
assertThat(result.potentialInVehicleTripIntervals().get(0).endedAt())
|
||||||
|
.isEqualTo(OffsetDateTime.parse("2026-05-03T22:00:00Z"));
|
||||||
|
assertThat(result.potentialInVehicleTripIntervals().get(0).containedPotentialInVehicleOvernightStayIntervalCount()).isEqualTo(2);
|
||||||
|
assertThat(result.potentialInVehicleTripIntervals().get(0).potentialInVehicleOvernightStayIntervals()).hasSize(2);
|
||||||
|
assertThat(result.potentialInVehicleTripIntervals().get(0).registrationKey()).isEqualTo("12:REG-1");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void evaluatesOperatingPeriodsFromSessionTimeline() {
|
void evaluatesOperatingPeriodsFromSessionTimeline() {
|
||||||
EventHubProperties properties = new EventHubProperties();
|
EventHubProperties properties = new EventHubProperties();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue