Commit a9cfb1d6 authored by Figue Orange's avatar Figue Orange
Browse files

remove merge with develop duplicates

parent 26828de8
package fr.gouv.clea.identification;
import fr.gouv.clea.config.BatchProperties;
import fr.gouv.clea.dto.ClusterPeriod;
import fr.gouv.clea.dto.SinglePlaceCluster;
import fr.gouv.clea.dto.SinglePlaceExposedVisits;
import fr.gouv.clea.entity.ExposedVisit;
import fr.gouv.clea.scoring.configuration.risk.RiskConfiguration;
import fr.gouv.clea.scoring.configuration.risk.RiskRule;
import fr.gouv.clea.utils.ExposedVisitComparator;
import org.springframework.batch.item.ItemProcessor;
public class SinglePlaceExposedVisitsProcessor implements ItemProcessor<SinglePlaceExposedVisits, SinglePlaceCluster> {
private final BatchProperties properties;
private final RiskConfiguration riskConfiguration;
public SinglePlaceExposedVisitsProcessor(BatchProperties properties, RiskConfiguration riskConfiguration) {
this.properties = properties;
this.riskConfiguration = riskConfiguration;
}
@Override
public SinglePlaceCluster process(SinglePlaceExposedVisits record) {
SinglePlaceCluster cluster = new SinglePlaceCluster();
cluster.setLocationTemporaryPublicId(record.getLocationTemporaryPublicId());
cluster.setVenueType(record.getVenueType());
cluster.setVenueCategory1(record.getVenueCategory1());
cluster.setVenueCategory2(record.getVenueCategory2());
ClusterPeriod backPeriod = null;
ClusterPeriod forwardPeriod = null;
final RiskRule riskRule = riskConfiguration.getConfigurationFor(cluster.getVenueType(), cluster.getVenueCategory1(), cluster.getVenueCategory2());
// Sorted visits by period then slot
record.getVisits().sort(new ExposedVisitComparator());
for (ExposedVisit visit : record.getVisits()) {
// Backward
backPeriod = processVisit(visit, cluster, backPeriod, visit.getBackwardVisits(),
riskRule.getClusterThresholdBackward(), riskRule.getRiskLevelBackward());
// Forward
forwardPeriod = processVisit(visit, cluster, forwardPeriod, visit.getForwardVisits(),
riskRule.getClusterThresholdForward(), riskRule.getRiskLevelForward());
}
// Finalize last periods after the loop
if (!noCurrentCluster(backPeriod)) {
cluster.addPeriod(backPeriod);
}
if (!noCurrentCluster(forwardPeriod)) {
cluster.addPeriod(forwardPeriod);
}
cluster.computeDurations(properties.getDurationUnitInSeconds());
return cluster.isEmpty() ? null : cluster;
}
protected ClusterPeriod processVisit(ExposedVisit visit, SinglePlaceCluster cluster,
ClusterPeriod period, long nbVisits, int threshold, float risk) {
if (isACluster(nbVisits, threshold)) {
// We detect that this visit is a cluster,
// 3 possible use-case:
// 1°) no current cluster, start one.
// 2°) existing cluster with same startPeriod : check previous slotIndex.
// 3°) existing cluster with different startPeriod => finalize the previous, create new one
if (noCurrentCluster(period)) {
period = initClusterPeriod(visit, risk);
} else if (period.isInSameCluster(visit)) {
period.adjustLimit(visit);
} else {
cluster.addPeriod(period);
// Init a new period because we know that the visit is in a cluster
period = initClusterPeriod(visit, risk);
}
} else if (!noCurrentCluster(period)) {
cluster.addPeriod(period);
period = null;
}
return period;
}
private ClusterPeriod initClusterPeriod(ExposedVisit v, float riskLevel) {
return ClusterPeriod.builder()
.periodStart(v.getPeriodStart())
.firstTimeSlot(v.getTimeSlot())
.lastTimeSlot(v.getTimeSlot())
.riskLevel(riskLevel)
.build();
}
private boolean noCurrentCluster(ClusterPeriod cluster) {
return null == cluster;
}
protected boolean isACluster(long nbExpositions, int threshold) {
return nbExpositions >= threshold;
}
}
package fr.gouv.clea.identification;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.when;
import java.util.UUID;
import org.assertj.core.data.Offset;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import fr.gouv.clea.config.BatchProperties;
import fr.gouv.clea.dto.ClusterPeriod;
import fr.gouv.clea.dto.SinglePlaceCluster;
import fr.gouv.clea.dto.SinglePlaceExposedVisits;
import fr.gouv.clea.entity.ExposedVisit;
import fr.gouv.clea.scoring.configuration.risk.RiskConfiguration;
import fr.gouv.clea.scoring.configuration.risk.RiskRule;
@ExtendWith(MockitoExtension.class)
class SinglePlaceExposedVisitsProcessorTest {
private BatchProperties properties = new BatchProperties();
@Mock
RiskConfiguration riskConfigurationMock;
public SinglePlaceExposedVisitsProcessorTest() {
properties.setDurationUnitInSeconds(180);
}
private final UUID UUID_SAMPLE = UUID.fromString("fa35fa88-2c44-4f13-9ec9-d38e77324c93");
private final long periodStart = 3822336080L;
@Test
void noClusterPeriod() {
when(riskConfigurationMock.getConfigurationFor(anyInt(), anyInt(), anyInt())).thenReturn(buildRiskRule());
SinglePlaceExposedVisits spe = new SinglePlaceExposedVisits();
spe.setLocationTemporaryPublicId(UUID_SAMPLE);
spe.setVenueType(18);
spe.setVenueCategory1(3);
spe.setVenueCategory2(2);
SinglePlaceCluster res = new SinglePlaceExposedVisitsProcessor(properties, riskConfigurationMock).process(spe);
assertThat(res).isNull();
}
@Test
void noClusterVisits() throws Exception {
when(riskConfigurationMock.getConfigurationFor(anyInt(), anyInt(), anyInt())).thenReturn(buildRiskRule());
SinglePlaceExposedVisits spe = new SinglePlaceExposedVisits();
spe.setLocationTemporaryPublicId(UUID_SAMPLE);
spe.setVenueType(18);
spe.setVenueCategory1(3);
spe.setVenueCategory2(2);
spe.addVisit(ExposedVisit.builder().periodStart(periodStart).timeSlot(0).forwardVisits(0).build());
spe.addVisit(ExposedVisit.builder().periodStart(periodStart).timeSlot(1).forwardVisits(0).build());
SinglePlaceCluster res = new SinglePlaceExposedVisitsProcessor(properties, riskConfigurationMock).process(spe);
assertThat(res).isNull();
}
@Test
void oneClusterPeriod() {
when(riskConfigurationMock.getConfigurationFor(anyInt(), anyInt(), anyInt())).thenReturn(buildRiskRule());
SinglePlaceExposedVisits spe = new SinglePlaceExposedVisits();
spe.setLocationTemporaryPublicId(UUID_SAMPLE);
spe.setVenueType(18);
spe.setVenueCategory1(3);
spe.setVenueCategory2(2);
spe.addVisit(ExposedVisit.builder().periodStart(periodStart).timeSlot(0).forwardVisits(0).build());
spe.addVisit(ExposedVisit.builder().periodStart(periodStart).timeSlot(1).forwardVisits(1).build());
spe.addVisit(ExposedVisit.builder().periodStart(periodStart).timeSlot(2).forwardVisits(1).build());
spe.addVisit(ExposedVisit.builder().periodStart(periodStart).timeSlot(3).forwardVisits(0).build());
spe.addVisit(ExposedVisit.builder().periodStart(periodStart).timeSlot(4).forwardVisits(0).build());
SinglePlaceCluster res = new SinglePlaceExposedVisitsProcessor(properties, riskConfigurationMock).process(spe);
assertThat(res).isNotNull();
assertThat(res.getPeriods()).hasSize(1);
ClusterPeriod p = res.getPeriods().get(0);
// cluster start at slot 1, not at slot 0
assertThat(p.getClusterStart()).as("clusterStart").isEqualTo(periodStart + properties.getDurationUnitInSeconds());
// Cluster for 2 slots
assertThat(p.getClusterDurationInSeconds()).as("clusterDuration").isEqualTo(2 * properties.getDurationUnitInSeconds());
}
@Test
void manyClusterPeriodSlots() {
when(riskConfigurationMock.getConfigurationFor(anyInt(), anyInt(), anyInt())).thenReturn(buildRiskRule());
long anotherPeriodStart = 3822422480L;
SinglePlaceExposedVisits spe = new SinglePlaceExposedVisits();
spe.setLocationTemporaryPublicId(UUID_SAMPLE);
spe.setVenueType(18);
spe.setVenueCategory1(3);
spe.setVenueCategory2(2);
spe.addVisit(ExposedVisit.builder().periodStart(periodStart).timeSlot(0).forwardVisits(0).build());
spe.addVisit(ExposedVisit.builder().periodStart(periodStart).timeSlot(1).forwardVisits(1).build());
spe.addVisit(ExposedVisit.builder().periodStart(periodStart).timeSlot(2).forwardVisits(0).build());
spe.addVisit(ExposedVisit.builder().periodStart(anotherPeriodStart).timeSlot(0).forwardVisits(1).build());
SinglePlaceCluster res = new SinglePlaceExposedVisitsProcessor(properties, riskConfigurationMock).process(spe);
assertThat(res).isNotNull();
assertThat(res.getPeriods()).hasSize(2);
ClusterPeriod p = res.getPeriods().get(0);
// cluster start at slot 1, not at slot 0
assertThat(p.getClusterStart()).as("clusterStart").isEqualTo(this.periodStart + properties.getDurationUnitInSeconds());
assertThat(p.getClusterDurationInSeconds()).as("clusterDuration").isEqualTo(1 * properties.getDurationUnitInSeconds());
p = res.getPeriods().get(1);
// cluster start at slot 0, not at slot 1
assertThat(p.getClusterStart()).as("clusterStart").isEqualTo(anotherPeriodStart);
assertThat(p.getClusterDurationInSeconds()).as("clusterDuration").isEqualTo(1* properties.getDurationUnitInSeconds());
}
@Test
void forwardRiskLevel() {
when(riskConfigurationMock.getConfigurationFor(anyInt(), anyInt(), anyInt())).thenReturn(buildRiskRule());
SinglePlaceExposedVisits spe = new SinglePlaceExposedVisits();
spe.setLocationTemporaryPublicId(UUID_SAMPLE);
spe.setVenueType(18);
spe.setVenueCategory1(3);
spe.setVenueCategory2(2);
spe.addVisit(ExposedVisit.builder().periodStart(periodStart).timeSlot(0).forwardVisits(100).build());
SinglePlaceCluster res = new SinglePlaceExposedVisitsProcessor(properties, riskConfigurationMock).process(spe);
assertThat(res).isNotNull();
assertThat(res.getPeriods()).hasSize(1);
ClusterPeriod p = res.getPeriods().get(0);
RiskRule evaluatedRiskLevel = riskConfigurationMock.getConfigurationFor(spe.getVenueType(), spe.getVenueCategory1(), spe.getVenueCategory2());
assertThat(p.getRiskLevel()).as("riskLevel").isCloseTo(evaluatedRiskLevel.getRiskLevelForward(), Offset.offset(0.01f));
}
@Test
void backwardRiskLevel() {
when(riskConfigurationMock.getConfigurationFor(anyInt(), anyInt(), anyInt())).thenReturn(buildRiskRule());
SinglePlaceExposedVisits spe = new SinglePlaceExposedVisits();
spe.setLocationTemporaryPublicId(UUID_SAMPLE);
spe.setVenueType(18);
spe.setVenueCategory1(3);
spe.setVenueCategory2(2);
spe.addVisit(ExposedVisit.builder().periodStart(periodStart).timeSlot(0).backwardVisits(100).build());
SinglePlaceCluster res = new SinglePlaceExposedVisitsProcessor(properties, riskConfigurationMock).process(spe);
assertThat(res).isNotNull();
assertThat(res.getPeriods()).hasSize(1);
ClusterPeriod p = res.getPeriods().get(0);
RiskRule evaluatedRiskLevel = riskConfigurationMock.getConfigurationFor(spe.getVenueType(), spe.getVenueCategory1(), spe.getVenueCategory2());
assertThat(p.getRiskLevel()).as("riskLevel").isCloseTo(evaluatedRiskLevel.getRiskLevelBackward(), Offset.offset(0.01f));
}
private RiskRule buildRiskRule() {
return RiskRule.builder()
.clusterThresholdForward(1)
.clusterThresholdBackward(3)
.riskLevelForward(3.0f)
.riskLevelBackward(2.0f)
.build();
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment