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.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/lib/openstudio-standards/btap/costing/README.md +502 -0
  3. data/lib/openstudio-standards/btap/costing/btap_costing.rb +473 -0
  4. data/lib/openstudio-standards/btap/costing/btap_measure_helper.rb +359 -0
  5. data/lib/openstudio-standards/btap/costing/btap_workflow.rb +117 -0
  6. data/lib/openstudio-standards/btap/costing/common_paths.rb +78 -0
  7. data/lib/openstudio-standards/btap/costing/common_resources/ConstructionProperties.csv +52 -0
  8. data/lib/openstudio-standards/btap/costing/common_resources/Constructions.csv +37 -0
  9. data/lib/openstudio-standards/btap/costing/common_resources/construction_sets.csv +1270 -0
  10. data/lib/openstudio-standards/btap/costing/common_resources/constructions_glazing.csv +61 -0
  11. data/lib/openstudio-standards/btap/costing/common_resources/constructions_opaque.csv +2256 -0
  12. data/lib/openstudio-standards/btap/costing/common_resources/costs.csv +1904 -0
  13. data/lib/openstudio-standards/btap/costing/common_resources/costs_local_factors.csv +2315 -0
  14. data/lib/openstudio-standards/btap/costing/common_resources/hvac_vent_ahu.csv +925 -0
  15. data/lib/openstudio-standards/btap/costing/common_resources/lighting.csv +364 -0
  16. data/lib/openstudio-standards/btap/costing/common_resources/lighting_sets.csv +2667 -0
  17. data/lib/openstudio-standards/btap/costing/common_resources/locations.csv +75 -0
  18. data/lib/openstudio-standards/btap/costing/common_resources/materials_glazing.csv +35 -0
  19. data/lib/openstudio-standards/btap/costing/common_resources/materials_hvac.csv +1699 -0
  20. data/lib/openstudio-standards/btap/costing/common_resources/materials_lighting.csv +267 -0
  21. data/lib/openstudio-standards/btap/costing/common_resources/materials_opaque.csv +164 -0
  22. data/lib/openstudio-standards/btap/costing/copy_test_results_files_to_expected_results.rb +11 -0
  23. data/lib/openstudio-standards/btap/costing/cost_building_from_file.rb +136 -0
  24. data/lib/openstudio-standards/btap/costing/costing_database_wrapper.rb +177 -0
  25. data/lib/openstudio-standards/btap/costing/daylighting_sensor_control_costing.rb +353 -0
  26. data/lib/openstudio-standards/btap/costing/dcv_costing.rb +314 -0
  27. data/lib/openstudio-standards/btap/costing/dummy.epw +8768 -0
  28. data/lib/openstudio-standards/btap/costing/dummy.osm +5320 -0
  29. data/lib/openstudio-standards/btap/costing/envelope_costing.rb +284 -0
  30. data/lib/openstudio-standards/btap/costing/heating_cooling_costing.rb +2584 -0
  31. data/lib/openstudio-standards/btap/costing/led_lighting_costing.rb +155 -0
  32. data/lib/openstudio-standards/btap/costing/lighting_costing.rb +209 -0
  33. data/lib/openstudio-standards/btap/costing/mech_sizing.json +502 -0
  34. data/lib/openstudio-standards/btap/costing/neb_end_use_prices.csv +42 -0
  35. data/lib/openstudio-standards/btap/costing/necb_2011_spacetype_info.csv +225 -0
  36. data/lib/openstudio-standards/btap/costing/necb_reference_runs.csv +28705 -0
  37. data/lib/openstudio-standards/btap/costing/nv_costing.rb +547 -0
  38. data/lib/openstudio-standards/btap/costing/parallel_tests.rb +92 -0
  39. data/lib/openstudio-standards/btap/costing/pv_ground_costing.rb +687 -0
  40. data/lib/openstudio-standards/btap/costing/shw_costing.rb +705 -0
  41. data/lib/openstudio-standards/btap/costing/test_list.txt +17 -0
  42. data/lib/openstudio-standards/btap/costing/test_run_all_test_locally.rb +26 -0
  43. data/lib/openstudio-standards/btap/costing/test_run_costing_tests.rb +80 -0
  44. data/lib/openstudio-standards/btap/costing/ventilation_costing.rb +2616 -0
  45. data/lib/openstudio-standards/constructions/modify.rb +2 -1
  46. data/lib/openstudio-standards/standards/Standards.Model.rb +39 -9
  47. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.Model.rb +2 -2
  48. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/ashrae_90_1_prm.UserData.rb +6 -1
  49. data/lib/openstudio-standards/standards/necb/BTAPPRE1980/btap_pre1980.rb +2 -27
  50. data/lib/openstudio-standards/standards/necb/BTAPPRE1980/hvac_system_3_and_8_single_speed.rb +68 -27
  51. data/lib/openstudio-standards/standards/necb/BTAPPRE1980/hvac_system_4.rb +64 -25
  52. data/lib/openstudio-standards/standards/necb/BTAPPRE1980/hvac_system_6.rb +9 -14
  53. data/lib/openstudio-standards/standards/necb/ECMS/hvac_systems.rb +46 -20
  54. data/lib/openstudio-standards/standards/necb/NECB2011/autozone.rb +635 -248
  55. data/lib/openstudio-standards/standards/necb/NECB2011/data/constants.json +43 -7
  56. data/lib/openstudio-standards/standards/necb/NECB2011/data/fuel_type_sets.json +7 -1
  57. data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/HighriseApartmentMult.osm +14272 -0
  58. data/lib/openstudio-standards/standards/necb/NECB2011/data/necb_2015_table_c1.json +1 -1
  59. data/lib/openstudio-standards/standards/necb/NECB2011/data/space_types.json +437 -437
  60. data/lib/openstudio-standards/standards/necb/NECB2011/data/systems.json +516 -0
  61. data/lib/openstudio-standards/standards/necb/NECB2011/data/systems_including_sys5.json +588 -0
  62. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_namer.rb +489 -0
  63. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_1_single_speed.rb +16 -6
  64. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_2_and_5.rb +48 -5
  65. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_3_and_8_multi_speed.rb +2 -2
  66. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_3_and_8_single_speed.rb +35 -27
  67. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_4.rb +34 -23
  68. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_6.rb +8 -6
  69. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_systems.rb +42 -13
  70. data/lib/openstudio-standards/standards/necb/NECB2011/necb_2011.rb +214 -25
  71. data/lib/openstudio-standards/standards/necb/NECB2011/system_fuels.rb +61 -1
  72. data/lib/openstudio-standards/standards/necb/NECB2015/data/space_types.json +636 -636
  73. data/lib/openstudio-standards/standards/necb/NECB2015/data/unitary_acs.json +38 -38
  74. data/lib/openstudio-standards/standards/necb/NECB2015/hvac_systems.rb +15 -6
  75. data/lib/openstudio-standards/standards/necb/NECB2017/data/space_types.json +636 -636
  76. data/lib/openstudio-standards/standards/necb/NECB2020/data/chillers.json +71 -71
  77. data/lib/openstudio-standards/standards/necb/README.md +343 -0
  78. data/lib/openstudio-standards/standards/necb/common/btap_data.rb +190 -28
  79. data/lib/openstudio-standards/standards/necb/common/btap_datapoint.rb +14 -5
  80. data/lib/openstudio-standards/standards/necb/common/eccc_electric_grid_intensity_20250311.csv +14 -0
  81. data/lib/openstudio-standards/standards/necb/common/nir_gas_grid_intensity_20250311.csv +14 -0
  82. data/lib/openstudio-standards/standards/necb/common/system_types.yaml +0 -0
  83. data/lib/openstudio-standards/utilities/logging.rb +18 -14
  84. data/lib/openstudio-standards/version.rb +1 -1
  85. data/lib/openstudio-standards/weather/modify.rb +2 -2
  86. data/lib/openstudio-standards.rb +12 -0
  87. 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