6464import de .symeda .sormas .api .contact .ContactLogic ;
6565import de .symeda .sormas .api .contact .FollowUpStatus ;
6666import 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 ;
6770import de .symeda .sormas .api .facility .FacilityCriteria ;
6871import de .symeda .sormas .api .facility .FacilityDto ;
6972import 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