buildingsync 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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