urbanopt-reporting 0.3.2 → 0.3.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/lib/measures/default_feature_reports/measure.rb +41 -4
- data/lib/measures/export_modelica_loads/LICENSE.md +27 -0
- data/lib/measures/export_modelica_loads/README.md +26 -0
- data/lib/measures/export_modelica_loads/README.md.erb +42 -0
- data/lib/measures/export_modelica_loads/docs/.gitkeep +0 -0
- data/lib/measures/export_modelica_loads/measure.rb +367 -0
- data/lib/measures/export_modelica_loads/measure.xml +92 -0
- data/lib/measures/export_modelica_loads/resources/report.html.in +13 -0
- data/lib/measures/export_time_series_modelica/LICENSE.md +1 -0
- data/lib/measures/export_time_series_modelica/README.md +59 -0
- data/lib/measures/export_time_series_modelica/README.md.erb +42 -0
- data/lib/measures/export_time_series_modelica/docs/.gitkeep +0 -0
- data/lib/measures/export_time_series_modelica/measure.rb +433 -0
- data/lib/measures/export_time_series_modelica/measure.xml +147 -0
- data/lib/measures/export_time_series_modelica/resources/os_lib_helper_methods.rb +399 -0
- data/lib/measures/export_time_series_modelica/resources/report.html.in +13 -0
- data/lib/urbanopt/reporting/default_reports/feature_report.rb +48 -0
- data/lib/urbanopt/reporting/default_reports/reporting_period.rb +14 -2
- data/lib/urbanopt/reporting/default_reports/scenario_report.rb +7 -4
- data/lib/urbanopt/reporting/default_reports/schema/scenario_schema.json +25 -13
- data/lib/urbanopt/reporting/version.rb +1 -1
- metadata +17 -2
@@ -0,0 +1,147 @@
|
|
1
|
+
<?xml version="1.0"?>
|
2
|
+
<measure>
|
3
|
+
<schema_version>3.0</schema_version>
|
4
|
+
<name>export_time_series_loads_csv</name>
|
5
|
+
<uid>9fcf6116-c2eb-43d6-93f0-e1bdd822f768</uid>
|
6
|
+
<version_id>3a539fd4-3978-4d0f-bd25-a54905fc7306</version_id>
|
7
|
+
<version_modified>20201212T061249Z</version_modified>
|
8
|
+
<xml_checksum>9BF1E6AC</xml_checksum>
|
9
|
+
<class_name>ExportTimeSeriesLoadsCSV</class_name>
|
10
|
+
<display_name>ExportTimeSeriesLoadsCSV</display_name>
|
11
|
+
<description>This measure will add the required output variables and create a CSV file with plant loop level mass flow rates and temperatures for use in a Modelica simulation. Note that this measure has certain
|
12
|
+
requirements for naming of hydronic loops (discussed in the modeler description section).</description>
|
13
|
+
<modeler_description>This measure is currently configured to report the temperatures and mass flow rates at the demand outlet and inlet nodes of hot water and chilled water loops, after adding the required output variables to the model. These values can be used to calculate the sum of the demand-side loads, and could thus represent the load on a connection to a district thermal energy system, or on
|
14
|
+
building-level primary equipment. This measure assumes that the model includes hydronic HVAC loops, and that the hot water and chilled water loop names can each be uniquely identified by a user-provided string. This measure also assumes that there is a single heating hot water loop
|
15
|
+
and a single chilled-water loop per building.</modeler_description>
|
16
|
+
<arguments>
|
17
|
+
<argument>
|
18
|
+
<name>hhw_loop_name</name>
|
19
|
+
<display_name>Name or Partial Name of Heating Hot Water Loop, non-case-sensitive</display_name>
|
20
|
+
<type>String</type>
|
21
|
+
<required>true</required>
|
22
|
+
<model_dependent>false</model_dependent>
|
23
|
+
<default_value>hot</default_value>
|
24
|
+
</argument>
|
25
|
+
<argument>
|
26
|
+
<name>chw_loop_name</name>
|
27
|
+
<display_name>Name or Partial Name of Chilled Water Loop, non-case-sensitive</display_name>
|
28
|
+
<type>String</type>
|
29
|
+
<required>true</required>
|
30
|
+
<model_dependent>false</model_dependent>
|
31
|
+
<default_value>chilled</default_value>
|
32
|
+
</argument>
|
33
|
+
<argument>
|
34
|
+
<name>dec_places_mass_flow</name>
|
35
|
+
<display_name>Number of Decimal Places to Round Mass Flow Rate</display_name>
|
36
|
+
<description>Number of decimal places to which mass flow rate will be rounded</description>
|
37
|
+
<type>Integer</type>
|
38
|
+
<required>true</required>
|
39
|
+
<model_dependent>false</model_dependent>
|
40
|
+
<default_value>3</default_value>
|
41
|
+
</argument>
|
42
|
+
<argument>
|
43
|
+
<name>dec_places_temp</name>
|
44
|
+
<display_name>Number of Decimal Places to Round Temperature</display_name>
|
45
|
+
<description>Number of decimal places to which temperature will be rounded</description>
|
46
|
+
<type>Integer</type>
|
47
|
+
<required>true</required>
|
48
|
+
<model_dependent>false</model_dependent>
|
49
|
+
<default_value>1</default_value>
|
50
|
+
</argument>
|
51
|
+
</arguments>
|
52
|
+
<outputs />
|
53
|
+
<provenances />
|
54
|
+
<tags>
|
55
|
+
<tag>Reporting.QAQC</tag>
|
56
|
+
</tags>
|
57
|
+
<attributes>
|
58
|
+
<attribute>
|
59
|
+
<name>Measure Type</name>
|
60
|
+
<value>ReportingMeasure</value>
|
61
|
+
<datatype>string</datatype>
|
62
|
+
</attribute>
|
63
|
+
<attribute>
|
64
|
+
<name>Intended Software Tool</name>
|
65
|
+
<value>OpenStudio Application</value>
|
66
|
+
<datatype>string</datatype>
|
67
|
+
</attribute>
|
68
|
+
<attribute>
|
69
|
+
<name>Intended Software Tool</name>
|
70
|
+
<value>Parametric Analysis Tool</value>
|
71
|
+
<datatype>string</datatype>
|
72
|
+
</attribute>
|
73
|
+
</attributes>
|
74
|
+
<files>
|
75
|
+
<file>
|
76
|
+
<filename>LICENSE.md</filename>
|
77
|
+
<filetype>md</filetype>
|
78
|
+
<usage_type>license</usage_type>
|
79
|
+
<checksum>CD7F5672</checksum>
|
80
|
+
</file>
|
81
|
+
<file>
|
82
|
+
<filename>README.md.erb</filename>
|
83
|
+
<filetype>erb</filetype>
|
84
|
+
<usage_type>readmeerb</usage_type>
|
85
|
+
<checksum>703C9964</checksum>
|
86
|
+
</file>
|
87
|
+
<file>
|
88
|
+
<filename>.gitkeep</filename>
|
89
|
+
<filetype>gitkeep</filetype>
|
90
|
+
<usage_type>doc</usage_type>
|
91
|
+
<checksum>00000000</checksum>
|
92
|
+
</file>
|
93
|
+
<file>
|
94
|
+
<filename>USA_CO_Golden-NREL.724666_TMY3.epw</filename>
|
95
|
+
<filetype>epw</filetype>
|
96
|
+
<usage_type>test</usage_type>
|
97
|
+
<checksum>BDF687C1</checksum>
|
98
|
+
</file>
|
99
|
+
<file>
|
100
|
+
<filename>report.html.in</filename>
|
101
|
+
<filetype>in</filetype>
|
102
|
+
<usage_type>resource</usage_type>
|
103
|
+
<checksum>3F69E3FB</checksum>
|
104
|
+
</file>
|
105
|
+
<file>
|
106
|
+
<filename>example_model.osm</filename>
|
107
|
+
<filetype>osm</filetype>
|
108
|
+
<usage_type>test</usage_type>
|
109
|
+
<checksum>15AD3659</checksum>
|
110
|
+
</file>
|
111
|
+
<file>
|
112
|
+
<filename>os_lib_helper_methods.rb</filename>
|
113
|
+
<filetype>rb</filetype>
|
114
|
+
<usage_type>resource</usage_type>
|
115
|
+
<checksum>5C26809A</checksum>
|
116
|
+
</file>
|
117
|
+
<file>
|
118
|
+
<filename>export_time_series_modelica_test.rb</filename>
|
119
|
+
<filetype>rb</filetype>
|
120
|
+
<usage_type>test</usage_type>
|
121
|
+
<checksum>B595A09A</checksum>
|
122
|
+
</file>
|
123
|
+
<file>
|
124
|
+
<filename>building_loads.csv</filename>
|
125
|
+
<filetype>csv</filetype>
|
126
|
+
<usage_type>test</usage_type>
|
127
|
+
<checksum>1E8091B8</checksum>
|
128
|
+
</file>
|
129
|
+
<file>
|
130
|
+
<version>
|
131
|
+
<software_program>OpenStudio</software_program>
|
132
|
+
<identifier>3.0.1</identifier>
|
133
|
+
<min_compatible>3.0.1</min_compatible>
|
134
|
+
</version>
|
135
|
+
<filename>measure.rb</filename>
|
136
|
+
<filetype>rb</filetype>
|
137
|
+
<usage_type>script</usage_type>
|
138
|
+
<checksum>C172F942</checksum>
|
139
|
+
</file>
|
140
|
+
<file>
|
141
|
+
<filename>README.md</filename>
|
142
|
+
<filetype>md</filetype>
|
143
|
+
<usage_type>readme</usage_type>
|
144
|
+
<checksum>08F470AC</checksum>
|
145
|
+
</file>
|
146
|
+
</files>
|
147
|
+
</measure>
|
@@ -0,0 +1,399 @@
|
|
1
|
+
# *******************************************************************************
|
2
|
+
# OpenStudio(R), Copyright (c) 2008-2019, Alliance for Sustainable Energy, LLC.
|
3
|
+
# All rights reserved.
|
4
|
+
# Redistribution and use in source and binary forms, with or without
|
5
|
+
# modification, are permitted provided that the following conditions are met:
|
6
|
+
#
|
7
|
+
# (1) Redistributions of source code must retain the above copyright notice,
|
8
|
+
# this list of conditions and the following disclaimer.
|
9
|
+
#
|
10
|
+
# (2) Redistributions in binary form must reproduce the above copyright notice,
|
11
|
+
# this list of conditions and the following disclaimer in the documentation
|
12
|
+
# and/or other materials provided with the distribution.
|
13
|
+
#
|
14
|
+
# (3) Neither the name of the copyright holder nor the names of any contributors
|
15
|
+
# may be used to endorse or promote products derived from this software without
|
16
|
+
# specific prior written permission from the respective party.
|
17
|
+
#
|
18
|
+
# (4) Other than as required in clauses (1) and (2), distributions in any form
|
19
|
+
# of modifications or other derivative works may not use the "OpenStudio"
|
20
|
+
# trademark, "OS", "os", or any other confusingly similar designation without
|
21
|
+
# specific prior written permission from Alliance for Sustainable Energy, LLC.
|
22
|
+
#
|
23
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS
|
24
|
+
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
25
|
+
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
26
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE
|
27
|
+
# UNITED STATES GOVERNMENT, OR THE UNITED STATES DEPARTMENT OF ENERGY, NOR ANY OF
|
28
|
+
# THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
29
|
+
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
30
|
+
# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
31
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
32
|
+
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
33
|
+
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
34
|
+
# *******************************************************************************
|
35
|
+
|
36
|
+
module OsLib_HelperMethods
|
37
|
+
# populate choice argument from model objects
|
38
|
+
def self.populateChoiceArgFromModelObjects(model, modelObject_args_hash, includeBuilding = nil)
|
39
|
+
# populate choice argument for constructions that are applied to surfaces in the model
|
40
|
+
modelObject_handles = OpenStudio::StringVector.new
|
41
|
+
modelObject_display_names = OpenStudio::StringVector.new
|
42
|
+
|
43
|
+
# looping through sorted hash of constructions
|
44
|
+
modelObject_args_hash.sort.map do |key, value|
|
45
|
+
modelObject_handles << value.handle.to_s
|
46
|
+
modelObject_display_names << key
|
47
|
+
end
|
48
|
+
|
49
|
+
unless includeBuilding.nil?
|
50
|
+
# add building to string vector with space type
|
51
|
+
building = model.getBuilding
|
52
|
+
modelObject_handles << building.handle.to_s
|
53
|
+
modelObject_display_names << includeBuilding
|
54
|
+
end
|
55
|
+
|
56
|
+
result = { 'modelObject_handles' => modelObject_handles, 'modelObject_display_names' => modelObject_display_names }
|
57
|
+
return result
|
58
|
+
end
|
59
|
+
|
60
|
+
# create variables in run from user arguments
|
61
|
+
def self.createRunVariables(runner, model, user_arguments, arguments)
|
62
|
+
result = {}
|
63
|
+
|
64
|
+
error = false
|
65
|
+
# use the built-in error checking
|
66
|
+
unless runner.validateUserArguments(arguments, user_arguments)
|
67
|
+
error = true
|
68
|
+
runner.registerError('Invalid argument values.')
|
69
|
+
end
|
70
|
+
|
71
|
+
user_arguments.each do |argument|
|
72
|
+
# get argument info
|
73
|
+
arg = user_arguments[argument]
|
74
|
+
arg_type = arg.print.lines($/)[1]
|
75
|
+
|
76
|
+
# create argument variable
|
77
|
+
if arg_type.include? 'Double, Required'
|
78
|
+
eval("result[\"#{arg.name}\"] = runner.getDoubleArgumentValue(\"#{arg.name}\", user_arguments)")
|
79
|
+
elsif arg_type.include? 'Integer, Required'
|
80
|
+
eval("result[\"#{arg.name}\"] = runner.getIntegerArgumentValue(\"#{arg.name}\", user_arguments)")
|
81
|
+
elsif arg_type.include? 'String, Required'
|
82
|
+
eval("result[\"#{arg.name}\"] = runner.getStringArgumentValue(\"#{arg.name}\", user_arguments)")
|
83
|
+
elsif arg_type.include? 'Boolean, Required'
|
84
|
+
eval("result[\"#{arg.name}\"] = runner.getBoolArgumentValue(\"#{arg.name}\", user_arguments)")
|
85
|
+
elsif arg_type.include? 'Choice, Required'
|
86
|
+
eval("result[\"#{arg.name}\"] = runner.getStringArgumentValue(\"#{arg.name}\", user_arguments)")
|
87
|
+
else
|
88
|
+
puts 'not setup to handle all argument types yet, or any optional arguments'
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
if error
|
93
|
+
return false
|
94
|
+
else
|
95
|
+
return result
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# check choice argument made from model objects
|
100
|
+
def self.checkChoiceArgFromModelObjects(object, variableName, to_ObjectType, runner, user_arguments)
|
101
|
+
apply_to_building = false
|
102
|
+
modelObject = nil
|
103
|
+
if object.empty?
|
104
|
+
handle = runner.getStringArgumentValue(variableName, user_arguments)
|
105
|
+
if handle.empty?
|
106
|
+
runner.registerError("No #{variableName} was chosen.") # this logic makes this not work on an optional model object argument
|
107
|
+
else
|
108
|
+
runner.registerError("The selected #{variableName} with handle '#{handle}' was not found in the model. It may have been removed by another measure.")
|
109
|
+
end
|
110
|
+
return false
|
111
|
+
else
|
112
|
+
if !eval("object.get.#{to_ObjectType}").empty?
|
113
|
+
modelObject = eval("object.get.#{to_ObjectType}").get
|
114
|
+
elsif !object.get.to_Building.empty?
|
115
|
+
apply_to_building = true
|
116
|
+
else
|
117
|
+
runner.registerError("Script Error - argument not showing up as #{variableName}.")
|
118
|
+
return false
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
result = { 'modelObject' => modelObject, 'apply_to_building' => apply_to_building }
|
123
|
+
end
|
124
|
+
|
125
|
+
# check choice argument made from model objects
|
126
|
+
def self.checkOptionalChoiceArgFromModelObjects(object, variableName, to_ObjectType, runner, user_arguments)
|
127
|
+
apply_to_building = false
|
128
|
+
modelObject = nil
|
129
|
+
if object.empty?
|
130
|
+
handle = runner.getOptionalStringArgumentValue(variableName, user_arguments)
|
131
|
+
if handle.empty?
|
132
|
+
# do nothing, this is a valid option
|
133
|
+
puts 'hello'
|
134
|
+
modelObject = nil
|
135
|
+
apply_to_building = false
|
136
|
+
else
|
137
|
+
runner.registerError("The selected #{variableName} with handle '#{handle}' was not found in the model. It may have been removed by another measure.")
|
138
|
+
return false
|
139
|
+
end
|
140
|
+
else
|
141
|
+
if !eval("object.get.#{to_ObjectType}").empty?
|
142
|
+
modelObject = eval("object.get.#{to_ObjectType}").get
|
143
|
+
elsif !object.get.to_Building.empty?
|
144
|
+
apply_to_building = true
|
145
|
+
else
|
146
|
+
runner.registerError("Script Error - argument not showing up as #{variableName}.")
|
147
|
+
return false
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
result = { 'modelObject' => modelObject, 'apply_to_building' => apply_to_building }
|
152
|
+
end
|
153
|
+
|
154
|
+
# check value of double arguments
|
155
|
+
def self.checkDoubleAndIntegerArguments(runner, user_arguments, arg_check_hash)
|
156
|
+
error = false
|
157
|
+
|
158
|
+
# get hash values
|
159
|
+
min = arg_check_hash['min']
|
160
|
+
max = arg_check_hash['max']
|
161
|
+
min_eq_bool = arg_check_hash['min_eq_bool']
|
162
|
+
max_eq_bool = arg_check_hash['max_eq_bool']
|
163
|
+
|
164
|
+
arg_check_hash['arg_array'].each do |argument|
|
165
|
+
argument = user_arguments[argument]
|
166
|
+
|
167
|
+
# get arg values
|
168
|
+
arg_value = nil
|
169
|
+
if argument.hasValue
|
170
|
+
arg_value = argument.valueDisplayName.to_f # instead of valueAsDouble so it allows integer arguments as well
|
171
|
+
elsif argument.hasDefaultValue
|
172
|
+
arg_value = argument.defaultValueDisplayName.to_f
|
173
|
+
end
|
174
|
+
arg_display = argument.displayName
|
175
|
+
|
176
|
+
unless min.nil?
|
177
|
+
if min_eq_bool
|
178
|
+
if arg_value < min
|
179
|
+
runner.registerError("Please enter value greater than or equal to #{min} for #{arg_display}.") # add in argument display name
|
180
|
+
error = true
|
181
|
+
end
|
182
|
+
else
|
183
|
+
if arg_value <= min
|
184
|
+
runner.registerError("Please enter value greater than #{min} for #{arg_display}.") # add in argument display name
|
185
|
+
error = true
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
unless max.nil?
|
190
|
+
if max_eq_bool
|
191
|
+
if arg_value > max
|
192
|
+
runner.registerError("Please enter value less than or equal to #{max} for #{arg_display}.") # add in argument display name
|
193
|
+
error = true
|
194
|
+
end
|
195
|
+
else
|
196
|
+
if arg_value >= max
|
197
|
+
runner.registerError("Please enter value less than #{max} for #{arg_display}.") # add in argument display name
|
198
|
+
error = true
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
# check for any errors
|
205
|
+
if error
|
206
|
+
return false
|
207
|
+
else
|
208
|
+
return true
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
# open channel to log info/warning/error messages
|
213
|
+
def self.setup_log_msgs(runner, debug = false)
|
214
|
+
# Open a channel to log info/warning/error messages
|
215
|
+
@msg_log = OpenStudio::StringStreamLogSink.new
|
216
|
+
if debug
|
217
|
+
@msg_log.setLogLevel(OpenStudio::Debug)
|
218
|
+
else
|
219
|
+
@msg_log.setLogLevel(OpenStudio::Info)
|
220
|
+
end
|
221
|
+
@start_time = Time.new
|
222
|
+
@runner = runner
|
223
|
+
end
|
224
|
+
|
225
|
+
# Get all the log messages and put into output
|
226
|
+
# for users to see.
|
227
|
+
def self.log_msgs
|
228
|
+
@msg_log.logMessages.each do |msg|
|
229
|
+
# DLM: you can filter on log channel here for now
|
230
|
+
if /openstudio.*/.match(msg.logChannel) # /openstudio\.model\..*/
|
231
|
+
# Skip certain messages that are irrelevant/misleading
|
232
|
+
next if msg.logMessage.include?('Skipping layer') || # Annoying/bogus "Skipping layer" warnings
|
233
|
+
msg.logChannel.include?('runmanager') || # RunManager messages
|
234
|
+
msg.logChannel.include?('setFileExtension') || # .ddy extension unexpected
|
235
|
+
msg.logChannel.include?('Translator') || # Forward translator and geometry translator
|
236
|
+
msg.logMessage.include?('UseWeatherFile') # 'UseWeatherFile' is not yet a supported option for YearDescription
|
237
|
+
|
238
|
+
# Report the message in the correct way
|
239
|
+
if msg.logLevel == OpenStudio::Info
|
240
|
+
@runner.registerInfo(msg.logMessage)
|
241
|
+
elsif msg.logLevel == OpenStudio::Warn
|
242
|
+
@runner.registerWarning("[#{msg.logChannel}] #{msg.logMessage}")
|
243
|
+
elsif msg.logLevel == OpenStudio::Error
|
244
|
+
@runner.registerError("[#{msg.logChannel}] #{msg.logMessage}")
|
245
|
+
elsif msg.logLevel == OpenStudio::Debug && @debug
|
246
|
+
@runner.registerInfo("DEBUG - #{msg.logMessage}")
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
250
|
+
@runner.registerInfo("Total Time = #{(Time.new - @start_time).round}sec.")
|
251
|
+
end
|
252
|
+
|
253
|
+
def self.check_upstream_measure_for_arg(runner, arg_name)
|
254
|
+
# 2.x methods (currently setup for measure display name but snake_case arg names)
|
255
|
+
arg_name_value = {}
|
256
|
+
runner.workflow.workflowSteps.each do |step|
|
257
|
+
if step.to_MeasureStep.is_initialized
|
258
|
+
measure_step = step.to_MeasureStep.get
|
259
|
+
|
260
|
+
measure_name = measure_step.measureDirName
|
261
|
+
if measure_step.name.is_initialized
|
262
|
+
measure_name = measure_step.name.get # this is instance name in PAT
|
263
|
+
end
|
264
|
+
if measure_step.result.is_initialized
|
265
|
+
result = measure_step.result.get
|
266
|
+
result.stepValues.each do |arg|
|
267
|
+
name = arg.name
|
268
|
+
value = arg.valueAsVariant.to_s
|
269
|
+
if name == arg_name
|
270
|
+
arg_name_value[:value] = value
|
271
|
+
arg_name_value[:measure_name] = measure_name
|
272
|
+
return arg_name_value # stop after find first one
|
273
|
+
end
|
274
|
+
end
|
275
|
+
else
|
276
|
+
# puts "No result for #{measure_name}"
|
277
|
+
end
|
278
|
+
else
|
279
|
+
# puts "This step is not a measure"
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
return arg_name_value
|
284
|
+
end
|
285
|
+
|
286
|
+
# populate choice argument from model objects. areaType should be string like "floorArea" or "exteriorArea"
|
287
|
+
# note: it seems like spaceType.floorArea does account for multiplier, so I don't have to call this method unless I have a custom collection of spaces.
|
288
|
+
def self.getAreaOfSpacesInArray(model, spaceArray, areaType = 'floorArea')
|
289
|
+
# find selected floor spaces, make array and get floor area.
|
290
|
+
totalArea = 0
|
291
|
+
spaceAreaHash = {}
|
292
|
+
spaceArray.each do |space|
|
293
|
+
spaceArea = eval("space.#{areaType}*space.multiplier")
|
294
|
+
spaceAreaHash[space] = spaceArea
|
295
|
+
totalArea += spaceArea
|
296
|
+
end
|
297
|
+
|
298
|
+
result = { 'totalArea' => totalArea, 'spaceAreaHash' => spaceAreaHash }
|
299
|
+
return result
|
300
|
+
end
|
301
|
+
|
302
|
+
# runs conversion and neat string, and returns value with units in string, optionally before or after the value
|
303
|
+
def self.neatConvertWithUnitDisplay(double, fromString, toString, digits, unitBefore = false, unitAfter = true, space = true, parentheses = true)
|
304
|
+
# convert units
|
305
|
+
doubleConverted = OpenStudio.convert(double, fromString, toString)
|
306
|
+
if !doubleConverted.nil?
|
307
|
+
doubleConverted = doubleConverted.get
|
308
|
+
else
|
309
|
+
puts "Couldn't convert values, check string choices passed in. From: #{fromString}, To: #{toString}"
|
310
|
+
end
|
311
|
+
|
312
|
+
# get neat version of converted
|
313
|
+
neatConverted = OpenStudio.toNeatString(doubleConverted, digits, true)
|
314
|
+
|
315
|
+
# add prefix
|
316
|
+
if unitBefore
|
317
|
+
if space == true && parentheses == true
|
318
|
+
prefix = "(#{toString}) "
|
319
|
+
elsif space == true && parentheses == false
|
320
|
+
prefix = "(#{toString})"
|
321
|
+
elsif space == false && parentheses == true
|
322
|
+
prefix = "#{toString} "
|
323
|
+
else
|
324
|
+
prefix = toString.to_s
|
325
|
+
end
|
326
|
+
else
|
327
|
+
prefix = ''
|
328
|
+
end
|
329
|
+
|
330
|
+
# add suffix
|
331
|
+
if unitAfter
|
332
|
+
if space == true && parentheses == true
|
333
|
+
suffix = " (#{toString})"
|
334
|
+
elsif space == true && parentheses == false
|
335
|
+
suffix = "(#{toString})"
|
336
|
+
elsif space == false && parentheses == true
|
337
|
+
suffix = " #{toString}"
|
338
|
+
else
|
339
|
+
suffix = toString.to_s
|
340
|
+
end
|
341
|
+
else
|
342
|
+
suffix = ''
|
343
|
+
end
|
344
|
+
|
345
|
+
finalString = "#{prefix}#{neatConverted}#{suffix}"
|
346
|
+
|
347
|
+
return finalString
|
348
|
+
end
|
349
|
+
|
350
|
+
# helper that loops through lifecycle costs getting total costs under "Construction" and add to counter if occurs during year 0
|
351
|
+
def self.getTotalCostForObjects(objectArray, category = 'Construction', onlyYearFromStartZero = true)
|
352
|
+
counter = 0
|
353
|
+
objectArray.each do |object|
|
354
|
+
object_LCCs = object.lifeCycleCosts
|
355
|
+
object_LCCs.each do |object_LCC|
|
356
|
+
if object_LCC.category == category
|
357
|
+
if onlyYearFromStartZero == false || object_LCC.yearsFromStart == 0
|
358
|
+
counter += object_LCC.totalCost
|
359
|
+
end
|
360
|
+
end
|
361
|
+
end
|
362
|
+
end
|
363
|
+
|
364
|
+
return counter
|
365
|
+
end
|
366
|
+
|
367
|
+
# helper that loops through lifecycle costs getting total costs under "Construction" and add to counter if occurs during year 0
|
368
|
+
def self.getSpaceTypeStandardsInformation(spaceTypeArray)
|
369
|
+
# hash of space types
|
370
|
+
spaceTypeStandardsInfoHash = {}
|
371
|
+
|
372
|
+
spaceTypeArray.each do |spaceType|
|
373
|
+
# get standards building
|
374
|
+
if !spaceType.standardsBuildingType.empty?
|
375
|
+
standardsBuilding = spaceType.standardsBuildingType.get
|
376
|
+
else
|
377
|
+
standardsBuilding = nil
|
378
|
+
end
|
379
|
+
|
380
|
+
# get standards space type
|
381
|
+
if !spaceType.standardsSpaceType.empty?
|
382
|
+
standardsSpaceType = spaceType.standardsSpaceType.get
|
383
|
+
else
|
384
|
+
standardsSpaceType = nil
|
385
|
+
end
|
386
|
+
|
387
|
+
# populate hash
|
388
|
+
spaceTypeStandardsInfoHash[spaceType] = [standardsBuilding, standardsSpaceType]
|
389
|
+
end
|
390
|
+
|
391
|
+
return spaceTypeStandardsInfoHash
|
392
|
+
end
|
393
|
+
|
394
|
+
# OpenStudio has built in toNeatString method
|
395
|
+
# OpenStudio::toNeatString(double,2,true)# double,decimals, show commas
|
396
|
+
|
397
|
+
# OpenStudio has built in helper for unit conversion. That can be done using OpenStudio::convert() as shown below.
|
398
|
+
# OpenStudio::convert(double,"from unit string","to unit string").get
|
399
|
+
end
|