Skip to content
This repository was archived by the owner on May 5, 2021. It is now read-only.

Commit b349401

Browse files
Add basic event generator for devmode SORMAS-Foundation#4185
1 parent e8aa4b8 commit b349401

File tree

1 file changed

+262
-0
lines changed

1 file changed

+262
-0
lines changed

sormas-ui/src/main/java/de/symeda/sormas/ui/configuration/DevModeView.java

+262
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@
6464
import de.symeda.sormas.api.contact.ContactLogic;
6565
import de.symeda.sormas.api.contact.FollowUpStatus;
6666
import de.symeda.sormas.api.contact.QuarantineType;
67+
import de.symeda.sormas.api.event.EventDto;
68+
import de.symeda.sormas.api.event.EventParticipantDto;
69+
import de.symeda.sormas.api.event.EventStatus;
6770
import de.symeda.sormas.api.facility.FacilityCriteria;
6871
import de.symeda.sormas.api.facility.FacilityDto;
6972
import de.symeda.sormas.api.i18n.Captions;
@@ -103,6 +106,7 @@ public class DevModeView extends AbstractConfigurationView {
103106

104107
private Binder<CaseGenerationConfig> caseGeneratorConfigBinder = new Binder<>();
105108
private Binder<ContactGenerationConfig> contactGeneratorConfigBinder = new Binder<>();
109+
private Binder<EventGenerationConfig> eventGeneratorConfigBinder = new Binder<>();
106110

107111
private FieldVisibilityCheckers fieldVisibilityCheckers;
108112

@@ -120,6 +124,7 @@ public DevModeView() {
120124
new Label(VaadinIcons.INFO_CIRCLE.getHtml() + " " + I18nProperties.getString(Strings.infoDeveloperOptions), ContentMode.HTML));
121125
contentLayout.addComponent(createCaseGeneratorLayout());
122126
contentLayout.addComponent(createContactGeneratorLayout());
127+
contentLayout.addComponent(createEventsGeneratorLayout());
123128

124129
addComponent(contentLayout);
125130
}
@@ -288,6 +293,91 @@ private VerticalLayout createContactGeneratorLayout() {
288293
return contactGeneratorLayout;
289294
}
290295

296+
private VerticalLayout createEventsGeneratorLayout() {
297+
VerticalLayout eventGeneratorLayout = new VerticalLayout();
298+
eventGeneratorLayout.setMargin(false);
299+
eventGeneratorLayout.setSpacing(false);
300+
301+
Label heading = new Label("Event Generation");
302+
CssStyles.style(heading, CssStyles.H2);
303+
eventGeneratorLayout.addComponent(heading);
304+
305+
HorizontalLayout eventOptionsFirstLineLayout = new HorizontalLayout();
306+
307+
TextField eventCountField = new TextField();
308+
eventCountField.setCaption(I18nProperties.getCaption(Captions.devModeContactCount));
309+
eventGeneratorConfigBinder.forField(eventCountField)
310+
.withConverter(new StringToIntegerConverter("Must be a number"))
311+
.bind(EventGenerationConfig::getEventCount, EventGenerationConfig::setEventCount);
312+
eventOptionsFirstLineLayout.addComponent(eventCountField);
313+
314+
DateField startDateField = new DateField();
315+
startDateField.setCaption(I18nProperties.getCaption(Captions.devModeContactStartDate));
316+
startDateField.setDateFormat(DateFormatHelper.getDateFormatPattern());
317+
startDateField.setLenient(true);
318+
eventGeneratorConfigBinder.bind(startDateField, EventGenerationConfig::getStartDate, EventGenerationConfig::setStartDate);
319+
eventOptionsFirstLineLayout.addComponent(startDateField);
320+
321+
DateField endDateField = new DateField();
322+
endDateField.setCaption(I18nProperties.getCaption(Captions.devModeContactEndDate));
323+
endDateField.setDateFormat(DateFormatHelper.getDateFormatPattern());
324+
endDateField.setLenient(true);
325+
eventGeneratorConfigBinder.bind(endDateField, EventGenerationConfig::getEndDate, EventGenerationConfig::setEndDate);
326+
eventOptionsFirstLineLayout.addComponent(endDateField);
327+
328+
ComboBox<Disease> diseaseField = new ComboBox<>(null, FacadeProvider.getDiseaseConfigurationFacade().getAllDiseases(true, true, true));
329+
diseaseField.setCaption(I18nProperties.getCaption(Captions.devModeContactDisease));
330+
eventGeneratorConfigBinder.bind(diseaseField, EventGenerationConfig::getDisease, EventGenerationConfig::setDisease);
331+
eventOptionsFirstLineLayout.addComponent(diseaseField);
332+
333+
List<RegionReferenceDto> regions = FacadeProvider.getRegionFacade().getAllActiveAsReference();
334+
ComboBox<RegionReferenceDto> regionField = new ComboBox<RegionReferenceDto>(null, regions);
335+
regionField.setCaption(I18nProperties.getCaption(Captions.devModeContactRegion));
336+
eventGeneratorConfigBinder.bind(regionField, EventGenerationConfig::getRegion, EventGenerationConfig::setRegion);
337+
eventOptionsFirstLineLayout.addComponent(regionField);
338+
339+
ComboBox<DistrictReferenceDto> districtField = new ComboBox<DistrictReferenceDto>();
340+
districtField.setCaption(I18nProperties.getCaption(Captions.devModeContactDistrict));
341+
eventGeneratorConfigBinder.bind(districtField, EventGenerationConfig::getDistrict, EventGenerationConfig::setDistrict);
342+
eventOptionsFirstLineLayout.addComponent(districtField);
343+
344+
regionField.addValueChangeListener(event -> {
345+
RegionReferenceDto region = event.getValue();
346+
if (region != null) {
347+
districtField.setItems(FacadeProvider.getDistrictFacade().getAllActiveByRegion(region.getUuid()));
348+
} else {
349+
districtField.setItems(new ArrayList<DistrictReferenceDto>());
350+
}
351+
});
352+
353+
Button generateButton = ButtonHelper.createButton("Generate Events", e -> generateEvents(), CssStyles.FORCE_CAPTION);
354+
eventOptionsFirstLineLayout.addComponent(generateButton);
355+
356+
eventGeneratorLayout.addComponent(eventOptionsFirstLineLayout);
357+
358+
HorizontalLayout eventOptionsSecondLineLayout = new HorizontalLayout();
359+
360+
TextField minParticipantsPerEventField = new TextField();
361+
minParticipantsPerEventField.setCaption("Min participants per event");
362+
eventGeneratorConfigBinder.forField(minParticipantsPerEventField)
363+
.withConverter(new StringToIntegerConverter("Must be a number"))
364+
.bind(EventGenerationConfig::getMinParticipantsPerEvent, EventGenerationConfig::setMinParticipantsPerEvent);
365+
eventOptionsSecondLineLayout.addComponent(minParticipantsPerEventField);
366+
367+
TextField maxParticipantsPerEventField = new TextField();
368+
maxParticipantsPerEventField.setCaption("Max participants per event");
369+
eventGeneratorConfigBinder.forField(maxParticipantsPerEventField)
370+
.withConverter(new StringToIntegerConverter("Must be a number"))
371+
.bind(EventGenerationConfig::getMaxParticipantsPerEvent, EventGenerationConfig::setMaxParticipantsPerEvent);
372+
eventOptionsSecondLineLayout.addComponent(maxParticipantsPerEventField);
373+
374+
EventGenerationConfig config = new EventGenerationConfig();
375+
eventGeneratorLayout.addComponent(eventOptionsSecondLineLayout);
376+
eventGeneratorConfigBinder.setBean(config);
377+
378+
return eventGeneratorLayout;
379+
}
380+
291381
private final String[] maleFirstNames = new String[] {
292382
"Nelson",
293383
"Malik",
@@ -323,6 +413,14 @@ private VerticalLayout createContactGeneratorLayout() {
323413
"Tinibu",
324414
"Okar",
325415
"Egwu" };
416+
private final String[] eventTitles = new String[] {
417+
"Wedding",
418+
"Party",
419+
"Funeral",
420+
"Concert",
421+
"Fair",
422+
"Rallye",
423+
"Demonstration" };
326424

327425
private static Random random() {
328426
return ThreadLocalRandom.current();
@@ -332,6 +430,12 @@ private static boolean randomPercent(int p) {
332430
return random().nextInt(100) <= p;
333431
}
334432

433+
private static int randomInt(int min, int max) {
434+
if (max <= min)
435+
return min;
436+
return min + random().nextInt(max - min);
437+
}
438+
335439
private static <T> T random(List<T> list) {
336440
return list.get(random().nextInt(list.size()));
337441
}
@@ -632,6 +736,87 @@ private void generateContacts() {
632736
}
633737
}
634738

739+
private void generateEvents() {
740+
741+
EventGenerationConfig config = eventGeneratorConfigBinder.getBean();
742+
743+
int generatedParticipants = 0;
744+
745+
List<Disease> diseases = FacadeProvider.getDiseaseConfigurationFacade().getAllDiseases(true, true, true);
746+
float baseOffset = random().nextFloat();
747+
int daysBetween = (int) ChronoUnit.DAYS.between(config.startDate, config.endDate);
748+
749+
long dt = System.nanoTime();
750+
751+
for (int i = 0; i < config.getEventCount(); i++) {
752+
Disease disease = config.getDisease();
753+
if (disease == null) {
754+
disease = random(diseases);
755+
}
756+
757+
LocalDateTime referenceDateTime =
758+
getReferenceDateTime(i, config.getEventCount(), baseOffset, disease, config.getStartDate(), daysBetween);
759+
760+
fieldVisibilityCheckers = new FieldVisibilityCheckers().add(new DiseaseFieldVisibilityChecker(disease))
761+
.add(new CountryFieldVisibilityChecker(FacadeProvider.getConfigFacade().getCountryLocale()));
762+
763+
EventDto event = EventDto.build();
764+
765+
// disease
766+
event.setDisease(disease); // reset
767+
if (event.getDisease() == Disease.OTHER) {
768+
event.setDiseaseDetails("RD " + (random().nextInt(20) + 1));
769+
}
770+
771+
// title
772+
event.setEventTitle(random(eventTitles));
773+
774+
// report
775+
UserReferenceDto userReference = UserProvider.getCurrent().getUserReference();
776+
event.setReportingUser(userReference);
777+
event.setReportDateTime(Date.from(referenceDateTime.atZone(ZoneId.systemDefault()).toInstant()));
778+
779+
// region & district
780+
event.getEventLocation().setRegion(config.getRegion());
781+
event.getEventLocation().setDistrict(config.getDistrict());
782+
783+
// status
784+
event.setEventStatus(EventStatus.EVENT);
785+
786+
FacadeProvider.getEventFacade().saveEvent(event);
787+
788+
// EventParticipants
789+
int numParticipants = randomInt(config.getMinParticipantsPerEvent(), config.getMaxParticipantsPerEvent());
790+
for (int j = 0; j < numParticipants; j++) {
791+
EventParticipantDto eventParticipant = EventParticipantDto.build(event.toReference(), UserProvider.getCurrent().getUserReference());
792+
// person
793+
// instead of creating new persons everytime, it would be nice if some persons came of the original database
794+
// also, some participants should get cases and contacts created for them
795+
PersonDto person = PersonDto.build();
796+
fillEntity(person, referenceDateTime);
797+
person.setSymptomJournalStatus(null);
798+
setPersonName(person);
799+
FacadeProvider.getPersonFacade().savePerson(person);
800+
eventParticipant.setPerson(person);
801+
eventParticipant.setInvolvementDescription("Participant");
802+
803+
FacadeProvider.getEventParticipantFacade().saveEventParticipant(eventParticipant);
804+
generatedParticipants++;
805+
}
806+
}
807+
808+
dt = System.nanoTime() - dt;
809+
long perCase = dt / config.getEventCount();
810+
String msg = String.format(
811+
"Generating %,d events with a total of %,d participants took %,d ms (%,d ms per event)",
812+
config.getEventCount(),
813+
generatedParticipants,
814+
dt / 1_000_000,
815+
perCase / 1_000_000);
816+
logger.info(msg);
817+
Notification.show("", msg, Notification.Type.TRAY_NOTIFICATION);
818+
}
819+
635820
private LocalDateTime getReferenceDateTime(int i, int count, float baseOffset, Disease disease, LocalDate startDate, int daysBetween) {
636821

637822
float x = (float) i / count;
@@ -803,4 +988,81 @@ public void setCreateWithVisits(boolean createWithVisits) {
803988
this.createWithVisits = createWithVisits;
804989
}
805990
}
991+
992+
private static class EventGenerationConfig {
993+
994+
private int eventCount = 10;
995+
private LocalDate startDate = LocalDate.now().minusDays(90);
996+
private LocalDate endDate = LocalDate.now();
997+
private Disease disease = null;
998+
private RegionReferenceDto region = null;
999+
private DistrictReferenceDto district = null;
1000+
private int minParticipantsPerEvent = 3;
1001+
private int maxParticipantsPerEvent = 10;
1002+
1003+
public int getEventCount() {
1004+
return eventCount;
1005+
}
1006+
1007+
public void setEventCount(int contactCount) {
1008+
this.eventCount = contactCount;
1009+
}
1010+
1011+
public LocalDate getStartDate() {
1012+
return startDate;
1013+
}
1014+
1015+
public void setStartDate(LocalDate startDate) {
1016+
this.startDate = startDate;
1017+
}
1018+
1019+
public LocalDate getEndDate() {
1020+
return endDate;
1021+
}
1022+
1023+
public void setEndDate(LocalDate endDate) {
1024+
this.endDate = endDate;
1025+
}
1026+
1027+
public Disease getDisease() {
1028+
return disease;
1029+
}
1030+
1031+
public void setDisease(Disease disease) {
1032+
this.disease = disease;
1033+
}
1034+
1035+
public RegionReferenceDto getRegion() {
1036+
return region;
1037+
}
1038+
1039+
public void setRegion(RegionReferenceDto region) {
1040+
this.region = region;
1041+
}
1042+
1043+
public DistrictReferenceDto getDistrict() {
1044+
return district;
1045+
}
1046+
1047+
public void setDistrict(DistrictReferenceDto district) {
1048+
this.district = district;
1049+
}
1050+
1051+
public int getMinParticipantsPerEvent() {
1052+
return minParticipantsPerEvent;
1053+
}
1054+
1055+
public void setMinParticipantsPerEvent(int minParticipantsPerEvent) {
1056+
this.minParticipantsPerEvent = minParticipantsPerEvent;
1057+
}
1058+
1059+
public int getMaxParticipantsPerEvent() {
1060+
return maxParticipantsPerEvent;
1061+
}
1062+
1063+
public void setMaxParticipantsPerEvent(int maxParticipantsPerEvent) {
1064+
this.maxParticipantsPerEvent = maxParticipantsPerEvent;
1065+
}
1066+
1067+
}
8061068
}

0 commit comments

Comments
 (0)