From d5d572c94326ea37054e297a529f5a56305bd6f5 Mon Sep 17 00:00:00 2001
From: markus
Date: Fri, 6 Nov 2020 12:36:53 +0100
Subject: [PATCH 01/12] add test_key_validation
---
cara/tests/apps/calculator/test_model_generator.py | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/cara/tests/apps/calculator/test_model_generator.py b/cara/tests/apps/calculator/test_model_generator.py
index 06a0dde2..3e2c9157 100644
--- a/cara/tests/apps/calculator/test_model_generator.py
+++ b/cara/tests/apps/calculator/test_model_generator.py
@@ -50,3 +50,9 @@ def test_present_intervals(baseline_form):
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))
assert baseline_form.present_interval().present_times == correct
+
+
+def test_key_validation(baseline_form_data):
+ baseline_form_data['activity_type'] = 'invalid key'
+ with pytest.raises(ValueError):
+ model_generator.FormData.from_dict(baseline_form_data)
\ No newline at end of file
From 11feee4050b20459736375a7aa022051bf9b457e Mon Sep 17 00:00:00 2001
From: markus
Date: Fri, 6 Nov 2020 12:57:21 +0100
Subject: [PATCH 02/12] create sets of valid values
---
cara/apps/calculator/model_generator.py | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/cara/apps/calculator/model_generator.py b/cara/apps/calculator/model_generator.py
index a945bd72..19ef97c2 100644
--- a/cara/apps/calculator/model_generator.py
+++ b/cara/apps/calculator/model_generator.py
@@ -254,6 +254,15 @@ def baseline_raw_form_data():
}
+ACTIVITY_TYPES = {'office', 'training', 'workshop'}
+EVENT_TYPES = {'single_event', 'recurrent_event'}
+MECHANICAL_VENTILATION_TYPES = {'air_changes', 'air_supply'}
+MASK_WEARING = {'continuous', 'removed'}
+VENTILATION_TYPES = {'natural', 'mechanical'}
+VOLUME_TYPES = {'room_volume', 'room_dimensions'}
+WINDOWS_OPEN = {'always', 'interval', 'breaks'}
+
+
def time_string_to_minutes(time: str) -> int:
"""
Converts time from string-format to an integer number of minutes after 00:00
From da95cedb4d7450dd00eac9381b2194281984755b Mon Sep 17 00:00:00 2001
From: markus
Date: Fri, 6 Nov 2020 13:50:15 +0100
Subject: [PATCH 03/12] change air_type to mechanical_ventilation_type
---
cara/apps/calculator/static/form.html | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/cara/apps/calculator/static/form.html b/cara/apps/calculator/static/form.html
index bd4c9df8..4d7b9917 100644
--- a/cara/apps/calculator/static/form.html
+++ b/cara/apps/calculator/static/form.html
@@ -41,9 +41,9 @@ Beta v1.0.0 Please send feedback to
-
+
Air supply flow rate
-
+
Air changes per hour
From 7dbb2cc632e9838f10a01870d693750ca95eae65 Mon Sep 17 00:00:00 2001
From: markus
Date: Fri, 6 Nov 2020 13:50:37 +0100
Subject: [PATCH 04/12] comment out breaks-option because of lacking model
capability
---
cara/apps/calculator/static/form.html | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/cara/apps/calculator/static/form.html b/cara/apps/calculator/static/form.html
index 4d7b9917..409b60f1 100644
--- a/cara/apps/calculator/static/form.html
+++ b/cara/apps/calculator/static/form.html
@@ -56,8 +56,8 @@ Beta v1.0.0 Please send feedback to
-
-
+
HEPA filtration:
From c4d474304a3fea2ee7879121d1ad50ab7a3e5078 Mon Sep 17 00:00:00 2001
From: markus
Date: Fri, 6 Nov 2020 13:51:03 +0100
Subject: [PATCH 05/12] add minutes_to_string
---
cara/apps/calculator/model_generator.py | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/cara/apps/calculator/model_generator.py b/cara/apps/calculator/model_generator.py
index 19ef97c2..4ba654ba 100644
--- a/cara/apps/calculator/model_generator.py
+++ b/cara/apps/calculator/model_generator.py
@@ -159,6 +159,14 @@ class FormData:
return models.SpecificInterval(tuple(present_intervals))
+ def minutes_to_string(self, minutes: int) -> str:
+ minute_string = str(minutes % 60)
+ minute_string = "0" * (2 - len(minute_string)) + minute_string
+ hour_string = str(minutes // 60)
+ hour_string = "0" * (2 - len(hour_string)) + hour_string
+
+ return f"{hour_string}:{minute_string}"
+
def model_from_form(form: FormData, tmp_raw_form_data) -> models.Model:
d = tmp_raw_form_data
From 0b6acecd47621b762a6b3bc0b638476745a33e25 Mon Sep 17 00:00:00 2001
From: markus
Date: Fri, 6 Nov 2020 13:51:34 +0100
Subject: [PATCH 06/12] use correct keys
---
cara/apps/calculator/templates/report.html.j2 | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/cara/apps/calculator/templates/report.html.j2 b/cara/apps/calculator/templates/report.html.j2
index b716814f..205bbdd9 100644
--- a/cara/apps/calculator/templates/report.html.j2
+++ b/cara/apps/calculator/templates/report.html.j2
@@ -24,7 +24,7 @@
Ventilation data:
Activity type:
- {% if activity_type == "office work" %}
+ {% if activity_type == "office" %}
Office work – typical scenario with all persons seated, talking.
{% elif activity_type == "workshop" %}
Workshop = assembly workshop environment, all persons doing light exercise, talking.
From 93207ff8e83636b61ee9931ecd0f3e1b40e50d02 Mon Sep 17 00:00:00 2001
From: markus
Date: Fri, 6 Nov 2020 13:52:04 +0100
Subject: [PATCH 07/12] use minutes_to_string in report
---
cara/apps/calculator/report_generator.py | 7 ++++---
cara/apps/calculator/templates/report.html.j2 | 6 +++---
2 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/cara/apps/calculator/report_generator.py b/cara/apps/calculator/report_generator.py
index a4fc0c36..1bc46b60 100644
--- a/cara/apps/calculator/report_generator.py
+++ b/cara/apps/calculator/report_generator.py
@@ -76,7 +76,8 @@ def build_report(model: models.Model, form: FormData):
context = {
'model': model,
- 'request': request,
+ 'request': request,
+ 'form': form,
'creation_date': time,
'model_version': 'Beta v1.0.0',
'simulation_name': form.simulation_name,
@@ -96,8 +97,8 @@ def build_report(model: models.Model, form: FormData):
'activity_type': form.activity_type,
'activity_start': form.activity_start,
'activity_finish': form.activity_finish,
- 'exposure_start': '00:00',
- 'exposure_finish': '01:15',
+ 'infected_start': 826,
+ 'infected_finish': 827,
'event_type': form.event_type,
'single_event_date': form.single_event_date,
'recurrent_event_month': form.recurrent_event_month,
diff --git a/cara/apps/calculator/templates/report.html.j2 b/cara/apps/calculator/templates/report.html.j2
index 205bbdd9..f44578d3 100644
--- a/cara/apps/calculator/templates/report.html.j2
+++ b/cara/apps/calculator/templates/report.html.j2
@@ -70,11 +70,11 @@
{% endif %}
Exposure time (presence of infected person):
{% if event_type == "single_event"%}
Single event on {{ single_event_date }}
@@ -91,7 +91,7 @@
{% if lunch_option%}
Yes
- - Start: {{ lunch_start }}    End: {{ lunch_finish }}
+ - Start: {{ form.minutes_to_string(lunch_start) }}    End: {{ form.minutes_to_string(lunch_finish) }}
{% else%}
No
From 76d74132ef8882e14f528758123f6a079ad77784 Mon Sep 17 00:00:00 2001
From: markus
Date: Fri, 6 Nov 2020 14:06:15 +0100
Subject: [PATCH 08/12] use correct windows_open value-name
---
cara/tests/apps/calculator/test_model_generator.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cara/tests/apps/calculator/test_model_generator.py b/cara/tests/apps/calculator/test_model_generator.py
index 3e2c9157..3e4e5126 100644
--- a/cara/tests/apps/calculator/test_model_generator.py
+++ b/cara/tests/apps/calculator/test_model_generator.py
@@ -29,7 +29,7 @@ def test_ventilation(baseline_form):
cd_b=0.6, window_height=1.6, opening_length=0.6,
)
baseline_form.ventilation_type = 'natural'
- baseline_form.windows_open = '10 min / 2h'
+ baseline_form.windows_open = 'interval'
baseline_form.event_type = 'recurrent_event'
baseline_form.recurrent_event_month = 'December'
baseline_form.window_height = 1.6
From a88ff3cf1f81a7a0fc774911c76d860ba906a2c0 Mon Sep 17 00:00:00 2001
From: markus
Date: Fri, 6 Nov 2020 14:17:34 +0100
Subject: [PATCH 09/12] resolve todo
---
cara/apps/calculator/model_generator.py | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/cara/apps/calculator/model_generator.py b/cara/apps/calculator/model_generator.py
index 4ba654ba..fddae399 100644
--- a/cara/apps/calculator/model_generator.py
+++ b/cara/apps/calculator/model_generator.py
@@ -189,8 +189,7 @@ def model_from_form(form: FormData, tmp_raw_form_data) -> models.Model:
# Initializes a mask of type 1 if mask wearing is "continuous", otherwise instantiates the mask attribute as
# the "No mask"-mask
- # TODO: figure out the possible values of mask_wearing in the form
- mask = models.Mask.types['Type I' if d['mask_wearing'] == "Continuous" else 'No mask']
+ mask = models.Mask.types['Type I' if d['mask_wearing'] == "continuous" else 'No mask']
# A dictionary containing the mapping of activities listed in the UI to the activity level and expiration level
# of the infected and exposed occupants respectively.
From 5e11292a6025f98dccc385faee0e353beecd1f45 Mon Sep 17 00:00:00 2001
From: markus
Date: Fri, 6 Nov 2020 14:18:00 +0100
Subject: [PATCH 10/12] validate keys
---
cara/apps/calculator/model_generator.py | 19 +++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)
diff --git a/cara/apps/calculator/model_generator.py b/cara/apps/calculator/model_generator.py
index fddae399..6901bc62 100644
--- a/cara/apps/calculator/model_generator.py
+++ b/cara/apps/calculator/model_generator.py
@@ -47,6 +47,17 @@ class FormData:
if value == "":
form_data[key] = "0"
+ validation_tuples = [('activity_type', ACTIVITY_TYPES),
+ ('event_type', EVENT_TYPES),
+ ('mechanical_ventilation_type', MECHANICAL_VENTILATION_TYPES),
+ ('mask_wearing', MASK_WEARING),
+ ('ventilation_type', VENTILATION_TYPES),
+ ('volume_type', VOLUME_TYPES),
+ ('windows_open', WINDOWS_OPEN)]
+ for key, valid_set in validation_tuples:
+ if form_data[key] not in valid_set:
+ raise ValueError(f"{form_data[key]} is not a valid value for {key}")
+
return cls(
activity_finish=time_string_to_minutes(form_data['activity_finish']),
activity_start=time_string_to_minutes(form_data['activity_start']),
@@ -87,11 +98,14 @@ class FormData:
def ventilation(self) -> models.Ventilation:
# Initializes a ventilation instance as a window if 'natural' is selected, or as a HEPA-filter otherwise
if self.ventilation_type == 'natural':
- if self.windows_open == '10 min / 2h':
+ if self.windows_open == 'interval':
period, duration = 120, 10
+ elif self.windows_number == 'breaks':
+ # TODO: Implement windows open in breaks
+ period, duration = 120, 120
else:
period, duration = 120, 120
- # I multiply the opening width by the number of windows to simulate the correct window area
+
if self.event_type == 'single_event':
month_number = int(self.single_event_date.split('/')[1])
month = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'][month_number - 1]
@@ -101,6 +115,7 @@ class FormData:
inside_temp = models.PiecewiseConstant((0, 24), (293,))
outside_temp = models.GenevaTemperatures[month]
+ # I multiply the opening width by the number of windows to simulate the correct window area
ventilation = models.WindowOpening(active=models.PeriodicInterval(period=period, duration=duration),
inside_temp=inside_temp, outside_temp=outside_temp, cd_b=0.6,
window_height=self.window_height,
From d7c64c875cab0fa54ed5e86a4cbe95e8b9a05745 Mon Sep 17 00:00:00 2001
From: markus
Date: Fri, 6 Nov 2020 14:42:15 +0100
Subject: [PATCH 11/12] move minutes_to_string into report_generator.py
---
cara/apps/calculator/model_generator.py | 8 --------
cara/apps/calculator/report_generator.py | 9 +++++++++
2 files changed, 9 insertions(+), 8 deletions(-)
diff --git a/cara/apps/calculator/model_generator.py b/cara/apps/calculator/model_generator.py
index 6901bc62..d71aae50 100644
--- a/cara/apps/calculator/model_generator.py
+++ b/cara/apps/calculator/model_generator.py
@@ -174,14 +174,6 @@ class FormData:
return models.SpecificInterval(tuple(present_intervals))
- def minutes_to_string(self, minutes: int) -> str:
- minute_string = str(minutes % 60)
- minute_string = "0" * (2 - len(minute_string)) + minute_string
- hour_string = str(minutes // 60)
- hour_string = "0" * (2 - len(hour_string)) + hour_string
-
- return f"{hour_string}:{minute_string}"
-
def model_from_form(form: FormData, tmp_raw_form_data) -> models.Model:
d = tmp_raw_form_data
diff --git a/cara/apps/calculator/report_generator.py b/cara/apps/calculator/report_generator.py
index 1bc46b60..1147897c 100644
--- a/cara/apps/calculator/report_generator.py
+++ b/cara/apps/calculator/report_generator.py
@@ -69,6 +69,15 @@ def plot(times, concentrations):
return fig
+def minutes_to_string(minutes: int) -> str:
+ minute_string = str(minutes % 60)
+ minute_string = "0" * (2 - len(minute_string)) + minute_string
+ hour_string = str(minutes // 60)
+ hour_string = "0" * (2 - len(hour_string)) + hour_string
+
+ return f"{hour_string}:{minute_string}"
+
+
def build_report(model: models.Model, form: FormData):
now = datetime.now()
time = now.strftime("%d/%m/%Y %H:%M:%S")
From a6a91471ba628f436a9dea486ed2616eed7d156f Mon Sep 17 00:00:00 2001
From: markus
Date: Fri, 6 Nov 2020 14:51:14 +0100
Subject: [PATCH 12/12] pre-process minutes
---
cara/apps/calculator/report_generator.py | 12 ++++++------
cara/apps/calculator/templates/report.html.j2 | 6 +++---
2 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/cara/apps/calculator/report_generator.py b/cara/apps/calculator/report_generator.py
index 1147897c..22f84977 100644
--- a/cara/apps/calculator/report_generator.py
+++ b/cara/apps/calculator/report_generator.py
@@ -104,16 +104,16 @@ def build_report(model: models.Model, form: FormData):
'total_people': form.total_people,
'infected_people': form.infected_people,
'activity_type': form.activity_type,
- 'activity_start': form.activity_start,
- 'activity_finish': form.activity_finish,
- 'infected_start': 826,
- 'infected_finish': 827,
+ '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),
'event_type': form.event_type,
'single_event_date': form.single_event_date,
'recurrent_event_month': form.recurrent_event_month,
'lunch_option': form.lunch_option,
- 'lunch_start': form.lunch_start,
- 'lunch_finish': form.lunch_finish,
+ 'lunch_start': minutes_to_string(form.lunch_start),
+ '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']],
diff --git a/cara/apps/calculator/templates/report.html.j2 b/cara/apps/calculator/templates/report.html.j2
index f44578d3..8c29bb1b 100644
--- a/cara/apps/calculator/templates/report.html.j2
+++ b/cara/apps/calculator/templates/report.html.j2
@@ -70,11 +70,11 @@
{% endif %}
Exposure time (presence of infected person):
{% if event_type == "single_event"%}
Single event on {{ single_event_date }}
@@ -91,7 +91,7 @@
{% if lunch_option%}
Yes
- - Start: {{ form.minutes_to_string(lunch_start) }}    End: {{ form.minutes_to_string(lunch_finish) }}
+ - Start: {{ lunch_start }}    End: {{ lunch_finish }}
{% else%}
No