Extract neutral working-time projection engine
This commit is contained in:
parent
4b5691d20f
commit
cd090010c6
|
|
@ -0,0 +1,31 @@
|
|||
package at.procon.eventhub.processing.driverworkingtime.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public record DriverWorkingTimeDerivedProjectionBundle(
|
||||
List<DriverWorkingTimeDrivingInterruptionInterval> drivingInterruptionIntervals,
|
||||
List<DriverWorkingTimeDrivingInterruptionInterval> dailyWeeklyRestCandidateIntervals,
|
||||
List<DriverWorkingTimeRestCoverageInterval> dailyWeeklyRestCandidateCoverageIntervals,
|
||||
List<DriverWorkingTimeRestCoverageInterval> unclassifiedDailyWeeklyRestCandidateCoverageIntervals,
|
||||
List<DriverWorkingTimeDrivingInterruptionInterval> drivingInterruptionVehicleChangeIntervals,
|
||||
List<DriverWorkingTimeVuCardAbsentInterval> vuCardAbsentIntervals,
|
||||
List<DriverWorkingTimeRestCoverageInterval> potentialHomeOvernightStayIntervals,
|
||||
List<DriverWorkingTimeRestCoverageInterval> potentialInVehicleOvernightStayIntervals,
|
||||
List<DriverWorkingTimePotentialInVehicleTripInterval> potentialInVehicleTripIntervals
|
||||
) {
|
||||
public DriverWorkingTimeDerivedProjectionBundle {
|
||||
drivingInterruptionIntervals = safe(drivingInterruptionIntervals);
|
||||
dailyWeeklyRestCandidateIntervals = safe(dailyWeeklyRestCandidateIntervals);
|
||||
dailyWeeklyRestCandidateCoverageIntervals = safe(dailyWeeklyRestCandidateCoverageIntervals);
|
||||
unclassifiedDailyWeeklyRestCandidateCoverageIntervals = safe(unclassifiedDailyWeeklyRestCandidateCoverageIntervals);
|
||||
drivingInterruptionVehicleChangeIntervals = safe(drivingInterruptionVehicleChangeIntervals);
|
||||
vuCardAbsentIntervals = safe(vuCardAbsentIntervals);
|
||||
potentialHomeOvernightStayIntervals = safe(potentialHomeOvernightStayIntervals);
|
||||
potentialInVehicleOvernightStayIntervals = safe(potentialInVehicleOvernightStayIntervals);
|
||||
potentialInVehicleTripIntervals = safe(potentialInVehicleTripIntervals);
|
||||
}
|
||||
|
||||
private static <T> List<T> safe(List<T> values) {
|
||||
return values == null ? List.of() : List.copyOf(values);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
package at.procon.eventhub.processing.driverworkingtime.model;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
public record DriverWorkingTimeDrivingInterruptionInterval(
|
||||
UUID sessionId,
|
||||
String driverKey,
|
||||
OffsetDateTime startedAt,
|
||||
OffsetDateTime endedAt,
|
||||
long durationSeconds,
|
||||
String previousDrivingSourceIntervalId,
|
||||
String nextDrivingSourceIntervalId,
|
||||
String previousRegistrationKey,
|
||||
String nextRegistrationKey,
|
||||
String previousVehicleKey,
|
||||
String nextVehicleKey
|
||||
) {
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
package at.procon.eventhub.processing.driverworkingtime.model;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
|
||||
public record DriverWorkingTimeGeoEvidenceEvent(
|
||||
String eventId,
|
||||
String eventDomain,
|
||||
OffsetDateTime occurredAt,
|
||||
Double latitude,
|
||||
Double longitude,
|
||||
Long distanceSeconds,
|
||||
Long odometerKm
|
||||
) {
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
package at.procon.eventhub.processing.driverworkingtime.model;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public record DriverWorkingTimePotentialInVehicleTripInterval(
|
||||
UUID sessionId,
|
||||
String driverKey,
|
||||
OffsetDateTime startedAt,
|
||||
OffsetDateTime endedAt,
|
||||
long durationSeconds,
|
||||
String registrationKey,
|
||||
String vehicleKey,
|
||||
int containedPotentialInVehicleOvernightStayIntervalCount,
|
||||
long containedPotentialInVehicleOvernightStayDurationSeconds,
|
||||
long containedCardAbsentDurationSeconds,
|
||||
OffsetDateTime firstPotentialInVehicleOvernightStayStartedAt,
|
||||
OffsetDateTime lastPotentialInVehicleOvernightStayEndedAt,
|
||||
String firstPreviousDrivingSourceIntervalId,
|
||||
String lastNextDrivingSourceIntervalId,
|
||||
List<DriverWorkingTimeRestCoverageInterval> potentialInVehicleOvernightStayIntervals
|
||||
) {
|
||||
public DriverWorkingTimePotentialInVehicleTripInterval {
|
||||
potentialInVehicleOvernightStayIntervals = potentialInVehicleOvernightStayIntervals == null
|
||||
? List.of()
|
||||
: List.copyOf(potentialInVehicleOvernightStayIntervals);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
package at.procon.eventhub.processing.driverworkingtime.model;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
public record DriverWorkingTimeRestCoverageInterval(
|
||||
UUID sessionId,
|
||||
String driverKey,
|
||||
OffsetDateTime startedAt,
|
||||
OffsetDateTime endedAt,
|
||||
long durationSeconds,
|
||||
long cardAbsentDurationSeconds,
|
||||
double cardAbsentCoveragePercent,
|
||||
String previousDrivingSourceIntervalId,
|
||||
String nextDrivingSourceIntervalId,
|
||||
String previousRegistrationKey,
|
||||
String nextRegistrationKey,
|
||||
String previousVehicleKey,
|
||||
String nextVehicleKey,
|
||||
Long beginBoundaryOdometerKm,
|
||||
Long endBoundaryOdometerKm,
|
||||
String beginGeoEventId,
|
||||
String beginGeoEventDomain,
|
||||
OffsetDateTime beginGeoOccurredAt,
|
||||
Double beginLatitude,
|
||||
Double beginLongitude,
|
||||
Long beginGeoDistanceSeconds,
|
||||
Long beginGeoOdometerKm,
|
||||
String endGeoEventId,
|
||||
String endGeoEventDomain,
|
||||
OffsetDateTime endGeoOccurredAt,
|
||||
Double endLatitude,
|
||||
Double endLongitude,
|
||||
Long endGeoDistanceSeconds,
|
||||
Long endGeoOdometerKm,
|
||||
Long geoEvidenceMovementMeters,
|
||||
String geoEvidenceMovementCategory,
|
||||
DriverWorkingTimeGeoEvidenceEvent beginGeoEvent,
|
||||
DriverWorkingTimeGeoEvidenceEvent endGeoEvent
|
||||
) {
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
package at.procon.eventhub.processing.driverworkingtime.model;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.OffsetDateTime;
|
||||
|
||||
public record DriverWorkingTimeSupportGeoEvent(
|
||||
String eventId,
|
||||
String driverKey,
|
||||
OffsetDateTime occurredAt,
|
||||
String eventDomain,
|
||||
String eventType,
|
||||
String eventLifecycle,
|
||||
String registrationKey,
|
||||
String vehicleKey,
|
||||
String country,
|
||||
String region,
|
||||
String countryFrom,
|
||||
String countryTo,
|
||||
String operation,
|
||||
BigDecimal latitude,
|
||||
BigDecimal longitude,
|
||||
Long odometerKm,
|
||||
String rawRecordPath
|
||||
) {
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
package at.procon.eventhub.processing.driverworkingtime.model;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
public record DriverWorkingTimeVuCardAbsentInterval(
|
||||
UUID sessionId,
|
||||
String driverKey,
|
||||
OffsetDateTime startedAt,
|
||||
OffsetDateTime endedAt,
|
||||
long durationSeconds,
|
||||
String previousUsageIntervalId,
|
||||
String nextUsageIntervalId,
|
||||
String previousRegistrationKey,
|
||||
String nextRegistrationKey,
|
||||
String previousVehicleKey,
|
||||
String nextVehicleKey
|
||||
) {
|
||||
}
|
||||
|
|
@ -0,0 +1,426 @@
|
|||
package at.procon.eventhub.processing.driverworkingtime.service;
|
||||
|
||||
import at.procon.eventhub.processing.driverworkingtime.model.DriverWorkingTimeActivityInterval;
|
||||
import at.procon.eventhub.processing.driverworkingtime.model.DriverWorkingTimeDerivedProjectionBundle;
|
||||
import at.procon.eventhub.processing.driverworkingtime.model.DriverWorkingTimeDrivingInterruptionInterval;
|
||||
import at.procon.eventhub.processing.driverworkingtime.model.DriverWorkingTimeGeoEvidenceEvent;
|
||||
import at.procon.eventhub.processing.driverworkingtime.model.DriverWorkingTimePotentialInVehicleTripInterval;
|
||||
import at.procon.eventhub.processing.driverworkingtime.model.DriverWorkingTimeProcessingInput;
|
||||
import at.procon.eventhub.processing.driverworkingtime.model.DriverWorkingTimeRestCoverageInterval;
|
||||
import at.procon.eventhub.processing.driverworkingtime.model.DriverWorkingTimeVehicleUsageInterval;
|
||||
import at.procon.eventhub.processing.driverworkingtime.model.DriverWorkingTimeVuCardAbsentInterval;
|
||||
import at.procon.eventhub.processing.eventprocessing.support.RuntimeSupportEvidenceEvent;
|
||||
import at.procon.eventhub.tachographfilesession.model.ExtractedSupportEvent;
|
||||
import at.procon.eventhub.tachographfilesession.model.ResolvedActivityInterval;
|
||||
import at.procon.eventhub.tachographfilesession.model.ResolvedDriverTimeline;
|
||||
import at.procon.eventhub.tachographfilesession.model.ResolvedVehicleUsageInterval;
|
||||
import at.procon.eventhub.tachographfilesession.model.TachographEsperDailyWeeklyRestCandidateCoverageIntervalEvent;
|
||||
import at.procon.eventhub.tachographfilesession.model.TachographEsperDrivingDerivedProjectionBundle;
|
||||
import at.procon.eventhub.tachographfilesession.model.TachographEsperDrivingInterruptionIntervalEvent;
|
||||
import at.procon.eventhub.tachographfilesession.model.TachographEsperGeoEvidenceEvent;
|
||||
import at.procon.eventhub.tachographfilesession.model.TachographEsperPotentialHomeOvernightStayIntervalEvent;
|
||||
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.service.DriverTimelineReusableProjectionBuilder;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class DriverWorkingTimeDerivedProjectionEngine {
|
||||
|
||||
private final DriverTimelineReusableProjectionBuilder legacyProjectionBuilder;
|
||||
|
||||
public DriverWorkingTimeDerivedProjectionEngine(
|
||||
DriverTimelineReusableProjectionBuilder legacyProjectionBuilder
|
||||
) {
|
||||
this.legacyProjectionBuilder = legacyProjectionBuilder;
|
||||
}
|
||||
|
||||
public DriverWorkingTimeDerivedProjectionBundle build(DriverWorkingTimeProcessingInput input) {
|
||||
Objects.requireNonNull(input, "input must not be null");
|
||||
ResolvedDriverTimeline timeline = toResolvedTimeline(input);
|
||||
TachographEsperDrivingDerivedProjectionBundle legacyBundle =
|
||||
legacyProjectionBuilder.buildEsperDrivingDerivedProjectionBundle(
|
||||
safeSessionId(input.sessionId()),
|
||||
input.driverKey(),
|
||||
timeline,
|
||||
input.significantDrivingMinutes(),
|
||||
input.minimumRestPeriodMinutes()
|
||||
);
|
||||
return new DriverWorkingTimeDerivedProjectionBundle(
|
||||
legacyBundle.drivingInterruptionIntervals().stream().map(this::mapDrivingInterruption).toList(),
|
||||
legacyBundle.dailyWeeklyRestCandidateIntervals().stream().map(this::mapDrivingInterruption).toList(),
|
||||
legacyBundle.dailyWeeklyRestCandidateCoverageIntervals().stream().map(this::mapRestCoverage).toList(),
|
||||
legacyBundle.unclassifiedDailyWeeklyRestCandidateCoverageIntervals().stream().map(this::mapRestCoverage).toList(),
|
||||
legacyBundle.drivingInterruptionVehicleChangeIntervals().stream().map(this::mapDrivingInterruption).toList(),
|
||||
legacyBundle.vuCardAbsentIntervals().stream().map(this::mapVuCardAbsent).toList(),
|
||||
legacyBundle.potentialHomeOvernightStayIntervals().stream().map(this::mapPotentialHome).toList(),
|
||||
legacyBundle.potentialInVehicleOvernightStayIntervals().stream().map(this::mapPotentialInVehicle).toList(),
|
||||
legacyBundle.potentialInVehicleTripIntervals().stream().map(this::mapPotentialTrip).toList()
|
||||
);
|
||||
}
|
||||
|
||||
private ResolvedDriverTimeline toResolvedTimeline(DriverWorkingTimeProcessingInput input) {
|
||||
List<ResolvedActivityInterval> activityIntervals = input.activityIntervals().stream()
|
||||
.map(this::toResolvedActivityInterval)
|
||||
.filter(Objects::nonNull)
|
||||
.toList();
|
||||
List<ResolvedVehicleUsageInterval> vehicleUsageIntervals = input.vehicleUsageIntervals().stream()
|
||||
.map(this::toResolvedVehicleUsageInterval)
|
||||
.filter(Objects::nonNull)
|
||||
.toList();
|
||||
List<ExtractedSupportEvent> supportEvents = input.supportEvidenceEvents().stream()
|
||||
.map(this::toExtractedSupportEvent)
|
||||
.filter(Objects::nonNull)
|
||||
.toList();
|
||||
OffsetDateTime loadedFrom = input.loadedFrom() == null
|
||||
? earliest(activityIntervals, vehicleUsageIntervals, supportEvents)
|
||||
: utc(input.loadedFrom());
|
||||
OffsetDateTime loadedTo = input.loadedTo() == null
|
||||
? latest(activityIntervals, vehicleUsageIntervals, supportEvents)
|
||||
: utc(input.loadedTo());
|
||||
return new ResolvedDriverTimeline(
|
||||
input.sourceKind(),
|
||||
loadedFrom,
|
||||
loadedTo,
|
||||
vehicleUsageIntervals,
|
||||
activityIntervals,
|
||||
supportEvents,
|
||||
List.of()
|
||||
);
|
||||
}
|
||||
|
||||
private ResolvedActivityInterval toResolvedActivityInterval(DriverWorkingTimeActivityInterval interval) {
|
||||
if (interval == null || interval.startedAt() == null || interval.endedAt() == null) {
|
||||
return null;
|
||||
}
|
||||
return new ResolvedActivityInterval(
|
||||
interval.intervalId(),
|
||||
utc(interval.startedAt()),
|
||||
utc(interval.endedAt()),
|
||||
interval.durationSeconds(),
|
||||
interval.activityType(),
|
||||
interval.cardSlot(),
|
||||
interval.cardStatus(),
|
||||
interval.drivingStatus(),
|
||||
interval.registrationKey(),
|
||||
interval.vehicleKey(),
|
||||
interval.sourceKind(),
|
||||
interval.sourceIntervalIds(),
|
||||
interval.synthetic(),
|
||||
interval.clippedToRequestedPeriod(),
|
||||
interval.level()
|
||||
);
|
||||
}
|
||||
|
||||
private ResolvedVehicleUsageInterval toResolvedVehicleUsageInterval(DriverWorkingTimeVehicleUsageInterval interval) {
|
||||
if (interval == null || interval.startedAt() == null) {
|
||||
return null;
|
||||
}
|
||||
return new ResolvedVehicleUsageInterval(
|
||||
safeSessionId(interval.sessionId()),
|
||||
interval.driverKey(),
|
||||
interval.intervalId(),
|
||||
utc(interval.startedAt()),
|
||||
utc(interval.endedAt()),
|
||||
interval.durationSeconds(),
|
||||
interval.odometerBeginKm(),
|
||||
interval.odometerEndKm(),
|
||||
interval.registrationKey(),
|
||||
interval.vehicleKey(),
|
||||
interval.sourceKind(),
|
||||
interval.sourceIntervalIds()
|
||||
);
|
||||
}
|
||||
|
||||
private ExtractedSupportEvent toExtractedSupportEvent(RuntimeSupportEvidenceEvent supportEvent) {
|
||||
if (supportEvent == null || supportEvent.occurredAt() == null) {
|
||||
return null;
|
||||
}
|
||||
Object rawRecordPath = supportEvent.rawAttributes().get("rawRecordPath");
|
||||
return new ExtractedSupportEvent(
|
||||
supportEvent.eventId(),
|
||||
supportEvent.driverKey(),
|
||||
utc(supportEvent.occurredAt()),
|
||||
supportEvent.eventDomain(),
|
||||
supportEvent.eventType(),
|
||||
supportEvent.lifecycle(),
|
||||
null,
|
||||
supportEvent.registrationKey(),
|
||||
supportEvent.vehicleKey(),
|
||||
supportEvent.countryCode(),
|
||||
supportEvent.regionCode(),
|
||||
supportEvent.countryFrom(),
|
||||
supportEvent.countryTo(),
|
||||
supportEvent.operation(),
|
||||
supportEvent.latitude(),
|
||||
supportEvent.longitude(),
|
||||
null,
|
||||
supportEvent.odometerKm(),
|
||||
null,
|
||||
supportEvent.speedKmh(),
|
||||
supportEvent.maxSpeedKmh(),
|
||||
rawRecordPath == null ? null : rawRecordPath.toString()
|
||||
);
|
||||
}
|
||||
|
||||
private DriverWorkingTimeDrivingInterruptionInterval mapDrivingInterruption(
|
||||
TachographEsperDrivingInterruptionIntervalEvent value
|
||||
) {
|
||||
return new DriverWorkingTimeDrivingInterruptionInterval(
|
||||
value.sessionId(),
|
||||
value.driverKey(),
|
||||
value.startedAt(),
|
||||
value.endedAt(),
|
||||
value.durationSeconds(),
|
||||
value.previousDrivingSourceIntervalId(),
|
||||
value.nextDrivingSourceIntervalId(),
|
||||
value.previousRegistrationKey(),
|
||||
value.nextRegistrationKey(),
|
||||
value.previousVehicleKey(),
|
||||
value.nextVehicleKey()
|
||||
);
|
||||
}
|
||||
|
||||
private DriverWorkingTimeVuCardAbsentInterval mapVuCardAbsent(TachographEsperVuCardAbsentIntervalEvent value) {
|
||||
return new DriverWorkingTimeVuCardAbsentInterval(
|
||||
value.sessionId(),
|
||||
value.driverKey(),
|
||||
value.startedAt(),
|
||||
value.endedAt(),
|
||||
value.durationSeconds(),
|
||||
value.previousUsageIntervalId(),
|
||||
value.nextUsageIntervalId(),
|
||||
value.previousRegistrationKey(),
|
||||
value.nextRegistrationKey(),
|
||||
value.previousVehicleKey(),
|
||||
value.nextVehicleKey()
|
||||
);
|
||||
}
|
||||
|
||||
private DriverWorkingTimeRestCoverageInterval mapRestCoverage(
|
||||
TachographEsperDailyWeeklyRestCandidateCoverageIntervalEvent value
|
||||
) {
|
||||
return new DriverWorkingTimeRestCoverageInterval(
|
||||
value.sessionId(),
|
||||
value.driverKey(),
|
||||
value.startedAt(),
|
||||
value.endedAt(),
|
||||
value.durationSeconds(),
|
||||
value.cardAbsentDurationSeconds(),
|
||||
value.cardAbsentCoveragePercent(),
|
||||
value.previousDrivingSourceIntervalId(),
|
||||
value.nextDrivingSourceIntervalId(),
|
||||
value.previousRegistrationKey(),
|
||||
value.nextRegistrationKey(),
|
||||
value.previousVehicleKey(),
|
||||
value.nextVehicleKey(),
|
||||
value.beginBoundaryOdometerKm(),
|
||||
value.endBoundaryOdometerKm(),
|
||||
value.beginGeoEventId(),
|
||||
value.beginGeoEventDomain(),
|
||||
value.beginGeoOccurredAt(),
|
||||
value.beginLatitude(),
|
||||
value.beginLongitude(),
|
||||
value.beginGeoDistanceSeconds(),
|
||||
value.beginGeoOdometerKm(),
|
||||
value.endGeoEventId(),
|
||||
value.endGeoEventDomain(),
|
||||
value.endGeoOccurredAt(),
|
||||
value.endLatitude(),
|
||||
value.endLongitude(),
|
||||
value.endGeoDistanceSeconds(),
|
||||
value.endGeoOdometerKm(),
|
||||
value.geoEvidenceMovementMeters(),
|
||||
value.geoEvidenceMovementCategory(),
|
||||
mapGeoEvidence(value.beginGeoEvent()),
|
||||
mapGeoEvidence(value.endGeoEvent())
|
||||
);
|
||||
}
|
||||
|
||||
private DriverWorkingTimeRestCoverageInterval mapPotentialHome(
|
||||
TachographEsperPotentialHomeOvernightStayIntervalEvent value
|
||||
) {
|
||||
return new DriverWorkingTimeRestCoverageInterval(
|
||||
value.sessionId(),
|
||||
value.driverKey(),
|
||||
value.startedAt(),
|
||||
value.endedAt(),
|
||||
value.durationSeconds(),
|
||||
value.cardAbsentDurationSeconds(),
|
||||
value.cardAbsentCoveragePercent(),
|
||||
value.previousDrivingSourceIntervalId(),
|
||||
value.nextDrivingSourceIntervalId(),
|
||||
value.previousRegistrationKey(),
|
||||
value.nextRegistrationKey(),
|
||||
value.previousVehicleKey(),
|
||||
value.nextVehicleKey(),
|
||||
value.beginBoundaryOdometerKm(),
|
||||
value.endBoundaryOdometerKm(),
|
||||
value.beginGeoEventId(),
|
||||
value.beginGeoEventDomain(),
|
||||
value.beginGeoOccurredAt(),
|
||||
value.beginLatitude(),
|
||||
value.beginLongitude(),
|
||||
value.beginGeoDistanceSeconds(),
|
||||
value.beginGeoOdometerKm(),
|
||||
value.endGeoEventId(),
|
||||
value.endGeoEventDomain(),
|
||||
value.endGeoOccurredAt(),
|
||||
value.endLatitude(),
|
||||
value.endLongitude(),
|
||||
value.endGeoDistanceSeconds(),
|
||||
value.endGeoOdometerKm(),
|
||||
value.geoEvidenceMovementMeters(),
|
||||
value.geoEvidenceMovementCategory(),
|
||||
mapGeoEvidence(value.beginGeoEvent()),
|
||||
mapGeoEvidence(value.endGeoEvent())
|
||||
);
|
||||
}
|
||||
|
||||
private DriverWorkingTimeRestCoverageInterval mapPotentialInVehicle(
|
||||
TachographEsperPotentialInVehicleOvernightStayIntervalEvent value
|
||||
) {
|
||||
return new DriverWorkingTimeRestCoverageInterval(
|
||||
value.sessionId(),
|
||||
value.driverKey(),
|
||||
value.startedAt(),
|
||||
value.endedAt(),
|
||||
value.durationSeconds(),
|
||||
value.cardAbsentDurationSeconds(),
|
||||
value.cardAbsentCoveragePercent(),
|
||||
value.previousDrivingSourceIntervalId(),
|
||||
value.nextDrivingSourceIntervalId(),
|
||||
value.previousRegistrationKey(),
|
||||
value.nextRegistrationKey(),
|
||||
value.previousVehicleKey(),
|
||||
value.nextVehicleKey(),
|
||||
value.beginBoundaryOdometerKm(),
|
||||
value.endBoundaryOdometerKm(),
|
||||
value.beginGeoEventId(),
|
||||
value.beginGeoEventDomain(),
|
||||
value.beginGeoOccurredAt(),
|
||||
value.beginLatitude(),
|
||||
value.beginLongitude(),
|
||||
value.beginGeoDistanceSeconds(),
|
||||
value.beginGeoOdometerKm(),
|
||||
value.endGeoEventId(),
|
||||
value.endGeoEventDomain(),
|
||||
value.endGeoOccurredAt(),
|
||||
value.endLatitude(),
|
||||
value.endLongitude(),
|
||||
value.endGeoDistanceSeconds(),
|
||||
value.endGeoOdometerKm(),
|
||||
value.geoEvidenceMovementMeters(),
|
||||
value.geoEvidenceMovementCategory(),
|
||||
mapGeoEvidence(value.beginGeoEvent()),
|
||||
mapGeoEvidence(value.endGeoEvent())
|
||||
);
|
||||
}
|
||||
|
||||
private DriverWorkingTimePotentialInVehicleTripInterval mapPotentialTrip(
|
||||
TachographEsperPotentialInVehicleTripIntervalEvent value
|
||||
) {
|
||||
return new DriverWorkingTimePotentialInVehicleTripInterval(
|
||||
value.sessionId(),
|
||||
value.driverKey(),
|
||||
value.startedAt(),
|
||||
value.endedAt(),
|
||||
value.durationSeconds(),
|
||||
value.registrationKey(),
|
||||
value.vehicleKey(),
|
||||
value.containedPotentialInVehicleOvernightStayIntervalCount(),
|
||||
value.containedPotentialInVehicleOvernightStayDurationSeconds(),
|
||||
value.containedCardAbsentDurationSeconds(),
|
||||
value.firstPotentialInVehicleOvernightStayStartedAt(),
|
||||
value.lastPotentialInVehicleOvernightStayEndedAt(),
|
||||
value.firstPreviousDrivingSourceIntervalId(),
|
||||
value.lastNextDrivingSourceIntervalId(),
|
||||
value.potentialInVehicleOvernightStayIntervals().stream().map(this::mapPotentialInVehicle).toList()
|
||||
);
|
||||
}
|
||||
|
||||
private DriverWorkingTimeGeoEvidenceEvent mapGeoEvidence(TachographEsperGeoEvidenceEvent value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
return new DriverWorkingTimeGeoEvidenceEvent(
|
||||
value.eventId(),
|
||||
value.eventDomain(),
|
||||
value.occurredAt(),
|
||||
value.latitude(),
|
||||
value.longitude(),
|
||||
value.distanceSeconds(),
|
||||
value.odometerKm()
|
||||
);
|
||||
}
|
||||
|
||||
private OffsetDateTime earliest(
|
||||
List<ResolvedActivityInterval> activityIntervals,
|
||||
List<ResolvedVehicleUsageInterval> vehicleUsageIntervals,
|
||||
List<ExtractedSupportEvent> supportEvents
|
||||
) {
|
||||
OffsetDateTime earliest = null;
|
||||
for (ResolvedActivityInterval interval : activityIntervals) {
|
||||
earliest = min(earliest, interval.from());
|
||||
}
|
||||
for (ResolvedVehicleUsageInterval interval : vehicleUsageIntervals) {
|
||||
earliest = min(earliest, interval.from());
|
||||
}
|
||||
for (ExtractedSupportEvent event : supportEvents) {
|
||||
earliest = min(earliest, event.occurredAt());
|
||||
}
|
||||
return earliest;
|
||||
}
|
||||
|
||||
private OffsetDateTime latest(
|
||||
List<ResolvedActivityInterval> activityIntervals,
|
||||
List<ResolvedVehicleUsageInterval> vehicleUsageIntervals,
|
||||
List<ExtractedSupportEvent> supportEvents
|
||||
) {
|
||||
OffsetDateTime latest = null;
|
||||
for (ResolvedActivityInterval interval : activityIntervals) {
|
||||
latest = max(latest, interval.to());
|
||||
}
|
||||
for (ResolvedVehicleUsageInterval interval : vehicleUsageIntervals) {
|
||||
latest = max(latest, interval.to());
|
||||
}
|
||||
for (ExtractedSupportEvent event : supportEvents) {
|
||||
latest = max(latest, event.occurredAt());
|
||||
}
|
||||
return latest;
|
||||
}
|
||||
|
||||
private UUID safeSessionId(UUID sessionId) {
|
||||
return sessionId == null ? new UUID(0L, 0L) : sessionId;
|
||||
}
|
||||
|
||||
private OffsetDateTime utc(OffsetDateTime value) {
|
||||
return value == null ? null : value.withOffsetSameInstant(java.time.ZoneOffset.UTC);
|
||||
}
|
||||
|
||||
private OffsetDateTime max(OffsetDateTime left, OffsetDateTime right) {
|
||||
if (left == null) {
|
||||
return right;
|
||||
}
|
||||
if (right == null) {
|
||||
return left;
|
||||
}
|
||||
return left.isAfter(right) ? left : right;
|
||||
}
|
||||
|
||||
private OffsetDateTime min(OffsetDateTime left, OffsetDateTime right) {
|
||||
if (left == null) {
|
||||
return right;
|
||||
}
|
||||
if (right == null) {
|
||||
return left;
|
||||
}
|
||||
return left.isBefore(right) ? left : right;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,21 +1,22 @@
|
|||
package at.procon.eventhub.processing.driverworkingtime.service;
|
||||
|
||||
import at.procon.eventhub.config.EventHubProperties;
|
||||
import at.procon.eventhub.processing.driverworkingtime.dto.DriverWorkingTimeProcessingResultDto;
|
||||
import at.procon.eventhub.processing.driverworkingtime.model.DriverWorkingTimeActivityInterval;
|
||||
import at.procon.eventhub.processing.driverworkingtime.model.DriverWorkingTimeDerivedProjectionBundle;
|
||||
import at.procon.eventhub.processing.driverworkingtime.model.DriverWorkingTimeDrivingInterruptionInterval;
|
||||
import at.procon.eventhub.processing.driverworkingtime.model.DriverWorkingTimeGeoEvidenceEvent;
|
||||
import at.procon.eventhub.processing.driverworkingtime.model.DriverWorkingTimePotentialInVehicleTripInterval;
|
||||
import at.procon.eventhub.processing.driverworkingtime.model.DriverWorkingTimeProcessingInput;
|
||||
import at.procon.eventhub.processing.driverworkingtime.model.DriverWorkingTimeRestCoverageInterval;
|
||||
import at.procon.eventhub.processing.driverworkingtime.model.DriverWorkingTimeVehicleUsageInterval;
|
||||
import at.procon.eventhub.processing.driverworkingtime.model.DriverWorkingTimeVuCardAbsentInterval;
|
||||
import at.procon.eventhub.processing.eventprocessing.support.RuntimeSupportEvidenceEvent;
|
||||
import at.procon.eventhub.tachographfilesession.model.*;
|
||||
import at.procon.eventhub.tachographfilesession.service.DriverTimelineBuilder;
|
||||
import at.procon.eventhub.tachographfilesession.service.DriverTimelineReusableProjectionBuilder;
|
||||
import at.procon.eventhub.tachographfilesession.service.TachographEsperProcessingInput;
|
||||
import java.time.Duration;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
|
@ -31,76 +32,59 @@ import org.springframework.stereotype.Service;
|
|||
@Service
|
||||
public class DriverWorkingTimeProcessingCore {
|
||||
|
||||
private final DriverTimelineBuilder driverTimelineBuilder;
|
||||
private final DriverTimelineReusableProjectionBuilder reusableProjectionBuilder;
|
||||
private final EventHubProperties properties;
|
||||
private final DriverWorkingTimeDerivedProjectionEngine derivedProjectionEngine;
|
||||
|
||||
public DriverWorkingTimeProcessingCore(
|
||||
DriverTimelineBuilder driverTimelineBuilder,
|
||||
DriverTimelineReusableProjectionBuilder reusableProjectionBuilder,
|
||||
EventHubProperties properties
|
||||
DriverWorkingTimeDerivedProjectionEngine derivedProjectionEngine
|
||||
) {
|
||||
this.driverTimelineBuilder = driverTimelineBuilder;
|
||||
this.reusableProjectionBuilder = reusableProjectionBuilder;
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
public DriverWorkingTimeProcessingResultDto process(TachographEsperProcessingInput input) {
|
||||
Objects.requireNonNull(input, "input must not be null");
|
||||
return process(toSourceNeutralInput(input));
|
||||
this.derivedProjectionEngine = derivedProjectionEngine;
|
||||
}
|
||||
|
||||
public DriverWorkingTimeProcessingResultDto process(DriverWorkingTimeProcessingInput input) {
|
||||
Objects.requireNonNull(input, "input must not be null");
|
||||
ResolvedDriverTimeline timeline = toResolvedTimeline(input);
|
||||
OffsetDateTime loadedFrom = input.loadedFrom();
|
||||
OffsetDateTime loadedTo = input.loadedTo();
|
||||
String driverKey = input.driverKey();
|
||||
OffsetDateTime requestedFrom = input.requestedFrom() == null ? timeline.loadedFrom() : utc(input.requestedFrom());
|
||||
OffsetDateTime requestedTo = input.requestedTo() == null ? timeline.loadedTo() : utc(input.requestedTo());
|
||||
OffsetDateTime requestedFrom = input.requestedFrom() == null ? loadedFrom : utc(input.requestedFrom());
|
||||
OffsetDateTime requestedTo = input.requestedTo() == null ? loadedTo : utc(input.requestedTo());
|
||||
if (requestedFrom != null && requestedTo != null && requestedTo.isBefore(requestedFrom)) {
|
||||
throw new IllegalArgumentException("occurredTo must not be before occurredFrom.");
|
||||
}
|
||||
|
||||
List<TachographEsperActivityIntervalEvent> activityIntervals = clipEsperActivityIntervalEvents(
|
||||
driverTimelineBuilder.buildEsperActivityIntervalEvents(input.sessionId(), driverKey, timeline),
|
||||
buildEsperActivityIntervalEvents(input.activityIntervals()),
|
||||
requestedFrom,
|
||||
requestedTo
|
||||
);
|
||||
List<TachographEsperActivityIntervalEvent> drivingIntervals = clipEsperActivityIntervalEvents(
|
||||
driverTimelineBuilder.buildEsperDrivingIntervalEvents(input.sessionId(), driverKey, timeline),
|
||||
buildEsperDrivingIntervalEvents(input.activityIntervals()),
|
||||
requestedFrom,
|
||||
requestedTo
|
||||
);
|
||||
|
||||
TachographEsperDrivingDerivedProjectionBundle derivedProjectionBundle =
|
||||
reusableProjectionBuilder.buildEsperDrivingDerivedProjectionBundle(
|
||||
safeSessionId(input.sessionId()),
|
||||
driverKey,
|
||||
timeline,
|
||||
input.significantDrivingMinutes(),
|
||||
input.minimumRestPeriodMinutes()
|
||||
);
|
||||
DriverWorkingTimeDerivedProjectionBundle derivedProjectionBundle = derivedProjectionEngine.build(input);
|
||||
|
||||
List<TachographEsperDrivingInterruptionIntervalEvent> rawDrivingInterruptionIntervals =
|
||||
derivedProjectionBundle.drivingInterruptionIntervals();
|
||||
derivedProjectionBundle.drivingInterruptionIntervals().stream().map(this::toLegacy).toList();
|
||||
List<TachographEsperDrivingInterruptionIntervalEvent> drivingInterruptionIntervals =
|
||||
clipEsperDrivingInterruptionIntervalEvents(rawDrivingInterruptionIntervals, requestedFrom, requestedTo);
|
||||
List<TachographEsperDrivingInterruptionIntervalEvent> rawDailyWeeklyRestCandidateIntervals =
|
||||
derivedProjectionBundle.dailyWeeklyRestCandidateIntervals();
|
||||
derivedProjectionBundle.dailyWeeklyRestCandidateIntervals().stream().map(this::toLegacy).toList();
|
||||
List<TachographEsperDrivingInterruptionIntervalEvent> dailyWeeklyRestCandidateIntervals =
|
||||
clipEsperDrivingInterruptionIntervalEvents(rawDailyWeeklyRestCandidateIntervals, requestedFrom, requestedTo);
|
||||
List<TachographEsperDrivingInterruptionIntervalEvent> rawDrivingInterruptionVehicleChangeIntervals =
|
||||
derivedProjectionBundle.drivingInterruptionVehicleChangeIntervals();
|
||||
derivedProjectionBundle.drivingInterruptionVehicleChangeIntervals().stream().map(this::toLegacy).toList();
|
||||
List<TachographEsperDrivingInterruptionIntervalEvent> drivingInterruptionVehicleChangeIntervals =
|
||||
clipEsperDrivingInterruptionIntervalEvents(rawDrivingInterruptionVehicleChangeIntervals, requestedFrom, requestedTo);
|
||||
|
||||
List<TachographEsperVehicleUsageIntervalEvent> rawVehicleUsageIntervals =
|
||||
driverTimelineBuilder.buildEsperVehicleUsageIntervalEvents(timeline);
|
||||
buildEsperVehicleUsageIntervalEvents(input.vehicleUsageIntervals());
|
||||
List<TachographEsperVuCardAbsentIntervalEvent> rawVuCardAbsentIntervals =
|
||||
derivedProjectionBundle.vuCardAbsentIntervals();
|
||||
derivedProjectionBundle.vuCardAbsentIntervals().stream().map(this::toLegacy).toList();
|
||||
|
||||
List<TachographEsperPotentialHomeOvernightStayIntervalEvent> potentialHomeOvernightStayIntervals =
|
||||
clipEsperPotentialHomeOvernightStayIntervalEvents(
|
||||
derivedProjectionBundle.potentialHomeOvernightStayIntervals(),
|
||||
derivedProjectionBundle.potentialHomeOvernightStayIntervals().stream().map(this::toLegacyPotentialHome).toList(),
|
||||
rawVuCardAbsentIntervals,
|
||||
rawVehicleUsageIntervals,
|
||||
requestedFrom,
|
||||
|
|
@ -108,7 +92,7 @@ public class DriverWorkingTimeProcessingCore {
|
|||
);
|
||||
List<TachographEsperDailyWeeklyRestCandidateCoverageIntervalEvent> dailyWeeklyRestCandidateCoverageIntervals =
|
||||
clipEsperDailyWeeklyRestCandidateCoverageIntervalEvents(
|
||||
derivedProjectionBundle.dailyWeeklyRestCandidateCoverageIntervals(),
|
||||
derivedProjectionBundle.dailyWeeklyRestCandidateCoverageIntervals().stream().map(this::toLegacyCoverage).toList(),
|
||||
rawVuCardAbsentIntervals,
|
||||
rawVehicleUsageIntervals,
|
||||
requestedFrom,
|
||||
|
|
@ -116,7 +100,7 @@ public class DriverWorkingTimeProcessingCore {
|
|||
);
|
||||
List<TachographEsperDailyWeeklyRestCandidateCoverageIntervalEvent> unclassifiedDailyWeeklyRestCandidateCoverageIntervals =
|
||||
clipEsperDailyWeeklyRestCandidateCoverageIntervalEvents(
|
||||
derivedProjectionBundle.unclassifiedDailyWeeklyRestCandidateCoverageIntervals(),
|
||||
derivedProjectionBundle.unclassifiedDailyWeeklyRestCandidateCoverageIntervals().stream().map(this::toLegacyCoverage).toList(),
|
||||
rawVuCardAbsentIntervals,
|
||||
rawVehicleUsageIntervals,
|
||||
requestedFrom,
|
||||
|
|
@ -124,7 +108,7 @@ public class DriverWorkingTimeProcessingCore {
|
|||
);
|
||||
List<TachographEsperPotentialInVehicleOvernightStayIntervalEvent> potentialInVehicleOvernightStayIntervals =
|
||||
clipEsperPotentialInVehicleOvernightStayIntervalEvents(
|
||||
derivedProjectionBundle.potentialInVehicleOvernightStayIntervals(),
|
||||
derivedProjectionBundle.potentialInVehicleOvernightStayIntervals().stream().map(this::toLegacyPotentialInVehicle).toList(),
|
||||
rawVuCardAbsentIntervals,
|
||||
rawVehicleUsageIntervals,
|
||||
requestedFrom,
|
||||
|
|
@ -132,7 +116,7 @@ public class DriverWorkingTimeProcessingCore {
|
|||
);
|
||||
List<TachographEsperPotentialInVehicleTripIntervalEvent> potentialInVehicleTripIntervals =
|
||||
clipEsperPotentialInVehicleTripIntervalEvents(
|
||||
derivedProjectionBundle.potentialInVehicleTripIntervals(),
|
||||
derivedProjectionBundle.potentialInVehicleTripIntervals().stream().map(this::toLegacy).toList(),
|
||||
potentialInVehicleOvernightStayIntervals,
|
||||
requestedFrom,
|
||||
requestedTo
|
||||
|
|
@ -148,7 +132,7 @@ public class DriverWorkingTimeProcessingCore {
|
|||
requestedTo
|
||||
);
|
||||
List<TachographEsperSupportGeoEvent> supportGeoEvents = clipEsperSupportGeoEvents(
|
||||
timeline.supportEvents(),
|
||||
buildSupportGeoEvents(input.supportEvidenceEvents()),
|
||||
driverKey,
|
||||
requestedFrom,
|
||||
requestedTo
|
||||
|
|
@ -157,9 +141,9 @@ public class DriverWorkingTimeProcessingCore {
|
|||
return new DriverWorkingTimeProcessingResultDto(
|
||||
input.sessionId(),
|
||||
driverKey,
|
||||
timeline.sourceKind(),
|
||||
timeline.loadedFrom(),
|
||||
timeline.loadedTo(),
|
||||
input.sourceKind(),
|
||||
loadedFrom,
|
||||
loadedTo,
|
||||
requestedFrom,
|
||||
requestedTo,
|
||||
activityIntervals.size(),
|
||||
|
|
@ -192,78 +176,19 @@ public class DriverWorkingTimeProcessingCore {
|
|||
);
|
||||
}
|
||||
|
||||
public DriverWorkingTimeProcessingResultDto processDriverWorkingTime(TachographEsperProcessingInput input) {
|
||||
public DriverWorkingTimeProcessingResultDto processDriverWorkingTime(DriverWorkingTimeProcessingInput input) {
|
||||
return process(input);
|
||||
}
|
||||
|
||||
private DriverWorkingTimeProcessingInput toSourceNeutralInput(TachographEsperProcessingInput input) {
|
||||
ResolvedDriverTimeline timeline = Objects.requireNonNull(input.timeline(), "timeline must not be null");
|
||||
String driverKey = input.driverKey();
|
||||
return new DriverWorkingTimeProcessingInput(
|
||||
input.sessionId(),
|
||||
driverKey,
|
||||
timeline.sourceKind(),
|
||||
timeline.loadedFrom(),
|
||||
timeline.loadedTo(),
|
||||
input.requestedFrom(),
|
||||
input.requestedTo(),
|
||||
input.significantDrivingMinutes(),
|
||||
input.minimumRestPeriodMinutes(),
|
||||
safeList(timeline.activityIntervals()).stream()
|
||||
.map(interval -> DriverWorkingTimeActivityInterval.fromResolved(input.sessionId(), driverKey, interval))
|
||||
.filter(Objects::nonNull)
|
||||
.toList(),
|
||||
safeList(timeline.vehicleUsageIntervals()).stream()
|
||||
.map(DriverWorkingTimeVehicleUsageInterval::fromResolved)
|
||||
.filter(Objects::nonNull)
|
||||
.toList(),
|
||||
safeList(timeline.supportEvents()).stream()
|
||||
.map(this::toSupportEvidenceEvent)
|
||||
.filter(Objects::nonNull)
|
||||
.toList(),
|
||||
input.notes()
|
||||
);
|
||||
}
|
||||
|
||||
private ResolvedDriverTimeline toResolvedTimeline(DriverWorkingTimeProcessingInput input) {
|
||||
List<ResolvedActivityInterval> activityIntervals = input.activityIntervals().stream()
|
||||
.map(this::toResolvedActivityInterval)
|
||||
.filter(Objects::nonNull)
|
||||
.toList();
|
||||
List<ResolvedVehicleUsageInterval> vehicleUsageIntervals = input.vehicleUsageIntervals().stream()
|
||||
.map(this::toResolvedVehicleUsageInterval)
|
||||
.filter(Objects::nonNull)
|
||||
.toList();
|
||||
List<ExtractedSupportEvent> supportEvents = input.supportEvidenceEvents().stream()
|
||||
.map(this::toExtractedSupportEvent)
|
||||
.filter(Objects::nonNull)
|
||||
.toList();
|
||||
OffsetDateTime loadedFrom = input.loadedFrom() == null
|
||||
? earliest(activityIntervals, vehicleUsageIntervals, supportEvents)
|
||||
: utc(input.loadedFrom());
|
||||
OffsetDateTime loadedTo = input.loadedTo() == null
|
||||
? latest(activityIntervals, vehicleUsageIntervals, supportEvents)
|
||||
: utc(input.loadedTo());
|
||||
return new ResolvedDriverTimeline(
|
||||
input.sourceKind(),
|
||||
loadedFrom,
|
||||
loadedTo,
|
||||
vehicleUsageIntervals,
|
||||
activityIntervals,
|
||||
supportEvents,
|
||||
List.of()
|
||||
);
|
||||
}
|
||||
|
||||
private ResolvedActivityInterval toResolvedActivityInterval(DriverWorkingTimeActivityInterval interval) {
|
||||
if (interval == null || interval.startedAt() == null || interval.endedAt() == null) {
|
||||
return null;
|
||||
}
|
||||
return new ResolvedActivityInterval(
|
||||
private List<TachographEsperActivityIntervalEvent> buildEsperActivityIntervalEvents(
|
||||
List<DriverWorkingTimeActivityInterval> intervals
|
||||
) {
|
||||
return safeList(intervals).stream()
|
||||
.filter(interval -> interval.startedAt() != null && interval.endedAt() != null)
|
||||
.map(interval -> new TachographEsperActivityIntervalEvent(
|
||||
safeSessionId(interval.sessionId()),
|
||||
interval.driverKey(),
|
||||
interval.intervalId(),
|
||||
utc(interval.startedAt()),
|
||||
utc(interval.endedAt()),
|
||||
interval.durationSeconds(),
|
||||
interval.activityType(),
|
||||
interval.cardSlot(),
|
||||
interval.cardStatus(),
|
||||
|
|
@ -271,18 +196,33 @@ public class DriverWorkingTimeProcessingCore {
|
|||
interval.registrationKey(),
|
||||
interval.vehicleKey(),
|
||||
interval.sourceKind(),
|
||||
utc(interval.startedAt()),
|
||||
utc(interval.endedAt()),
|
||||
interval.durationSeconds(),
|
||||
interval.sourceIntervalIds(),
|
||||
interval.synthetic(),
|
||||
interval.clippedToRequestedPeriod(),
|
||||
interval.level()
|
||||
);
|
||||
))
|
||||
.sorted(Comparator.comparing(TachographEsperActivityIntervalEvent::startedAt)
|
||||
.thenComparing(TachographEsperActivityIntervalEvent::endedAt))
|
||||
.toList();
|
||||
}
|
||||
|
||||
private ResolvedVehicleUsageInterval toResolvedVehicleUsageInterval(DriverWorkingTimeVehicleUsageInterval interval) {
|
||||
if (interval == null || interval.startedAt() == null) {
|
||||
return null;
|
||||
private List<TachographEsperActivityIntervalEvent> buildEsperDrivingIntervalEvents(
|
||||
List<DriverWorkingTimeActivityInterval> intervals
|
||||
) {
|
||||
return buildEsperActivityIntervalEvents(intervals).stream()
|
||||
.filter(interval -> Objects.equals("DRIVE", interval.activityType()))
|
||||
.toList();
|
||||
}
|
||||
return new ResolvedVehicleUsageInterval(
|
||||
|
||||
private List<TachographEsperVehicleUsageIntervalEvent> buildEsperVehicleUsageIntervalEvents(
|
||||
List<DriverWorkingTimeVehicleUsageInterval> intervals
|
||||
) {
|
||||
return safeList(intervals).stream()
|
||||
.filter(interval -> interval.startedAt() != null)
|
||||
.map(interval -> new TachographEsperVehicleUsageIntervalEvent(
|
||||
safeSessionId(interval.sessionId()),
|
||||
interval.driverKey(),
|
||||
interval.intervalId(),
|
||||
|
|
@ -295,106 +235,240 @@ public class DriverWorkingTimeProcessingCore {
|
|||
interval.vehicleKey(),
|
||||
interval.sourceKind(),
|
||||
interval.sourceIntervalIds()
|
||||
);
|
||||
))
|
||||
.sorted(Comparator.comparing(TachographEsperVehicleUsageIntervalEvent::startedAt)
|
||||
.thenComparing(TachographEsperVehicleUsageIntervalEvent::endedAt, Comparator.nullsLast(Comparator.naturalOrder())))
|
||||
.toList();
|
||||
}
|
||||
|
||||
private RuntimeSupportEvidenceEvent toSupportEvidenceEvent(ExtractedSupportEvent supportEvent) {
|
||||
if (supportEvent == null || supportEvent.occurredAt() == null) {
|
||||
private List<TachographEsperSupportGeoEvent> buildSupportGeoEvents(
|
||||
List<RuntimeSupportEvidenceEvent> supportEvents
|
||||
) {
|
||||
return safeList(supportEvents).stream()
|
||||
.filter(event -> event.occurredAt() != null)
|
||||
.map(event -> new TachographEsperSupportGeoEvent(
|
||||
event.eventId(),
|
||||
event.driverKey(),
|
||||
utc(event.occurredAt()),
|
||||
event.eventDomain(),
|
||||
event.eventType(),
|
||||
event.lifecycle(),
|
||||
event.registrationKey(),
|
||||
event.vehicleKey(),
|
||||
event.countryCode(),
|
||||
event.regionCode(),
|
||||
event.countryFrom(),
|
||||
event.countryTo(),
|
||||
event.operation(),
|
||||
event.latitude(),
|
||||
event.longitude(),
|
||||
event.odometerKm(),
|
||||
rawRecordPath(event)
|
||||
))
|
||||
.sorted(Comparator.comparing(TachographEsperSupportGeoEvent::occurredAt)
|
||||
.thenComparing(TachographEsperSupportGeoEvent::eventId, Comparator.nullsLast(String::compareTo)))
|
||||
.toList();
|
||||
}
|
||||
|
||||
private String rawRecordPath(RuntimeSupportEvidenceEvent event) {
|
||||
if (event == null) {
|
||||
return null;
|
||||
}
|
||||
return new RuntimeSupportEvidenceEvent(
|
||||
supportEvent.eventId(),
|
||||
null,
|
||||
null,
|
||||
supportEvent.eventDomain(),
|
||||
supportEvent.eventType(),
|
||||
supportEvent.eventLifecycle(),
|
||||
supportEvent.driverKey(),
|
||||
supportEvent.vehicleKey(),
|
||||
supportEvent.registrationKey(),
|
||||
utc(supportEvent.occurredAt()),
|
||||
supportEvent.occurredAt().toEpochSecond(),
|
||||
supportEvent.latitude(),
|
||||
supportEvent.longitude(),
|
||||
supportEvent.country(),
|
||||
supportEvent.region(),
|
||||
supportEvent.countryFrom(),
|
||||
supportEvent.countryTo(),
|
||||
supportEvent.operation(),
|
||||
supportEvent.odometerKm(),
|
||||
supportEvent.avgSpeedKmh(),
|
||||
supportEvent.maxSpeedKmh(),
|
||||
Map.of("rawRecordPath", supportEvent.rawRecordPath())
|
||||
Object value = event.rawAttributes().get("rawRecordPath");
|
||||
return value == null ? null : value.toString();
|
||||
}
|
||||
|
||||
private TachographEsperDrivingInterruptionIntervalEvent toLegacy(DriverWorkingTimeDrivingInterruptionInterval value) {
|
||||
return new TachographEsperDrivingInterruptionIntervalEvent(
|
||||
safeSessionId(value.sessionId()),
|
||||
value.driverKey(),
|
||||
value.startedAt(),
|
||||
value.endedAt(),
|
||||
value.durationSeconds(),
|
||||
value.previousDrivingSourceIntervalId(),
|
||||
value.nextDrivingSourceIntervalId(),
|
||||
value.previousRegistrationKey(),
|
||||
value.nextRegistrationKey(),
|
||||
value.previousVehicleKey(),
|
||||
value.nextVehicleKey()
|
||||
);
|
||||
}
|
||||
|
||||
private ExtractedSupportEvent toExtractedSupportEvent(RuntimeSupportEvidenceEvent supportEvent) {
|
||||
if (supportEvent == null || supportEvent.occurredAt() == null) {
|
||||
private TachographEsperVuCardAbsentIntervalEvent toLegacy(DriverWorkingTimeVuCardAbsentInterval value) {
|
||||
return new TachographEsperVuCardAbsentIntervalEvent(
|
||||
safeSessionId(value.sessionId()),
|
||||
value.driverKey(),
|
||||
value.startedAt(),
|
||||
value.endedAt(),
|
||||
value.durationSeconds(),
|
||||
value.previousUsageIntervalId(),
|
||||
value.nextUsageIntervalId(),
|
||||
value.previousRegistrationKey(),
|
||||
value.nextRegistrationKey(),
|
||||
value.previousVehicleKey(),
|
||||
value.nextVehicleKey()
|
||||
);
|
||||
}
|
||||
|
||||
private TachographEsperDailyWeeklyRestCandidateCoverageIntervalEvent toLegacyCoverage(
|
||||
DriverWorkingTimeRestCoverageInterval value
|
||||
) {
|
||||
return new TachographEsperDailyWeeklyRestCandidateCoverageIntervalEvent(
|
||||
safeSessionId(value.sessionId()),
|
||||
value.driverKey(),
|
||||
value.startedAt(),
|
||||
value.endedAt(),
|
||||
value.durationSeconds(),
|
||||
value.cardAbsentDurationSeconds(),
|
||||
value.cardAbsentCoveragePercent(),
|
||||
value.previousDrivingSourceIntervalId(),
|
||||
value.nextDrivingSourceIntervalId(),
|
||||
value.previousRegistrationKey(),
|
||||
value.nextRegistrationKey(),
|
||||
value.previousVehicleKey(),
|
||||
value.nextVehicleKey(),
|
||||
value.beginBoundaryOdometerKm(),
|
||||
value.endBoundaryOdometerKm(),
|
||||
value.beginGeoEventId(),
|
||||
value.beginGeoEventDomain(),
|
||||
value.beginGeoOccurredAt(),
|
||||
value.beginLatitude(),
|
||||
value.beginLongitude(),
|
||||
value.beginGeoDistanceSeconds(),
|
||||
value.beginGeoOdometerKm(),
|
||||
value.endGeoEventId(),
|
||||
value.endGeoEventDomain(),
|
||||
value.endGeoOccurredAt(),
|
||||
value.endLatitude(),
|
||||
value.endLongitude(),
|
||||
value.endGeoDistanceSeconds(),
|
||||
value.endGeoOdometerKm(),
|
||||
value.geoEvidenceMovementMeters(),
|
||||
value.geoEvidenceMovementCategory(),
|
||||
toLegacy(value.beginGeoEvent()),
|
||||
toLegacy(value.endGeoEvent())
|
||||
);
|
||||
}
|
||||
|
||||
private TachographEsperPotentialHomeOvernightStayIntervalEvent toLegacyPotentialHome(
|
||||
DriverWorkingTimeRestCoverageInterval value
|
||||
) {
|
||||
return new TachographEsperPotentialHomeOvernightStayIntervalEvent(
|
||||
safeSessionId(value.sessionId()),
|
||||
value.driverKey(),
|
||||
value.startedAt(),
|
||||
value.endedAt(),
|
||||
value.durationSeconds(),
|
||||
value.cardAbsentDurationSeconds(),
|
||||
value.cardAbsentCoveragePercent(),
|
||||
value.previousDrivingSourceIntervalId(),
|
||||
value.nextDrivingSourceIntervalId(),
|
||||
value.previousRegistrationKey(),
|
||||
value.nextRegistrationKey(),
|
||||
value.previousVehicleKey(),
|
||||
value.nextVehicleKey(),
|
||||
value.beginBoundaryOdometerKm(),
|
||||
value.endBoundaryOdometerKm(),
|
||||
value.beginGeoEventId(),
|
||||
value.beginGeoEventDomain(),
|
||||
value.beginGeoOccurredAt(),
|
||||
value.beginLatitude(),
|
||||
value.beginLongitude(),
|
||||
value.beginGeoDistanceSeconds(),
|
||||
value.beginGeoOdometerKm(),
|
||||
value.endGeoEventId(),
|
||||
value.endGeoEventDomain(),
|
||||
value.endGeoOccurredAt(),
|
||||
value.endLatitude(),
|
||||
value.endLongitude(),
|
||||
value.endGeoDistanceSeconds(),
|
||||
value.endGeoOdometerKm(),
|
||||
value.geoEvidenceMovementMeters(),
|
||||
value.geoEvidenceMovementCategory(),
|
||||
toLegacy(value.beginGeoEvent()),
|
||||
toLegacy(value.endGeoEvent())
|
||||
);
|
||||
}
|
||||
|
||||
private TachographEsperPotentialInVehicleOvernightStayIntervalEvent toLegacyPotentialInVehicle(
|
||||
DriverWorkingTimeRestCoverageInterval value
|
||||
) {
|
||||
return new TachographEsperPotentialInVehicleOvernightStayIntervalEvent(
|
||||
safeSessionId(value.sessionId()),
|
||||
value.driverKey(),
|
||||
value.startedAt(),
|
||||
value.endedAt(),
|
||||
value.durationSeconds(),
|
||||
value.cardAbsentDurationSeconds(),
|
||||
value.cardAbsentCoveragePercent(),
|
||||
value.previousDrivingSourceIntervalId(),
|
||||
value.nextDrivingSourceIntervalId(),
|
||||
value.previousRegistrationKey(),
|
||||
value.nextRegistrationKey(),
|
||||
value.previousVehicleKey(),
|
||||
value.nextVehicleKey(),
|
||||
value.beginBoundaryOdometerKm(),
|
||||
value.endBoundaryOdometerKm(),
|
||||
value.beginGeoEventId(),
|
||||
value.beginGeoEventDomain(),
|
||||
value.beginGeoOccurredAt(),
|
||||
value.beginLatitude(),
|
||||
value.beginLongitude(),
|
||||
value.beginGeoDistanceSeconds(),
|
||||
value.beginGeoOdometerKm(),
|
||||
value.endGeoEventId(),
|
||||
value.endGeoEventDomain(),
|
||||
value.endGeoOccurredAt(),
|
||||
value.endLatitude(),
|
||||
value.endLongitude(),
|
||||
value.endGeoDistanceSeconds(),
|
||||
value.endGeoOdometerKm(),
|
||||
value.geoEvidenceMovementMeters(),
|
||||
value.geoEvidenceMovementCategory(),
|
||||
toLegacy(value.beginGeoEvent()),
|
||||
toLegacy(value.endGeoEvent())
|
||||
);
|
||||
}
|
||||
|
||||
private TachographEsperPotentialInVehicleTripIntervalEvent toLegacy(
|
||||
DriverWorkingTimePotentialInVehicleTripInterval value
|
||||
) {
|
||||
return new TachographEsperPotentialInVehicleTripIntervalEvent(
|
||||
safeSessionId(value.sessionId()),
|
||||
value.driverKey(),
|
||||
value.startedAt(),
|
||||
value.endedAt(),
|
||||
value.durationSeconds(),
|
||||
value.registrationKey(),
|
||||
value.vehicleKey(),
|
||||
value.containedPotentialInVehicleOvernightStayIntervalCount(),
|
||||
value.containedPotentialInVehicleOvernightStayDurationSeconds(),
|
||||
value.containedCardAbsentDurationSeconds(),
|
||||
value.firstPotentialInVehicleOvernightStayStartedAt(),
|
||||
value.lastPotentialInVehicleOvernightStayEndedAt(),
|
||||
value.firstPreviousDrivingSourceIntervalId(),
|
||||
value.lastNextDrivingSourceIntervalId(),
|
||||
value.potentialInVehicleOvernightStayIntervals().stream()
|
||||
.map(this::toLegacyPotentialInVehicle)
|
||||
.toList()
|
||||
);
|
||||
}
|
||||
|
||||
private TachographEsperGeoEvidenceEvent toLegacy(DriverWorkingTimeGeoEvidenceEvent value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
Object rawRecordPath = supportEvent.rawAttributes().get("rawRecordPath");
|
||||
return new ExtractedSupportEvent(
|
||||
supportEvent.eventId(),
|
||||
supportEvent.driverKey(),
|
||||
utc(supportEvent.occurredAt()),
|
||||
supportEvent.eventDomain(),
|
||||
supportEvent.eventType(),
|
||||
supportEvent.lifecycle(),
|
||||
null,
|
||||
supportEvent.registrationKey(),
|
||||
supportEvent.vehicleKey(),
|
||||
supportEvent.countryCode(),
|
||||
supportEvent.regionCode(),
|
||||
supportEvent.countryFrom(),
|
||||
supportEvent.countryTo(),
|
||||
supportEvent.operation(),
|
||||
supportEvent.latitude(),
|
||||
supportEvent.longitude(),
|
||||
null,
|
||||
supportEvent.odometerKm(),
|
||||
null,
|
||||
supportEvent.speedKmh(),
|
||||
supportEvent.maxSpeedKmh(),
|
||||
rawRecordPath == null ? null : rawRecordPath.toString()
|
||||
return new TachographEsperGeoEvidenceEvent(
|
||||
value.eventId(),
|
||||
value.eventDomain(),
|
||||
value.occurredAt(),
|
||||
value.latitude(),
|
||||
value.longitude(),
|
||||
value.distanceSeconds(),
|
||||
value.odometerKm()
|
||||
);
|
||||
}
|
||||
|
||||
private OffsetDateTime earliest(
|
||||
List<ResolvedActivityInterval> activityIntervals,
|
||||
List<ResolvedVehicleUsageInterval> vehicleUsageIntervals,
|
||||
List<ExtractedSupportEvent> supportEvents
|
||||
) {
|
||||
OffsetDateTime earliest = null;
|
||||
for (ResolvedActivityInterval interval : activityIntervals) {
|
||||
earliest = min(earliest, interval.from());
|
||||
}
|
||||
for (ResolvedVehicleUsageInterval interval : vehicleUsageIntervals) {
|
||||
earliest = min(earliest, interval.from());
|
||||
}
|
||||
for (ExtractedSupportEvent event : supportEvents) {
|
||||
earliest = min(earliest, event.occurredAt());
|
||||
}
|
||||
return earliest;
|
||||
}
|
||||
|
||||
private OffsetDateTime latest(
|
||||
List<ResolvedActivityInterval> activityIntervals,
|
||||
List<ResolvedVehicleUsageInterval> vehicleUsageIntervals,
|
||||
List<ExtractedSupportEvent> supportEvents
|
||||
) {
|
||||
OffsetDateTime latest = null;
|
||||
for (ResolvedActivityInterval interval : activityIntervals) {
|
||||
latest = max(latest, interval.to());
|
||||
}
|
||||
for (ResolvedVehicleUsageInterval interval : vehicleUsageIntervals) {
|
||||
latest = max(latest, interval.to());
|
||||
}
|
||||
for (ExtractedSupportEvent event : supportEvents) {
|
||||
latest = max(latest, event.occurredAt());
|
||||
}
|
||||
return latest;
|
||||
}
|
||||
|
||||
private UUID safeSessionId(UUID sessionId) {
|
||||
return sessionId == null ? new UUID(0L, 0L) : sessionId;
|
||||
}
|
||||
|
|
@ -498,7 +572,7 @@ public class DriverWorkingTimeProcessingCore {
|
|||
}
|
||||
|
||||
private List<TachographEsperSupportGeoEvent> clipEsperSupportGeoEvents(
|
||||
List<ExtractedSupportEvent> supportEvents,
|
||||
List<TachographEsperSupportGeoEvent> supportEvents,
|
||||
String driverKey,
|
||||
OffsetDateTime requestedFrom,
|
||||
OffsetDateTime requestedTo
|
||||
|
|
@ -511,25 +585,6 @@ public class DriverWorkingTimeProcessingCore {
|
|||
.filter(event -> event.occurredAt() != null)
|
||||
.filter(event -> event.latitude() != null && event.longitude() != null)
|
||||
.filter(event -> !event.occurredAt().isBefore(requestedFrom) && !event.occurredAt().isAfter(requestedTo))
|
||||
.map(event -> new TachographEsperSupportGeoEvent(
|
||||
event.eventId(),
|
||||
event.driverKey(),
|
||||
event.occurredAt(),
|
||||
event.eventDomain(),
|
||||
event.eventType(),
|
||||
event.eventLifecycle(),
|
||||
event.registrationKey(),
|
||||
event.vehicleKey(),
|
||||
event.country(),
|
||||
event.region(),
|
||||
event.countryFrom(),
|
||||
event.countryTo(),
|
||||
event.operation(),
|
||||
event.latitude(),
|
||||
event.longitude(),
|
||||
event.odometerKm(),
|
||||
event.rawRecordPath()
|
||||
))
|
||||
.sorted(Comparator.comparing(TachographEsperSupportGeoEvent::occurredAt)
|
||||
.thenComparing(TachographEsperSupportGeoEvent::eventDomain, Comparator.nullsLast(String::compareTo))
|
||||
.thenComparing(TachographEsperSupportGeoEvent::eventId, Comparator.nullsLast(String::compareTo)))
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import at.procon.eventhub.processing.dto.UnifiedRuntimeProcessingApiRequest;
|
|||
import at.procon.eventhub.processing.driverworkingtime.model.DriverWorkingTimeActivityInterval;
|
||||
import at.procon.eventhub.processing.driverworkingtime.model.DriverWorkingTimeProcessingInput;
|
||||
import at.procon.eventhub.processing.driverworkingtime.model.DriverWorkingTimeVehicleUsageInterval;
|
||||
import at.procon.eventhub.processing.driverworkingtime.service.DriverWorkingTimeDerivedProjectionEngine;
|
||||
import at.procon.eventhub.processing.eventprocessing.support.RuntimeSupportEvidenceNormalizationResult;
|
||||
import at.procon.eventhub.processing.eventprocessing.support.RuntimeSupportEvidenceEvent;
|
||||
import at.procon.eventhub.processing.eventprocessing.support.RuntimeSupportEvidenceNormalizer;
|
||||
|
|
@ -66,7 +67,7 @@ public class UnifiedRuntimeDerivedProjectionService {
|
|||
driverTimelineBuilder,
|
||||
reusableProjectionBuilder,
|
||||
properties,
|
||||
new DriverWorkingTimeProcessingCore(driverTimelineBuilder, reusableProjectionBuilder, properties),
|
||||
new DriverWorkingTimeProcessingCore(new DriverWorkingTimeDerivedProjectionEngine(reusableProjectionBuilder)),
|
||||
supportEvidenceNormalizer
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package at.procon.eventhub.tachographfilesession.service;
|
|||
|
||||
import at.procon.eventhub.config.EventHubProperties;
|
||||
import at.procon.eventhub.processing.driverworkingtime.dto.DriverWorkingTimeProcessingResultDto;
|
||||
import at.procon.eventhub.processing.driverworkingtime.service.DriverWorkingTimeDerivedProjectionEngine;
|
||||
import at.procon.eventhub.processing.driverworkingtime.service.DriverWorkingTimeProcessingCore;
|
||||
import at.procon.eventhub.tachographfilesession.dto.TachographEsperDriverProcessingResultDto;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
|
@ -27,14 +28,16 @@ public class TachographEsperProcessingCore {
|
|||
DriverTimelineReusableProjectionBuilder reusableProjectionBuilder,
|
||||
EventHubProperties properties
|
||||
) {
|
||||
this(new DriverWorkingTimeProcessingCore(driverTimelineBuilder, reusableProjectionBuilder, properties));
|
||||
this(new DriverWorkingTimeProcessingCore(new DriverWorkingTimeDerivedProjectionEngine(reusableProjectionBuilder)));
|
||||
}
|
||||
|
||||
public TachographEsperDriverProcessingResultDto process(TachographEsperProcessingInput input) {
|
||||
return TachographEsperDriverProcessingResultDto.fromDriverWorkingTime(delegate.process(input));
|
||||
return TachographEsperDriverProcessingResultDto.fromDriverWorkingTime(
|
||||
delegate.process(TachographEsperProcessingInputAdapter.toDriverWorkingTimeInput(input))
|
||||
);
|
||||
}
|
||||
|
||||
public DriverWorkingTimeProcessingResultDto processDriverWorkingTime(TachographEsperProcessingInput input) {
|
||||
return delegate.process(input);
|
||||
return delegate.process(TachographEsperProcessingInputAdapter.toDriverWorkingTimeInput(input));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,71 @@
|
|||
package at.procon.eventhub.tachographfilesession.service;
|
||||
|
||||
import at.procon.eventhub.processing.driverworkingtime.model.DriverWorkingTimeActivityInterval;
|
||||
import at.procon.eventhub.processing.driverworkingtime.model.DriverWorkingTimeProcessingInput;
|
||||
import at.procon.eventhub.processing.driverworkingtime.model.DriverWorkingTimeVehicleUsageInterval;
|
||||
import at.procon.eventhub.processing.eventprocessing.support.RuntimeSupportEvidenceEvent;
|
||||
import at.procon.eventhub.tachographfilesession.model.ExtractedSupportEvent;
|
||||
import at.procon.eventhub.tachographfilesession.model.ResolvedDriverTimeline;
|
||||
import java.util.List;
|
||||
|
||||
final class TachographEsperProcessingInputAdapter {
|
||||
|
||||
private TachographEsperProcessingInputAdapter() {
|
||||
}
|
||||
|
||||
static DriverWorkingTimeProcessingInput toDriverWorkingTimeInput(TachographEsperProcessingInput input) {
|
||||
ResolvedDriverTimeline timeline = input.timeline();
|
||||
String driverKey = input.driverKey();
|
||||
return new DriverWorkingTimeProcessingInput(
|
||||
input.sessionId(),
|
||||
driverKey,
|
||||
timeline.sourceKind(),
|
||||
timeline.loadedFrom(),
|
||||
timeline.loadedTo(),
|
||||
input.requestedFrom(),
|
||||
input.requestedTo(),
|
||||
input.significantDrivingMinutes(),
|
||||
input.minimumRestPeriodMinutes(),
|
||||
timeline.activityIntervals().stream()
|
||||
.map(interval -> DriverWorkingTimeActivityInterval.fromResolved(input.sessionId(), driverKey, interval))
|
||||
.toList(),
|
||||
timeline.vehicleUsageIntervals().stream()
|
||||
.map(DriverWorkingTimeVehicleUsageInterval::fromResolved)
|
||||
.toList(),
|
||||
timeline.supportEvents().stream()
|
||||
.map(TachographEsperProcessingInputAdapter::toSupportEvidenceEvent)
|
||||
.toList(),
|
||||
input.notes()
|
||||
);
|
||||
}
|
||||
|
||||
private static RuntimeSupportEvidenceEvent toSupportEvidenceEvent(ExtractedSupportEvent supportEvent) {
|
||||
if (supportEvent == null || supportEvent.occurredAt() == null) {
|
||||
return null;
|
||||
}
|
||||
return new RuntimeSupportEvidenceEvent(
|
||||
supportEvent.eventId(),
|
||||
null,
|
||||
null,
|
||||
supportEvent.eventDomain(),
|
||||
supportEvent.eventType(),
|
||||
supportEvent.eventLifecycle(),
|
||||
supportEvent.driverKey(),
|
||||
supportEvent.vehicleKey(),
|
||||
supportEvent.registrationKey(),
|
||||
supportEvent.occurredAt(),
|
||||
supportEvent.occurredAt().toEpochSecond(),
|
||||
supportEvent.latitude(),
|
||||
supportEvent.longitude(),
|
||||
supportEvent.country(),
|
||||
supportEvent.region(),
|
||||
supportEvent.countryFrom(),
|
||||
supportEvent.countryTo(),
|
||||
supportEvent.operation(),
|
||||
supportEvent.odometerKm(),
|
||||
supportEvent.avgSpeedKmh(),
|
||||
supportEvent.maxSpeedKmh(),
|
||||
java.util.Map.of("rawRecordPath", supportEvent.rawRecordPath())
|
||||
);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue