Merge branch 'key-validation' into 'master'
Key validation See merge request cara/cara!38
This commit is contained in:
commit
c308387341
5 changed files with 59 additions and 20 deletions
|
|
@ -48,6 +48,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']),
|
||||
|
|
@ -89,11 +100,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]
|
||||
|
|
@ -103,6 +117,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,
|
||||
|
|
@ -190,8 +205,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.
|
||||
|
|
@ -264,6 +278,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
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
@ -76,7 +85,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,
|
||||
|
|
@ -94,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,
|
||||
'exposure_start': '00:00',
|
||||
'exposure_finish': '01:15',
|
||||
'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']],
|
||||
|
|
|
|||
|
|
@ -41,9 +41,9 @@ Beta v1.0.0 <span style="float:right; font-weight:bold">Please send feedback to
|
|||
<input type="hidden" id="no_ventilation" name="ventilation_type" value="" />
|
||||
|
||||
<div id="DIVmechanical_ventilation" style="display:none">
|
||||
<input type="radio" id="air_type_supply" name="air_type" value="air_supply" onclick="require_fields(this)">
|
||||
<input type="radio" id="air_type_supply" name="mechanical_ventilation_type" value="air_supply" onclick="require_fields(this)">
|
||||
Air supply flow rate <input type="number" step=0.01 id="air_supply" name="air_supply" min="0" placeholder="(m³)"><br>
|
||||
<input type="radio" id="air_type_changes" name="air_type" value="air_changes" onclick="require_fields(this)">
|
||||
<input type="radio" id="air_type_changes" name="mechanical_ventilation_type" value="air_changes" onclick="require_fields(this)">
|
||||
Air changes per hour <input type="number" step=0.01 id="air_changes" name="air_changes" min="0"><br>
|
||||
</div>
|
||||
|
||||
|
|
@ -56,8 +56,8 @@ Beta v1.0.0 <span style="float:right; font-weight:bold">Please send feedback to
|
|||
<label for="always">Always</label>
|
||||
<input type="radio" id="interval" name="windows_open" value="interval">
|
||||
<label for="interval">10 min / 2h</label>
|
||||
<input type="radio" id="breaks" name="windows_open" value="breaks">
|
||||
<label for="breaks">Breaks</label><br>
|
||||
<!--input type="radio" id="breaks" name="windows_open" value="breaks">
|
||||
<label for="breaks">Breaks</label--><br>
|
||||
</div>
|
||||
|
||||
HEPA filtration:
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
<p class="data_title">Ventilation data:</p>
|
||||
<ul>
|
||||
<li><p class="data_text">Mechanical ventilation:
|
||||
{% if ventilation_type == "mechanical_ventilation"%}
|
||||
{% if ventilation_type == "mechanical"%}
|
||||
Yes </p></li>
|
||||
<ul>
|
||||
<li><p class="data_subtext">Air supply flow rate: {{ air_supply }}</p></li>
|
||||
|
|
@ -34,7 +34,7 @@
|
|||
No </li>
|
||||
{% endif %}
|
||||
<li><p class="data_text">Natural ventilation:
|
||||
{% if ventilation_type == "natural_ventilation"%}
|
||||
{% if ventilation_type == "natural"%}
|
||||
Yes </p></li>
|
||||
<ul>
|
||||
<li><p class="data_subtext">Number of windows: {{ windows_number }}</p></li>
|
||||
|
|
@ -61,7 +61,7 @@
|
|||
{% endif %}
|
||||
infected.</p></li>
|
||||
<li><p class="data_text">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.
|
||||
|
|
@ -74,7 +74,7 @@
|
|||
</ul>
|
||||
<li><p class="data_text">Exposure time (presence of infected person):</p></li>
|
||||
<ul>
|
||||
<li><p class="data_subtext">Start time: {{ exposure_start }}    End time: {{ exposure_finish }}</p></li>
|
||||
<li><p class="data_subtext">Start time: {{ infected_start }}    End time: {{ infected_finish }}</p></li>
|
||||
</ul>
|
||||
{% if event_type == "single_event"%}
|
||||
<li><p class="data_text">Single event on {{ single_event_date }}</p></li>
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ def test_ventilation_window(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
|
||||
|
|
@ -107,3 +107,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)
|
||||
Loading…
Reference in a new issue