Merge branch 'master' of https://gitlab.cern.ch/cara/cara into develop/expert_app_ventilation_temp
This commit is contained in:
commit
775339cdad
6 changed files with 78 additions and 28 deletions
|
|
@ -24,11 +24,14 @@ class FormData:
|
|||
coffee_duration: int
|
||||
event_type: str
|
||||
floor_area: float
|
||||
hepa_amount: float
|
||||
hepa_option: bool
|
||||
infected_people: int
|
||||
lunch_option: bool
|
||||
mask_type: str
|
||||
mask_wearing: str
|
||||
mechanical_ventilation_type: str
|
||||
model_version: str
|
||||
opening_distance: float
|
||||
recurrent_event_month: str
|
||||
room_number: str
|
||||
|
|
@ -58,6 +61,7 @@ class FormData:
|
|||
validation_tuples = [('activity_type', ACTIVITY_TYPES),
|
||||
('event_type', EVENT_TYPES),
|
||||
('mechanical_ventilation_type', MECHANICAL_VENTILATION_TYPES),
|
||||
('mask_type', MASK_TYPES),
|
||||
('mask_wearing', MASK_WEARING),
|
||||
('ventilation_type', VENTILATION_TYPES),
|
||||
('volume_type', VOLUME_TYPES),
|
||||
|
|
@ -89,13 +93,16 @@ class FormData:
|
|||
coffee_duration=int(form_data['coffee_duration']),
|
||||
event_type=form_data['event_type'],
|
||||
floor_area=float(form_data['floor_area']),
|
||||
hepa_amount=float(form_data['hepa_amount']),
|
||||
hepa_option=(form_data['hepa_option'] == '1'),
|
||||
infected_people=int(form_data['infected_people']),
|
||||
lunch_finish=time_string_to_minutes(form_data['lunch_finish']),
|
||||
lunch_option=(form_data['lunch_option'] == '1'),
|
||||
lunch_start=time_string_to_minutes(form_data['lunch_start']),
|
||||
mask_type=form_data['mask_type'],
|
||||
mask_wearing=form_data['mask_wearing'],
|
||||
mechanical_ventilation_type=form_data['mechanical_ventilation_type'],
|
||||
model_version=form_data['model_version'],
|
||||
opening_distance=float(form_data['opening_distance']),
|
||||
recurrent_event_month=form_data['recurrent_event_month'],
|
||||
room_number=form_data['room_number'],
|
||||
|
|
@ -151,7 +158,7 @@ class FormData:
|
|||
active=always_on, q_air_mech=self.air_supply)
|
||||
|
||||
if self.hepa_option:
|
||||
hepa = models.HEPAFilter(active=always_on, q_air_mech=250.)
|
||||
hepa = models.HEPAFilter(active=always_on, q_air_mech=self.hepa_amount)
|
||||
return models.MultipleVentilation((ventilation,hepa))
|
||||
else:
|
||||
return ventilation
|
||||
|
|
@ -228,9 +235,9 @@ def model_from_form(form: FormData) -> models.Model:
|
|||
# Initializes the virus as SARS_Cov_2
|
||||
virus = models.Virus.types['SARS_CoV_2']
|
||||
|
||||
# Initializes a mask of type 1 if mask wearing is "continuous", otherwise instantiates the mask attribute as
|
||||
# Initializes the mask type if mask wearing is "continuous", otherwise instantiates the mask attribute as
|
||||
# the "No mask"-mask
|
||||
mask = models.Mask.types['Type I' if form.mask_wearing == "continuous" else 'No mask']
|
||||
mask = models.Mask.types[form.mask_type if form.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.
|
||||
|
|
@ -279,6 +286,7 @@ def baseline_raw_form_data():
|
|||
'coffee_duration': '10',
|
||||
'event_type': 'recurrent_event',
|
||||
'floor_area': '',
|
||||
'hepa_amount': '250',
|
||||
'hepa_option': '0',
|
||||
'infected_finish': '18:00',
|
||||
'infected_people': '1',
|
||||
|
|
@ -286,8 +294,10 @@ def baseline_raw_form_data():
|
|||
'lunch_finish': '13:30',
|
||||
'lunch_option': '1',
|
||||
'lunch_start': '12:30',
|
||||
'mask_type': 'Type I',
|
||||
'mask_wearing': 'removed',
|
||||
'mechanical_ventilation_type': '',
|
||||
'model_version': 'BetaV1.1.0',
|
||||
'opening_distance': '0.2',
|
||||
'recurrent_event_month': 'January',
|
||||
'room_number': '123',
|
||||
|
|
@ -307,6 +317,7 @@ def baseline_raw_form_data():
|
|||
ACTIVITY_TYPES = {'office', 'training', 'workshop'}
|
||||
EVENT_TYPES = {'single_event', 'recurrent_event'}
|
||||
MECHANICAL_VENTILATION_TYPES = {'air_changes', 'air_supply', 'not-applicable'}
|
||||
MASK_TYPES = {'Type I', 'FFP2'}
|
||||
MASK_WEARING = {'continuous', 'removed'}
|
||||
VENTILATION_TYPES = {'natural', 'mechanical', 'no-ventilation'}
|
||||
VOLUME_TYPES = {'room_volume', 'room_dimensions'}
|
||||
|
|
|
|||
|
|
@ -87,8 +87,7 @@ def build_report(model: models.Model, form: FormData):
|
|||
'model': model,
|
||||
'request': request,
|
||||
'form': form,
|
||||
'creation_date': time,
|
||||
'model_version': 'Beta v1.0.0',
|
||||
'creation_date': time,
|
||||
}
|
||||
|
||||
context.update(calculate_report_data(model))
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ function on_ventilation_type_change() {
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
function getChildElement(elem) {
|
||||
// Get the element named in the given element's data-enables attribute.
|
||||
return $("#" + elem.data("enables"));
|
||||
|
|
@ -63,6 +62,18 @@ function require_fields(obj) {
|
|||
case "lunch_option_yes":
|
||||
require_lunch(true);
|
||||
break;
|
||||
case "mask_on":
|
||||
require_mask(true);
|
||||
break;
|
||||
case "mask_off":
|
||||
require_mask(false);
|
||||
break;
|
||||
case "hepa_yes":
|
||||
require_hepa(true);
|
||||
break;
|
||||
case "hepa_no":
|
||||
require_hepa(false);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -122,9 +133,18 @@ function require_recurrent_event(option) {
|
|||
|
||||
function require_lunch(option) {
|
||||
$("#lunch_start").prop('required', option);
|
||||
$("#mask_ffp2").prop('required', option);
|
||||
}
|
||||
|
||||
function require_lunch(option) {
|
||||
$("#mask_type1").prop('required', option);
|
||||
$("#lunch_finish").prop('required', option);
|
||||
}
|
||||
|
||||
function require_hepa(option) {
|
||||
$("#hepa_amount").prop('required', option);
|
||||
}
|
||||
|
||||
function setMaxInfectedPeople() {
|
||||
$("#infected_people").attr("max", $("#total_people").val());
|
||||
}
|
||||
|
|
@ -136,7 +156,6 @@ $(function () {
|
|||
});
|
||||
});
|
||||
|
||||
|
||||
function show_disclaimer() {
|
||||
var dots = document.getElementById("dots");
|
||||
var moreText = document.getElementById("more");
|
||||
|
|
@ -203,8 +222,7 @@ function parseValToNumber(obj) {
|
|||
return parseInt(obj.val().replace(':',''), 10);
|
||||
}
|
||||
|
||||
/* ------ On Load ---------- */
|
||||
|
||||
/* -------On Load------- */
|
||||
$(document).ready(function () {
|
||||
// When the document is ready, deal with the fact that we may be here
|
||||
// as a result of a forward/back browser action. If that is the case, update
|
||||
|
|
@ -230,7 +248,6 @@ $(document).ready(function () {
|
|||
if (radioValue.val()) {
|
||||
require_fields(radioValue.get(0));
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
/* -------Debugging------- */
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
{% extends "layout.html.j2" %}
|
||||
|
||||
{% set MODEL_VERSION="BetaV1.1.0" %}
|
||||
{% set CALCULATOR_ACTIVE=1 %}
|
||||
{% set DEBUG=False %}
|
||||
|
||||
{% block extra_headers %}
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.css" integrity="sha512-aOG0c6nPNzGk+5zjwyJaoRUgCdOrfSDhmMID2u4+OIslr0GjpLKo7Xm0Ao3xmpM4T8AmIouRkqwj1nrdVsLKEQ==" crossorigin="anonymous">
|
||||
|
|
@ -18,10 +20,16 @@
|
|||
<div class="text-component text-component-page clearfix"></div>
|
||||
<div style="height: 8em; display: block;"></div>
|
||||
|
||||
Beta v1.0.0 <span style="float:right; font-weight:bold">Please send feedback to <a href="mailto:CARA-dev@cern.ch">CARA-dev@cern.ch</a></span>
|
||||
{{ MODEL_VERSION }} <span style="float:right; font-weight:bold">Please send feedback to <a href="mailto:CARA-dev@cern.ch">CARA-dev@cern.ch</a></span>
|
||||
<h1> <p><b>CARA</b> Covid Airborne Risk Assessment tool</p></h1>
|
||||
|
||||
{% if DEBUG %}
|
||||
<form id="covid_calculator" name="covid_calculator" onsubmit="return debug_submit(this)">
|
||||
{% else %}
|
||||
<form id="covid_calculator" name="covid_calculator" action="/calculator/report" onsubmit="return validate_form(this)" method="POST">
|
||||
{% endif %}
|
||||
|
||||
<input type="hidden" name="model_version" value={{ MODEL_VERSION }}></input>
|
||||
|
||||
<div style="width: 33%; float:left;">
|
||||
|
||||
|
|
@ -63,11 +71,20 @@ Beta v1.0.0 <span style="float:right; font-weight:bold">Please send feedback to
|
|||
</div>
|
||||
|
||||
HEPA filtration:
|
||||
<input type="radio" id="hepa_filter" name="hepa_option" value=1>
|
||||
<label for="hepa_filter">Yes</label>
|
||||
|
||||
<input type="radio" id="hepa_filter" name="hepa_option" value=0 checked="checked">
|
||||
<label for="hepa_filter">No</label>
|
||||
<input type="radio" id="hepa_no" name="hepa_option" value=0 onclick="require_fields(this)" checked="checked">
|
||||
<label for="hepa_no">No</label>
|
||||
<input type="radio" id="hepa_yes" name="hepa_option" value=1 onclick="require_fields(this)">
|
||||
<label for="hepa_yes">Yes</label>
|
||||
<input type="number" step=0.01 id="hepa_amount" name="hepa_amount" placeholder="(m³ / hour)" min="0">
|
||||
<hr width="80%">
|
||||
|
||||
<b>Face masks:</b><br>
|
||||
Are masks worn when occupants are at workstations?
|
||||
<input type="radio" id="mask_on" name="mask_wearing" value="continuous" required>Yes
|
||||
<input type="radio" id="mask_off" name="mask_wearing" value="removed" required checked="checked">No<br>
|
||||
Type of masks used:
|
||||
<input type="radio" id="mask_type1" name="mask_type" value="Type I" checked="checked" onclick="require_fields(this)">Type 1
|
||||
<input type="radio" id="mask_ffp2" name="mask_type" value="FFP2" onclick="require_fields(this)">FFP2<br>
|
||||
<hr width="80%">
|
||||
</div>
|
||||
|
||||
|
|
@ -79,6 +96,7 @@ Beta v1.0.0 <span style="float:right; font-weight:bold">Please send feedback to
|
|||
Total number of occupants: <input type="number" id="total_people" name="total_people" min=1 required><br>
|
||||
Number of infected people: <input type="number" id="infected_people" name="infected_people" min=1 required><br>
|
||||
<hr width="80%">
|
||||
|
||||
Activity type: <select id="activity_type" name="activity_type">
|
||||
<option value="office">Office/Meeting</option>
|
||||
<option value="workshop">Workshop</option>
|
||||
|
|
@ -91,8 +109,8 @@ Beta v1.0.0 <span style="float:right; font-weight:bold">Please send feedback to
|
|||
Start: <input type="time" id="infected_start" name="infected_start" value="09:00" required>
|
||||
Finish: <input type="time" id="infected_finish" class="finish_time" name="infected_finish" value="18:00" required>
|
||||
<span id="infected_time_error" class="red_text" hidden>Finish time must be after start</span><br>
|
||||
|
||||
<hr width="80%">
|
||||
|
||||
When is the event?<br>
|
||||
<input type="radio" id="event_type_single" name="event_type" value="single_event" onclick="require_fields(this)" required></input>
|
||||
<label for="event_type_single">Single event</label>
|
||||
|
|
@ -116,6 +134,7 @@ Beta v1.0.0 <span style="float:right; font-weight:bold">Please send feedback to
|
|||
<option value="December">December</option>
|
||||
</select><br>
|
||||
<hr width="80%">
|
||||
|
||||
<!-- Lunch Options -->
|
||||
Lunch break:
|
||||
<input type="radio" id="lunch_option_no" name="lunch_option" value=0 checked="checked" onclick="require_fields(this)">
|
||||
|
|
@ -147,13 +166,8 @@ Beta v1.0.0 <span style="float:right; font-weight:bold">Please send feedback to
|
|||
<option value="30">30</option>
|
||||
</select><br>
|
||||
Coffee breaks are spread evenly throughout the day.
|
||||
|
||||
<br>
|
||||
<hr width="80%">
|
||||
Face masks: <br>
|
||||
Are masks worn when occupants are at workstations? <br>
|
||||
<input type="radio" id="continuous" name="mask_wearing" value="continuous" required>Yes
|
||||
<input type="radio" id="removed" name="mask_wearing" value="removed" required checked="checked">No
|
||||
</div>
|
||||
|
||||
<div style="width: 33%; float:left;">
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
<h1>Output from CARA - COVID Airborne Risk Assessment tool</h1>
|
||||
|
||||
<p class=subtitle> Created {{ creation_date }} using model version {{ model_version }}</p><br>
|
||||
<p class=subtitle> Created {{ creation_date }} using model version {{ form.model_version }}</p><br>
|
||||
|
||||
<p>Simulation Name: {{ form.simulation_name }}</p>
|
||||
<p>Room Number: {{ form.room_number }}</p>
|
||||
|
|
@ -55,7 +55,11 @@
|
|||
No </p></li>
|
||||
{% endif %}
|
||||
<li><p class="data_text">HEPA Filtration: {{ 'Yes' if form.hepa_option else 'No' }}</li>
|
||||
<!--TODO: X type of filter with y flow rate (default model assumption) ? This was in the output doc..? -->
|
||||
{% if form.hepa_option %}
|
||||
<ul>
|
||||
<li><p class="data_text">HEPA amount: {{ form.hepa_amount }}</p></li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
</ul>
|
||||
|
||||
<p class="data_title">Event data:</p>
|
||||
|
|
@ -112,10 +116,10 @@
|
|||
|
||||
<p class="data_title">Mask wearing:</p>
|
||||
<ul>
|
||||
<li><p class="data_text">Masks worn at workstations?
|
||||
{{ "No" if form.mask_wearing == "removed" else "Yes" }}
|
||||
</p></li>
|
||||
<li><p class="data_text">Mask type: Type 1</p></li>
|
||||
<li><p class="data_text">Masks worn at workstations? {{ 'Yes' if form.mask_wearing == "continuous" else 'No' }} </p></li>
|
||||
{% if form.mask_wearing == "continuous" %}
|
||||
<li><p class="data_text">Mask type: {{ form.mask_type }}</p></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
|
||||
<p class="result_title">Results:</p>
|
||||
|
|
|
|||
|
|
@ -338,6 +338,11 @@ Mask.types = {
|
|||
η_leaks=0.15, # (Huang 2007)
|
||||
η_inhale=0.3, # (Browen 2010)
|
||||
),
|
||||
'FFP2': Mask(
|
||||
η_exhale=0.95, # (same outward effect as type 1 - Asadi 2020)
|
||||
η_leaks=0.15, # (same outward effect as type 1 - Asadi 2020)
|
||||
η_inhale=0.865, # (94% penetration efficiency + 8% max inward leakage -> EN 149)
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue