# *******************************************************************************
# OpenStudio(R), Copyright (c) Alliance for Sustainable Energy, LLC.
# See also https://openstudio.net/license
# *******************************************************************************
# see the URL below for information on how to write OpenStudio measures
# http://openstudio.nrel.gov/openstudio-measure-writing-guide
# see the URL below for information on using life cycle cost objects in OpenStudio
# http://openstudio.nrel.gov/openstudio-life-cycle-examples
# see the URL below for access to C++ documentation on model objects (click on "model" in the main window to view model objects)
# http://openstudio.nrel.gov/sites/openstudio.nrel.gov/files/nv_data/cpp_documentation_it/model/html/namespaces.html
# start the measure
class ReportModelChanges < OpenStudio::Measure::ModelMeasure
# define the name that a user will see, this method may be deprecated as
# the display name in PAT comes from the name field in measure.xml
def name
return 'ReportModelChanges'
end
# define the arguments that the user will input
def arguments(model)
args = OpenStudio::Measure::OSArgumentVector.new
# make an argument for your name
compare_model_path = OpenStudio::Measure::OSArgument.makeStringArgument('compare_model_path', true)
compare_model_path.setDisplayName('Path to model for comparison')
args << compare_model_path
return args
end
# define what happens when the measure is run
def run(model, runner, user_arguments)
super(model, runner, user_arguments)
# use the built-in error checking
if !runner.validateUserArguments(arguments(model), user_arguments)
return false
end
# assign the user inputs to variables
compare_model_path = runner.getStringArgumentValue('compare_model_path', user_arguments)
# load the model
vt = OpenStudio::OSVersion::VersionTranslator.new
compare_model = vt.loadModel(compare_model_path)
if compare_model.empty?
runner.registerError("Cannot load model from #{compare_model_path} for comparison.")
return false
end
compare_model = compare_model.get
only_model = []
only_compare = []
both = []
diffs = []
num_ignored = 0
# loop through model and find objects in this model only or in both
model.getModelObjects.each do |object|
# TODO: compare these some other way
if !object.iddObject.hasNameField
num_ignored += 1
next
end
compare_object = compare_model.getObjectByTypeAndName(object.iddObject.type, object.name.to_s)
if compare_object.empty?
only_model << object
else
both << [object, compare_object.get]
end
end
# loop through model and find objects in comparison model only
compare_model.getModelObjects.each do |compare_object|
# TODO: compare these some other way
if !compare_object.iddObject.hasNameField
num_ignored += 1
next
end
object = model.getObjectByTypeAndName(compare_object.iddObject.type, compare_object.name.to_s)
if object.empty?
only_compare << compare_object
end
end
# loop through and perform the diffs
both.each do |b|
object = b[0]
compare_object = b[1]
idd_object = object.iddObject
object_num_fields = object.numFields
compare_num_fields = compare_object.numFields
diff = "
\n"
diff += "#{object.iddObject.name} | | |
\n"
diff += "Model Object | Comparison Object | Field Name |
\n"
# loop over fields skipping handle
same = true
(1...[object_num_fields, compare_num_fields].max).each do |i|
field_name = idd_object.getField(i).get.name
object_value = ''
if i < object_num_fields
object_value = object.getString(i).to_s
end
object_value = '-' if object_value.empty?
compare_value = ''
if i < compare_num_fields
compare_value = compare_object.getString(i).to_s
end
compare_value = '-' if compare_value.empty?
row_color = 'green'
if object_value != compare_value
same = false
row_color = 'red'
end
diff += "#{object_value} | #{compare_value} | #{field_name} |
\n"
end
diff += "
\n"
if !same
diffs << diff
end
end
# path for reports
report_path = Dir.pwd + '/report.html'
# write the report
File.open(report_path, 'w') do |file|
file << "\nObjects Only In Model
\n"
file << "\n"
only_model.each do |object|
file << "#{object} |
\n"
end
file << "
\n"
file << "\n"
file << "\nObjects Only In Comparison Model
\n"
file << "\n"
only_compare.each do |object|
file << "#{object} |
\n"
end
file << "
\n"
file << "\n"
file << "\nObjects In Both Models With Differences
\n"
diffs.each do |diff|
file << diff
end
file << "\n"
end
runner.registerInfo("Report generated at: #{report_path}")
runner.registerWarning("#{num_ignored} objects did not have names and were not compared")
return true
end
end
# this allows the measure to be use by the application
ReportModelChanges.new.registerWithApplication