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,494 @@
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
+ module BuildingSync
40
+ # helper class for helper methods in BuildingSync
41
+ module Helper
42
+ def help_element_class_type_check(xml_element, expected_type)
43
+ if xml_element.name != expected_type
44
+ OpenStudio.logFree(OpenStudio::Error, "BuildingSync.#{expected_type}.initialize", "Attempted to initialize #{expected_type} object with Element name of: #{xml_element.name}")
45
+ raise StandardError, "Attempted to initialize #{expected_type} object with Element name of: #{xml_element.name}"
46
+ end
47
+ end
48
+
49
+ def help_get_or_create(parent, new_element_type)
50
+ new_element = parent.elements[new_element_type]
51
+ if new_element.nil?
52
+ new_element = REXML::Element.new(new_element_type, parent)
53
+ end
54
+ return new_element
55
+ end
56
+
57
+ # get text value from xml element
58
+ # @param xml_element [REXML::Element]
59
+ # @return [String] if text value exists
60
+ # @return [nil] if text value doesnt exist or element is complex (has children)
61
+ def help_get_text_value(xml_element)
62
+ if xml_element && !xml_element.text.nil?
63
+ return xml_element.text
64
+ end
65
+ return nil
66
+ end
67
+
68
+ def help_get_text_value_as_float(xml_element)
69
+ v = help_get_text_value(xml_element)
70
+ return v.to_f
71
+ end
72
+
73
+ def help_get_text_value_as_integer(xml_element)
74
+ v = help_get_text_value(xml_element)
75
+ return v.to_i
76
+ end
77
+
78
+ def help_get_text_value_as_bool(xml_element)
79
+ v = help_get_text_value(xml_element)
80
+ return v.to_bool
81
+ end
82
+
83
+ # convert between supported units
84
+ # @param val [Numeric] value to convert, i.e. 1
85
+ # @param from_unit [String] starting units
86
+ # @param to_unit [String] desired end units
87
+ # @return [Float] if successful, converted value
88
+ # @return [nil] if unsuccessful
89
+ def help_convert(val, from_unit, to_unit)
90
+ if from_unit == to_unit
91
+ return val
92
+ end
93
+
94
+ btu_multiples = [
95
+ {
96
+ 'from' => 'Btu',
97
+ 'kBtu' => 0.001,
98
+ 'MMBtu' => 0.000001
99
+ },
100
+ {
101
+ 'from' => 'kBtu',
102
+ 'Btu' => 1000,
103
+ 'MMBtu' => 0.001
104
+ },
105
+ {
106
+ 'from' => 'MMBtu',
107
+ 'Btu' => 1000000,
108
+ 'kBtu' => 1000
109
+ }
110
+ ]
111
+ map = btu_multiples.find { |from| from['from'] == from_unit }
112
+ if !map.nil? && !map.empty?
113
+ mult = map[to_unit]
114
+ if !mult.nil?
115
+ return val * mult
116
+ else
117
+ OpenStudio.logFree(OpenStudio::Error, 'BuildingSync.Helper.help_convert', "Unable to convert from: #{from_unit} to #{to_unit}")
118
+ end
119
+ else
120
+ OpenStudio.logFree(OpenStudio::Error, 'BuildingSync.Helper.help_convert', "Unable to convert from: #{from_unit} to #{to_unit}")
121
+ return nil
122
+ end
123
+ end
124
+
125
+ # get attribute value from xml element
126
+ # @param xml_element [REXML::Element]
127
+ # @param attribute_name [String] name of attribute to get the value for
128
+ # @return [String] if attribute
129
+ # @return [nil] if attribute doesnt exist
130
+ def help_get_attribute_value(xml_element, attribute_name)
131
+ if xml_element && !xml_element.attribute(attribute_name).nil?
132
+ return xml_element.attribute(attribute_name).value
133
+ end
134
+ return nil
135
+ end
136
+
137
+ # get date value from xml element
138
+ # @param xml_element [REXML::Element]
139
+ # @return [Date] if the text can be parsed as a date
140
+ # @return [nil] if the text cant be parsed as a date
141
+ def help_get_text_value_as_date(xml_element)
142
+ if xml_element && !xml_element.text.nil?
143
+ begin
144
+ return Date.parse(xml_element.text)
145
+ rescue ArgumentError
146
+ return nil
147
+ end
148
+ end
149
+ return nil
150
+ end
151
+
152
+ # get date datetime from xml element
153
+ # @param xml_element [REXML::Element]
154
+ # @return [DateTime] if the text can be parsed as a date
155
+ # @return [nil] if the text cant be parsed as a date
156
+ def help_get_text_value_as_datetime(xml_element)
157
+ if xml_element && !xml_element.text.nil?
158
+ begin
159
+ return DateTime.parse(xml_element.text)
160
+ rescue ArgumentError
161
+ return nil
162
+ end
163
+ end
164
+ return nil
165
+ end
166
+
167
+ # get zone name list
168
+ # @param zones [array<OpenStudio::Model::ThermalZone>]
169
+ # @return array
170
+ def help_get_zone_name_list(zones)
171
+ names = []
172
+ zones.each do |zone|
173
+ names << zone.name.get
174
+ end
175
+ return names
176
+ end
177
+
178
+ # read xml file document
179
+ # @param xml_file_path [String]
180
+ # @return REXML::Document
181
+ def help_load_doc(xml_file_path)
182
+ doc = nil
183
+ File.open(xml_file_path, 'r') do |file_content|
184
+ doc = REXML::Document.new(file_content, ignore_whitespace_nodes: :all)
185
+ end
186
+ return doc
187
+ end
188
+
189
+ # print all schedules to a file
190
+ # @param file_name [String]
191
+ # @param default_schedule_set [OpenStudio::Model::DefaultScheduleSet]
192
+ def help_print_all_schedules(file_name, default_schedule_set)
193
+ f = File.open(file_name, 'w')
194
+ help_print_schedule(f, default_schedule_set.numberofPeopleSchedule)
195
+ help_print_schedule(f, default_schedule_set.hoursofOperationSchedule)
196
+ help_print_schedule(f, default_schedule_set.peopleActivityLevelSchedule)
197
+ help_print_schedule(f, default_schedule_set.lightingSchedule)
198
+ help_print_schedule(f, default_schedule_set.electricEquipmentSchedule)
199
+ help_print_schedule(f, default_schedule_set.gasEquipmentSchedule)
200
+ help_print_schedule(f, default_schedule_set.hotWaterEquipmentSchedule)
201
+ help_print_schedule(f, default_schedule_set.infiltrationSchedule)
202
+ help_print_schedule(f, default_schedule_set.steamEquipmentSchedule)
203
+ help_print_schedule(f, default_schedule_set.otherEquipmentSchedule)
204
+ f.close
205
+ end
206
+
207
+ # write a schedule profile
208
+ # @param f [File]
209
+ # @param profile [OpenStudio::Model::ScheduleDay]
210
+ # @param rule [OpenStudio::Model::ScheduleRule]
211
+ # @param cut_off_value [Float]
212
+ def help_write_profile(f, profile, rule, cut_off_value = 0.5)
213
+ time_row = "#{profile.name},"
214
+ if rule.nil?
215
+ time_row += ',,,,,,,'
216
+ else
217
+ if rule.applySunday
218
+ time_row += 'X,'
219
+ else
220
+ time_row += ','
221
+ end
222
+ if rule.applyMonday
223
+ time_row += 'X,'
224
+ else
225
+ time_row += ','
226
+ end
227
+ if rule.applyTuesday
228
+ time_row += 'X,'
229
+ else
230
+ time_row += ','
231
+ end
232
+ if rule.applyWednesday
233
+ time_row += 'X,'
234
+ else
235
+ time_row += ','
236
+ end
237
+ if rule.applyThursday
238
+ time_row += 'X,'
239
+ else
240
+ time_row += ','
241
+ end
242
+ if rule.applyFriday
243
+ time_row += 'X,'
244
+ else
245
+ time_row += ','
246
+ end
247
+ if rule.applySaturday
248
+ time_row += 'X,'
249
+ else
250
+ time_row += ','
251
+ end
252
+ end
253
+ time_row += ','
254
+ value_row = ",,,,,,,,#{help_get_duration(profile, cut_off_value)},"
255
+
256
+ profile.times.each do |time|
257
+ time_row += "#{time},"
258
+ value_row += "#{profile.getValue(time)},"
259
+ end
260
+ f.write time_row + "\n"
261
+ f.write value_row + "\n"
262
+ end
263
+
264
+ # print schedule
265
+ # @param f [File]
266
+ # @param optional_schedule [OpenStudio::Model::OptionalSchedule]
267
+ # @param cut_off_value [Float]
268
+ def help_print_schedule(f, optional_schedule, cut_off_value = 0.5)
269
+ if optional_schedule.is_a?(OpenStudio::Model::OptionalSchedule) && optional_schedule.is_initialized
270
+ schedule = optional_schedule.get
271
+ if schedule.is_a?(OpenStudio::Model::OptionalSchedule) && schedule.is_initialized
272
+ schedule = schedule.get
273
+ end
274
+ else
275
+ schedule = optional_schedule
276
+ end
277
+ if schedule.is_a?(OpenStudio::Model::Schedule)
278
+ schedule_rule_set = schedule.to_ScheduleRuleset.get
279
+ f.puts "schedule_rule_set name: ,#{schedule_rule_set.name}, duration:, #{help_calculate_hours(optional_schedule, cut_off_value)}"
280
+ defaultProfile = schedule_rule_set.defaultDaySchedule
281
+
282
+ f.puts 'Name, Su, Mo, Tu, We, Th, Fr, Sa, Duration, TimeValue1, TV2, ...'
283
+ help_write_profile(f, defaultProfile, nil, cut_off_value)
284
+
285
+ schedule_rule_set.scheduleRules.each do |rule|
286
+ help_write_profile(f, rule.daySchedule, rule, cut_off_value)
287
+ end
288
+ f.puts
289
+ else
290
+ puts "schedule: #{schedule}"
291
+ end
292
+ end
293
+
294
+ # get start time weekday
295
+ # @param schedule_rule_set [OpenStudio::Model::ScheduleRuleSet]
296
+ # @param cut_off_value [Float]
297
+ def help_get_start_time_weekday(schedule_rule_set, cut_off_value = 0.5)
298
+ profile = schedule_rule_set.defaultDaySchedule
299
+ schedule_rule_set.scheduleRules.each do |rule|
300
+ if rule.applyMonday
301
+ profile = rule.daySchedule
302
+ end
303
+ end
304
+
305
+ return help_get_start_time(profile, cut_off_value)
306
+ end
307
+
308
+ # get end time weekday
309
+ # @param schedule_rule_set [OpenStudio::Model::ScheduleRuleSet]
310
+ # @param cut_off_value [Float]
311
+ def help_get_end_time_weekday(schedule_rule_set, cut_off_value = 0.5)
312
+ profile = schedule_rule_set.defaultDaySchedule
313
+ schedule_rule_set.scheduleRules.each do |rule|
314
+ if rule.applyMonday
315
+ profile = rule.daySchedule
316
+ end
317
+ end
318
+
319
+ return help_get_end_time(profile, cut_off_value)
320
+ end
321
+
322
+ # get start time Saturday
323
+ # @param schedule_rule_set [OpenStudio::Model::ScheduleRuleSet]
324
+ # @param cut_off_value [Float]
325
+ def help_get_start_time_sat(schedule_rule_set, cut_off_value = 0.5)
326
+ profile = schedule_rule_set.defaultDaySchedule
327
+ schedule_rule_set.scheduleRules.each do |rule|
328
+ if rule.applySaturday
329
+ profile = rule.daySchedule
330
+ end
331
+ end
332
+
333
+ return help_get_start_time(profile, cut_off_value)
334
+ end
335
+
336
+ # get end time Saturday
337
+ # @param schedule_rule_set [OpenStudio::Model::ScheduleRuleSet]
338
+ # @param cut_off_value [Float]
339
+ def help_get_end_time_sat(schedule_rule_set, cut_off_value = 0.5)
340
+ profile = schedule_rule_set.defaultDaySchedule
341
+ schedule_rule_set.scheduleRules.each do |rule|
342
+ if rule.applySaturday
343
+ profile = rule.daySchedule
344
+ end
345
+ end
346
+
347
+ return help_get_end_time(profile, cut_off_value)
348
+ end
349
+
350
+ # get start time Sunday
351
+ # @param schedule_rule_set [OpenStudio::Model::ScheduleRuleSet]
352
+ # @param cut_off_value [Float]
353
+ def help_get_start_time_sun(schedule_rule_set, cut_off_value = 0.5)
354
+ profile = schedule_rule_set.defaultDaySchedule
355
+ schedule_rule_set.scheduleRules.each do |rule|
356
+ if rule.applySunday
357
+ profile = rule.daySchedule
358
+ end
359
+ end
360
+
361
+ return help_get_start_time(profile, cut_off_value)
362
+ end
363
+
364
+ # get end time Sunday
365
+ # @param schedule_rule_set [OpenStudio::Model::ScheduleRuleSet]
366
+ # @param cut_off_value [Float]
367
+ def help_get_end_time_sun(schedule_rule_set, cut_off_value = 0.5)
368
+ profile = schedule_rule_set.defaultDaySchedule
369
+ schedule_rule_set.scheduleRules.each do |rule|
370
+ if rule.applySunday
371
+ profile = rule.daySchedule
372
+ end
373
+ end
374
+
375
+ return help_get_end_time(profile, cut_off_value)
376
+ end
377
+
378
+ # get start time
379
+ # @param profile [OpenStudio::Model::ScheduleDay]
380
+ # @param cut_off_value [Float]
381
+ def help_get_start_time(profile, cut_off_value)
382
+ last_time = OpenStudio::Time.new
383
+ profile.times.each do |time|
384
+ if profile.getValue(time) >= cut_off_value
385
+ return last_time
386
+ end
387
+ last_time = time
388
+ end
389
+ return OpenStudio::Time.new
390
+ end
391
+
392
+ # get end time
393
+ # @param profile [OpenStudio::Model::ScheduleDay]
394
+ # @param cut_off_value [Float]
395
+ def help_get_end_time(profile, cut_off_value)
396
+ last_time = nil
397
+ profile.times.each do |time|
398
+ if profile.getValue(time) >= cut_off_value
399
+ last_time = time
400
+ elsif profile.getValue(time) < cut_off_value && !last_time.nil?
401
+ return last_time
402
+ end
403
+ end
404
+ return OpenStudio::Time.new
405
+ end
406
+
407
+ # get schedule rule set from schedule
408
+ # @param optional_schedule [OpenStudio::Model::OptionalSchedule]
409
+ # @return [OpenStudio::Model::ScheduleRuleSet]
410
+ def help_get_schedule_rule_set_from_schedule(optional_schedule)
411
+ if optional_schedule.is_a?(OpenStudio::Model::OptionalSchedule)
412
+ if optional_schedule.is_initialized
413
+ schedule = optional_schedule.get
414
+ else
415
+ return nil
416
+ end
417
+ else
418
+ schedule = optional_schedule
419
+ end
420
+ return schedule.to_ScheduleRuleset.get
421
+ end
422
+
423
+ # calculate schedule hours that are at or above the cut off value
424
+ # @param optional_schedule [OpenStudio::Model::OptionalSchedule]
425
+ # @return [OpenStudio::Model::ScheduleRuleSet]
426
+ # @ return [Float]
427
+ def help_calculate_hours(optional_schedule, cut_off_value = 0.5)
428
+ calculated_hours_per_week = 0.0
429
+ schedule_rule_set = help_get_schedule_rule_set_from_schedule(optional_schedule)
430
+ return 0.0 if schedule_rule_set.nil?
431
+ defaultProfile = schedule_rule_set.defaultDaySchedule
432
+ default_profile_duration = help_get_duration(defaultProfile, cut_off_value)
433
+ default_number_of_days = 7
434
+ schedule_rule_set.scheduleRules.each do |rule|
435
+ profile_duration = help_get_duration(rule.daySchedule, cut_off_value)
436
+ number_of_days = help_count_number_of_days(rule)
437
+ default_number_of_days -= number_of_days
438
+ calculated_hours_per_week += profile_duration * number_of_days
439
+ end
440
+ calculated_hours_per_week += default_profile_duration * default_number_of_days
441
+ return calculated_hours_per_week
442
+ end
443
+
444
+ # count number of days
445
+ # @param rule [OpenStudio::Model::ScheduleRule]
446
+ # return [Integer]
447
+ def help_count_number_of_days(rule)
448
+ count = 0
449
+ count += 1 if rule.applyFriday
450
+ count += 1 if rule.applyMonday
451
+ count += 1 if rule.applySaturday
452
+ count += 1 if rule.applySunday
453
+ count += 1 if rule.applyThursday
454
+ count += 1 if rule.applyTuesday
455
+ count += 1 if rule.applyWednesday
456
+ return count
457
+ end
458
+
459
+ # get duration
460
+ # @param profile [OpenStudio::Model::ScheduleDay]
461
+ # @param cut_off_value [Float]
462
+ # return [Float]
463
+ def help_get_duration(profile, cut_off_value)
464
+ last_time = nil
465
+ duration_above_cut_off = 0.0
466
+ profile.times.each do |time|
467
+ if profile.getValue(time) >= cut_off_value
468
+ if last_time.nil?
469
+ duration_above_cut_off += time.totalHours
470
+ else
471
+ duration_above_cut_off += time.totalHours - last_time.totalHours
472
+ end
473
+ end
474
+ last_time = time
475
+ end
476
+
477
+ return duration_above_cut_off
478
+ end
479
+
480
+ # get default schedule set
481
+ # @param model [OpenStudio::Model]
482
+ # return [OpenStudio::Model::DefaultScheduleSet]
483
+ def help_get_default_schedule_set(model)
484
+ if model.getBuilding.defaultScheduleSet.is_initialized
485
+ return model.getBuilding.defaultScheduleSet.get
486
+ else
487
+ space_types = model.getSpaceTypes
488
+ space_types.each do |space_type|
489
+ return space_type.defaultScheduleSet.get
490
+ end
491
+ end
492
+ end
493
+ end
494
+ end