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.
- checksums.yaml +7 -0
- data/.github/workflows/continuous_integration.yml +146 -0
- data/.gitignore +33 -0
- data/.rspec +3 -0
- data/.rubocop.yml +10 -0
- data/CHANGELOG.md +50 -0
- data/Gemfile +31 -0
- data/Jenkinsfile +10 -0
- data/LICENSE.md +29 -0
- data/README.md +105 -0
- data/Rakefile +77 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/buildingsync.gemspec +37 -0
- data/config.rb.in +26 -0
- data/doc_templates/LICENSE.md +29 -0
- data/doc_templates/README.md.erb +42 -0
- data/doc_templates/copyright_erb.txt +38 -0
- data/doc_templates/copyright_js.txt +5 -0
- data/doc_templates/copyright_ruby.txt +36 -0
- data/lib/buildingsync.rb +43 -0
- data/lib/buildingsync/all_resource_total.rb +54 -0
- data/lib/buildingsync/audit_date.rb +54 -0
- data/lib/buildingsync/constants.rb +49 -0
- data/lib/buildingsync/contact.rb +54 -0
- data/lib/buildingsync/extension.rb +57 -0
- data/lib/buildingsync/generator.rb +584 -0
- data/lib/buildingsync/get_bcl_weather_file.rb +326 -0
- data/lib/buildingsync/helpers/Model.hvac.rb +216 -0
- data/lib/buildingsync/helpers/helper.rb +494 -0
- data/lib/buildingsync/helpers/xml_get_set.rb +215 -0
- data/lib/buildingsync/makers/phase_zero_base.osw +178 -0
- data/lib/buildingsync/makers/workflow_maker.json +811 -0
- data/lib/buildingsync/makers/workflow_maker.rb +581 -0
- data/lib/buildingsync/makers/workflow_maker_base.rb +167 -0
- data/lib/buildingsync/model_articulation/building.rb +1119 -0
- data/lib/buildingsync/model_articulation/building_and_system_types.json +121 -0
- data/lib/buildingsync/model_articulation/building_section.rb +190 -0
- data/lib/buildingsync/model_articulation/building_system.rb +49 -0
- data/lib/buildingsync/model_articulation/envelope_system.rb +102 -0
- data/lib/buildingsync/model_articulation/exterior_floor_system_type.rb +64 -0
- data/lib/buildingsync/model_articulation/facility.rb +439 -0
- data/lib/buildingsync/model_articulation/foundation_system_type.rb +64 -0
- data/lib/buildingsync/model_articulation/hvac_system.rb +395 -0
- data/lib/buildingsync/model_articulation/lighting_system.rb +102 -0
- data/lib/buildingsync/model_articulation/loads_system.rb +287 -0
- data/lib/buildingsync/model_articulation/location_element.rb +129 -0
- data/lib/buildingsync/model_articulation/measure.rb +57 -0
- data/lib/buildingsync/model_articulation/roof_system_type.rb +64 -0
- data/lib/buildingsync/model_articulation/service_hot_water_system.rb +87 -0
- data/lib/buildingsync/model_articulation/site.rb +242 -0
- data/lib/buildingsync/model_articulation/spatial_element.rb +343 -0
- data/lib/buildingsync/model_articulation/wall_system_type.rb +64 -0
- data/lib/buildingsync/report.rb +217 -0
- data/lib/buildingsync/resource_use.rb +55 -0
- data/lib/buildingsync/scenario.rb +622 -0
- data/lib/buildingsync/selection_tool.rb +98 -0
- data/lib/buildingsync/time_series.rb +85 -0
- data/lib/buildingsync/translator.rb +167 -0
- data/lib/buildingsync/utility.rb +67 -0
- data/lib/buildingsync/version.rb +45 -0
- 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
|