Refine rest candidate derivation chain
This commit is contained in:
parent
3b2f893246
commit
317983eba8
|
|
@ -21,6 +21,7 @@ public record TachographEsperDriverProcessingResultDto(
|
|||
int drivingIntervalCount,
|
||||
int drivingInterruptionIntervalCount,
|
||||
int drivingInterruptionVehicleChangeIntervalCount,
|
||||
int dailyWeeklyRestCandidateIntervalCount,
|
||||
int potentialHomeOvernightStayIntervalCount,
|
||||
int vehicleUsageIntervalCount,
|
||||
int vuCardAbsentIntervalCount,
|
||||
|
|
@ -28,6 +29,7 @@ public record TachographEsperDriverProcessingResultDto(
|
|||
List<TachographEsperActivityIntervalEvent> drivingIntervals,
|
||||
List<TachographEsperDrivingInterruptionIntervalEvent> drivingInterruptionIntervals,
|
||||
List<TachographEsperDrivingInterruptionIntervalEvent> drivingInterruptionVehicleChangeIntervals,
|
||||
List<TachographEsperDrivingInterruptionIntervalEvent> dailyWeeklyRestCandidateIntervals,
|
||||
List<TachographEsperPotentialHomeOvernightStayIntervalEvent> potentialHomeOvernightStayIntervals,
|
||||
List<TachographEsperVehicleUsageIntervalEvent> vehicleUsageIntervals,
|
||||
List<TachographEsperVuCardAbsentIntervalEvent> vuCardAbsentIntervals,
|
||||
|
|
|
|||
|
|
@ -55,6 +55,8 @@ public class DriverTimelineBuilder {
|
|||
loadResource("esper/tachograph-driving-interruption-interval-events.epl");
|
||||
private static final String DRIVING_INTERRUPTION_VEHICLE_CHANGE_INTERVAL_EVENTS_EPL =
|
||||
loadResource("esper/tachograph-driving-interruption-vehicle-change-interval-events.epl");
|
||||
private static final String DAILY_WEEKLY_REST_CANDIDATE_INTERVAL_EVENTS_EPL_TEMPLATE =
|
||||
loadResource("esper/tachograph-daily-weekly-rest-candidate-interval-events.epl");
|
||||
private static final String POTENTIAL_HOME_OVERNIGHT_STAY_INTERVAL_EVENTS_EPL_TEMPLATE =
|
||||
loadResource("esper/tachograph-potential-home-overnight-stay-interval-events.epl");
|
||||
private static final String VEHICLE_USAGE_INTERVAL_EVENTS_EPL =
|
||||
|
|
@ -209,12 +211,11 @@ public class DriverTimelineBuilder {
|
|||
}
|
||||
|
||||
public List<TachographEsperPotentialHomeOvernightStayIntervalEvent> buildEsperPotentialHomeOvernightStayIntervalEvents(
|
||||
List<TachographEsperDrivingInterruptionIntervalEvent> drivingInterruptionIntervals,
|
||||
List<TachographEsperVuCardAbsentIntervalEvent> vuCardAbsentIntervals,
|
||||
int minimumRestPeriodMinutes
|
||||
List<TachographEsperDrivingInterruptionIntervalEvent> drivingInterruptionVehicleChangeIntervals,
|
||||
List<TachographEsperVuCardAbsentIntervalEvent> vuCardAbsentIntervals
|
||||
) {
|
||||
if (drivingInterruptionIntervals == null
|
||||
|| drivingInterruptionIntervals.isEmpty()
|
||||
if (drivingInterruptionVehicleChangeIntervals == null
|
||||
|| drivingInterruptionVehicleChangeIntervals.isEmpty()
|
||||
|| vuCardAbsentIntervals == null
|
||||
|| vuCardAbsentIntervals.isEmpty()) {
|
||||
return List.of();
|
||||
|
|
@ -223,7 +224,7 @@ public class DriverTimelineBuilder {
|
|||
executeWithRuntime(
|
||||
configuration -> {
|
||||
configuration.getCommon().addEventType(
|
||||
"TachographDrivingInterruptionIntervalInputEvent",
|
||||
"TachographDrivingInterruptionVehicleChangeIntervalInputEvent",
|
||||
drivingInterruptionIntervalInputDefinition()
|
||||
);
|
||||
configuration.getCommon().addEventType(
|
||||
|
|
@ -231,7 +232,7 @@ public class DriverTimelineBuilder {
|
|||
vuCardAbsentIntervalInputDefinition()
|
||||
);
|
||||
},
|
||||
renderPotentialHomeOvernightStayIntervalEventsEpl(minimumRestPeriodMinutes),
|
||||
POTENTIAL_HOME_OVERNIGHT_STAY_INTERVAL_EVENTS_EPL_TEMPLATE,
|
||||
"potentialHomeOvernightStayIntervals",
|
||||
newData -> collectPotentialHomeOvernightStayIntervalEvents(newData, result),
|
||||
runtime -> {
|
||||
|
|
@ -241,6 +242,34 @@ public class DriverTimelineBuilder {
|
|||
"TachographVuCardAbsentIntervalInputEvent"
|
||||
);
|
||||
}
|
||||
for (TachographEsperDrivingInterruptionIntervalEvent interval : drivingInterruptionVehicleChangeIntervals) {
|
||||
runtime.getEventService().sendEventMap(
|
||||
toDrivingInterruptionIntervalInputMap(interval),
|
||||
"TachographDrivingInterruptionVehicleChangeIntervalInputEvent"
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<TachographEsperDrivingInterruptionIntervalEvent> buildEsperDailyWeeklyRestCandidateIntervalEvents(
|
||||
List<TachographEsperDrivingInterruptionIntervalEvent> drivingInterruptionIntervals,
|
||||
int minimumRestPeriodMinutes
|
||||
) {
|
||||
if (drivingInterruptionIntervals == null || drivingInterruptionIntervals.isEmpty()) {
|
||||
return List.of();
|
||||
}
|
||||
List<TachographEsperDrivingInterruptionIntervalEvent> result = new ArrayList<>();
|
||||
executeWithRuntime(
|
||||
configuration -> configuration.getCommon().addEventType(
|
||||
"TachographDrivingInterruptionIntervalInputEvent",
|
||||
drivingInterruptionIntervalInputDefinition()
|
||||
),
|
||||
renderDailyWeeklyRestCandidateIntervalEventsEpl(minimumRestPeriodMinutes),
|
||||
"dailyWeeklyRestCandidateIntervals",
|
||||
newData -> collectDrivingInterruptionIntervalEventsFromTimestamps(newData, result),
|
||||
runtime -> {
|
||||
for (TachographEsperDrivingInterruptionIntervalEvent interval : drivingInterruptionIntervals) {
|
||||
runtime.getEventService().sendEventMap(
|
||||
toDrivingInterruptionIntervalInputMap(interval),
|
||||
|
|
@ -1002,10 +1031,10 @@ public class DriverTimelineBuilder {
|
|||
);
|
||||
}
|
||||
|
||||
private String renderPotentialHomeOvernightStayIntervalEventsEpl(int minimumRestPeriodMinutes) {
|
||||
private String renderDailyWeeklyRestCandidateIntervalEventsEpl(int minimumRestPeriodMinutes) {
|
||||
long thresholdSeconds = Math.max(1, minimumRestPeriodMinutes) * 60L;
|
||||
return POTENTIAL_HOME_OVERNIGHT_STAY_INTERVAL_EVENTS_EPL_TEMPLATE.replace(
|
||||
"${POTENTIAL_HOME_OVERNIGHT_STAY_THRESHOLD_SECONDS}",
|
||||
return DAILY_WEEKLY_REST_CANDIDATE_INTERVAL_EVENTS_EPL_TEMPLATE.replace(
|
||||
"${MINIMUM_REST_PERIOD_THRESHOLD_SECONDS}",
|
||||
Long.toString(thresholdSeconds)
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -174,11 +174,24 @@ public class TachographFileSessionProcessingService {
|
|||
requestedFrom,
|
||||
requestedTo
|
||||
);
|
||||
List<TachographEsperDrivingInterruptionIntervalEvent> rawDailyWeeklyRestCandidateIntervals =
|
||||
driverTimelineBuilder.buildEsperDailyWeeklyRestCandidateIntervalEvents(
|
||||
rawDrivingInterruptionIntervals,
|
||||
minimumRestPeriodMinutes
|
||||
);
|
||||
List<TachographEsperDrivingInterruptionIntervalEvent> dailyWeeklyRestCandidateIntervals =
|
||||
clipEsperDrivingInterruptionIntervalEvents(
|
||||
rawDailyWeeklyRestCandidateIntervals,
|
||||
requestedFrom,
|
||||
requestedTo
|
||||
);
|
||||
List<TachographEsperDrivingInterruptionIntervalEvent> rawDrivingInterruptionVehicleChangeIntervals =
|
||||
driverTimelineBuilder.buildEsperDrivingInterruptionVehicleChangeIntervalEvents(
|
||||
rawDailyWeeklyRestCandidateIntervals
|
||||
);
|
||||
List<TachographEsperDrivingInterruptionIntervalEvent> drivingInterruptionVehicleChangeIntervals =
|
||||
clipEsperDrivingInterruptionIntervalEvents(
|
||||
driverTimelineBuilder.buildEsperDrivingInterruptionVehicleChangeIntervalEvents(
|
||||
rawDrivingInterruptionIntervals
|
||||
),
|
||||
rawDrivingInterruptionVehicleChangeIntervals,
|
||||
requestedFrom,
|
||||
requestedTo
|
||||
);
|
||||
|
|
@ -187,9 +200,8 @@ public class TachographFileSessionProcessingService {
|
|||
List<TachographEsperPotentialHomeOvernightStayIntervalEvent> potentialHomeOvernightStayIntervals =
|
||||
clipEsperPotentialHomeOvernightStayIntervalEvents(
|
||||
driverTimelineBuilder.buildEsperPotentialHomeOvernightStayIntervalEvents(
|
||||
rawDrivingInterruptionIntervals,
|
||||
rawVuCardAbsentIntervals,
|
||||
minimumRestPeriodMinutes
|
||||
rawDrivingInterruptionVehicleChangeIntervals,
|
||||
rawVuCardAbsentIntervals
|
||||
),
|
||||
rawVuCardAbsentIntervals,
|
||||
requestedFrom,
|
||||
|
|
@ -218,6 +230,7 @@ public class TachographFileSessionProcessingService {
|
|||
drivingIntervals.size(),
|
||||
drivingInterruptionIntervals.size(),
|
||||
drivingInterruptionVehicleChangeIntervals.size(),
|
||||
dailyWeeklyRestCandidateIntervals.size(),
|
||||
potentialHomeOvernightStayIntervals.size(),
|
||||
vehicleUsageIntervals.size(),
|
||||
vuCardAbsentIntervals.size(),
|
||||
|
|
@ -225,6 +238,7 @@ public class TachographFileSessionProcessingService {
|
|||
drivingIntervals,
|
||||
drivingInterruptionIntervals,
|
||||
drivingInterruptionVehicleChangeIntervals,
|
||||
dailyWeeklyRestCandidateIntervals,
|
||||
potentialHomeOvernightStayIntervals,
|
||||
vehicleUsageIntervals,
|
||||
vuCardAbsentIntervals,
|
||||
|
|
@ -403,7 +417,12 @@ public class TachographFileSessionProcessingService {
|
|||
return null;
|
||||
}
|
||||
long durationSeconds = Duration.between(start, end).getSeconds();
|
||||
long unknownDurationSeconds = overlapSeconds(start, end, rawVuCardAbsentIntervals, interval.driverKey());
|
||||
long unknownDurationSeconds = overlapSeconds(
|
||||
start,
|
||||
end,
|
||||
rawVuCardAbsentIntervals,
|
||||
interval.driverKey()
|
||||
);
|
||||
double unknownCoveragePercent = durationSeconds == 0L
|
||||
? 0.0d
|
||||
: (unknownDurationSeconds * 100.0d) / durationSeconds;
|
||||
|
|
@ -993,8 +1012,9 @@ public class TachographFileSessionProcessingService {
|
|||
"This endpoint returns Esper-backed per-driver interval projections from the in-memory tachograph file-session model.",
|
||||
"Driving intervals are a filtered projection of activity intervals where activityType = DRIVE.",
|
||||
"Driving interruption intervals are gaps between consecutive driving intervals longer than the configured significant-driving threshold.",
|
||||
"Driving interruption vehicle-change intervals are DTI intervals where previousRegistrationKey differs from nextRegistrationKey.",
|
||||
"Potential home overnight stay intervals are DTI intervals longer than the configured minimum rest-period threshold where VU card-absent overlap covers at least 95% of the DTI.",
|
||||
"Driving interruption vehicle-change intervals are daily/weekly rest candidates where previousRegistrationKey differs from nextRegistrationKey.",
|
||||
"Daily/weekly rest candidate intervals are driving interruption intervals longer than the configured minimum rest-period threshold.",
|
||||
"Potential home overnight stay intervals are vehicle-change daily/weekly rest candidates where VU card-absent overlap covers at least 95% of the candidate interval.",
|
||||
"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.",
|
||||
"Vehicle-usage intervals clear clipped odometer endpoints because boundary odometer values cannot be recomputed safely from the source interval."
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
@name('dailyWeeklyRestCandidateIntervals')
|
||||
select *
|
||||
from TachographDrivingInterruptionIntervalInputEvent(durationSeconds > ${MINIMUM_REST_PERIOD_THRESHOLD_SECONDS});
|
||||
|
|
@ -1,65 +1,65 @@
|
|||
@name('potentialHomeOvernightStayIntervals')
|
||||
select
|
||||
d.sessionId as sessionId,
|
||||
d.driverKey as driverKey,
|
||||
d.startedAt as startedAt,
|
||||
d.endedAt as endedAt,
|
||||
d.durationSeconds as durationSeconds,
|
||||
c.sessionId as sessionId,
|
||||
c.driverKey as driverKey,
|
||||
c.startedAt as startedAt,
|
||||
c.endedAt as endedAt,
|
||||
c.durationSeconds as durationSeconds,
|
||||
sum(
|
||||
case
|
||||
when u.startedAtEpochSecond <= d.startedAtEpochSecond and u.endedAtEpochSecond >= d.endedAtEpochSecond
|
||||
then d.durationSeconds
|
||||
when u.startedAtEpochSecond <= d.startedAtEpochSecond
|
||||
then u.endedAtEpochSecond - d.startedAtEpochSecond
|
||||
when u.endedAtEpochSecond >= d.endedAtEpochSecond
|
||||
then d.endedAtEpochSecond - u.startedAtEpochSecond
|
||||
when u.startedAtEpochSecond <= c.startedAtEpochSecond and u.endedAtEpochSecond >= c.endedAtEpochSecond
|
||||
then c.durationSeconds
|
||||
when u.startedAtEpochSecond <= c.startedAtEpochSecond
|
||||
then u.endedAtEpochSecond - c.startedAtEpochSecond
|
||||
when u.endedAtEpochSecond >= c.endedAtEpochSecond
|
||||
then c.endedAtEpochSecond - u.startedAtEpochSecond
|
||||
else u.endedAtEpochSecond - u.startedAtEpochSecond
|
||||
end
|
||||
) as unknownDurationSeconds,
|
||||
(sum(
|
||||
case
|
||||
when u.startedAtEpochSecond <= d.startedAtEpochSecond and u.endedAtEpochSecond >= d.endedAtEpochSecond
|
||||
then d.durationSeconds
|
||||
when u.startedAtEpochSecond <= d.startedAtEpochSecond
|
||||
then u.endedAtEpochSecond - d.startedAtEpochSecond
|
||||
when u.endedAtEpochSecond >= d.endedAtEpochSecond
|
||||
then d.endedAtEpochSecond - u.startedAtEpochSecond
|
||||
when u.startedAtEpochSecond <= c.startedAtEpochSecond and u.endedAtEpochSecond >= c.endedAtEpochSecond
|
||||
then c.durationSeconds
|
||||
when u.startedAtEpochSecond <= c.startedAtEpochSecond
|
||||
then u.endedAtEpochSecond - c.startedAtEpochSecond
|
||||
when u.endedAtEpochSecond >= c.endedAtEpochSecond
|
||||
then c.endedAtEpochSecond - u.startedAtEpochSecond
|
||||
else u.endedAtEpochSecond - u.startedAtEpochSecond
|
||||
end
|
||||
) * 100.0d) / d.durationSeconds as unknownCoveragePercent,
|
||||
d.previousDrivingSourceIntervalId as previousDrivingSourceIntervalId,
|
||||
d.nextDrivingSourceIntervalId as nextDrivingSourceIntervalId,
|
||||
d.previousRegistrationKey as previousRegistrationKey,
|
||||
d.nextRegistrationKey as nextRegistrationKey,
|
||||
d.previousVehicleKey as previousVehicleKey,
|
||||
d.nextVehicleKey as nextVehicleKey
|
||||
from TachographDrivingInterruptionIntervalInputEvent(durationSeconds > ${POTENTIAL_HOME_OVERNIGHT_STAY_THRESHOLD_SECONDS}) as d unidirectional,
|
||||
) * 100.0d) / c.durationSeconds as unknownCoveragePercent,
|
||||
c.previousDrivingSourceIntervalId as previousDrivingSourceIntervalId,
|
||||
c.nextDrivingSourceIntervalId as nextDrivingSourceIntervalId,
|
||||
c.previousRegistrationKey as previousRegistrationKey,
|
||||
c.nextRegistrationKey as nextRegistrationKey,
|
||||
c.previousVehicleKey as previousVehicleKey,
|
||||
c.nextVehicleKey as nextVehicleKey
|
||||
from TachographDrivingInterruptionVehicleChangeIntervalInputEvent as c unidirectional,
|
||||
TachographVuCardAbsentIntervalInputEvent#keepall as u
|
||||
where u.driverKey = d.driverKey
|
||||
and u.startedAtEpochSecond < d.endedAtEpochSecond
|
||||
and u.endedAtEpochSecond > d.startedAtEpochSecond
|
||||
where u.driverKey = c.driverKey
|
||||
and u.startedAtEpochSecond < c.endedAtEpochSecond
|
||||
and u.endedAtEpochSecond > c.startedAtEpochSecond
|
||||
group by
|
||||
d.sessionId,
|
||||
d.driverKey,
|
||||
d.startedAt,
|
||||
d.endedAt,
|
||||
d.startedAtEpochSecond,
|
||||
d.endedAtEpochSecond,
|
||||
d.durationSeconds,
|
||||
d.previousDrivingSourceIntervalId,
|
||||
d.nextDrivingSourceIntervalId,
|
||||
d.previousRegistrationKey,
|
||||
d.nextRegistrationKey,
|
||||
d.previousVehicleKey,
|
||||
d.nextVehicleKey
|
||||
c.sessionId,
|
||||
c.driverKey,
|
||||
c.startedAt,
|
||||
c.endedAt,
|
||||
c.startedAtEpochSecond,
|
||||
c.endedAtEpochSecond,
|
||||
c.durationSeconds,
|
||||
c.previousDrivingSourceIntervalId,
|
||||
c.nextDrivingSourceIntervalId,
|
||||
c.previousRegistrationKey,
|
||||
c.nextRegistrationKey,
|
||||
c.previousVehicleKey,
|
||||
c.nextVehicleKey
|
||||
having sum(
|
||||
case
|
||||
when u.startedAtEpochSecond <= d.startedAtEpochSecond and u.endedAtEpochSecond >= d.endedAtEpochSecond
|
||||
then d.durationSeconds
|
||||
when u.startedAtEpochSecond <= d.startedAtEpochSecond
|
||||
then u.endedAtEpochSecond - d.startedAtEpochSecond
|
||||
when u.endedAtEpochSecond >= d.endedAtEpochSecond
|
||||
then d.endedAtEpochSecond - u.startedAtEpochSecond
|
||||
when u.startedAtEpochSecond <= c.startedAtEpochSecond and u.endedAtEpochSecond >= c.endedAtEpochSecond
|
||||
then c.durationSeconds
|
||||
when u.startedAtEpochSecond <= c.startedAtEpochSecond
|
||||
then u.endedAtEpochSecond - c.startedAtEpochSecond
|
||||
when u.endedAtEpochSecond >= c.endedAtEpochSecond
|
||||
then c.endedAtEpochSecond - u.startedAtEpochSecond
|
||||
else u.endedAtEpochSecond - u.startedAtEpochSecond
|
||||
end
|
||||
) * 100L >= d.durationSeconds * 95L;
|
||||
) * 100L >= c.durationSeconds * 95L;
|
||||
|
|
|
|||
|
|
@ -84,6 +84,7 @@ class TachographFileSessionControllerTest {
|
|||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
2,
|
||||
1,
|
||||
List.of(new TachographEsperActivityIntervalEvent(
|
||||
|
|
@ -150,6 +151,19 @@ class TachographFileSessionControllerTest {
|
|||
"VIN-1",
|
||||
"VIN-2"
|
||||
)),
|
||||
List.of(new TachographEsperDrivingInterruptionIntervalEvent(
|
||||
sessionId,
|
||||
"12:123",
|
||||
OffsetDateTime.parse("2026-05-12T10:00:00Z"),
|
||||
OffsetDateTime.parse("2026-05-12T22:00:00Z"),
|
||||
43_200L,
|
||||
"ACT-2",
|
||||
"ACT-3",
|
||||
"12:REG-1",
|
||||
"12:REG-2",
|
||||
"VIN-1",
|
||||
"VIN-2"
|
||||
)),
|
||||
List.of(new TachographEsperPotentialHomeOvernightStayIntervalEvent(
|
||||
sessionId,
|
||||
"12:123",
|
||||
|
|
@ -258,6 +272,7 @@ class TachographFileSessionControllerTest {
|
|||
.andExpect(jsonPath("$.activityIntervalCount").value(2))
|
||||
.andExpect(jsonPath("$.drivingInterruptionIntervalCount").value(1))
|
||||
.andExpect(jsonPath("$.drivingInterruptionVehicleChangeIntervalCount").value(1))
|
||||
.andExpect(jsonPath("$.dailyWeeklyRestCandidateIntervalCount").value(1))
|
||||
.andExpect(jsonPath("$.potentialHomeOvernightStayIntervalCount").value(1))
|
||||
.andExpect(jsonPath("$.vuCardAbsentIntervalCount").value(1))
|
||||
.andExpect(jsonPath("$.drivingInterruptionIntervals[0].previousRegistrationKey").value("12:REG-1"))
|
||||
|
|
|
|||
|
|
@ -378,6 +378,46 @@ class DriverTimelineBuilderTest {
|
|||
assertThat(absentIntervals.get(0).nextVehicleKey()).isEqualTo("VIN-2");
|
||||
}
|
||||
|
||||
@Test
|
||||
void buildsDailyWeeklyRestCandidateIntervalsFromDrivingInterruptionIntervals() {
|
||||
UUID sessionId = UUID.randomUUID();
|
||||
List<TachographEsperDrivingInterruptionIntervalEvent> drivingInterruptionIntervals = List.of(
|
||||
new TachographEsperDrivingInterruptionIntervalEvent(
|
||||
sessionId,
|
||||
"12:123",
|
||||
OffsetDateTime.parse("2026-05-01T10:00:00Z"),
|
||||
OffsetDateTime.parse("2026-05-01T20:00:00Z"),
|
||||
36_000L,
|
||||
"ACT-1",
|
||||
"ACT-2",
|
||||
"12:REG-1",
|
||||
"12:REG-1",
|
||||
"VIN-1",
|
||||
"VIN-1"
|
||||
),
|
||||
new TachographEsperDrivingInterruptionIntervalEvent(
|
||||
sessionId,
|
||||
"12:123",
|
||||
OffsetDateTime.parse("2026-05-02T10:00:00Z"),
|
||||
OffsetDateTime.parse("2026-05-02T18:00:00Z"),
|
||||
28_800L,
|
||||
"ACT-3",
|
||||
"ACT-4",
|
||||
"12:REG-1",
|
||||
"12:REG-1",
|
||||
"VIN-1",
|
||||
"VIN-1"
|
||||
)
|
||||
);
|
||||
|
||||
List<TachographEsperDrivingInterruptionIntervalEvent> candidates =
|
||||
builder.buildEsperDailyWeeklyRestCandidateIntervalEvents(drivingInterruptionIntervals, 540);
|
||||
|
||||
assertThat(candidates).hasSize(1);
|
||||
assertThat(candidates.get(0).startedAt()).isEqualTo(OffsetDateTime.parse("2026-05-01T10:00:00Z"));
|
||||
assertThat(candidates.get(0).endedAt()).isEqualTo(OffsetDateTime.parse("2026-05-01T20:00:00Z"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void buildsEsperDrivingInterruptionIntervalEventsFromSignificantDrivingGaps() {
|
||||
DriverExtractionSession driver = new DriverExtractionSession(
|
||||
|
|
@ -478,9 +518,9 @@ class DriverTimelineBuilderTest {
|
|||
"ACT-1",
|
||||
"ACT-2",
|
||||
"12:REG-1",
|
||||
"12:REG-1",
|
||||
"12:REG-2",
|
||||
"VIN-1",
|
||||
"VIN-1"
|
||||
"VIN-2"
|
||||
)
|
||||
);
|
||||
List<TachographEsperVuCardAbsentIntervalEvent> vuCardAbsentIntervals = List.of(
|
||||
|
|
@ -499,13 +539,17 @@ class DriverTimelineBuilderTest {
|
|||
)
|
||||
);
|
||||
|
||||
List<TachographEsperDrivingInterruptionIntervalEvent> dailyWeeklyRestCandidateIntervals =
|
||||
builder.buildEsperDailyWeeklyRestCandidateIntervalEvents(interruptions, 720);
|
||||
List<TachographEsperDrivingInterruptionIntervalEvent> drivingInterruptionVehicleChangeIntervals =
|
||||
builder.buildEsperDrivingInterruptionVehicleChangeIntervalEvents(dailyWeeklyRestCandidateIntervals);
|
||||
List<TachographEsperPotentialHomeOvernightStayIntervalEvent> intervals =
|
||||
builder.buildEsperPotentialHomeOvernightStayIntervalEvents(
|
||||
interruptions,
|
||||
vuCardAbsentIntervals,
|
||||
720
|
||||
drivingInterruptionVehicleChangeIntervals,
|
||||
vuCardAbsentIntervals
|
||||
);
|
||||
|
||||
assertThat(drivingInterruptionVehicleChangeIntervals).hasSize(1);
|
||||
assertThat(intervals).hasSize(1);
|
||||
assertThat(intervals.get(0).sessionId()).isEqualTo(sessionId);
|
||||
assertThat(intervals.get(0).driverKey()).isEqualTo("12:123");
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ class TachographFileSessionProcessingServiceTest {
|
|||
assertThat(result.drivingIntervalCount()).isEqualTo(1);
|
||||
assertThat(result.drivingInterruptionIntervalCount()).isEqualTo(0);
|
||||
assertThat(result.drivingInterruptionVehicleChangeIntervalCount()).isEqualTo(0);
|
||||
assertThat(result.dailyWeeklyRestCandidateIntervalCount()).isEqualTo(0);
|
||||
assertThat(result.potentialHomeOvernightStayIntervalCount()).isEqualTo(0);
|
||||
assertThat(result.vehicleUsageIntervalCount()).isEqualTo(2);
|
||||
assertThat(result.vuCardAbsentIntervalCount()).isEqualTo(1);
|
||||
|
|
@ -169,7 +170,8 @@ class TachographFileSessionProcessingServiceTest {
|
|||
assertThat(result.activityIntervals().get(0).clippedToRequestedPeriod()).isTrue();
|
||||
assertThat(result.drivingIntervalCount()).isEqualTo(2);
|
||||
assertThat(result.drivingInterruptionIntervalCount()).isEqualTo(1);
|
||||
assertThat(result.drivingInterruptionVehicleChangeIntervalCount()).isEqualTo(1);
|
||||
assertThat(result.drivingInterruptionVehicleChangeIntervalCount()).isEqualTo(0);
|
||||
assertThat(result.dailyWeeklyRestCandidateIntervalCount()).isEqualTo(0);
|
||||
assertThat(result.potentialHomeOvernightStayIntervalCount()).isEqualTo(0);
|
||||
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"));
|
||||
|
|
@ -177,11 +179,6 @@ class TachographFileSessionProcessingServiceTest {
|
|||
assertThat(result.drivingInterruptionIntervals().get(0).nextRegistrationKey()).isEqualTo("12:REG-2");
|
||||
assertThat(result.drivingInterruptionIntervals().get(0).previousVehicleKey()).isEqualTo("VIN-1");
|
||||
assertThat(result.drivingInterruptionIntervals().get(0).nextVehicleKey()).isEqualTo("VIN-2");
|
||||
assertThat(result.drivingInterruptionVehicleChangeIntervals().get(0).startedAt()).isEqualTo(OffsetDateTime.parse("2026-05-01T09:00:00Z"));
|
||||
assertThat(result.drivingInterruptionVehicleChangeIntervals().get(0).previousRegistrationKey()).isEqualTo("12:REG-1");
|
||||
assertThat(result.drivingInterruptionVehicleChangeIntervals().get(0).nextRegistrationKey()).isEqualTo("12:REG-2");
|
||||
assertThat(result.drivingInterruptionVehicleChangeIntervals().get(0).previousVehicleKey()).isEqualTo("VIN-1");
|
||||
assertThat(result.drivingInterruptionVehicleChangeIntervals().get(0).nextVehicleKey()).isEqualTo("VIN-2");
|
||||
assertThat(result.vehicleUsageIntervalCount()).isEqualTo(2);
|
||||
assertThat(result.vehicleUsageIntervals().get(0).startedAt()).isEqualTo(OffsetDateTime.parse("2026-05-01T08:45:00Z"));
|
||||
assertThat(result.vehicleUsageIntervals().get(0).odometerBeginKm()).isNull();
|
||||
|
|
@ -230,7 +227,7 @@ class TachographFileSessionProcessingServiceTest {
|
|||
),
|
||||
List.of(
|
||||
new ExtractedCardActivityInterval("ACT-1", OffsetDateTime.parse("2026-05-01T08:00:00Z"), OffsetDateTime.parse("2026-05-01T10:00:00Z"), "DRIVE", "DRIVER", "INSERTED", "SINGLE", "12:REG-1", "VIN-1", "a"),
|
||||
new ExtractedCardActivityInterval("ACT-2", OffsetDateTime.parse("2026-05-02T00:00:00Z"), OffsetDateTime.parse("2026-05-02T00:30:00Z"), "DRIVE", "DRIVER", "INSERTED", "SINGLE", "12:REG-1", "VIN-1", "b")
|
||||
new ExtractedCardActivityInterval("ACT-2", OffsetDateTime.parse("2026-05-02T00:00:00Z"), OffsetDateTime.parse("2026-05-02T00:30:00Z"), "DRIVE", "DRIVER", "INSERTED", "SINGLE", "12:REG-2", "VIN-2", "b")
|
||||
),
|
||||
List.of(),
|
||||
List.of()
|
||||
|
|
@ -257,6 +254,13 @@ class TachographFileSessionProcessingServiceTest {
|
|||
)
|
||||
);
|
||||
|
||||
assertThat(result.dailyWeeklyRestCandidateIntervalCount()).isEqualTo(1);
|
||||
assertThat(result.drivingInterruptionVehicleChangeIntervalCount()).isEqualTo(1);
|
||||
assertThat(result.dailyWeeklyRestCandidateIntervals().get(0).startedAt()).isEqualTo(OffsetDateTime.parse("2026-05-01T11:00:00Z"));
|
||||
assertThat(result.dailyWeeklyRestCandidateIntervals().get(0).endedAt()).isEqualTo(OffsetDateTime.parse("2026-05-01T23:00:00Z"));
|
||||
assertThat(result.drivingInterruptionVehicleChangeIntervals().get(0).startedAt()).isEqualTo(OffsetDateTime.parse("2026-05-01T11:00:00Z"));
|
||||
assertThat(result.drivingInterruptionVehicleChangeIntervals().get(0).previousRegistrationKey()).isEqualTo("12:REG-1");
|
||||
assertThat(result.drivingInterruptionVehicleChangeIntervals().get(0).nextRegistrationKey()).isEqualTo("12:REG-2");
|
||||
assertThat(result.potentialHomeOvernightStayIntervalCount()).isEqualTo(1);
|
||||
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"));
|
||||
|
|
|
|||
Loading…
Reference in New Issue