diff --git a/cara/apps/calculator/model_generator.py b/cara/apps/calculator/model_generator.py index 5b202406..41e6b2b6 100644 --- a/cara/apps/calculator/model_generator.py +++ b/cara/apps/calculator/model_generator.py @@ -12,6 +12,8 @@ class FormData: activity_finish: int lunch_start: int lunch_finish: int + infected_start: int + infected_finish: int activity_type: str air_changes: float @@ -92,7 +94,9 @@ class FormData: window_height=float(form_data['window_height']), window_width=float(form_data['window_width']), windows_number=int(form_data['windows_number']), - windows_open=form_data['windows_open'] + windows_open=form_data['windows_open'], + infected_start=time_string_to_minutes(form_data['infected_start']), + infected_finish=time_string_to_minutes(form_data['infected_finish']), ) # TODO: Remove the tmp_raw_form_data usage. @@ -139,13 +143,22 @@ class FormData: else: return ventilation - def present_interval(self) -> models.Interval: + def coffee_break_times(self) -> typing.Tuple[typing.Tuple[int, int]]: coffee_period = (self.activity_finish - self.activity_start) // self.coffee_breaks + coffee_times = [] + for minute in range(self.activity_start, self.activity_finish, coffee_period): + start = minute + coffee_period // 2 + end = start + self.coffee_duration + coffee_times.append((start, end)) + return tuple(coffee_times) + + def present_interval(self) -> models.Interval: leave_times = [self.lunch_start] enter_times = [self.lunch_finish] - for minute in range(self.activity_start, self.activity_finish, coffee_period): - leave_times.append(minute + coffee_period // 2) - enter_times.append(minute + coffee_period // 2 + self.coffee_duration) + + for coffee_start, coffee_end in self.coffee_break_times(): + leave_times.append(coffee_start) + enter_times.append(coffee_end) # These lists represent the times where the infected person leaves or enters the room, respectively, sorted in # reverse order. Note that these lists allows the person to "leave" when they should not even be present in the @@ -156,20 +169,20 @@ class FormData: # This loop iterates through the lists above, populating present_intervals with (enter, leave) intervals # representing the infected person entering and leaving the room. Note that if one of the evenly spaced coffee- # breaks happens to coincide with the lunch-break, it is simply ignored. - is_present = True present_intervals = [] - time = self.activity_start - while time < self.activity_finish: + time = self.infected_start + is_present = True + while time < self.infected_finish: if is_present: if not leave_times: - present_intervals.append((time / 60, self.activity_finish / 60)) + present_intervals.append((time / 60, self.infected_finish / 60)) break - if leave_times[-1] < time: + if leave_times[-1] <= time: leave_times.pop() else: new_time = leave_times.pop() - present_intervals.append((time / 60, min(new_time, self.activity_finish) / 60)) + present_intervals.append((time / 60, min(new_time, self.infected_finish) / 60)) is_present = False time = new_time @@ -252,12 +265,14 @@ def baseline_raw_form_data(): 'air_changes': '', 'air_supply': '', 'ceiling_height': '', - 'coffee_breaks': '5', + 'coffee_breaks': '2', 'coffee_duration': '10', 'coffee_option': '1', 'event_type': 'single_event', 'floor_area': '', 'hepa_option': '0', + 'infected_finish': '15:00', + 'infected_start': '10:00', 'infected_people': '1', 'lunch_finish': '13:30', 'lunch_option': '1', diff --git a/cara/apps/calculator/report_generator.py b/cara/apps/calculator/report_generator.py index 22f84977..7c230296 100644 --- a/cara/apps/calculator/report_generator.py +++ b/cara/apps/calculator/report_generator.py @@ -106,8 +106,8 @@ def build_report(model: models.Model, form: FormData): 'activity_type': form.activity_type, 'activity_start': minutes_to_string(form.activity_start), 'activity_finish': minutes_to_string(form.activity_finish), - 'infected_start': minutes_to_string(826), - 'infected_finish': minutes_to_string(827), + 'infected_start': minutes_to_string(form.infected_start), + 'infected_finish': minutes_to_string(form.infected_finish), 'event_type': form.event_type, 'single_event_date': form.single_event_date, 'recurrent_event_month': form.recurrent_event_month, @@ -116,7 +116,7 @@ def build_report(model: models.Model, form: FormData): 'lunch_finish': minutes_to_string(form.lunch_finish), 'coffee_breaks': form.coffee_breaks, 'coffee_duration': form.coffee_duration, - 'coffee_times': [['00:00','00:00'], ['00:00','00:00'], ['00:00','00:00'], ['00:00','00:00']], + 'coffee_times': [[minutes_to_string(start), minutes_to_string(finish)] for start, finish in form.coffee_break_times()], 'mask_wearing': form.mask_wearing, } diff --git a/cara/tests/apps/calculator/test_model_generator.py b/cara/tests/apps/calculator/test_model_generator.py index 56ca44ed..f6eb739c 100644 --- a/cara/tests/apps/calculator/test_model_generator.py +++ b/cara/tests/apps/calculator/test_model_generator.py @@ -92,7 +92,7 @@ def test_ventilation_window_hepa(baseline_form): baseline_form.opening_distance = 0.6 baseline_form.hepa_option = True - ts = np.linspace(8, 16, 100) + ts = np.linspace(9, 17, 100) np.testing.assert_allclose([ventilation.air_exchange(room, t) for t in ts], [baseline_form.ventilation().air_exchange(room, t) for t in ts]) @@ -100,12 +100,14 @@ def test_ventilation_window_hepa(baseline_form): def test_present_intervals(baseline_form): baseline_form.coffee_duration = 15 baseline_form.coffee_option = True - baseline_form.coffee_breaks = 4 + baseline_form.coffee_breaks = 2 baseline_form.activity_start = 9 * 60 baseline_form.activity_finish = 17 * 60 baseline_form.lunch_start = 12 * 60 + 30 baseline_form.lunch_finish = 13 * 60 + 30 - correct = ((9, 10), (10.25, 12), (12.25, 12.5), (13.5, 14), (14.25, 16), (16.25, 17)) + baseline_form.infected_start = 10 * 60 + baseline_form.infected_finish = 15 * 60 + correct = ((10, 11), (11.25, 12.5), (13.5, 15.0)) assert baseline_form.present_interval().present_times == correct