openstudio-ee 0.2.1 → 0.3.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 +4 -4
- data/.rubocop.yml +1 -1
- data/CHANGELOG.md +7 -0
- data/Rakefile +0 -2
- data/lib/measures/GLHEProExportLoadsforGroundHeatExchangerSizing/measure.rb +1 -1
- data/lib/measures/GLHEProExportLoadsforGroundHeatExchangerSizing/measure.xml +3 -4
- data/lib/measures/nze_hvac/measure.rb +8 -6
- data/lib/measures/nze_hvac/measure.xml +9 -9
- data/lib/openstudio/ee_measures/version.rb +1 -1
- data/openstudio-ee.gemspec +6 -8
- metadata +11 -50
- data/lib/measures/ImproveFanTotalEfficiencybyPercentage/measure.rb +0 -333
- data/lib/measures/ImproveFanTotalEfficiencybyPercentage/measure.xml +0 -150
- data/lib/measures/ReplaceFanTotalEfficiency/measure.rb +0 -330
- data/lib/measures/ReplaceFanTotalEfficiency/measure.xml +0 -150
- data/lib/measures/add_apszhp_to_each_zone/measure.rb +0 -607
- data/lib/measures/add_apszhp_to_each_zone/measure.xml +0 -184
- data/lib/measures/add_energy_recovery_ventilator/measure.rb +0 -354
- data/lib/measures/add_energy_recovery_ventilator/measure.xml +0 -78
- data/lib/measures/improve_simple_glazing_by_percentage/measure.rb +0 -81
- data/lib/measures/improve_simple_glazing_by_percentage/measure.xml +0 -70
- data/lib/measures/reduce_water_use_by_percentage/measure.rb +0 -61
- data/lib/measures/reduce_water_use_by_percentage/measure.xml +0 -62
- data/lib/measures/replace_hvac_with_gshp_and_doas/measure.rb +0 -511
- data/lib/measures/replace_hvac_with_gshp_and_doas/measure.xml +0 -375
- data/lib/measures/replace_hvac_with_gshp_and_doas/resources/OsLib_AedgMeasures.rb +0 -454
- data/lib/measures/replace_hvac_with_gshp_and_doas/resources/OsLib_Constructions.rb +0 -221
- data/lib/measures/replace_hvac_with_gshp_and_doas/resources/OsLib_Geometry.rb +0 -41
- data/lib/measures/replace_hvac_with_gshp_and_doas/resources/OsLib_HVAC.rb +0 -1682
- data/lib/measures/replace_hvac_with_gshp_and_doas/resources/OsLib_HelperMethods.rb +0 -114
- data/lib/measures/replace_hvac_with_gshp_and_doas/resources/OsLib_LightingAndEquipment.rb +0 -99
- data/lib/measures/replace_hvac_with_gshp_and_doas/resources/OsLib_Schedules.rb +0 -142
- data/lib/measures/replace_simple_glazing/measure.rb +0 -86
- data/lib/measures/replace_simple_glazing/measure.xml +0 -78
- data/lib/measures/set_boiler_thermal_efficiency/measure.rb +0 -520
- data/lib/measures/set_boiler_thermal_efficiency/measure.xml +0 -78
- data/lib/measures/set_water_heater_efficiency_heat_lossand_peak_water_flow_rate/measure.rb +0 -207
- data/lib/measures/set_water_heater_efficiency_heat_lossand_peak_water_flow_rate/measure.xml +0 -78
- data/lib/measures/tenant_star_internal_loads/measure.rb +0 -134
- data/lib/measures/tenant_star_internal_loads/measure.xml +0 -67
- data/lib/measures/tenant_star_internal_loads/resources/os_lib_helper_methods.rb +0 -401
- data/lib/measures/vr_fwith_doas/measure.rb +0 -468
- data/lib/measures/vr_fwith_doas/measure.xml +0 -298
- data/lib/measures/vr_fwith_doas/resources/OsLib_AedgMeasures.rb +0 -454
- data/lib/measures/vr_fwith_doas/resources/OsLib_Constructions.rb +0 -221
- data/lib/measures/vr_fwith_doas/resources/OsLib_Geometry.rb +0 -41
- data/lib/measures/vr_fwith_doas/resources/OsLib_HVAC.rb +0 -1516
- data/lib/measures/vr_fwith_doas/resources/OsLib_HelperMethods.rb +0 -114
- data/lib/measures/vr_fwith_doas/resources/OsLib_LightingAndEquipment.rb +0 -99
- data/lib/measures/vr_fwith_doas/resources/OsLib_Schedules.rb +0 -142
@@ -1,114 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module OsLib_HelperMethods
|
4
|
-
# populate choice argument from model objects
|
5
|
-
def self.populateChoiceArgFromModelObjects(model, modelObject_args_hash, includeBuilding = nil)
|
6
|
-
# populate choice argument for constructions that are applied to surfaces in the model
|
7
|
-
modelObject_handles = OpenStudio::StringVector.new
|
8
|
-
modelObject_display_names = OpenStudio::StringVector.new
|
9
|
-
|
10
|
-
# looping through sorted hash of constructions
|
11
|
-
modelObject_args_hash.sort.map do |key, value|
|
12
|
-
modelObject_handles << value.handle.to_s
|
13
|
-
modelObject_display_names << key
|
14
|
-
end
|
15
|
-
|
16
|
-
if !includeBuilding.nil?
|
17
|
-
# add building to string vector with space type
|
18
|
-
building = model.getBuilding
|
19
|
-
modelObject_handles << building.handle.to_s
|
20
|
-
modelObject_display_names << includeBuilding
|
21
|
-
end
|
22
|
-
|
23
|
-
result = { 'modelObject_handles' => modelObject_handles, 'modelObject_display_names' => modelObject_display_names }
|
24
|
-
return result
|
25
|
-
end # end of OsLib_HelperMethods.populateChoiceArgFromModelObjects
|
26
|
-
|
27
|
-
# check choice argument made from model objects
|
28
|
-
def self.checkChoiceArgFromModelObjects(object, variableName, to_ObjectType, runner, user_arguments)
|
29
|
-
apply_to_building = false
|
30
|
-
modelObject = nil
|
31
|
-
if object.empty?
|
32
|
-
handle = runner.getStringArgumentValue(variableName, user_arguments)
|
33
|
-
if handle.empty?
|
34
|
-
runner.registerError("No #{variableName} was chosen.") # this logic makes this not work on an optional model object argument
|
35
|
-
else
|
36
|
-
runner.registerError("The selected #{variableName} with handle '#{handle}' was not found in the model. It may have been removed by another measure.")
|
37
|
-
end
|
38
|
-
return false
|
39
|
-
else
|
40
|
-
if !eval("object.get.#{to_ObjectType}").empty?
|
41
|
-
modelObject = eval("object.get.#{to_ObjectType}").get
|
42
|
-
elsif !object.get.to_Building.empty?
|
43
|
-
apply_to_building = true
|
44
|
-
else
|
45
|
-
runner.registerError("Script Error - argument not showing up as #{variableName}.")
|
46
|
-
return false
|
47
|
-
end
|
48
|
-
end # end of if construction.empty?
|
49
|
-
|
50
|
-
result = { 'modelObject' => modelObject, 'apply_to_building' => apply_to_building }
|
51
|
-
end # end of OsLib_HelperMethods.checkChoiceArgFromModelObjects
|
52
|
-
|
53
|
-
# check choice argument made from model objects
|
54
|
-
def self.checkOptionalChoiceArgFromModelObjects(object, variableName, to_ObjectType, runner, user_arguments)
|
55
|
-
apply_to_building = false
|
56
|
-
modelObject = nil
|
57
|
-
if object.empty?
|
58
|
-
handle = runner.getOptionalStringArgumentValue(variableName, user_arguments)
|
59
|
-
if handle.empty?
|
60
|
-
# do nothing, this is a valid option
|
61
|
-
modelObject = nil
|
62
|
-
apply_to_building = false
|
63
|
-
else
|
64
|
-
runner.registerError("The selected #{variableName} with handle '#{handle}' was not found in the model. It may have been removed by another measure.")
|
65
|
-
return false
|
66
|
-
end
|
67
|
-
else
|
68
|
-
if !eval("object.get.#{to_ObjectType}").empty?
|
69
|
-
modelObject = eval("object.get.#{to_ObjectType}").get
|
70
|
-
elsif !object.get.to_Building.empty?
|
71
|
-
apply_to_building = true
|
72
|
-
else
|
73
|
-
runner.registerError("Script Error - argument not showing up as #{variableName}.")
|
74
|
-
return false
|
75
|
-
end
|
76
|
-
end # end of if construction.empty?
|
77
|
-
|
78
|
-
result = { 'modelObject' => modelObject, 'apply_to_building' => apply_to_building }
|
79
|
-
end # end of OsLib_HelperMethods.checkChoiceArgFromModelObjects
|
80
|
-
|
81
|
-
# check value of double arguments
|
82
|
-
def self.checkDoubleArguments(runner, min, max, argumentHash)
|
83
|
-
# error flag
|
84
|
-
error = false
|
85
|
-
|
86
|
-
argumentHash.each do |display, argument|
|
87
|
-
if !min.nil?
|
88
|
-
if argument < min
|
89
|
-
runner.registerError("Please enter value between #{min} and #{max} for #{display}.") # add in argument display name
|
90
|
-
error = true
|
91
|
-
end
|
92
|
-
end
|
93
|
-
if !max.nil?
|
94
|
-
if argument > max
|
95
|
-
runner.registerError("Please enter value between #{min} and #{max} for #{display}.") # add in argument display name
|
96
|
-
error = true
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end # end of argumentArray.each do
|
100
|
-
|
101
|
-
# check for any errors
|
102
|
-
if error
|
103
|
-
return false
|
104
|
-
else
|
105
|
-
return true
|
106
|
-
end
|
107
|
-
end # end of OsLib_HelperMethods.checkDoubleArguments
|
108
|
-
|
109
|
-
# OpenStudio has built in toNeatString method
|
110
|
-
# OpenStudio::toNeatString(double,2,true)# double,decimals, show commas
|
111
|
-
|
112
|
-
# OpenStudio has built in helper for unit conversion. That can be done using OpenStudio::convert() as shown below.
|
113
|
-
# OpenStudio::convert(double,"from unit string","to unit string").get
|
114
|
-
end
|
@@ -1,99 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "#{File.dirname(__FILE__)}/OsLib_Schedules"
|
4
|
-
|
5
|
-
# load OpenStudio measure libraries
|
6
|
-
module OsLib_LightingAndEquipment
|
7
|
-
include OsLib_Schedules
|
8
|
-
|
9
|
-
# return min ans max from array
|
10
|
-
def self.getExteriorLightsValue(model)
|
11
|
-
facility = model.getFacility
|
12
|
-
starting_exterior_lights_power = 0
|
13
|
-
starting_exterior_lights = facility.exteriorLights
|
14
|
-
starting_exterior_lights.each do |starting_exterior_light|
|
15
|
-
starting_exterior_light_multiplier = starting_exterior_light.multiplier
|
16
|
-
starting_exterior_light_def = starting_exterior_light.exteriorLightsDefinition
|
17
|
-
starting_exterior_light_base_power = starting_exterior_light_def.designLevel
|
18
|
-
starting_exterior_lights_power += starting_exterior_light_base_power * starting_exterior_light_multiplier
|
19
|
-
end
|
20
|
-
|
21
|
-
result = { 'exteriorLightingPower' => starting_exterior_lights_power, 'exteriorLights' => starting_exterior_lights }
|
22
|
-
return result
|
23
|
-
end # end of OsLib_LightingAndEquipment.getExteriorLightsValue
|
24
|
-
|
25
|
-
# return min ans max from array
|
26
|
-
def self.removeAllExteriorLights(model, runner)
|
27
|
-
facility = model.getFacility
|
28
|
-
lightsRemoved = false
|
29
|
-
starting_exterior_lights = facility.exteriorLights
|
30
|
-
starting_exterior_lights.each do |starting_exterior_light|
|
31
|
-
runner.registerInfo("Removed exterior light named #{starting_exterior_light.name}.")
|
32
|
-
starting_exterior_light.remove
|
33
|
-
lightsRemoved = true
|
34
|
-
end
|
35
|
-
|
36
|
-
result = lightsRemoved
|
37
|
-
return result
|
38
|
-
end # end of OsLib_LightingAndEquipment.removeAllExteriorLights
|
39
|
-
|
40
|
-
# return min ans max from array
|
41
|
-
def self.addExteriorLights(model, runner, options = {})
|
42
|
-
# set defaults to use if user inputs not passed in
|
43
|
-
defaults = {
|
44
|
-
'name' => 'Exterior Light',
|
45
|
-
'power' => 0,
|
46
|
-
'subCategory' => 'Exterior Lighting',
|
47
|
-
'controlOption' => 'AstronomicalClock',
|
48
|
-
'setbackStartTime' => 0,
|
49
|
-
'setbackEndTime' => 0,
|
50
|
-
'setbackFraction' => 0.25
|
51
|
-
}
|
52
|
-
|
53
|
-
# merge user inputs with defaults
|
54
|
-
options = defaults.merge(options)
|
55
|
-
|
56
|
-
ext_lights_def = OpenStudio::Model::ExteriorLightsDefinition.new(model)
|
57
|
-
ext_lights_def.setName("#{options['name']} Definition")
|
58
|
-
runner.registerInfo("Setting #{ext_lights_def.name} to a design power of #{options['power']} Watts")
|
59
|
-
ext_lights_def.setDesignLevel(options['power'])
|
60
|
-
|
61
|
-
# creating schedule type limits for the exterior lights schedule
|
62
|
-
ext_lights_sch_type_limits = OpenStudio::Model::ScheduleTypeLimits.new(model)
|
63
|
-
ext_lights_sch_type_limits.setName("#{options['name']} Fractional")
|
64
|
-
ext_lights_sch_type_limits.setLowerLimitValue(0)
|
65
|
-
ext_lights_sch_type_limits.setUpperLimitValue(1)
|
66
|
-
ext_lights_sch_type_limits.setNumericType('Continuous')
|
67
|
-
|
68
|
-
# prepare values for profile
|
69
|
-
if options['setbackStartTime'] == 24
|
70
|
-
profile = { options['setbackEndTime'] => options['setbackFraction'], 24.0 => 1.0 }
|
71
|
-
elsif options['setbackStartTime'] == 0
|
72
|
-
profile = { options['setbackEndTime'] => options['setbackFraction'], 24.0 => 1.0 }
|
73
|
-
elsif options['setbackStartTime'] > options['setbackEndTime']
|
74
|
-
profile = { options['setbackEndTime'] => options['setbackFraction'], options['setbackStartTime'] => 1.0, 24.0 => options['setbackFraction'] }
|
75
|
-
else
|
76
|
-
profile = { options['setbackStartTime'] => 1.0, options['setbackEndTime'] => options['setbackFraction'] }
|
77
|
-
end
|
78
|
-
|
79
|
-
# inputs
|
80
|
-
createSimpleSchedule_inputs = {
|
81
|
-
'name' => options['name'],
|
82
|
-
'winterTimeValuePairs' => profile,
|
83
|
-
'summerTimeValuePairs' => profile,
|
84
|
-
'defaultTimeValuePairs' => profile
|
85
|
-
}
|
86
|
-
|
87
|
-
# create a ruleset schedule with a basic profile
|
88
|
-
ext_lights_sch = OsLib_Schedules.createSimpleSchedule(model, createSimpleSchedule_inputs)
|
89
|
-
|
90
|
-
# creating exterior lights object
|
91
|
-
ext_lights = OpenStudio::Model::ExteriorLights.new(ext_lights_def, ext_lights_sch)
|
92
|
-
ext_lights.setName("#{options['power']} w Exterior Light")
|
93
|
-
ext_lights.setControlOption(options['controlOption'])
|
94
|
-
ext_lights.setEndUseSubcategory(options['subCategory'])
|
95
|
-
|
96
|
-
result = ext_lights
|
97
|
-
return result
|
98
|
-
end # end of OsLib_LightingAndEquipment.addExteriorLights
|
99
|
-
end
|
@@ -1,142 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module OsLib_Schedules
|
4
|
-
# create a ruleset schedule with a basic profile
|
5
|
-
def self.createSimpleSchedule(model, options = {})
|
6
|
-
defaults = {
|
7
|
-
'name' => nil,
|
8
|
-
'winterTimeValuePairs' => { 24.0 => 0.0 },
|
9
|
-
'summerTimeValuePairs' => { 24.0 => 1.0 },
|
10
|
-
'defaultTimeValuePairs' => { 24.0 => 1.0 }
|
11
|
-
}
|
12
|
-
|
13
|
-
# merge user inputs with defaults
|
14
|
-
options = defaults.merge(options)
|
15
|
-
|
16
|
-
# ScheduleRuleset
|
17
|
-
sch_ruleset = OpenStudio::Model::ScheduleRuleset.new(model)
|
18
|
-
if name
|
19
|
-
sch_ruleset.setName(options['name'])
|
20
|
-
end
|
21
|
-
|
22
|
-
# Winter Design Day
|
23
|
-
winter_dsn_day = OpenStudio::Model::ScheduleDay.new(model)
|
24
|
-
sch_ruleset.setWinterDesignDaySchedule(winter_dsn_day)
|
25
|
-
winter_dsn_day = sch_ruleset.winterDesignDaySchedule
|
26
|
-
winter_dsn_day.setName("#{sch_ruleset.name} Winter Design Day")
|
27
|
-
options['winterTimeValuePairs'].each do |k, v|
|
28
|
-
hour = k.truncate
|
29
|
-
min = ((k - hour) * 60).to_i
|
30
|
-
winter_dsn_day.addValue(OpenStudio::Time.new(0, hour, min, 0), v)
|
31
|
-
end
|
32
|
-
|
33
|
-
# Summer Design Day
|
34
|
-
summer_dsn_day = OpenStudio::Model::ScheduleDay.new(model)
|
35
|
-
sch_ruleset.setSummerDesignDaySchedule(summer_dsn_day)
|
36
|
-
summer_dsn_day = sch_ruleset.summerDesignDaySchedule
|
37
|
-
summer_dsn_day.setName("#{sch_ruleset.name} Summer Design Day")
|
38
|
-
options['summerTimeValuePairs'].each do |k, v|
|
39
|
-
hour = k.truncate
|
40
|
-
min = ((k - hour) * 60).to_i
|
41
|
-
summer_dsn_day.addValue(OpenStudio::Time.new(0, hour, min, 0), v)
|
42
|
-
end
|
43
|
-
|
44
|
-
# All Days
|
45
|
-
week_day = sch_ruleset.defaultDaySchedule
|
46
|
-
week_day.setName("#{sch_ruleset.name} Schedule Week Day")
|
47
|
-
options['defaultTimeValuePairs'].each do |k, v|
|
48
|
-
hour = k.truncate
|
49
|
-
min = ((k - hour) * 60).to_i
|
50
|
-
week_day.addValue(OpenStudio::Time.new(0, hour, min, 0), v)
|
51
|
-
end
|
52
|
-
|
53
|
-
result = sch_ruleset
|
54
|
-
return result
|
55
|
-
end # end of OsLib_Schedules.createSimpleSchedule
|
56
|
-
|
57
|
-
# create a complex ruleset schedule
|
58
|
-
def self.createComplexSchedule(model, options = {})
|
59
|
-
defaults = {
|
60
|
-
'name' => nil,
|
61
|
-
'default_day' => ['always_on', [24.0, 1.0]]
|
62
|
-
}
|
63
|
-
|
64
|
-
# merge user inputs with defaults
|
65
|
-
options = defaults.merge(options)
|
66
|
-
|
67
|
-
# ScheduleRuleset
|
68
|
-
sch_ruleset = OpenStudio::Model::ScheduleRuleset.new(model)
|
69
|
-
if name
|
70
|
-
sch_ruleset.setName(options['name'])
|
71
|
-
end
|
72
|
-
|
73
|
-
# Winter Design Day
|
74
|
-
unless options['winter_design_day'].nil?
|
75
|
-
winter_dsn_day = OpenStudio::Model::ScheduleDay.new(model)
|
76
|
-
sch_ruleset.setWinterDesignDaySchedule(winter_dsn_day)
|
77
|
-
winter_dsn_day = sch_ruleset.winterDesignDaySchedule
|
78
|
-
winter_dsn_day.setName("#{sch_ruleset.name} Winter Design Day")
|
79
|
-
options['winter_design_day'].each do |data_pair|
|
80
|
-
hour = data_pair[0].truncate
|
81
|
-
min = ((data_pair[0] - hour) * 60).to_i
|
82
|
-
winter_dsn_day.addValue(OpenStudio::Time.new(0, hour, min, 0), data_pair[1])
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
# Summer Design Day
|
87
|
-
unless options['summer_design_day'].nil?
|
88
|
-
summer_dsn_day = OpenStudio::Model::ScheduleDay.new(model)
|
89
|
-
sch_ruleset.setSummerDesignDaySchedule(summer_dsn_day)
|
90
|
-
summer_dsn_day = sch_ruleset.summerDesignDaySchedule
|
91
|
-
summer_dsn_day.setName("#{sch_ruleset.name} Summer Design Day")
|
92
|
-
options['summer_design_day'].each do |data_pair|
|
93
|
-
hour = data_pair[0].truncate
|
94
|
-
min = ((data_pair[0] - hour) * 60).to_i
|
95
|
-
summer_dsn_day.addValue(OpenStudio::Time.new(0, hour, min, 0), data_pair[1])
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
# Default Day
|
100
|
-
default_day = sch_ruleset.defaultDaySchedule
|
101
|
-
default_day.setName("#{sch_ruleset.name} #{options['default_day'][0]}")
|
102
|
-
default_data_array = options['default_day']
|
103
|
-
default_data_array.delete_at(0)
|
104
|
-
default_data_array.each do |data_pair|
|
105
|
-
hour = data_pair[0].truncate
|
106
|
-
min = ((data_pair[0] - hour) * 60).to_i
|
107
|
-
default_day.addValue(OpenStudio::Time.new(0, hour, min, 0), data_pair[1])
|
108
|
-
end
|
109
|
-
|
110
|
-
# Rules
|
111
|
-
options['rules']&.each do |data_array|
|
112
|
-
rule = OpenStudio::Model::ScheduleRule.new(sch_ruleset)
|
113
|
-
rule.setName("#{sch_ruleset.name} #{data_array[0]} Rule")
|
114
|
-
date_range = data_array[1].split('-')
|
115
|
-
start_date = date_range[0].split('/')
|
116
|
-
end_date = date_range[1].split('/')
|
117
|
-
rule.setStartDate(model.getYearDescription.makeDate(start_date[0].to_i, start_date[1].to_i))
|
118
|
-
rule.setEndDate(model.getYearDescription.makeDate(end_date[0].to_i, end_date[1].to_i))
|
119
|
-
days = data_array[2].split('/')
|
120
|
-
rule.setApplySunday(true) if days.include? 'Sun'
|
121
|
-
rule.setApplyMonday(true) if days.include? 'Mon'
|
122
|
-
rule.setApplyTuesday(true) if days.include? 'Tue'
|
123
|
-
rule.setApplyWednesday(true) if days.include? 'Wed'
|
124
|
-
rule.setApplyThursday(true) if days.include? 'Thu'
|
125
|
-
rule.setApplyFriday(true) if days.include? 'Fri'
|
126
|
-
rule.setApplySaturday(true) if days.include? 'Sat'
|
127
|
-
day_schedule = rule.daySchedule
|
128
|
-
day_schedule.setName("#{sch_ruleset.name} #{data_array[0]}")
|
129
|
-
data_array.delete_at(0)
|
130
|
-
data_array.delete_at(0)
|
131
|
-
data_array.delete_at(0)
|
132
|
-
data_array.each do |data_pair|
|
133
|
-
hour = data_pair[0].truncate
|
134
|
-
min = ((data_pair[0] - hour) * 60).to_i
|
135
|
-
day_schedule.addValue(OpenStudio::Time.new(0, hour, min, 0), data_pair[1])
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
result = sch_ruleset
|
140
|
-
return result
|
141
|
-
end # end of OsLib_Schedules.createComplexSchedule
|
142
|
-
end
|