From dea9a7fb17f28f21bb545666aa68a5bde36184ac Mon Sep 17 00:00:00 2001 From: Khalim Conn-Kowlessar Date: Thu, 23 Nov 2023 08:47:37 +0000 Subject: [PATCH] implemented solid floor insulation --- recommendations/Costs.py | 205 +++++++++++++++++++++++++++++++++++---- 1 file changed, 187 insertions(+), 18 deletions(-) diff --git a/recommendations/Costs.py b/recommendations/Costs.py index 49298d5f..1c8cf6d8 100644 --- a/recommendations/Costs.py +++ b/recommendations/Costs.py @@ -29,7 +29,7 @@ p2.set_basic_property_dimensions() import pandas as pd -df = pd.read_csv("/Users/khalimconn-kowlessar/Downloads/Hestia Materials - suspended_floor_insulation.csv") +df = pd.read_csv("/Users/khalimconn-kowlessar/Downloads/Hestia Materials - solid_floor_insulation.csv") df = df.to_dict("records") # This data comes from SPONs @@ -69,6 +69,9 @@ class Costs: # We assume a conservative 10% contingency for all works which is a rate defined by SPONs CONTINGENCY = 0.1 + # Where there is more uncertainty, a higher contingency rate is used + HIGH_RISH_CONTINGENCY = 0.15 + # Preliminaries are a percentage of the total cost of the work and covers the cost of site-specific costs # such as site preparation, safety measures and project management. This rate can vary but we'll assume a 10% # rate, on the total cost before VAT, as recommended by SPONs @@ -100,7 +103,7 @@ class Costs: if not self.labour_adjustment_factor: raise ValueError("Labour adjustment factor not found") - def cavity_wall_insulation(self, material): + def cavity_wall_insulation(self, wall_area, material): """ Calculates the total cost for cavity wall insulation based on material and labor costs, including contingency, preliminaries, profit, and VAT. @@ -123,7 +126,7 @@ class Costs: # } material_cost_per_m2 = material["material_cost"] - wall_area = self.property.insulation_wall_area + # wall_area = self.property.insulation_wall_area # This is the amount of material required in m3, assuming a standard 75mm depth volume = 0.075 * wall_area @@ -156,7 +159,7 @@ class Costs: "labour_hours": labour_hours } - def loft_insulation(self, material): + def loft_insulation(self, floor_area, material): """ Calculates the total cost for cavity wall insulation based on material and labor costs, including contingency, preliminaries, profit, and VAT. @@ -175,7 +178,7 @@ class Costs: # } material_cost_per_m2 = material["material_cost"] - floor_area = self.property.floor_area + # floor_area = self.property.floor_area base_material_cost = material_cost_per_m2 * floor_area labour_cost = material["labour_cost"] * floor_area * self.labour_adjustment_factor @@ -205,7 +208,7 @@ class Costs: "labour_hours": labour_hours } - def internal_wall_insulation(self, material, non_insulation_materials): + def internal_wall_insulation(self, wall_area, material, non_insulation_materials): """ Broadly speaking, the high level steps to an internal wall insulation job are the following: @@ -309,7 +312,7 @@ class Costs: # 'thermal_conductivity': "", # 'thermal_conductivity_unit': "", # 'total_cost': 4.88, - # 'type': 'iwi_finishes'} + # 'type': 'iwi_redecoration'} # ] # # material = { @@ -330,17 +333,16 @@ class Costs: # } # Cost per m2 - wall_area = self.property.insulation_wall_area + # wall_area = self.property.insulation_wall_area # Extract and check the different types of data we'll need demolition_data = [x for x in non_insulation_materials if x["type"] == "iwi_wall_demolition"] vapour_barrier_data = [x for x in non_insulation_materials if x["type"] == "iwi_vapour_barrier"] redecoration_data = [x for x in non_insulation_materials if x["type"] == "iwi_redecoration"] - finishes_data = [x for x in non_insulation_materials if x["type"] == "iwi_finishes"] if not demolition_data: raise ValueError("No data found for iwi_wall_demolition") - if (len(vapour_barrier_data) != 1) or (len(redecoration_data) != 2) or (len(finishes_data) != 1): + if (len(vapour_barrier_data) != 1) or (len(redecoration_data) != 3): raise ValueError("Incorrect number of data entries for non-insulation materials") # Break out the individual material costs @@ -350,7 +352,6 @@ class Costs: insulation_material_costs = material["material_cost"] * wall_area vapour_barrier_material_costs = vapour_barrier_data[0]["material_cost"] * wall_area redecoration_material_costs = sum([x["material_cost"] * wall_area for x in redecoration_data]) - finishes_material_costs = finishes_data[0]["material_cost"] * wall_area demolition_plant_costs = np.mean([x["plant_cost"] * wall_area for x in demolition_data]) @@ -358,15 +359,14 @@ class Costs: insulation_labour_costs = material["labour_cost"] * wall_area vapour_barrier_labour_costs = vapour_barrier_data[0]["labour_cost"] * wall_area redecoration_labour_costs = sum([x["labour_cost"] * wall_area for x in redecoration_data]) - finishes_labour_costs = finishes_data[0]["labour_cost"] * wall_area labour_costs = (demolition_labour_costs + insulation_labour_costs + vapour_barrier_labour_costs + - redecoration_labour_costs + finishes_labour_costs) + redecoration_labour_costs) labour_costs = labour_costs * self.labour_adjustment_factor materials_costs = (demolition_material_costs + insulation_material_costs + vapour_barrier_material_costs + - redecoration_material_costs + finishes_material_costs) + redecoration_material_costs) subtotal_before_profit = labour_costs + materials_costs + demolition_plant_costs @@ -384,10 +384,9 @@ class Costs: insulation_labour_hours = material["labour_hours_per_unit"] * wall_area vapour_barrier_labour_hours = vapour_barrier_data[0]["labour_hours_per_unit"] * wall_area redecoration_labour_hours = sum([x["labour_hours_per_unit"] * wall_area for x in redecoration_data]) - finishes_labour_hours = finishes_data[0]["labour_hours_per_unit"] * wall_area labour_hours = (demolition_labour_hours + insulation_labour_hours + vapour_barrier_labour_hours + - redecoration_labour_hours + finishes_labour_hours) + redecoration_labour_hours) # To install internal wall insulation, a small to medium size project might be conducted by a team of 3-5 people labour_days = (labour_hours / 8) / 5 @@ -404,7 +403,7 @@ class Costs: "labour_days": labour_days } - def suspended_floor_insulation(self, material, non_insulation_materials): + def suspended_floor_insulation(self, insulation_floor_area, material, non_insulation_materials): """ We characterise the steps for suspended floor insulation as the following tasks: @@ -455,7 +454,7 @@ class Costs: # 'Gradus woven polypropylene tufted loop\n\n as a baseline. We assume re-use of carpets, ' # 'therefore we need just labour rates'}] - insulation_floor_area = self.property.floor_area / self.property.number_of_floors + # insulation_floor_area = self.property.floor_area / self.property.number_of_floors demolition_data = [x for x in non_insulation_materials if x["type"] == "suspended_floor_demolition"] vapour_barrier_data = [x for x in non_insulation_materials if x["type"] == "suspended_floor_vapour_barrier"] @@ -517,3 +516,173 @@ class Costs: "labour_hours": labour_hours, "labour_days": labour_days } + + def solid_floor_insulation(self, insulation_floor_area, material, non_insulation_materials): + """ + We characterise the steps for solid floor insulation as the following tasks: + + 1) Removal of Carpet and Underfelt: This is the initial stage where any existing floor coverings, like carpets, + tiles, or linoleum, are carefully removed. This exposes the solid floor beneath, which is typically concrete. + + 2) Preparation of Flooring: This step is critical. It involves: + - Cleaning the existing floor surface thoroughly to remove debris and ensure a flat surface. + - Assessing and repairing any damage to the concrete floor. This might include filling cracks or leveling + uneven areas. + + 3) Installation of a Damp Proof Membrane (DPM): Before installing insulation, a DPM is often laid down to + prevent moisture from rising into the insulation and the interior space. This step is crucial in areas prone to + dampness. + + 4) Install Insulation: The insulation, often in the form of rigid foam boards, is laid over the DPM. + The choice of insulation material will depend on the desired thermal properties and the available floor height. + Care is taken to minimize thermal bridges and ensure a snug fit between insulation boards. + + 5) Laying a New Subfloor: Over the insulation, a new subfloor is often installed. This could be a layer of + screed (a type of concrete) or wooden boarding, depending on the specific requirements and preferences. + + 6) Re-decoration and Finishing Touches: Once the subfloor is in place and has set or dried (if necessary), + the final floor finish can be applied. This might involve: + - Laying new tiles, wooden flooring, or other chosen materials. + - If you're planning to re-carpet, this would be the stage to do it. + - Skirting boards may need to be refitted or replaced. + + 7) Considerations for Doors and Fixtures: It's important to note that raising the floor level can affect door + thresholds and other fixtures. Doors may need to be trimmed, and fixtures might need adjustments. + :param material: + :param non_insulation_materials: + :return: + """ + + material = { + 'type': 'solid_floor_insulation', 'description': 'Kay-Cel Expanded Polystyrene Board', + 'depth': 100.0, 'depth_unit': 'mm', 'cost_unit': 'gbp_per_m2', 'thermal_conductivity': 0.033, + 'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'prime_material_cost': 0, + 'material_cost': 12.02, 'labour_cost': 4.4, 'labour_hours_per_unit': 0.19, 'plant_cost': 0, + 'total_cost': 16.42, 'link': 'SPONs', 'Notes': 0 + } + + non_insulation_materials = [ + {'type': 'solid_floor_demolition', 'description': 'Removal of carpet and underfelt', 'depth': 0, + 'depth_unit': 0, 'cost_unit': 0, 'thermal_conductivity': 0, 'thermal_conductivity_unit': 0, + 'prime_material_cost': 0, 'material_cost': 0, 'labour_cost': 3.32, 'labour_hours_per_unit': 0.11, + 'plant_cost': 0, 'total_cost': 3.32, 'link': 'SPONs', + 'Notes': 'We ignore the plant cost that is in SPONs because we assume the carpet is not scrapped and ' + 'therefore there is no need for a skip'}, + {'type': 'solid_floor_preparation', + 'description': 'clean surface of concrete to receive new damp-proof membrane', 'depth': 0, + 'depth_unit': 0, 'cost_unit': 0, 'thermal_conductivity': 0, 'thermal_conductivity_unit': 0, + 'prime_material_cost': 0, 'material_cost': 0, 'labour_cost': 4.36, 'labour_hours_per_unit': 0.14, + 'plant_cost': 0, 'total_cost': 4.36, 'link': 0, 'Notes': 0}, {'type': 'solid_floor_preparation', + 'description': 'Clean out crack to ' + 'form a 20mm×20mm ' + 'groove and fill with ' + 'cement: mortar mixed ' + 'with bonding agent', + 'depth': 0, 'depth_unit': 0, + 'cost_unit': 0, + 'thermal_conductivity': 0, + 'thermal_conductivity_unit': 0, + 'prime_material_cost': 0, + 'material_cost': 6.91, + 'labour_cost': 18.99, + 'labour_hours_per_unit': 0.61, + 'plant_cost': 0.16, + 'total_cost': 26.06, 'link': 0, + 'Notes': 'This step is the ' + 'assessment and repair of ' + 'any damage to the concrete ' + 'floor such as filling ' + 'cracks or levelling uneven ' + 'areas'}, + {'type': 'solid_floor_vapour_barrier', 'description': 'Visqueen High Performance Vapour Barrier', + 'depth': 0, 'depth_unit': 0, 'cost_unit': 0, 'thermal_conductivity': 0, + 'thermal_conductivity_unit': 0, 'prime_material_cost': 0.58, 'material_cost': 1.21, 'labour_cost': 0.48, + 'labour_hours_per_unit': 0.02, 'plant_cost': 0, 'total_cost': 1.69, 'link': 'SPONs', 'Notes': 0}, + {'type': 'solid_floor_redecoration', + 'description': 'Screeded beds; protection to compressible formwork exceeding 600mm wide', 'depth': 0, + 'depth_unit': 0, 'cost_unit': 0, 'thermal_conductivity': 0, 'thermal_conductivity_unit': 0, + 'prime_material_cost': 9.6, 'material_cost': 9.89, 'labour_cost': 2.67, 'labour_hours_per_unit': 0.15, + 'plant_cost': 0, 'total_cost': 12.56, 'link': 'SPONs', + 'Notes': 'This is the screed layer, placed on top of the insulation'}, + {'type': 'solid_floor_redecoration', 'description': 'Fitting carpet', 'depth': 0, 'depth_unit': 0, + 'cost_unit': 0, 'thermal_conductivity': 0, 'thermal_conductivity_unit': 0, + 'prime_material_cost': 0, 'material_cost': 0, 'labour_cost': 6.59, 'labour_hours_per_unit': 0.37, + 'plant_cost': 0, 'total_cost': 6.59, 'link': 'SPONs', + 'Notes': 'SPONs does not have data on re-fitting the carpet so we use the data in Fitted carpeting; ' + 'Gradus woven polypropylene tufted loop\n\n as a baseline. We assume re-use of carpets, ' + 'therefore we need just labour rates'}, + {'type': 'solid_floor_redecoration', + 'description': 'Fitting existing softwood skirting or architrave to new frames; 150mm high', 'depth': 0, + 'depth_unit': 0, 'cost_unit': 0, 'thermal_conductivity': 0, 'thermal_conductivity_unit': 0, + 'prime_material_cost': 0, 'material_cost': 0.01, 'labour_cost': 4.87, 'labour_hours_per_unit': 0.12, + 'plant_cost': 0, 'total_cost': 4.88, 'link': 'SPONs', 'Notes': 0} + ] + + # insulation_floor_area = self.property.floor_area / self.property.number_of_floors + + demolition_data = [x for x in non_insulation_materials if x["type"] == "solid_floor_demolition"] + preparation_data = [x for x in non_insulation_materials if x["type"] == "solid_floor_preparation"] + vapour_barrier_data = [x for x in non_insulation_materials if x["type"] == "solid_floor_vapour_barrier"] + redecoration_data = [x for x in non_insulation_materials if x["type"] == "solid_floor_redecoration"] + + if ((len(demolition_data) != 1) or (len(preparation_data) != 2) or (len(vapour_barrier_data) != 1) or + (len(redecoration_data) != 3)): + raise ValueError("Incorrect number of data entries for non-insulation materials") + + # Break out the individual material costs + preparation_material_costs = sum([x["material_cost"] * insulation_floor_area for x in preparation_data]) + insulation_material_costs = material["material_cost"] * insulation_floor_area + vapour_barrier_material_costs = vapour_barrier_data[0]["material_cost"] * insulation_floor_area + redecoration_material_costs = sum([x["material_cost"] * insulation_floor_area for x in redecoration_data]) + + demolition_labour_costs = sum([x["labour_cost"] * insulation_floor_area for x in demolition_data]) + preparation_labour_costs = sum([x["labour_cost"] * insulation_floor_area for x in preparation_data]) + insulation_labour_costs = material["labour_cost"] * insulation_floor_area + vapour_barrier_labour_costs = vapour_barrier_data[0]["labour_cost"] * insulation_floor_area + redecoration_labour_costs = sum([x["labour_cost"] * insulation_floor_area for x in redecoration_data]) + + preparation_plant_costs = sum([x["plant_cost"] * insulation_floor_area for x in preparation_data]) + + labour_costs = (demolition_labour_costs + insulation_labour_costs + vapour_barrier_labour_costs + + redecoration_labour_costs + preparation_labour_costs) + + labour_costs = labour_costs * self.labour_adjustment_factor + + materials_cost = (preparation_material_costs + insulation_material_costs + vapour_barrier_material_costs + + redecoration_material_costs) + + subtotal_before_profit = labour_costs + materials_cost + preparation_plant_costs + + # We use HIGH_RISH_CONTINGENCY because of the potential for issues with moving fittings and trimming doors, + # as well as scope for damage to the existing floor during preparation. + contingency_cost = subtotal_before_profit * self.HIGH_RISH_CONTINGENCY + preliminaries_cost = subtotal_before_profit * self.PRELIMINARIES + profit_cost = subtotal_before_profit * self.PROFIT_MARGIN + + subtotal_before_vat = subtotal_before_profit + contingency_cost + preliminaries_cost + profit_cost + vat_cost = subtotal_before_vat * self.VAT_RATE + total_cost = subtotal_before_vat + vat_cost + + demolition_labour_hours = sum([x["labour_hours_per_unit"] * insulation_floor_area for x in demolition_data]) + preparation_labour_hours = sum([x["labour_hours_per_unit"] * insulation_floor_area for x in preparation_data]) + insulation_labour_hours = material["labour_hours_per_unit"] * insulation_floor_area + vapour_barrier_labour_hours = vapour_barrier_data[0]["labour_hours_per_unit"] * insulation_floor_area + redecoration_labour_hours = sum([x["labour_hours_per_unit"] * insulation_floor_area for x in redecoration_data]) + + labour_hours = (demolition_labour_hours + insulation_labour_hours + vapour_barrier_labour_hours + + redecoration_labour_hours + preparation_labour_hours) + + # Assume a team of 3 people for a small to medium size project + labour_days = (labour_hours / 8) / 3 + + return { + "total": total_cost, + "subtotal": subtotal_before_vat, + "vat": vat_cost, + "contingency": contingency_cost, + "preliminaries": preliminaries_cost, + "material": materials_cost, + "profit": profit_cost, + "labour_hours": labour_hours, + "labour_days": labour_days + }