buildingsync 0.2.0

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 (62) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/continuous_integration.yml +146 -0
  3. data/.gitignore +33 -0
  4. data/.rspec +3 -0
  5. data/.rubocop.yml +10 -0
  6. data/CHANGELOG.md +50 -0
  7. data/Gemfile +31 -0
  8. data/Jenkinsfile +10 -0
  9. data/LICENSE.md +29 -0
  10. data/README.md +105 -0
  11. data/Rakefile +77 -0
  12. data/bin/console +15 -0
  13. data/bin/setup +8 -0
  14. data/buildingsync.gemspec +37 -0
  15. data/config.rb.in +26 -0
  16. data/doc_templates/LICENSE.md +29 -0
  17. data/doc_templates/README.md.erb +42 -0
  18. data/doc_templates/copyright_erb.txt +38 -0
  19. data/doc_templates/copyright_js.txt +5 -0
  20. data/doc_templates/copyright_ruby.txt +36 -0
  21. data/lib/buildingsync.rb +43 -0
  22. data/lib/buildingsync/all_resource_total.rb +54 -0
  23. data/lib/buildingsync/audit_date.rb +54 -0
  24. data/lib/buildingsync/constants.rb +49 -0
  25. data/lib/buildingsync/contact.rb +54 -0
  26. data/lib/buildingsync/extension.rb +57 -0
  27. data/lib/buildingsync/generator.rb +584 -0
  28. data/lib/buildingsync/get_bcl_weather_file.rb +326 -0
  29. data/lib/buildingsync/helpers/Model.hvac.rb +216 -0
  30. data/lib/buildingsync/helpers/helper.rb +494 -0
  31. data/lib/buildingsync/helpers/xml_get_set.rb +215 -0
  32. data/lib/buildingsync/makers/phase_zero_base.osw +178 -0
  33. data/lib/buildingsync/makers/workflow_maker.json +811 -0
  34. data/lib/buildingsync/makers/workflow_maker.rb +581 -0
  35. data/lib/buildingsync/makers/workflow_maker_base.rb +167 -0
  36. data/lib/buildingsync/model_articulation/building.rb +1119 -0
  37. data/lib/buildingsync/model_articulation/building_and_system_types.json +121 -0
  38. data/lib/buildingsync/model_articulation/building_section.rb +190 -0
  39. data/lib/buildingsync/model_articulation/building_system.rb +49 -0
  40. data/lib/buildingsync/model_articulation/envelope_system.rb +102 -0
  41. data/lib/buildingsync/model_articulation/exterior_floor_system_type.rb +64 -0
  42. data/lib/buildingsync/model_articulation/facility.rb +439 -0
  43. data/lib/buildingsync/model_articulation/foundation_system_type.rb +64 -0
  44. data/lib/buildingsync/model_articulation/hvac_system.rb +395 -0
  45. data/lib/buildingsync/model_articulation/lighting_system.rb +102 -0
  46. data/lib/buildingsync/model_articulation/loads_system.rb +287 -0
  47. data/lib/buildingsync/model_articulation/location_element.rb +129 -0
  48. data/lib/buildingsync/model_articulation/measure.rb +57 -0
  49. data/lib/buildingsync/model_articulation/roof_system_type.rb +64 -0
  50. data/lib/buildingsync/model_articulation/service_hot_water_system.rb +87 -0
  51. data/lib/buildingsync/model_articulation/site.rb +242 -0
  52. data/lib/buildingsync/model_articulation/spatial_element.rb +343 -0
  53. data/lib/buildingsync/model_articulation/wall_system_type.rb +64 -0
  54. data/lib/buildingsync/report.rb +217 -0
  55. data/lib/buildingsync/resource_use.rb +55 -0
  56. data/lib/buildingsync/scenario.rb +622 -0
  57. data/lib/buildingsync/selection_tool.rb +98 -0
  58. data/lib/buildingsync/time_series.rb +85 -0
  59. data/lib/buildingsync/translator.rb +167 -0
  60. data/lib/buildingsync/utility.rb +67 -0
  61. data/lib/buildingsync/version.rb +45 -0
  62. metadata +223 -0
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ # *******************************************************************************
4
+ # OpenStudio(R), Copyright (c) 2008-2020, Alliance for Sustainable Energy, LLC.
5
+ # BuildingSync(R), Copyright (c) 2015-2020, Alliance for Sustainable Energy, LLC.
6
+ # All rights reserved.
7
+ #
8
+ # Redistribution and use in source and binary forms, with or without
9
+ # modification, are permitted provided that the following conditions are met:
10
+ #
11
+ # (1) Redistributions of source code must retain the above copyright notice,
12
+ # this list of conditions and the following disclaimer.
13
+ #
14
+ # (2) Redistributions in binary form must reproduce the above copyright notice,
15
+ # this list of conditions and the following disclaimer in the documentation
16
+ # and/or other materials provided with the distribution.
17
+ #
18
+ # (3) Neither the name of the copyright holder nor the names of any contributors
19
+ # may be used to endorse or promote products derived from this software without
20
+ # specific prior written permission from the respective party.
21
+ #
22
+ # (4) Other than as required in clauses (1) and (2), distributions in any form
23
+ # of modifications or other derivative works may not use the "OpenStudio"
24
+ # trademark, "OS", "os", or any other confusingly similar designation without
25
+ # specific prior written permission from Alliance for Sustainable Energy, LLC.
26
+ #
27
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS
28
+ # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
29
+ # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE
31
+ # UNITED STATES GOVERNMENT, OR THE UNITED STATES DEPARTMENT OF ENERGY, NOR ANY OF
32
+ # THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
33
+ # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
34
+ # OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36
+ # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37
+ # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38
+ # *******************************************************************************
39
+
40
+ module BuildingSync
41
+ # Contact class
42
+ class Contact
43
+ include BuildingSync::Helper
44
+ include BuildingSync::XmlGetSet
45
+ # @param base_xml [REXML::Element]
46
+ # @param ns [String]
47
+ def initialize(base_xml, ns)
48
+ @base_xml = base_xml
49
+ @ns = ns
50
+
51
+ help_element_class_type_check(base_xml, 'Contact')
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ # *******************************************************************************
4
+ # OpenStudio(R), Copyright (c) 2008-2020, Alliance for Sustainable Energy, LLC.
5
+ # BuildingSync(R), Copyright (c) 2015-2020, Alliance for Sustainable Energy, LLC.
6
+ # All rights reserved.
7
+ #
8
+ # Redistribution and use in source and binary forms, with or without
9
+ # modification, are permitted provided that the following conditions are met:
10
+ #
11
+ # (1) Redistributions of source code must retain the above copyright notice,
12
+ # this list of conditions and the following disclaimer.
13
+ #
14
+ # (2) Redistributions in binary form must reproduce the above copyright notice,
15
+ # this list of conditions and the following disclaimer in the documentation
16
+ # and/or other materials provided with the distribution.
17
+ #
18
+ # (3) Neither the name of the copyright holder nor the names of any contributors
19
+ # may be used to endorse or promote products derived from this software without
20
+ # specific prior written permission from the respective party.
21
+ #
22
+ # (4) Other than as required in clauses (1) and (2), distributions in any form
23
+ # of modifications or other derivative works may not use the "OpenStudio"
24
+ # trademark, "OS", "os", or any other confusingly similar designation without
25
+ # specific prior written permission from Alliance for Sustainable Energy, LLC.
26
+ #
27
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS
28
+ # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
29
+ # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE
31
+ # UNITED STATES GOVERNMENT, OR THE UNITED STATES DEPARTMENT OF ENERGY, NOR ANY OF
32
+ # THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
33
+ # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
34
+ # OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36
+ # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37
+ # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38
+ # *******************************************************************************
39
+
40
+ require 'openstudio/model_articulation/version'
41
+ require 'openstudio/extension'
42
+
43
+ module BuildingSync
44
+ # Extension class
45
+ class Extension < OpenStudio::Extension::Extension
46
+ # Override the base class
47
+ # The Extension class contains both the instance of the BuildingSync file (in XML) and the
48
+ # helper methods from the OpenStudio::Extension gem to support managing measures that are related
49
+ # to BuildingSync.
50
+ def initialize
51
+ # Initialize the root directory for use in the extension class. This must be done, otherwise the
52
+ # root_dir will be the root_dir in the OpenStudio Extension Gem.
53
+ super
54
+ @root_dir = File.absolute_path(File.join(File.dirname(__FILE__), '..', '..'))
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,584 @@
1
+ # frozen_string_literal: true
2
+
3
+ # *******************************************************************************
4
+ # OpenStudio(R), Copyright (c) 2008-2020, Alliance for Sustainable Energy, LLC.
5
+ # BuildingSync(R), Copyright (c) 2015-2020, Alliance for Sustainable Energy, LLC.
6
+ # All rights reserved.
7
+ #
8
+ # Redistribution and use in source and binary forms, with or without
9
+ # modification, are permitted provided that the following conditions are met:
10
+ #
11
+ # (1) Redistributions of source code must retain the above copyright notice,
12
+ # this list of conditions and the following disclaimer.
13
+ #
14
+ # (2) Redistributions in binary form must reproduce the above copyright notice,
15
+ # this list of conditions and the following disclaimer in the documentation
16
+ # and/or other materials provided with the distribution.
17
+ #
18
+ # (3) Neither the name of the copyright holder nor the names of any contributors
19
+ # may be used to endorse or promote products derived from this software without
20
+ # specific prior written permission from the respective party.
21
+ #
22
+ # (4) Other than as required in clauses (1) and (2), distributions in any form
23
+ # of modifications or other derivative works may not use the "OpenStudio"
24
+ # trademark, "OS", "os", or any other confusingly similar designation without
25
+ # specific prior written permission from Alliance for Sustainable Energy, LLC.
26
+ #
27
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS
28
+ # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
29
+ # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE
31
+ # UNITED STATES GOVERNMENT, OR THE UNITED STATES DEPARTMENT OF ENERGY, NOR ANY OF
32
+ # THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
33
+ # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
34
+ # OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36
+ # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37
+ # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38
+ # *******************************************************************************
39
+ require 'builder/xmlmarkup'
40
+ require 'rexml/document'
41
+
42
+ require 'buildingsync/helpers/helper'
43
+
44
+ module BuildingSync
45
+ # Generator class that generates basic data that is used mostly for testing
46
+ class Generator
47
+ include BuildingSync::Helper
48
+ # @param version [String] version of BuildingSync
49
+ def initialize(ns = 'auc', version = '2.2.0')
50
+ supported_versions = ['2.0', '2.2.0']
51
+ if !supported_versions.include? version
52
+ @version = nil
53
+ OpenStudio.logFree(OpenStudio::Error, 'BuildingSync.Generator.initialize', "The version: #{version} is not one of the supported versions: #{supported_versions}")
54
+ else
55
+ @version = version
56
+ end
57
+ @ns = ns
58
+ end
59
+
60
+ # Starts from scratch and creates all necessary elements up to and including an
61
+ # - Sites/Site/Buildings/Building/Sections/Section
62
+ # - Reports/Report/Scenarios/Scenario
63
+ # @return [String] string formatted XML document
64
+ def create_bsync_root_to_building
65
+ xml = Builder::XmlMarkup.new(indent: 2)
66
+ auc_ns = 'http://buildingsync.net/schemas/bedes-auc/2019'
67
+ location = "https://raw.githubusercontent.com/BuildingSync/schema/v#{@version}/BuildingSync.xsd"
68
+ xml.instruct! :xml
69
+ xml.tag!("#{@ns}:BuildingSync",
70
+ :"xmlns:#{@ns}" => auc_ns,
71
+ :"xsi:schemaLocation" => "#{auc_ns} #{location}",
72
+ :"xmlns:xsi" => 'http://www.w3.org/2001/XMLSchema-instance',
73
+ :version => @version.to_s) do |buildsync|
74
+
75
+ buildsync.tag!("#{@ns}:Facilities") do |faclts|
76
+ faclts.tag!("#{@ns}:Facility", ID: 'Facility1') do |faclt|
77
+ faclt.tag!("#{@ns}:Sites") do |sites|
78
+ sites.tag!("#{@ns}:Site", ID: 'Site1') do |site|
79
+ site.tag!("#{@ns}:Buildings") do |builds|
80
+ builds.tag!("#{@ns}:Building", ID: 'Building1') do |build|
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
89
+
90
+ def get_or_create_linked_premises(element_xml)
91
+ linked_premises_xml = help_get_or_create(element_xml, "#{@ns}:LinkedPremises")
92
+ return linked_premises_xml
93
+ end
94
+
95
+ def add_linked_premise_of_type(premise_type_xml, premise_type, id)
96
+ linked_xml = REXML::Element.new("#{@ns}:Linked#{premise_type}ID", premise_type_xml)
97
+ linked_xml.add_attribute('IDref', id)
98
+ return linked_xml
99
+ end
100
+
101
+ def get_or_create_premise_of_type(premise_xml, premise_type)
102
+ premise_type_xml = help_get_or_create(premise_xml, "#{@ns}:#{premise_type}")
103
+ return premise_type_xml
104
+ end
105
+
106
+ def add_linked_premise(base_xml, id, premise_type)
107
+ linked_premises_xml = get_or_create_linked_premises(base_xml)
108
+ premise_type_xml = get_or_create_premise_of_type(linked_premises_xml, premise_type)
109
+ add_linked_premise_of_type(premise_type_xml, premise_type, id)
110
+ return linked_premises_xml
111
+ end
112
+
113
+ def add_linked_building(base_xml, id)
114
+ add_linked_premise(base_xml, id, 'Building')
115
+ end
116
+
117
+ def add_linked_section(base_xml, id)
118
+ add_linked_premise(base_xml, id, 'Section')
119
+ end
120
+
121
+ # @see add_hvac_system_to_facility
122
+ def add_hvac_system_to_first_facility(doc, id = 'HVACSystem-1', principal_hvac_system_type = nil)
123
+ facility_xml = get_first_facility_element(doc)
124
+ return add_hvac_system_to_facility(facility_xml, id, principal_hvac_system_type)
125
+ end
126
+
127
+ # @see add_lighting_system_to_facility
128
+ def add_lighting_system_to_first_facility(doc, id = 'LightingSystem-1')
129
+ facility_xml = get_first_facility_element(doc)
130
+ return add_lighting_system_to_facility(facility_xml, id)
131
+ end
132
+
133
+ # @see add_plug_load_to_facility
134
+ def add_plug_load_to_first_facility(doc, id = 'PlugLoad-1')
135
+ facility_xml = get_first_facility_element(doc)
136
+ return add_plug_load_to_facility(facility_xml, id)
137
+ end
138
+
139
+ # Adds hvac system with id. also adds principal hvac element if specified
140
+ # @see get_or_create_system_of_type
141
+ # @param facility_xml [REXML::Element]
142
+ # @param id [String]
143
+ def add_hvac_system_to_facility(facility_xml, id = 'HVACSystem-1', principal_hvac_system_type = nil)
144
+ systems_xml = get_or_create_systems(facility_xml)
145
+ hvac_system_xml = get_or_create_system_of_type(systems_xml, 'HVACSystem')
146
+
147
+ hvac_system_xml.add_attribute('ID', id)
148
+ if !principal_hvac_system_type.nil?
149
+ principal_xml = REXML::Element.new("#{@ns}:PrincipalHVACSystemType", hvac_system_xml)
150
+ principal_xml.text = principal_hvac_system_type
151
+ end
152
+ return hvac_system_xml
153
+ end
154
+
155
+ # Adds lighting system with id. wrapper around:
156
+ # @see get_or_create_system_of_type
157
+ # @param facility_xml [REXML::Element]
158
+ # @param id [String]
159
+ def add_lighting_system_to_facility(facility_xml, id = 'LightingSystem-1')
160
+ systems_xml = get_or_create_systems(facility_xml)
161
+ lighting_system_xml = get_or_create_system_of_type(systems_xml, 'LightingSystem')
162
+ lighting_system_xml.add_attribute('ID', id)
163
+ return lighting_system_xml
164
+ end
165
+
166
+ # Adds plug load with id. wrapper around:
167
+ # @see get_or_create_system_of_type
168
+ # @param facility_xml [REXML::Element]
169
+ # @param id [String]
170
+ def add_plug_load_to_facility(facility_xml, id = 'PlugLoad-1')
171
+ systems_xml = get_or_create_systems(facility_xml)
172
+ new_system_xml = get_or_create_system_of_type(systems_xml, 'PlugLoad')
173
+ new_system_xml.add_attribute('ID', id)
174
+ return new_system_xml
175
+ end
176
+
177
+ # Create new system without id. Will check for pluralized version and create if not there,
178
+ # else gets existing pluralized version and adds new singular as child.
179
+ # @example:
180
+ # systems_xml = <auc:Systems/>
181
+ # system_type = HVACSystem
182
+ # returns <auc:Systems><auc:HVACSystems><auc:HVACSystem/></..></..>
183
+ # @example:
184
+ # systems_xml = <auc:Systems><auc:HVACSystems/></..>
185
+ # system_type = HVACSystem
186
+ # returns <auc:System><auc:HVACSystems><auc:HVACSystem/></..></..>
187
+ # @param systems_xml [REXML::Element] pass the auc:Systems element
188
+ # @param system_type [String] a valid BSync system type: HVACSystem, LightingSystem, etc.
189
+ def get_or_create_system_of_type(systems_xml, system_type)
190
+ new_systems_xml = help_get_or_create(systems_xml, "#{@ns}:#{system_type}s")
191
+ new_system_xml = REXML::Element.new("#{@ns}:#{system_type}", new_systems_xml)
192
+ return new_system_xml
193
+ end
194
+
195
+ # Get or create <auc:Systems/> from <auc:Facility>...</..>
196
+ def get_or_create_systems(facility_xml)
197
+ return help_get_or_create(facility_xml, "#{@ns}:Systems")
198
+ end
199
+
200
+ def add_section_to_first_building(doc, id = 'Section-1')
201
+ building_xml = get_first_building_element(doc)
202
+ sections_xml = help_get_or_create(building_xml, "#{@ns}:Sections")
203
+ section = REXML::Element.new("#{@ns}:Section", sections_xml)
204
+ section.add_attribute('ID', id)
205
+ return section
206
+ end
207
+
208
+ def add_energy_resource_use_to_scenario(scenario_xml, energy_resource_type = 'Electricity', end_use = 'All end uses', id = 'ResourceUse-1', native_units = nil)
209
+ resource_uses = help_get_or_create(scenario_xml, "#{@ns}:ResourceUses")
210
+
211
+ # Define ResourceUse and add ID
212
+ resource_use = REXML::Element.new("#{@ns}:ResourceUse", resource_uses)
213
+ resource_use.add_attribute('ID', id)
214
+
215
+ # Add ResourceUnits
216
+ if !native_units.nil?
217
+ nu = REXML::Element.new("#{@ns}:ResourceUnits", resource_use)
218
+ nu.text = native_units
219
+ end
220
+
221
+ # Add EnergyResource
222
+ energy_resource = REXML::Element.new("#{@ns}:EnergyResource", resource_use)
223
+ energy_resource.text = energy_resource_type
224
+
225
+ # Add EndUse
226
+ eu = REXML::Element.new("#{@ns}:EndUse", resource_use)
227
+ eu.text = end_use
228
+ return resource_use
229
+ end
230
+
231
+ def add_all_resource_total_to_scenario(scenario_xml, end_use = 'All end uses', id = 'AllResourceTotal-1')
232
+ all_resource_totals = help_get_or_create(scenario_xml, "#{@ns}:AllResourceTotals")
233
+
234
+ all_resource_total = REXML::Element.new("#{@ns}:AllResourceTotal", all_resource_totals)
235
+ all_resource_total.add_attribute('ID', id)
236
+ eu = REXML::Element.new("#{@ns}:EndUse", all_resource_total)
237
+ eu.text = end_use
238
+
239
+ return all_resource_total
240
+ end
241
+
242
+ def add_time_series_to_scenario(scenario_xml, id = 'TimeSeries-1')
243
+ time_series_data = help_get_or_create(scenario_xml, "#{@ns}:TimeSeriesData")
244
+ time_series = REXML::Element.new("#{@ns}:TimeSeries", time_series_data)
245
+ time_series.add_attribute('ID', id)
246
+ return time_series
247
+ end
248
+
249
+ # @param doc [REXML::Document]
250
+ # @param scenario_type [String] see add_scenario_type_to_scenario
251
+ # @param id [String] id for the new scenario
252
+ # @return [REXML::Element] newly added scenario
253
+ def add_scenario_to_first_report(doc, scenario_type = nil, id = 'Scenario-1')
254
+ report = doc.get_elements(".//#{@ns}:Reports/#{@ns}:Report").first
255
+ return add_scenario_to_report(report, scenario_type, id)
256
+ end
257
+
258
+ # Add a Scenario element to the Report XML element provided.
259
+ # If auc:Scenarios does not exist, this is added as well
260
+ # @param report_xml [REXML::Element] an XML element of auc:Report
261
+ # @param scenario_type [String] see add_scenario_type_to_scenario
262
+ # @param id [String] id of the Scenario element to add
263
+ # @return [REXML::Element] the newly created Scenario element
264
+ def add_scenario_to_report(report_xml, scenario_type = nil, id = 'Scenario-1')
265
+ scenarios = report_xml.get_elements("./#{@ns}:Scenarios").first
266
+ if scenarios.nil?
267
+ scenarios = REXML::Element.new("#{@ns}:Scenarios", report_xml)
268
+ end
269
+ scenario = REXML::Element.new("#{@ns}:Scenario", scenarios)
270
+ scenario.add_attribute('ID', id)
271
+ return add_scenario_type_to_scenario(scenario, scenario_type)
272
+ end
273
+
274
+ # Add a Report element to the first Facility in the doc.
275
+ # If auc:Reports does not exist, this is added as well
276
+ # @param doc [REXML::Document] a buildingsync document with atleast an auc:Facility
277
+ # @param id [String] id of the Report element to add
278
+ # @return [REXML::Element] the newly created Report element
279
+ def add_report_to_first_facility(doc, id = 'Report-1')
280
+ facility_xml = doc.get_elements(".//#{@ns}:Facilities/#{@ns}:Facility").first
281
+ reports = help_get_or_create(facility_xml, "#{@ns}:Reports")
282
+ report = REXML::Element.new("#{@ns}:Report", reports)
283
+ report.add_attribute('ID', id)
284
+ return report
285
+ end
286
+
287
+ # Add a specific scenario type to the provided scenario element
288
+ # @param scenario_element [REXML::Element]
289
+ # @param scenario_type [String] one of: ['CBMeasured', 'CBModeled', 'POM', 'Benchmark', 'Target']
290
+ # @return [REXML::Element] Scenario element
291
+ def add_scenario_type_to_scenario(scenario_element, scenario_type)
292
+ scenario_type_element = REXML::Element.new("#{@ns}:ScenarioType", scenario_element)
293
+ if scenario_type.nil?
294
+ return scenario_element
295
+ elsif scenario_type == 'CBMeasured'
296
+ cb_element = REXML::Element.new("#{@ns}:CurrentBuilding", scenario_type_element)
297
+ cm_element = REXML::Element.new("#{@ns}:CalculationMethod", cb_element)
298
+ measured = REXML::Element.new("#{@ns}:Measured", cm_element)
299
+ elsif scenario_type == 'CBModeled'
300
+ cb_element = REXML::Element.new("#{@ns}:CurrentBuilding", scenario_type_element)
301
+ cm_element = REXML::Element.new("#{@ns}:CalculationMethod", cb_element)
302
+ modeled = REXML::Element.new("#{@ns}:Modeled", cm_element)
303
+ elsif scenario_type == 'POM'
304
+ pom = REXML::Element.new("#{@ns}:PackageOfMeasures", scenario_type_element)
305
+ elsif scenario_type == 'Benchmark'
306
+ benchmark = REXML::Element.new("#{@ns}:Benchmark", scenario_type_element)
307
+ elsif scenario_type == 'Target'
308
+ target = REXML::Element.new("#{@ns}:Target", scenario_type_element)
309
+ end
310
+ return scenario_element
311
+ end
312
+
313
+ # creates a minimum building sync snippet
314
+ # @param occupancy_classification [String]
315
+ # @param year_of_const [Integer]
316
+ # @param floor_area_type [String]
317
+ # @param floor_area_value [Float]
318
+ # @param ns [String]
319
+ # @return REXML::Document
320
+ def create_minimum_snippet(occupancy_classification, year_of_const = 2000, floor_area_type = 'Gross', floor_area_value = 1000, floors_above_grade = 1)
321
+ doc_string = create_bsync_root_to_building
322
+ doc = REXML::Document.new(doc_string)
323
+
324
+ facility_element = doc.elements["/#{@ns}:BuildingSync/#{@ns}:Facilities/#{@ns}:Facility"]
325
+ site_element = facility_element.elements["#{@ns}:Sites/#{@ns}:Site"]
326
+ building_element = site_element.elements["#{@ns}:Buildings/#{@ns}:Building"]
327
+
328
+ # Add Facility info
329
+ report_element = add_report_to_first_facility(doc)
330
+ junk = add_scenario_to_report(report_element, 'CBModeled')
331
+
332
+ # Add Site info
333
+ occupancy_classification_element = REXML::Element.new("#{@ns}:OccupancyClassification", site_element)
334
+ occupancy_classification_element.text = occupancy_classification
335
+
336
+ # Add Building info
337
+ year_of_construction_element = REXML::Element.new("#{@ns}:YearOfConstruction", building_element)
338
+ year_of_construction_element.text = year_of_const
339
+ floor_areas_element = REXML::Element.new("#{@ns}:FloorAreas", building_element)
340
+ floor_area_element = REXML::Element.new("#{@ns}:FloorArea", floor_areas_element)
341
+ floor_area_type_element = REXML::Element.new("#{@ns}:FloorAreaType", floor_area_element)
342
+ floor_area_type_element.text = floor_area_type
343
+ floor_area_value_element = REXML::Element.new("#{@ns}:FloorAreaValue", floor_area_element)
344
+ floor_area_value_element.text = floor_area_value
345
+ floors_above_grade_element = REXML::Element.new("#{@ns}:FloorsAboveGrade", building_element)
346
+ floors_above_grade_element.text = floors_above_grade
347
+ occupancy_classification_element = REXML::Element.new("#{@ns}:OccupancyClassification", building_element)
348
+ occupancy_classification_element.text = occupancy_classification
349
+
350
+ return doc
351
+ end
352
+
353
+ # creates a minimum facility
354
+ # @param occupancy_classification [String]
355
+ # @param year_of_const [Integer]
356
+ # @param floor_area_type [String]
357
+ # @param floor_area_value [Float]
358
+ # @return BuildingSync::Facility
359
+ def create_minimum_facility(occupancy_classification, year_of_const, floor_area_type, floor_area_value, floors_above_grade = 1)
360
+ xml_snippet = create_minimum_snippet(occupancy_classification, year_of_const, floor_area_type, floor_area_value, floors_above_grade)
361
+ facility_element = xml_snippet.elements["/#{@ns}:BuildingSync/#{@ns}:Facilities/#{@ns}:Facility"]
362
+ if !facility_element.nil?
363
+ return BuildingSync::Facility.new(facility_element, @ns)
364
+ else
365
+ expect(facility_element.nil?).to be false
366
+ end
367
+ end
368
+
369
+ # create minimum site
370
+ # @param occupancy_classification [String]
371
+ # @param year_of_const [Integer]
372
+ # @param floor_area_type [String]
373
+ # @param floor_area_value [Float]
374
+ # @return [BuildingSync::Site]
375
+ def create_minimum_site(occupancy_classification, year_of_const, floor_area_type, floor_area_value)
376
+ xml_snippet = create_minimum_snippet(occupancy_classification, year_of_const, floor_area_type, floor_area_value)
377
+ site_element = xml_snippet.elements["/#{@ns}:BuildingSync/#{@ns}:Facilities/#{@ns}:Facility/#{@ns}:Sites/#{@ns}:Site"]
378
+ if !site_element.nil?
379
+ return BuildingSync::Site.new(site_element, @ns)
380
+ else
381
+ expect(site_element.nil?).to be false
382
+ end
383
+ end
384
+
385
+ def create_minimum_building(occupancy_classification, year_of_const, floor_area_type, floor_area_value)
386
+ xml_snippet = create_minimum_snippet(occupancy_classification, year_of_const, floor_area_type, floor_area_value)
387
+
388
+ building_element = xml_snippet.elements["/#{@ns}:BuildingSync/#{@ns}:Facilities/#{@ns}:Facility/#{@ns}:Sites/#{@ns}:Site/#{@ns}:Buildings/#{@ns}:Building"]
389
+ if !building_element.nil?
390
+ return BuildingSync::Building.new(building_element, '', '', @ns)
391
+ else
392
+ expect(building_element.nil?).to be false
393
+ end
394
+ end
395
+
396
+ def create_minimum_section_xml(typical_usage_hours = 40)
397
+ section = REXML::Element.new("#{@ns}:Section")
398
+ # adding the XML elements for the typical hourly usage per week
399
+ typical_usages = REXML::Element.new("#{@ns}:TypicalOccupantUsages")
400
+ section.add_element(typical_usages)
401
+ typical_usage = REXML::Element.new("#{@ns}:TypicalOccupantUsage")
402
+ typical_usages.add_element(typical_usage)
403
+ typical_usage_unit = REXML::Element.new("#{@ns}:TypicalOccupantUsageUnits")
404
+ typical_usage_unit.text = 'Hours per week'
405
+ typical_usage.add_element(typical_usage_unit)
406
+ typical_usage_value = REXML::Element.new("#{@ns}:TypicalOccupantUsageValue")
407
+ typical_usage_value.text = typical_usage_hours
408
+ typical_usage.add_element(typical_usage_value)
409
+ return section
410
+ end
411
+
412
+ # -- Generate Baseline functions
413
+ def generate_baseline_facilities(xml_path)
414
+ facilities = []
415
+ doc = help_load_doc(xml_path)
416
+
417
+ doc.elements.each("#{@ns}:BuildingSync/#{@ns}:Facilities/#{@ns}:Facility") do |facility_element|
418
+ facilities.push(BuildingSync::Facility.new(facility_element, @ns))
419
+ end
420
+ return facilities
421
+ end
422
+
423
+ def generate_baseline_sites(xml_path)
424
+ sites = []
425
+ doc = help_load_doc(xml_path)
426
+ facility_xml = get_first_facility_element(doc)
427
+
428
+ facility_xml.elements.each("#{@ns}:Sites/#{@ns}:Site") do |site_element|
429
+ sites.push(BuildingSync::Site.new(site_element, @ns))
430
+ end
431
+ return sites
432
+ end
433
+
434
+ def generate_baseline_buildings(xml_path, occupancy_classification, total_floor_area)
435
+ buildings = []
436
+
437
+ doc = help_load_doc(xml_path)
438
+ site_xml = get_first_site_element(doc)
439
+
440
+ site_xml.elements.each("#{@ns}:Buildings/#{@ns}:Building") do |building_element|
441
+ buildings.push(BuildingSync::Building.new(building_element, occupancy_classification, total_floor_area, @ns))
442
+ end
443
+ return buildings
444
+ end
445
+
446
+ def generate_baseline_building_sections(xml_path, occupancy_classification, total_floor_area)
447
+ building_sections = []
448
+
449
+ doc = help_load_doc(xml_path)
450
+ building_xml = get_first_building_element(doc)
451
+
452
+ building_xml.elements.each("#{@ns}:Sections/#{@ns}:Section") do |building_element|
453
+ building_sections.push(BuildingSync::BuildingSection.new(building_element, occupancy_classification, total_floor_area, 1, @ns))
454
+ end
455
+ return building_sections
456
+ end
457
+
458
+ def get_first_facility_element(doc)
459
+ facility = doc.get_elements("#{@ns}:BuildingSync/#{@ns}:Facilities/#{@ns}:Facility").first
460
+ return facility
461
+ end
462
+
463
+ def get_first_site_element(doc)
464
+ site = doc.get_elements("/#{@ns}:BuildingSync/#{@ns}:Facilities/#{@ns}:Facility/#{@ns}:Sites/#{@ns}:Site").first
465
+ return site
466
+ end
467
+
468
+ def get_first_building_element(doc)
469
+ building = doc.get_elements("/#{@ns}:BuildingSync/#{@ns}:Facilities/#{@ns}:Facility/#{@ns}:Sites/#{@ns}:Site/#{@ns}:Buildings/#{@ns}:Building").first
470
+ return building
471
+ end
472
+
473
+ def get_first_building_section_element(doc)
474
+ section = doc.get_elements("/#{@ns}:BuildingSync/#{@ns}:Facilities/#{@ns}:Facility/#{@ns}:Sites/#{@ns}:Site/#{@ns}:Buildings/#{@ns}:Building/#{@ns}:Sections/#{@ns}:Section").first
475
+ return section
476
+ end
477
+
478
+ def get_first_report_element(doc)
479
+ report = doc.get_elements("/#{@ns}:BuildingSync/#{@ns}:Facilities/#{@ns}:Facility/#{@ns}:Reports/#{@ns}:Report").first
480
+ return report
481
+ end
482
+
483
+ def get_first_scenario_element(doc)
484
+ scenario = doc.get_elements("/#{@ns}:BuildingSync/#{@ns}:Facilities/#{@ns}:Facility/#{@ns}:Reports/#{@ns}:Report/#{@ns}:Scenarios/#{@ns}:Scenario").first
485
+ return scenario
486
+ end
487
+
488
+ def get_first_utility_element(doc)
489
+ scenario = doc.get_elements("/#{@ns}:BuildingSync/#{@ns}:Facilities/#{@ns}:Facility/#{@ns}:Reports/#{@ns}:Report/#{@ns}:Utilities/#{@ns}:Utility").first
490
+ return scenario
491
+ end
492
+
493
+ def get_first_hvac_system_element(doc)
494
+ scenario = doc.get_elements("/#{@ns}:BuildingSync/#{@ns}:Facilities/#{@ns}:Facility/#{@ns}:Systems/#{@ns}:HVACSystems/#{@ns}:HVACSystem").first
495
+ return scenario
496
+ end
497
+
498
+ def get_utility_from_file(xml_file_path)
499
+ doc = nil
500
+ File.open(xml_file_path, 'r') do |file|
501
+ doc = REXML::Document.new(file)
502
+ end
503
+ report = get_first_utility_element(doc)
504
+ return BuildingSync::Utility.new(report, @ns)
505
+ end
506
+
507
+ def get_report_from_file(xml_file_path)
508
+ doc = nil
509
+ File.open(xml_file_path, 'r') do |file|
510
+ doc = REXML::Document.new(file)
511
+ end
512
+ report = get_first_report_element(doc)
513
+ return BuildingSync::Report.new(report, @ns)
514
+ end
515
+
516
+ def get_facility_from_file(xml_file_path)
517
+ doc = nil
518
+ File.open(xml_file_path, 'r') do |file|
519
+ doc = REXML::Document.new(file)
520
+ end
521
+ facility = get_first_facility_element(doc)
522
+ return BuildingSync::Facility.new(facility, @ns)
523
+ end
524
+
525
+ def get_building_from_file(xml_file_path)
526
+ doc = nil
527
+ File.open(xml_file_path, 'r') do |file|
528
+ doc = REXML::Document.new(file)
529
+ end
530
+ building = get_first_building_element(doc)
531
+ return BuildingSync::Building.new(building, 'Office', '20000', @ns)
532
+ end
533
+
534
+ def get_building_section_from_file(xml_file_path)
535
+ doc = nil
536
+ File.open(xml_file_path, 'r') do |file|
537
+ doc = REXML::Document.new(file)
538
+ end
539
+ section = get_first_building_section_element(doc)
540
+ return BuildingSync::BuildingSection.new(section, 'Office', '20000', 1, @ns)
541
+ end
542
+
543
+ # get hvac system from xml file
544
+ # @param xml_file_name [String]
545
+ # @param standard_to_be_used [String]
546
+ # @return [BuildingSync::HVACSystem]
547
+ def get_hvac_system_from_file(xml_file_path)
548
+ doc = nil
549
+ File.open(xml_file_path, 'r') do |file|
550
+ doc = REXML::Document.new(file)
551
+ end
552
+ hvac_system = get_first_hvac_system_element(doc)
553
+ return BuildingSync::HVACSystem.new(hvac_system, @ns)
554
+ end
555
+
556
+ # create and return the set of elements:
557
+ # auc:CalculationMethod/auc:Modeled/
558
+ # auc:SoftwareProgramUsed = OpenStudio
559
+ # auc:SoftwareProgramVersion = ...
560
+ # auc:WeatherDataType = TMY
561
+ # auc:SimulationCompletionStatus = Success or Failed, depending on result[:completion_status]
562
+ # @param result [hash] must have key: result[:completed_status]
563
+ # @return [REXML::Element]
564
+ def create_calculation_method_element(result)
565
+ calc_method = REXML::Element.new("#{@ns}:CalculationMethod")
566
+ modeled = REXML::Element.new("#{@ns}:Modeled", calc_method)
567
+ software_program_used = REXML::Element.new("#{@ns}:SoftwareProgramUsed", modeled)
568
+ software_program_used.text = 'OpenStudio'
569
+
570
+ software_program_version = REXML::Element.new("#{@ns}:SoftwareProgramVersion", modeled)
571
+ software_program_version.text = OpenStudio.openStudioLongVersion.to_s
572
+
573
+ weather_data_type = REXML::Element.new("#{@ns}:WeatherDataType", modeled)
574
+ weather_data_type.text = 'TMY3'
575
+
576
+ sim_completion_status = REXML::Element.new("#{@ns}:SimulationCompletionStatus", modeled)
577
+ sim_completion_status.text = result[:completed_status] == 'Success' ? 'Finished' : 'Failed'
578
+
579
+ return calc_method
580
+ end
581
+
582
+ attr_reader :version
583
+ end
584
+ end