openstudio-standards 0.8.3 → 0.8.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/openstudio-standards/btap/costing/README.md +502 -0
- data/lib/openstudio-standards/btap/costing/btap_costing.rb +473 -0
- data/lib/openstudio-standards/btap/costing/btap_measure_helper.rb +359 -0
- data/lib/openstudio-standards/btap/costing/btap_workflow.rb +117 -0
- data/lib/openstudio-standards/btap/costing/common_paths.rb +78 -0
- data/lib/openstudio-standards/btap/costing/common_resources/ConstructionProperties.csv +52 -0
- data/lib/openstudio-standards/btap/costing/common_resources/Constructions.csv +37 -0
- data/lib/openstudio-standards/btap/costing/common_resources/construction_sets.csv +1270 -0
- data/lib/openstudio-standards/btap/costing/common_resources/constructions_glazing.csv +61 -0
- data/lib/openstudio-standards/btap/costing/common_resources/constructions_opaque.csv +2256 -0
- data/lib/openstudio-standards/btap/costing/common_resources/costs.csv +1904 -0
- data/lib/openstudio-standards/btap/costing/common_resources/costs_local_factors.csv +2315 -0
- data/lib/openstudio-standards/btap/costing/common_resources/hvac_vent_ahu.csv +925 -0
- data/lib/openstudio-standards/btap/costing/common_resources/lighting.csv +364 -0
- data/lib/openstudio-standards/btap/costing/common_resources/lighting_sets.csv +2667 -0
- data/lib/openstudio-standards/btap/costing/common_resources/locations.csv +75 -0
- data/lib/openstudio-standards/btap/costing/common_resources/materials_glazing.csv +35 -0
- data/lib/openstudio-standards/btap/costing/common_resources/materials_hvac.csv +1699 -0
- data/lib/openstudio-standards/btap/costing/common_resources/materials_lighting.csv +267 -0
- data/lib/openstudio-standards/btap/costing/common_resources/materials_opaque.csv +164 -0
- data/lib/openstudio-standards/btap/costing/copy_test_results_files_to_expected_results.rb +11 -0
- data/lib/openstudio-standards/btap/costing/cost_building_from_file.rb +136 -0
- data/lib/openstudio-standards/btap/costing/costing_database_wrapper.rb +177 -0
- data/lib/openstudio-standards/btap/costing/daylighting_sensor_control_costing.rb +353 -0
- data/lib/openstudio-standards/btap/costing/dcv_costing.rb +314 -0
- data/lib/openstudio-standards/btap/costing/dummy.epw +8768 -0
- data/lib/openstudio-standards/btap/costing/dummy.osm +5320 -0
- data/lib/openstudio-standards/btap/costing/envelope_costing.rb +284 -0
- data/lib/openstudio-standards/btap/costing/heating_cooling_costing.rb +2584 -0
- data/lib/openstudio-standards/btap/costing/led_lighting_costing.rb +155 -0
- data/lib/openstudio-standards/btap/costing/lighting_costing.rb +209 -0
- data/lib/openstudio-standards/btap/costing/mech_sizing.json +502 -0
- data/lib/openstudio-standards/btap/costing/neb_end_use_prices.csv +42 -0
- data/lib/openstudio-standards/btap/costing/necb_2011_spacetype_info.csv +225 -0
- data/lib/openstudio-standards/btap/costing/necb_reference_runs.csv +28705 -0
- data/lib/openstudio-standards/btap/costing/nv_costing.rb +547 -0
- data/lib/openstudio-standards/btap/costing/parallel_tests.rb +92 -0
- data/lib/openstudio-standards/btap/costing/pv_ground_costing.rb +687 -0
- data/lib/openstudio-standards/btap/costing/shw_costing.rb +705 -0
- data/lib/openstudio-standards/btap/costing/test_list.txt +17 -0
- data/lib/openstudio-standards/btap/costing/test_run_all_test_locally.rb +26 -0
- data/lib/openstudio-standards/btap/costing/test_run_costing_tests.rb +80 -0
- data/lib/openstudio-standards/btap/costing/ventilation_costing.rb +2616 -0
- data/lib/openstudio-standards/constructions/modify.rb +2 -1
- data/lib/openstudio-standards/standards/Standards.Model.rb +39 -9
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.Model.rb +2 -2
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/ashrae_90_1_prm.UserData.rb +6 -1
- data/lib/openstudio-standards/standards/necb/BTAPPRE1980/btap_pre1980.rb +2 -27
- data/lib/openstudio-standards/standards/necb/BTAPPRE1980/hvac_system_3_and_8_single_speed.rb +68 -27
- data/lib/openstudio-standards/standards/necb/BTAPPRE1980/hvac_system_4.rb +64 -25
- data/lib/openstudio-standards/standards/necb/BTAPPRE1980/hvac_system_6.rb +9 -14
- data/lib/openstudio-standards/standards/necb/ECMS/hvac_systems.rb +46 -20
- data/lib/openstudio-standards/standards/necb/NECB2011/autozone.rb +635 -248
- data/lib/openstudio-standards/standards/necb/NECB2011/data/constants.json +43 -7
- data/lib/openstudio-standards/standards/necb/NECB2011/data/fuel_type_sets.json +7 -1
- data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/HighriseApartmentMult.osm +14272 -0
- data/lib/openstudio-standards/standards/necb/NECB2011/data/necb_2015_table_c1.json +1 -1
- data/lib/openstudio-standards/standards/necb/NECB2011/data/space_types.json +437 -437
- data/lib/openstudio-standards/standards/necb/NECB2011/data/systems.json +516 -0
- data/lib/openstudio-standards/standards/necb/NECB2011/data/systems_including_sys5.json +588 -0
- data/lib/openstudio-standards/standards/necb/NECB2011/hvac_namer.rb +489 -0
- data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_1_single_speed.rb +16 -6
- data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_2_and_5.rb +48 -5
- data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_3_and_8_multi_speed.rb +2 -2
- data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_3_and_8_single_speed.rb +35 -27
- data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_4.rb +34 -23
- data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_6.rb +8 -6
- data/lib/openstudio-standards/standards/necb/NECB2011/hvac_systems.rb +42 -13
- data/lib/openstudio-standards/standards/necb/NECB2011/necb_2011.rb +214 -25
- data/lib/openstudio-standards/standards/necb/NECB2011/system_fuels.rb +61 -1
- data/lib/openstudio-standards/standards/necb/NECB2015/data/space_types.json +636 -636
- data/lib/openstudio-standards/standards/necb/NECB2015/data/unitary_acs.json +38 -38
- data/lib/openstudio-standards/standards/necb/NECB2015/hvac_systems.rb +15 -6
- data/lib/openstudio-standards/standards/necb/NECB2017/data/space_types.json +636 -636
- data/lib/openstudio-standards/standards/necb/NECB2020/data/chillers.json +71 -71
- data/lib/openstudio-standards/standards/necb/README.md +343 -0
- data/lib/openstudio-standards/standards/necb/common/btap_data.rb +190 -28
- data/lib/openstudio-standards/standards/necb/common/btap_datapoint.rb +14 -5
- data/lib/openstudio-standards/standards/necb/common/eccc_electric_grid_intensity_20250311.csv +14 -0
- data/lib/openstudio-standards/standards/necb/common/nir_gas_grid_intensity_20250311.csv +14 -0
- data/lib/openstudio-standards/standards/necb/common/system_types.yaml +0 -0
- data/lib/openstudio-standards/utilities/logging.rb +18 -14
- data/lib/openstudio-standards/version.rb +1 -1
- data/lib/openstudio-standards/weather/modify.rb +2 -2
- data/lib/openstudio-standards.rb +12 -0
- metadata +53 -2
@@ -0,0 +1,155 @@
|
|
1
|
+
class BTAPCosting
|
2
|
+
|
3
|
+
def cost_audit_led_lighting(model:, prototype_creator:)
|
4
|
+
a = 0 # This is for reporting purposes.
|
5
|
+
standards_template = model.building.get.standardsTemplate.to_s
|
6
|
+
if standards_template.include?('NECB')
|
7
|
+
standards_template = standards_template.gsub(/(?<=\p{L})(?=\d)/, ' ') #insert a space between NECB and 2011/2015/2017
|
8
|
+
end
|
9
|
+
# puts standards_template
|
10
|
+
|
11
|
+
#-------------------------------------------------------------------------------------------------------------------
|
12
|
+
led_cost_total = 0.0
|
13
|
+
#-------------------------------------------------------------------------------------------------------------------
|
14
|
+
model.getSpaces.sort.each do |space|
|
15
|
+
|
16
|
+
##### Find height of the space
|
17
|
+
max_space_height_m = 0.0
|
18
|
+
space.surfaces.sort.select { |surface| surface.surfaceType == 'Wall' }.each do |wall_surface|
|
19
|
+
# Find the vertex with the max z value.
|
20
|
+
vertex_with_max_height = wall_surface.vertices.max_by(&:z)
|
21
|
+
# Replace max if this surface has something bigger.
|
22
|
+
max_space_height_m = vertex_with_max_height.z if vertex_with_max_height.z > max_space_height_m
|
23
|
+
end
|
24
|
+
# puts "max_space_height_m - #{max_space_height_m}"
|
25
|
+
max_space_height_ft = (OpenStudio.convert(max_space_height_m, 'm', 'ft').get) #Convert height to ft
|
26
|
+
# puts "max_space_height_ft - #{max_space_height_ft}"
|
27
|
+
|
28
|
+
##### Find space's floor area
|
29
|
+
floor_surface = nil
|
30
|
+
floor_area_m2 = 0.0
|
31
|
+
floor_vertices = []
|
32
|
+
space.surfaces.sort.each do |surface|
|
33
|
+
# puts floor_area_m2
|
34
|
+
if surface.surfaceType == 'Floor'
|
35
|
+
floor_surface = surface
|
36
|
+
floor_area_m2 += surface.netArea
|
37
|
+
# puts floor_area_m2
|
38
|
+
end
|
39
|
+
end
|
40
|
+
floor_area_ft2 = (OpenStudio.convert(floor_area_m2, 'm^2', 'ft^2').get) #convert floor_area_m2 to ft2
|
41
|
+
# puts "floor_area_m2 - #{floor_area_m2}"
|
42
|
+
# puts "floor_area_ft2 - #{floor_area_ft2}"
|
43
|
+
|
44
|
+
##### Find type of the space
|
45
|
+
space_type = space.spaceType()
|
46
|
+
# puts space_type.get
|
47
|
+
space_type_name = space_type.get.standardsSpaceType
|
48
|
+
# puts "space_type_name - #{space_type_name}"
|
49
|
+
|
50
|
+
##### Figure out if the space has LED lighting; and calculate its associated cost
|
51
|
+
space_type.get.lights.sort.each do |light|
|
52
|
+
space_lights_definition = light.lightsDefinition
|
53
|
+
space_lights_definition_name = space_lights_definition.name
|
54
|
+
# puts space_lights_definition_name
|
55
|
+
|
56
|
+
if space_lights_definition_name.to_s.include?('LED lighting')
|
57
|
+
led_cost_space = 0.0
|
58
|
+
##### COSTING-related step: Find fixture type that should be used in the space based on space_type, template, and lights_type
|
59
|
+
search_fixture_type = {
|
60
|
+
row_id_1: space_type_name,
|
61
|
+
row_id_2: standards_template,
|
62
|
+
row_id_3: 'LED'
|
63
|
+
}
|
64
|
+
sheet_name = 'lighting_sets'
|
65
|
+
if max_space_height_ft < 7.88
|
66
|
+
column_search = 'Fixture_type_less_than_7.88ft_ht'
|
67
|
+
elsif max_space_height_ft >= 7.88 && max_space_height_ft < 15.75
|
68
|
+
column_search = 'Fixture_type_7.88_to_15.75ft_ht'
|
69
|
+
else #i.e. max_space_height_ft >= 15.75ft_ht
|
70
|
+
column_search = 'Fixture_type_greater_than_>15.75ft_ht'
|
71
|
+
end
|
72
|
+
row_search_1 = 'space_type'
|
73
|
+
row_search_2 = 'template'
|
74
|
+
row_search_3 = 'Type'
|
75
|
+
fixture_type = get_fixture_type_id(fixture_info: search_fixture_type, sheet_name: sheet_name, row_name_1: row_search_1, row_name_2: row_search_2, row_name_3: row_search_3, column_search: column_search)
|
76
|
+
# puts "fixture_type - #{fixture_type}"
|
77
|
+
|
78
|
+
##### COSTING-related step: Find 'id_layers' and 'Id_layers_quantity_multipliers' based on fixture_type; and calculate LED cost
|
79
|
+
search_id_layers = @costing_database['raw']['lighting'].select { |data|
|
80
|
+
data['lighting_type_id'].to_f.round(1) == fixture_type.to_f.round(1)
|
81
|
+
}.first
|
82
|
+
if search_id_layers.nil?
|
83
|
+
puts("No data found for #{search_id_layers}!")
|
84
|
+
raise
|
85
|
+
end
|
86
|
+
ids = search_id_layers['id_layers'].to_s.split(',')
|
87
|
+
# puts "id_layers - #{ids}"
|
88
|
+
|
89
|
+
search_id_layers_quantity_multipliers = @costing_database['raw']['lighting'].select { |data|
|
90
|
+
data['lighting_type_id'].to_f.round(1) == fixture_type.to_f.round(1)
|
91
|
+
}.first
|
92
|
+
if search_id_layers_quantity_multipliers.nil?
|
93
|
+
puts("No data found for #{search_id_layers_quantity_multipliers}!")
|
94
|
+
raise
|
95
|
+
end
|
96
|
+
id_quants = search_id_layers_quantity_multipliers['Id_layers_quantity_multipliers'].to_s.split(',')
|
97
|
+
# puts "id_layers_quantity_multipliers - #{id_quants}"
|
98
|
+
|
99
|
+
overall_mult = 1.0
|
100
|
+
|
101
|
+
index_id_quant = 0.0
|
102
|
+
ids.each do |id|
|
103
|
+
quantity_led = id_quants[index_id_quant].to_f * overall_mult * floor_area_ft2
|
104
|
+
# id_description_search = @costing_database['raw']['materials_lighting'].select { |data|
|
105
|
+
# data['lighting_type_id'].to_f.round(1) == id.to_f.round(1)
|
106
|
+
# }.first
|
107
|
+
# id_description = id_description_search['description']
|
108
|
+
|
109
|
+
search_led = {
|
110
|
+
row_id_1: nil,
|
111
|
+
row_id_2: id
|
112
|
+
}
|
113
|
+
sheet_name = 'materials_lighting'
|
114
|
+
column_1 = nil
|
115
|
+
column_2 = 'lighting_type_id'
|
116
|
+
tags = ['lighting', 'led_lighting']
|
117
|
+
led_costing = assembly_cost(cost_info:search_led,
|
118
|
+
sheet_name:sheet_name,
|
119
|
+
column_1:column_1,
|
120
|
+
column_2:column_2,
|
121
|
+
quantity:quantity_led,
|
122
|
+
tags: tags)
|
123
|
+
led_cost_space += led_costing
|
124
|
+
index_id_quant += 1.0
|
125
|
+
end
|
126
|
+
|
127
|
+
led_cost_total += led_cost_space
|
128
|
+
|
129
|
+
@costing_report["lighting"]["led_lighting"] << {
|
130
|
+
'space' => space.name.to_s,
|
131
|
+
'led_costing' => led_cost_space,
|
132
|
+
}
|
133
|
+
|
134
|
+
a += 1
|
135
|
+
|
136
|
+
end #if space_lights_definition_name.to_s.include?('LED lighting')
|
137
|
+
end #space_type.get.lights.sort.each do |light|
|
138
|
+
#-------------------------------------------------------------------------------------------------------------------
|
139
|
+
|
140
|
+
end #model.getSpaces.sort.each do |space|
|
141
|
+
#-------------------------------------------------------------------------------------------------------------------
|
142
|
+
|
143
|
+
if a > 0
|
144
|
+
@costing_report["lighting"]["led_lighting"] << {
|
145
|
+
'total_cost' => led_cost_total
|
146
|
+
}
|
147
|
+
end
|
148
|
+
|
149
|
+
puts "\nLED lighting costing data successfully generated. Total LED lighting costs: $#{led_cost_total.round(2)}"
|
150
|
+
|
151
|
+
return led_cost_total
|
152
|
+
|
153
|
+
end #cost_audit_led_lighting(model, prototype_creator)
|
154
|
+
|
155
|
+
end
|
@@ -0,0 +1,209 @@
|
|
1
|
+
class BTAPCosting
|
2
|
+
|
3
|
+
def cost_audit_lighting(model, prototype_creator)
|
4
|
+
# Store number of stories. Required for envelope costing logic.
|
5
|
+
num_of_above_ground_stories = model.getBuilding.standardsNumberOfAboveGroundStories.to_i
|
6
|
+
|
7
|
+
template_type = prototype_creator.template
|
8
|
+
|
9
|
+
closest_loc = get_closest_cost_location(model.getWeatherFile.latitude, model.getWeatherFile.longitude)
|
10
|
+
generate_construction_cost_database_for_city(@costing_report["city"],@costing_report["province_state"])
|
11
|
+
|
12
|
+
totLgtCost = 0
|
13
|
+
|
14
|
+
# daylighting sensor control costing
|
15
|
+
dsc_cost_total = cost_audit_daylighting_sensor_control(model: model, prototype_creator: prototype_creator)
|
16
|
+
|
17
|
+
# led lighting costing
|
18
|
+
led_cost_total = cost_audit_led_lighting(model: model, prototype_creator: prototype_creator)
|
19
|
+
|
20
|
+
totLgtCost += dsc_cost_total
|
21
|
+
|
22
|
+
# Iterate through the thermal zones.
|
23
|
+
|
24
|
+
#Create Zonal report.
|
25
|
+
@costing_report["lighting"]["fixture_report"] = []
|
26
|
+
@costing_report["lighting"]["space_report"] = []
|
27
|
+
model.getThermalZones.sort.each do |zone|
|
28
|
+
# Iterate through spaces.
|
29
|
+
spaceNum = 0 # Counting number of spaces for reporting
|
30
|
+
total_with_region = 0
|
31
|
+
zone.spaces.sort.each do |space|
|
32
|
+
spaceNum += 1 # Counting number of spaces for reporting
|
33
|
+
# Get SpaceType defined for space.. if not defined it will skip the spacetype. May have to deal with Attic spaces.
|
34
|
+
if space.spaceType.empty? or space.spaceType.get.standardsSpaceType.empty? or space.spaceType.get.standardsBuildingType.empty?
|
35
|
+
raise ("standards Space type and building type is not defined for space:#{space.name.get}. Skipping this space for costing.")
|
36
|
+
end
|
37
|
+
|
38
|
+
# Get space type standard names.
|
39
|
+
space_type = space.spaceType.get.standardsSpaceType
|
40
|
+
building_type = space.spaceType.get.standardsBuildingType
|
41
|
+
space_light = space.spaceType.get.lights
|
42
|
+
space_has_no_light = space_light.empty?
|
43
|
+
|
44
|
+
# Figure out what light_type is used in the building
|
45
|
+
light_type = 'Nil'
|
46
|
+
if space_has_no_light == false
|
47
|
+
space.spaceType.get.lights.sort.each do |light|
|
48
|
+
space_lights_definition = light.lightsDefinition
|
49
|
+
space_lights_definition_name = space_lights_definition.name
|
50
|
+
if space_lights_definition_name.to_s.include?('LED lighting') or template_type=='NECB2020' # Note: NECB2020's lights default is LED
|
51
|
+
light_type = 'LED'
|
52
|
+
else
|
53
|
+
light_type = 'CFL'
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Get standard lighting sets based on collected information (spacetype, no of stories, etc..)
|
59
|
+
if space_has_no_light == false
|
60
|
+
lighting_set = @costing_database['raw']['lighting_sets'].detect {|data|
|
61
|
+
data['template'].to_s.gsub(/\s*/, '') == template_type and
|
62
|
+
data['building_type'].to_s.downcase == building_type.to_s.downcase and
|
63
|
+
data['space_type'].to_s.downcase == space_type.to_s.downcase and
|
64
|
+
data['Type'].to_s.downcase == light_type.to_s.downcase
|
65
|
+
}
|
66
|
+
else
|
67
|
+
lighting_set = @costing_database['raw']['lighting_sets'].detect {|data|
|
68
|
+
data['template'].to_s.gsub(/\s*/, '') == template_type and
|
69
|
+
data['building_type'].to_s.downcase == building_type.to_s.downcase and
|
70
|
+
data['space_type'].to_s.downcase == space_type.to_s.downcase
|
71
|
+
}
|
72
|
+
end
|
73
|
+
|
74
|
+
# Determine average space height using space volume and floor area (convert to feet)
|
75
|
+
ceilHgt, flrArea = 0
|
76
|
+
if space.floorArea > 0
|
77
|
+
ceilHgt = space.volume / space.floorArea
|
78
|
+
ceilHgt = OpenStudio.convert(ceilHgt,"m","ft").get
|
79
|
+
flrArea = OpenStudio.convert(space.floorArea,"m^2","ft^2").get
|
80
|
+
end
|
81
|
+
|
82
|
+
# Find Fixture type for this space ceiling height (ft)
|
83
|
+
fixtureType = 'Nil'
|
84
|
+
fixture_description = ""
|
85
|
+
if lighting_set.nil?
|
86
|
+
raise("Error: lighting_set empty for zone #{zone.name.to_s} and space type #{building_type} #{space_type.to_s}!")
|
87
|
+
else
|
88
|
+
if ceilHgt > 0 && ceilHgt < 7.88
|
89
|
+
fixtureType = lighting_set["Fixture_type_less_than_7.88ft_ht"]
|
90
|
+
elsif ceilHgt >= 7.88 && ceilHgt <= 15.75
|
91
|
+
fixtureType = lighting_set["Fixture_type_7.88_to_15.75ft_ht"]
|
92
|
+
elsif ceilHgt > 15.75
|
93
|
+
fixtureType = lighting_set["Fixture_type_greater_than_>15.75ft_ht"]
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# Costs are 0 for 'Nil' because no fixture type due to either zero floor area, zero ceiling height or a 'Nil'
|
98
|
+
# setting for fixture type in lighting_sets sheet ("- undefined -" space)
|
99
|
+
if fixtureType != 'Nil'
|
100
|
+
# Get lighting type sets based on fixtureType
|
101
|
+
lighting_type = @costing_database['raw']['lighting'].select {|lighting_layer_data|
|
102
|
+
lighting_layer_data['lighting_type_id'].to_s == fixtureType.to_s
|
103
|
+
}.first
|
104
|
+
|
105
|
+
# Scan through layer IDs in id_layers field to get API data from materials_lighting sheet
|
106
|
+
materials_lighting_database = @costing_database["raw"]["materials_lighting"]
|
107
|
+
|
108
|
+
layer_type_IDs = []
|
109
|
+
layer_type_mult = []
|
110
|
+
layer_MaterialCost = 0
|
111
|
+
layer_LabourCost = 0
|
112
|
+
|
113
|
+
if lighting_type["id_layers"].empty?
|
114
|
+
raise ("Lighting type layers list for lighting type ID #{fixtureType} is empty.")
|
115
|
+
else
|
116
|
+
layer_type_IDs = lighting_type["id_layers"].split(/\s*,\s*/)
|
117
|
+
layer_type_mult = lighting_type["Id_layers_quantity_multipliers"].split(/\s*,\s*/)
|
118
|
+
lighting_layers = layer_type_IDs.zip(layer_type_mult).to_h
|
119
|
+
|
120
|
+
lighting_layers.each do |layer_id, layer_mult|
|
121
|
+
# Note: The column in the spreadsheet labelled "lighting_type_id" is mislabelled and should
|
122
|
+
# really be "lighting_type_layer_id" but left it as-is (below).
|
123
|
+
lighting_material = materials_lighting_database.find do |data|
|
124
|
+
data["lighting_type_id"].to_s == layer_id.to_s
|
125
|
+
end
|
126
|
+
if lighting_material.nil?
|
127
|
+
puts "Lighting material error..could not find lighting material #{layer_id} in #{materials_lighting_database}"
|
128
|
+
raise
|
129
|
+
else
|
130
|
+
costing_data = @costing_database['costs'].detect {|data| data['id'].to_s.upcase == lighting_material['id'].to_s.upcase}
|
131
|
+
if costing_data.nil?
|
132
|
+
puts "Lighting material id #{lighting_material['id']} not found in costing data. Skipping."
|
133
|
+
raise
|
134
|
+
else
|
135
|
+
# Get cost information from lookup.
|
136
|
+
material_cost = costing_data['baseCosts']['materialOpCost'].to_f * layer_mult.to_f * flrArea * zone.multiplier
|
137
|
+
labour_cost = costing_data['baseCosts']['laborOpCost'].to_f * layer_mult.to_f * flrArea * zone.multiplier
|
138
|
+
layer_MaterialCost += material_cost
|
139
|
+
layer_LabourCost += labour_cost
|
140
|
+
|
141
|
+
regional_material, regional_installation =
|
142
|
+
get_regional_cost_factors(@costing_report["province_state"], @costing_report["city"], lighting_material)
|
143
|
+
total_with_region = layer_MaterialCost * regional_material / 100.0 + layer_LabourCost * regional_installation / 100.0
|
144
|
+
|
145
|
+
# Gather info for costed items output file
|
146
|
+
tags = ['lighting','necb_default']
|
147
|
+
add_costed_item(material_id: costing_data['id'],
|
148
|
+
quantity: layer_mult.to_f * flrArea * zone.multiplier,
|
149
|
+
material_mult: costing_data['material_mult'].to_f,
|
150
|
+
labour_mult: costing_data['labour_mult'].to_f,
|
151
|
+
equip_mult: 1.0,
|
152
|
+
tags: tags)
|
153
|
+
|
154
|
+
|
155
|
+
end # costing_data Nil check
|
156
|
+
end # lighting_material Nil check
|
157
|
+
end # lighting layer ids loop
|
158
|
+
|
159
|
+
totLgtCost += total_with_region
|
160
|
+
fixture_description = lighting_type["description"]
|
161
|
+
end # lighting layer ids check
|
162
|
+
end # fixtureType Nil check
|
163
|
+
|
164
|
+
zName = zone.name.to_s
|
165
|
+
|
166
|
+
# Create Lighting space report.
|
167
|
+
@costing_report["lighting"]["space_report"] << {
|
168
|
+
'space' => space.name.to_s,
|
169
|
+
'zone' => zone.name.to_s,
|
170
|
+
'building_type' =>space.spaceType.get.standardsBuildingType.to_s,
|
171
|
+
'space_type' => space.spaceType.get.standardsSpaceType.to_s,
|
172
|
+
'zone_multiplier' => space.multiplier,
|
173
|
+
'fixture_type' => fixtureType,
|
174
|
+
'fixture_desciption' => fixture_description,
|
175
|
+
'height_avg_ft' => ceilHgt.round(1),
|
176
|
+
'floor_area_ft2' => (flrArea * space.multiplier).round(1),
|
177
|
+
'cost' => total_with_region.round(2),
|
178
|
+
'cost_per_ft2' => (total_with_region / ( flrArea * space.multiplier )).round(2),
|
179
|
+
'note' => ""
|
180
|
+
}
|
181
|
+
|
182
|
+
# Create Lighting Zonal report.
|
183
|
+
lighting_fixture_report = @costing_report["lighting"]["fixture_report"].detect {|fixture_report| fixture_report["fixture_type"] == fixtureType}
|
184
|
+
unless lighting_fixture_report.nil?
|
185
|
+
lighting_fixture_report['floor_area_ft2'] = (lighting_fixture_report['floor_area_ft2'] + (flrArea * space.multiplier)).round(1)
|
186
|
+
lighting_fixture_report['cost'] = (lighting_fixture_report['cost'] + total_with_region).round(2)
|
187
|
+
lighting_fixture_report['cost_per_ft2'] = (lighting_fixture_report['cost'] / lighting_fixture_report['floor_area_ft2']).round(2)
|
188
|
+
lighting_fixture_report['spaces'] << space.name.get
|
189
|
+
lighting_fixture_report['number_of_spaces'] = lighting_fixture_report['spaces'].size
|
190
|
+
else
|
191
|
+
@costing_report["lighting"]["fixture_report"] << {
|
192
|
+
'fixture_type' => fixtureType,
|
193
|
+
'fixture_description' => fixture_description,
|
194
|
+
'floor_area_ft2' => (flrArea * space.multiplier).round(1),
|
195
|
+
'cost' => total_with_region.round(2),
|
196
|
+
'cost_per_ft2' => (total_with_region / (flrArea * space.multiplier)).round(2),
|
197
|
+
'spaces' => [space.name.get],
|
198
|
+
'number_of_spaces' => 1
|
199
|
+
}
|
200
|
+
end
|
201
|
+
end # Spaces loop
|
202
|
+
end # thermalzone loop
|
203
|
+
|
204
|
+
@costing_report["lighting"]['total_lighting_cost'] = totLgtCost.round(2)
|
205
|
+
puts "\nLighting costing data successfully generated. Total lighting cost is $#{totLgtCost.round(2)}"
|
206
|
+
|
207
|
+
return totLgtCost
|
208
|
+
end
|
209
|
+
end
|