310 lines
22 KiB
Django/Jinja
310 lines
22 KiB
Django/Jinja
{% extends "layout.html.j2" %}
|
|
|
|
{% set MODEL_VERSION="v1.4.1" %}
|
|
{% set DEBUG=False %}
|
|
{% set active_page="calculator/" %}
|
|
|
|
{% 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">
|
|
<link rel="stylesheet" href="/calculator/static/css/form.css">
|
|
{% endblock extra_headers %}
|
|
|
|
{% block body_scripts %}
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js" integrity="sha512-uto9mlQzrs59VwILcLiRYeLKPPbS/bT71da/OEBYEwcdNUk8jYIy+D176RYoop1Da+f9mvkYrmj5MCLZWEtQuA==" crossorigin="anonymous"></script>
|
|
<script src="/calculator/static/js/form.js"></script>
|
|
{% endblock body_scripts %}
|
|
|
|
|
|
{% block main %}
|
|
<div style="margin: 2em;">
|
|
<div class="text-component text-component-page clearfix"></div>
|
|
<div style="height: 8em; display: block;"></div>
|
|
|
|
{{ 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>
|
|
<div>
|
|
<img src="/static/images/cara_logo.png" style="height:175px; width:100px; display:inline-block; vertical-align:middle; object-fit:cover;">
|
|
<h1 style="display:inline-block; vertical-align:middle;"><b>CARA - </b> COVID Airborne Risk Assessment calculator</h1>
|
|
</div>
|
|
|
|
{% 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 %}
|
|
{{ xsrf_form_html }}
|
|
|
|
<input type="hidden" name="model_version" value={{ MODEL_VERSION }}>
|
|
|
|
<div style="width: 33%; float:left;">
|
|
|
|
<!-- General Options -->
|
|
<b>Simulation name:</b> <input type="text" name="simulation_name" placeholder="E.g. Workshop without masks" required><br>
|
|
Room number: <input type="text" name="room_number" placeholder="E.g. 17/R-033" required><br>
|
|
<hr width="80%">
|
|
<b>Room data:</b>
|
|
<div data-tooltip="The area you wish to study (choose one of the 2 options). Use GIS Portal or measure.">
|
|
<span class="tooltip_text">?</span>
|
|
</div><br>
|
|
<input type="radio" id="room_data_volume" name="volume_type" value="room_volume_explicit" onclick="require_fields(this)" tabindex="-1" required>
|
|
<label for="room_data_volume">Room volume:</label>
|
|
<input type="number" step="any" id="room_volume" class="non_zero" name="room_volume" placeholder="Room volume (m³)" min="0" data-has-radio="#room_data_volume"><br>
|
|
<input type="radio" id="room_data_dimensions" name="volume_type" value="room_volume_from_dimensions" onclick="require_fields(this)" tabindex="-1" required>
|
|
<label for="room_data_dimensions">Floor area:</label>
|
|
<input type="number" step="any" id="floor_area" class="non_zero" name="floor_area" placeholder="Room floor area (m²)" min="0" data-has-radio="#room_data_dimensions"><br>
|
|
<label for="room_data_dimensions">Ceiling height:</label>
|
|
<input type="number" step="any" id="ceiling_height" class="non_zero" name="ceiling_height" placeholder="Room ceiling height (m²)" min="0" data-has-radio="#room_data_dimensions"><br>
|
|
<hr width="80%">
|
|
|
|
<!-- Ventilation Options -->
|
|
<b>Ventilation data:</b>
|
|
<div data-tooltip="The available means of venting / filtration of indoor spaces.">
|
|
<span class="tooltip_text">?</span>
|
|
</div><br>
|
|
Ventilation type:
|
|
<input type="radio" id="no_ventilation" name="ventilation_type" value="no_ventilation" checked>
|
|
<label for="no_ventilation">No ventilation</label>
|
|
<input type="radio" id="mechanical_ventilation" name="ventilation_type" value="mechanical_ventilation" data-enables="#DIVmechanical_ventilation">
|
|
<label for="mechanical_ventilation">Mechanical</label>
|
|
<input type="radio" id="natural_ventilation" name="ventilation_type" value="natural_ventilation" data-enables="#DIVnatural_ventilation">
|
|
<label for="natural_ventilation">Natural</label><br>
|
|
|
|
<div id="DIVmechanical_ventilation" class="tabbed" style="display:none">
|
|
<input type="radio" id="mech_type_air_supply" name="mechanical_ventilation_type" value="mech_type_air_supply" onclick="require_fields(this)" tabindex="-1">
|
|
<label for="mech_type_air_supply">Air supply flow rate</label>
|
|
<input type="number" step="any" id="air_supply" class="non_zero" name="air_supply" min="0" placeholder="(m³ / hour)" data-has-radio="#mech_type_air_supply"><br>
|
|
<input type="radio" id="mech_type_air_changes" name="mechanical_ventilation_type" value="mech_type_air_changes" onclick="require_fields(this)" tabindex="-1">
|
|
<label for="mech_type_air_changes">Air changes per hour</label>
|
|
<input type="number" step="any" id="air_changes" class="non_zero" name="air_changes" min="0" placeholder="(h⁻¹) only fresh air" data-has-radio="#mech_type_air_changes"><br>
|
|
</div>
|
|
|
|
<div id="DIVnatural_ventilation" class="tabbed" style="display:none">
|
|
Number of windows: <input type="number" id="windows_number" class="non_zero" name="windows_number" min="1"><br>
|
|
Height of window: <input type="number" step="any" id="window_height" class="non_zero" name="window_height" placeholder="meters" min="0"><br>
|
|
Window type:
|
|
<input type="radio" id="window_sliding" name="window_type" value="window_sliding" onclick="require_fields(this)" checked="checked">
|
|
<label for="window_sliding">Sliding / Side-Hung</label>
|
|
<input type="radio" id="window_hinged" name="window_type" value="window_hinged" onclick="require_fields(this)">
|
|
<label for="window_hinged">Top- or Bottom-Hung</label> <br>
|
|
Width of window: <input type="number" step="any" id="window_width" class="non_zero disabled" name="window_width" placeholder="meters" min="0" data-has-radio="#window_hinged"><br>
|
|
Opening distance: <input type="number" step="any" id="opening_distance" class="non_zero" name="opening_distance" placeholder="meters" min="0"><br>
|
|
Windows open:</span><br>
|
|
<span class="tabbed"><input type="radio" id="windows_open_permanently" name="window_opening_regime" value="windows_open_permanently" onclick="require_fields(this)" checked="checked"></span>
|
|
<label for="windows_open_permanently">Permanently</label><br>
|
|
<span class="tabbed"><input type="radio" id="windows_open_periodically" name="window_opening_regime" value="windows_open_periodically" onclick="require_fields(this)"></span>
|
|
<label for="windows_open_periodically">Periodically:</label>
|
|
<input type="number" step="any" id="windows_duration" class="non_zero disabled" name="windows_duration" placeholder="Duration (min)" min="1" data-has-radio="#windows_open_periodically"> /
|
|
<input type="number" step="any" id="windows_frequency" class="non_zero disabled" name="windows_frequency" placeholder="Frequency (min)" min="1" data-has-radio="#windows_open_periodically">
|
|
<br>
|
|
</div>
|
|
|
|
HEPA filtration:
|
|
<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="any" id="hepa_amount" class="non_zero disabled" name="hepa_amount" placeholder="(m³ / hour)" min="0" data-has-radio="#hepa_yes">
|
|
<hr width="80%">
|
|
|
|
<b>Face masks:</b>
|
|
<div data-tooltip="Masks worn at workstations or removed when a 2m physical distance is respected and proper venting is ensured.">
|
|
<span class="tooltip_text">?</span>
|
|
</div><br>
|
|
Are masks worn when occupants are at workstations?
|
|
<input type="radio" id="mask_on" name="mask_wearing_option" value="mask_on" required>
|
|
<label for="mask_on">Yes</label>
|
|
<input type="radio" id="mask_off" name="mask_wearing_option" value="mask_off" required checked="checked">
|
|
<label for="mask_off">No</label><br>
|
|
Type of masks used:
|
|
<input type="radio" id="mask_type_1" name="mask_type" value="Type I" checked="checked" onclick="require_fields(this)">
|
|
<label for="mask_type_1">Type 1</label>
|
|
<input type="radio" id="mask_type_ffp2" name="mask_type" value="FFP2" onclick="require_fields(this)">
|
|
<label for="mask_type_ffp2">FFP2</label><br>
|
|
<hr width="80%">
|
|
</div>
|
|
|
|
<div style="width: 33%; float:left;">
|
|
|
|
<!-- Event Options -->
|
|
<b>Event data:</b>
|
|
<div data-tooltip="The total no. of occupants in the room and how many of them you assume are infected.">
|
|
<span class="tooltip_text">?</span>
|
|
</div><br>
|
|
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>
|
|
<span id="training_limit_error" class="red_text" hidden>Training activities limited to 1 infected<br></span>
|
|
<hr width="80%">
|
|
|
|
Activity type:
|
|
<select id="activity_type" name="activity_type">
|
|
<option value="office">Office</option>
|
|
<option value="meeting">Meeting</option>
|
|
<option value="callcentre">Call Centre</option>
|
|
<option value="library">Library</option>
|
|
<option value="lab">Laboratory</option>
|
|
<option value="workshop">Workshop</option>
|
|
<option value="training">Training</option>
|
|
<option value="gym">Gym</option>
|
|
</select><br>
|
|
Exposed person(s) presence: <br>
|
|
<span class="tabbed">Start: </span><input type="time" id="exposed_start" class="start_time" data-time-group="exposed" data-lunch-break="exposed_lunch" name="exposed_start" value="09:00" required>
|
|
Finish: <input type="time" id="exposed_finish" class="finish_time" data-time-group="exposed" data-lunch-break="exposed_lunch" name="exposed_finish" value="18:00" required><br>
|
|
Infected person(s) presence: <br>
|
|
<span class="tabbed">Start: </span><input type="time" id="infected_start" class="start_time" data-time-group="infected" data-lunch-break="infected_lunch" name="infected_start" value="09:00" required>
|
|
Finish: <input type="time" id="infected_finish" class="finish_time" data-time-group="infected" data-lunch-break="infected_lunch" name="infected_finish" value="18:00" required><br>
|
|
<hr width="80%">
|
|
|
|
Which month is the event?
|
|
<select id="event_month" name="event_month" value="January" required>
|
|
<option value="January">January</option>
|
|
<option value="February">February</option>
|
|
<option value="March">March</option>
|
|
<option value="April">April</option>
|
|
<option value="May">May</option>
|
|
<option value="June">June</option>
|
|
<option value="July">July</option>
|
|
<option value="August">August</option>
|
|
<option value="September">September</option>
|
|
<option value="October">October</option>
|
|
<option value="November">November</option>
|
|
<option value="December">December</option>
|
|
</select><br>
|
|
<hr width="80%">
|
|
|
|
<span id="activity_breaks">
|
|
<b>Activity breaks:</b>
|
|
<div data-tooltip="Input breaks that, by default, are the same for infected/exposed person(s) unless specified otherwise.">
|
|
<span class="tooltip_text">?</span>
|
|
</div>
|
|
</span><br>
|
|
|
|
<!-- Lunch Options -->
|
|
<input type="checkbox" id="infected_dont_have_breaks_with_exposed" name="infected_dont_have_breaks_with_exposed" value='1' onclick="toggle_split_breaks()">
|
|
<label for="infected_dont_have_breaks_with_exposed">Input separate breaks for infected and exposed person(s)</label><br>
|
|
<div id="DIVexposed_breaks" style="float:left; margin-left:10pt;">
|
|
<span id="exposed_break_title" style="display:none;"><b>Exposed person(s) breaks:</b></span>
|
|
<div style="padding:10px; border: 2px solid rgb(47, 52, 66);">
|
|
Lunch break:
|
|
<input type="radio" id="exposed_lunch_option_no" data-lunch-select="exposed" name="exposed_lunch_option" value=0 onclick="require_fields(this)">
|
|
<label for="exposed_lunch_option_no">No</label>
|
|
<input type="radio" id="exposed_lunch_option_yes" data-lunch-select="exposed" name="exposed_lunch_option" value=1 checked="checked" onclick="require_fields(this)">
|
|
<label for="exposed_lunch_option_yes">Yes</label><br>
|
|
|
|
Start: <input type="time" id="exposed_lunch_start" class="start_time" data-time-group="exposed_lunch" data-lunch-for="exposed" data-has-radio="#exposed_lunch_option_yes" name="exposed_lunch_start" value="12:30" required>
|
|
Finish: <input type="time" id="exposed_lunch_finish" class="finish_time" data-time-group="exposed_lunch" data-lunch-for="exposed" data-has-radio="#exposed_lunch_option_yes" name="exposed_lunch_finish" value="13:30" required><br>
|
|
|
|
<!-- Coffee Options -->
|
|
Coffee Breaks:
|
|
<input type="radio" id="exposed_coffee_break_0" name="exposed_coffee_break_option" value="coffee_break_0" checked="checked">
|
|
<label for="exposed_coffee_break_0" >No breaks</label>
|
|
<input type="radio" id="exposed_coffee_break_2" name="exposed_coffee_break_option" value="coffee_break_2">
|
|
<label for="exposed_coffee_break_2">2</label>
|
|
<input type="radio" id="exposed_coffee_break_4" name="exposed_coffee_break_option" value="coffee_break_4">
|
|
<label for="exposed_coffee_break_4">4</label><br>
|
|
|
|
Duration (minutes):
|
|
<select id="exposed_coffee_duration" name="exposed_coffee_duration">
|
|
<option value="5">5</option>
|
|
<option value="10">10</option>
|
|
<option value="15">15</option>
|
|
<option value="20">20</option>
|
|
<option value="25">25</option>
|
|
<option value="30">30</option>
|
|
</select><br>
|
|
</div>
|
|
<br>
|
|
</div>
|
|
|
|
<div id="DIVinfected_breaks" style="display:none; float:left; margin-left:10pt;">
|
|
<b>Infected person(s) breaks:</b>
|
|
<div style="padding:10px; border: 2px solid rgb(47, 52, 66);">
|
|
Lunch break:
|
|
<input type="radio" id="infected_lunch_option_no" data-lunch-select="infected" name="infected_lunch_option" value=0 onclick="require_fields(this)">
|
|
<label for="infected_lunch_option_no">No</label>
|
|
<input type="radio" id="infected_lunch_option_yes" data-lunch-select="infected" name="infected_lunch_option" value=1 checked="checked" onclick="require_fields(this)">
|
|
<label for="infected_lunch_option_yes">Yes</label><br>
|
|
|
|
Start: <input type="time" id="infected_lunch_start" class="start_time" data-time-group="infected_lunch" data-lunch-for="infected" data-has-radio="#infected_lunch_option_yes" name="infected_lunch_start" value="12:30">
|
|
Finish: <input type="time" id="infected_lunch_finish" class="finish_time" data-time-group="infected_lunch" data-lunch-for="infected" data-has-radio="#infected_lunch_option_yes" name="infected_lunch_finish" value="13:30"><br>
|
|
|
|
<!-- Coffee Options -->
|
|
Coffee Breaks:
|
|
<input type="radio" id="infected_coffee_break_0" name="infected_coffee_break_option" value="coffee_break_0" checked="checked">
|
|
<label for="infected_coffee_break_0" >No breaks</label>
|
|
<input type="radio" id="infected_coffee_break_2" name="infected_coffee_break_option" value="coffee_break_2">
|
|
<label for="infected_coffee_break_2">2</label>
|
|
<input type="radio" id="infected_coffee_break_4" name="infected_coffee_break_option" value="coffee_break_4">
|
|
<label for="infected_coffee_break_4">4</label><br>
|
|
|
|
Duration (minutes):
|
|
<select id="infected_coffee_duration" name="infected_coffee_duration">
|
|
<option value="5">5</option>
|
|
<option value="10">10</option>
|
|
<option value="15">15</option>
|
|
<option value="20">20</option>
|
|
<option value="25">25</option>
|
|
<option value="30">30</option>
|
|
</select><br>
|
|
</div>
|
|
<br>
|
|
</div>
|
|
|
|
<br style="clear:both;">
|
|
<i>Coffee breaks are spread evenly throughout the day.</i><br>
|
|
<hr width="80%">
|
|
</div>
|
|
|
|
<div style="width: 33%; float:left;">
|
|
|
|
<b>Quick Guide:</b><br>
|
|
This tool simulates the long range airborne spread SARS-CoV-2 virus in a finite volume and estimates the risk of COVID-19 infection. It is based on current scientific data and can be used to compare the effectiveness of different mitigation measures.<br>
|
|
<b>Ventilation data:</b> <br>
|
|
<ul>
|
|
<li>Mechanical ventilation = the HVAC supply of fresh air. Check the flow rates with the concerned technical department.</li>
|
|
<li>Natural ventilation = the type of window opening. The opening distance is between the fixed frame and movable part when open (commonly used values are window height of 1.6m and window opening between 0.15m and 0.6m). In case of periodic opening, specify the duration (e.g. for 10 min) and frequency (e.g. every 60 min).</li>
|
|
<li>HEPA filtration = the air flow of the device. The following values are based on the different fan velocities of a specific commercial device proposed by the HSE Unit:</li>
|
|
<ul>
|
|
<li>Level 6 (max) = 430 m<sup>3</sup>/h (noisy)</li>
|
|
<li>Level 5 = 250 m<sup>3</sup>/h (ok w.r.t. noise, recommended)</li>
|
|
<li>Level 4 = 130 m<sup>3</sup>/h (silent)</li>
|
|
<li>Level 3 = 95 m<sup>3</sup>/h (silent)</li>
|
|
</ul>
|
|
</ul>
|
|
<b>Activity types:</b><br>
|
|
The type of activity applies to both the infected and exposed persons:
|
|
<ul>
|
|
<li>Office = Typical office scenario with all persons seated, in conversation (talking 33% of the time, otherwise breathing normally).</li>
|
|
<li>Meeting = Typical meeting scenario with all persons seated, in conversation (talking time is shared equally between all persons).</li>
|
|
<li>Call Centre = A conservative assumption for office spaces, assumes all occupants are seated and talking continuously.</li>
|
|
<li>Library = assumes all occupants are seated, breathing and not talking.</li>
|
|
<li>Laboratory = Typical lab scenario with all persons doing light physical activity and talking 50% of the time.</li>
|
|
<li>Workshop = Typical mechanical assembly workshop or equipment installation scenario with all persons doing moderate activity and talking 50% of the time.</li>
|
|
<li>Training = Training course scenario. One person (Trainer) standing, talking, all others seated, talking quietly (whispering). It is assumed the Trainer is the infected person, for the worst case scenario.</li>
|
|
<li>Gym = Included for comparison purposes only, all persons are doing heavy exercise and breathing (no talking).</li>
|
|
</ul>
|
|
<b>Activity breaks:</b><br>
|
|
<ul>
|
|
<li>If coffee breaks are included, they are spread out evenly throughout the day, in addition to any lunch break (if applicable).</li>
|
|
</ul>
|
|
Refer to <a href="/calculator/user-guide"> COVID Calculator App user guide </a> for more detailed explanations on how to use this tool. <br>
|
|
</div>
|
|
|
|
<button type='submit' id="generate_report">Generate report</button><br><br><br><br>
|
|
</form>
|
|
|
|
<!-- Dialog boxes -->
|
|
<div id="DIALOG_welcome" title="Welcome to CARA!" class="dialog">
|
|
<p>This software is provided with a disclaimer and code license.<span id="dots"></span><span id="more" style="display: none;">
|
|
<br><br><b>Disclaimer:</b><br><br>
|
|
<span id="disclaimer">The risk assessment tool simulates the long-range airborne spread SARS-CoV-2 virus in a finite volume, assuming a homogenous mixture, and estimates the risk of COVID-19 infection therein. The results DO NOT include short-range airborne exposure (where the physical distance plays a factor) nor the other known modes of SARS-CoV-2 transmission. Hence, the output from this model is only valid when the other recommended public health & safety instructions are observed, such as adequate physical distancing, good hand hygiene and other barrier measures.<br><br>
|
|
The model used is based on scientific publications relating to airborne transmission of infectious diseases, dose-response exposures and aerosol science, as of December 2020.<br><br>
|
|
Note that this model applies a deterministic approach, i.e., it is assumed at least one person is infected and shedding viruses into the simulated volume. Nonetheless, it is also important to understand that the absolute risk of infection is uncertain, as it will depend on the probability that someone infected attends the event. The model is most useful for comparing the impact and effectiveness of different mitigation measures such as ventilation, filtration, exposure time, physical activity and the size of the room, only considering long-range airborne transmission of COVID-19 in indoor settings.<br><br>
|
|
This tool is designed to be informative, allowing the user to adapt different settings and model the relative impact on the estimated infection probabilities. The objective is to facilitate targeted decision-making and investment through comparisons, rather than a singular determination of absolute risk. While the SARS-CoV-2 virus is in circulation among the population, the notion of 'zero risk' or a 'completely safe scenario' does not exist. Each event modelled is unique and the results generated therein are only as accurate as the inputs and assumptions.<br><br></span>
|
|
<br><br><b>Code License:</b><br><br>
|
|
<span id="code_license">This code is licensed under GPL V3.</span></p><br>
|
|
<button onclick="show_disclaimer()" id="myBtn" tabindex="-1">Read more</button><br><br>
|
|
</div>
|
|
|
|
<div class="text-component text-component-page clearfix"></div>
|
|
<br>
|
|
</div>
|
|
{% endblock main %}
|