64
64
import de .symeda .sormas .api .contact .ContactLogic ;
65
65
import de .symeda .sormas .api .contact .FollowUpStatus ;
66
66
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 ;
67
70
import de .symeda .sormas .api .facility .FacilityCriteria ;
68
71
import de .symeda .sormas .api .facility .FacilityDto ;
69
72
import de .symeda .sormas .api .i18n .Captions ;
@@ -103,6 +106,7 @@ public class DevModeView extends AbstractConfigurationView {
103
106
104
107
private Binder <CaseGenerationConfig > caseGeneratorConfigBinder = new Binder <>();
105
108
private Binder <ContactGenerationConfig > contactGeneratorConfigBinder = new Binder <>();
109
+ private Binder <EventGenerationConfig > eventGeneratorConfigBinder = new Binder <>();
106
110
107
111
private FieldVisibilityCheckers fieldVisibilityCheckers ;
108
112
@@ -120,6 +124,7 @@ public DevModeView() {
120
124
new Label (VaadinIcons .INFO_CIRCLE .getHtml () + " " + I18nProperties .getString (Strings .infoDeveloperOptions ), ContentMode .HTML ));
121
125
contentLayout .addComponent (createCaseGeneratorLayout ());
122
126
contentLayout .addComponent (createContactGeneratorLayout ());
127
+ contentLayout .addComponent (createEventsGeneratorLayout ());
123
128
124
129
addComponent (contentLayout );
125
130
}
@@ -288,6 +293,91 @@ private VerticalLayout createContactGeneratorLayout() {
288
293
return contactGeneratorLayout ;
289
294
}
290
295
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
+
291
381
private final String [] maleFirstNames = new String [] {
292
382
"Nelson" ,
293
383
"Malik" ,
@@ -323,6 +413,14 @@ private VerticalLayout createContactGeneratorLayout() {
323
413
"Tinibu" ,
324
414
"Okar" ,
325
415
"Egwu" };
416
+ private final String [] eventTitles = new String [] {
417
+ "Wedding" ,
418
+ "Party" ,
419
+ "Funeral" ,
420
+ "Concert" ,
421
+ "Fair" ,
422
+ "Rallye" ,
423
+ "Demonstration" };
326
424
327
425
private static Random random () {
328
426
return ThreadLocalRandom .current ();
@@ -332,6 +430,12 @@ private static boolean randomPercent(int p) {
332
430
return random ().nextInt (100 ) <= p ;
333
431
}
334
432
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
+
335
439
private static <T > T random (List <T > list ) {
336
440
return list .get (random ().nextInt (list .size ()));
337
441
}
@@ -632,6 +736,87 @@ private void generateContacts() {
632
736
}
633
737
}
634
738
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
+
635
820
private LocalDateTime getReferenceDateTime (int i , int count , float baseOffset , Disease disease , LocalDate startDate , int daysBetween ) {
636
821
637
822
float x = (float ) i / count ;
@@ -803,4 +988,81 @@ public void setCreateWithVisits(boolean createWithVisits) {
803
988
this .createWithVisits = createWithVisits ;
804
989
}
805
990
}
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
+ }
806
1068
}
0 commit comments