diff --git a/caimira/apps/calculator/co2_model_generator.py b/caimira/apps/calculator/co2_model_generator.py index 51f34d25..3aa13118 100644 --- a/caimira/apps/calculator/co2_model_generator.py +++ b/caimira/apps/calculator/co2_model_generator.py @@ -100,13 +100,17 @@ class CO2FormData: return instance def build_model(self) -> models.CO2Data: + population_presence=self.population_present_interval() + last_time_present = population_presence.boundaries()[-1][-1] + last_present_time_index = next((index for index, time in enumerate(self.CO2_data['times']) + if time > last_time_present), len(self.CO2_data['times'])) return models.CO2Data( room_volume=self.room_volume, number=self.total_people, - presence=self.population_present_interval(), - ventilation_transition_times=self.ventilation_transition_times(), - times=self.CO2_data['times'], - CO2_concentrations=self.CO2_data['CO2'] + presence=population_presence, + ventilation_transition_times=self.ventilation_transition_times(last_time_present), + times=self.CO2_data['times'][:last_present_time_index], + CO2_concentrations=self.CO2_data['CO2'][:last_present_time_index], ) def _compute_breaks_in_interval(self, start, finish, n_breaks, duration) -> models.BoundarySequence_t: @@ -310,9 +314,10 @@ class CO2FormData: breaks=breaks, ) - def ventilation_transition_times(self) -> typing.Tuple[float, ...]: + def ventilation_transition_times(self, last_present_time) -> typing.Tuple[float, ...]: if self.ventilation_type == 'natural_ventilation' and self.window_opening_regime == 'windows_open_periodically': - return tuple(sorted(set(models.PeriodicInterval(self.windows_frequency, - self.windows_duration, min(self.infected_start, self.exposed_start)/60).transition_times()))) + transition_times = sorted(models.PeriodicInterval(self.windows_frequency, + self.windows_duration, min(self.infected_start, self.exposed_start)/60).transition_times()) + return tuple(filter(lambda x: x < last_present_time, transition_times)) else: - return (min(self.infected_start/60, self.exposed_start/60), max(self.infected_finish/60, self.exposed_finish/60)) # all day long + return tuple((min(self.infected_start, self.exposed_start)/60, max(self.infected_finish, self.exposed_finish)/60), ) # all day long diff --git a/caimira/apps/calculator/model_generator.py b/caimira/apps/calculator/model_generator.py index a953e4e5..230582e3 100644 --- a/caimira/apps/calculator/model_generator.py +++ b/caimira/apps/calculator/model_generator.py @@ -436,10 +436,24 @@ class FormData: def ventilation(self) -> models._VentilationBase: always_on = models.PeriodicInterval(period=120, duration=120) + periodic_interval = models.PeriodicInterval(self.windows_frequency, self.windows_duration, min(self.infected_start, self.exposed_start)/60) + + if self.CO2_data_option: + ventilations = [] + if self.ventilation_type == 'natural_ventilation' and self.window_opening_regime == 'windows_open_periodically': + for index, time in enumerate(sorted(list(periodic_interval.transition_times()))[:-1]): + if index < len(self.CO2_fitting_result['ventilation_values']): + ventilations.append(models.AirChange(active=models.SpecificInterval(present_times=((time, time + self.windows_duration/60), )), + air_exch=self.CO2_fitting_result['ventilation_values'][index])) + else: break + else: + ventilations.append(models.AirChange(active=always_on, air_exch=self.CO2_fitting_result['ventilation_values'][0])) + return models.MultipleVentilation(tuple(ventilations)) + # Initializes a ventilation instance as a window if 'natural_ventilation' is selected, or as a HEPA-filter otherwise if self.ventilation_type == 'natural_ventilation': if self.window_opening_regime == 'windows_open_periodically': - window_interval = models.PeriodicInterval(self.windows_frequency, self.windows_duration, min(self.infected_start, self.exposed_start)/60) + window_interval = periodic_interval else: window_interval = always_on @@ -521,7 +535,7 @@ class FormData: elif (self.activity_type == 'precise'): activity_defn, expiration_defn = self.generate_precise_activity_expiration() - if self.CO2_data_option: + if self.CO2_data_option: activity = mc.Activity(self.CO2_fitting_result['exhalation_rate'], self.CO2_fitting_result['exhalation_rate']) else: activity = activity_distributions[activity_defn] diff --git a/caimira/apps/calculator/static/js/co2_form.js b/caimira/apps/calculator/static/js/co2_form.js index 2a68e0b9..09e7c8c8 100644 --- a/caimira/apps/calculator/static/js/co2_form.js +++ b/caimira/apps/calculator/static/js/co2_form.js @@ -74,9 +74,9 @@ function displayJsonToHtmlTable(jsonData) { if (i < 5) { htmlData += "" + - Math.round(row["Times"] * 10) / 10 + + row["Times"].toFixed(2) + "" + - Math.round(row["CO2"] * 10) / 10 + + row["CO2"].toFixed(2) + ""; } structure["times"].push(row["Times"]); @@ -85,8 +85,8 @@ function displayJsonToHtmlTable(jsonData) { if (jsonLength >= 5) htmlData += " ... ... "; table.innerHTML = htmlData; - console.log(structure); format.value = JSON.stringify(structure); + $('#generate_fitting_data').prop("disabled", false); } else { table.innerHTML = "There is no data in Excel"; } @@ -160,6 +160,7 @@ function submit_fitting_algorithm(url) { } function clear_fitting_algorithm() { + $('#generate_fitting_data').prop("disabled", true); $("#display_excel_data tbody").remove(); $('#CO2_fitting_result').val(''); $('#formatted_data').val(''); diff --git a/caimira/apps/calculator/static/js/form.js b/caimira/apps/calculator/static/js/form.js index 1d1e39f1..81623bc8 100644 --- a/caimira/apps/calculator/static/js/form.js +++ b/caimira/apps/calculator/static/js/form.js @@ -493,10 +493,36 @@ function on_coffee_break_option_change() { } } +function ventilation_from_fitting(condition) { + let CO2_data_options = $('input[type=radio][name=ventilation_type]'); + let hepa_options = $('input[type=radio][name=hepa_option]'); + if (condition) { + $('input[type=radio][id=no_ventilation]').click(); + CO2_data_options.each(function (index){ + $(this).prop("disabled", true); + }); + hepa_options.each(function (index){ + $(this).prop("disabled", true); + }); + $('#DIVhepa_amount').after($('#window_opening_regime')); + } + else { + CO2_data_options.each(function (index){ + $(this).prop("disabled", false); + }); + hepa_options.each(function (index){ + $(this).prop("disabled", false); + }); + $('#DIVopening_distance').after($('#window_opening_regime')); + } +} + function on_CO2_data_option_change() { CO2_data_options = $('input[type=radio][name=CO2_data_option]'); CO2_data_options.each(function (index){ if (this.checked) { + // if (this.id == 'CO2_data_yes') ventilation_from_fitting(true); + // else if (this.id == 'CO2_data_no') ventilation_from_fitting(false); getChildElement($(this)).show(); require_fields(this); } diff --git a/caimira/apps/templates/base/calculator.form.html.j2 b/caimira/apps/templates/base/calculator.form.html.j2 index 462cea56..4b47b334 100644 --- a/caimira/apps/templates/base/calculator.form.html.j2 +++ b/caimira/apps/templates/base/calculator.form.html.j2 @@ -269,44 +269,46 @@
-
+
-
Window open: -
- ? +
+
Window open: +
+ ? +
-
- - - - - -
-
-
-
-
-
-
-
+ + + + + +
+
+
+
+
+
+
+
+

HEPA filtration:
-
- - - - -
-
-
-
-
+
+ + + + +
+
+
+
+

@@ -675,7 +677,7 @@
-