boost::optional<BCLMeasure> WorkflowJSON_Impl::addMeasure(const BCLMeasure& bclMeasure) { boost::optional<BCLMeasure> existingMeasure = getBCLMeasureByUUID(bclMeasure.uuid()); boost::optional<openstudio::path> existingMeasureDirName; if (existingMeasure){ // TODO: check that measure type has not changed? existingMeasureDirName = existingMeasure->directory(); boost::filesystem::remove_all(*existingMeasureDirName); } std::vector<openstudio::path> paths = absoluteMeasurePaths(); OS_ASSERT(!paths.empty()); // Get the name of the directory (=last level directory name), eg: /path/to/measure_folder => measure_folder openstudio::path lastLevelDirectoryName = getLastLevelDirectoryName( bclMeasure.directory() ); if (!toUUID(toString(lastLevelDirectoryName)).isNull()){ // directory name is convertible to uuid, use the class name lastLevelDirectoryName = toPath(bclMeasure.className()); } int i = 1; while (boost::filesystem::exists(paths[0] / lastLevelDirectoryName)){ std::stringstream ss; ss << toString(lastLevelDirectoryName) << " " << i; lastLevelDirectoryName = toPath(ss.str()); } openstudio::path newMeasureDirName = paths[0] / lastLevelDirectoryName; // If we have an existing measure if( existingMeasureDirName) { openstudio::path lastLevelExistingDirectoryName = getLastLevelDirectoryName(*existingMeasureDirName); // And the previous directory name isn't the same as the new one if( lastLevelExistingDirectoryName != lastLevelDirectoryName ) { // update steps for (auto& step : m_steps){ if (auto measureStep = step.optionalCast<MeasureStep>()){ if (measureStep->measureDirName() == toString(lastLevelExistingDirectoryName) ) { measureStep->setMeasureDirName(toString(lastLevelDirectoryName)); } } } } } onUpdate(); return bclMeasure.clone(newMeasureDirName); }
bool RubyMeasure_Impl::setMeasure(const BCLMeasure& bclMeasure) { FileReferenceType inputFileType = bclMeasure.inputFileType(); FileReferenceType outputFileType = bclMeasure.outputFileType(); if (!fileTypesAreCompatible(inputFileType,outputFileType)) { return false; } m_bclMeasure = bclMeasure; m_bclMeasureDirectory = bclMeasure.directory(); m_bclMeasureUUID = bclMeasure.uuid(); m_bclMeasureVersionUUID = bclMeasure.versionUUID(); m_perturbationScript.reset(); m_inputFileType = inputFileType; m_outputFileType = outputFileType; m_isUserScript = false; clearArguments(); // emits onChange(AnalysisObject_Impl::InvalidatesResults) return true; }
BCLMeasureDialog::BCLMeasureDialog(const BCLMeasure& bclMeasure, QWidget* parent) : m_bclMeasureToCopy(bclMeasure) { setWindowTitle("Copy Measure"); init(); m_nameLineEdit->setText(toQString(bclMeasure.displayName() + " Copy")); m_descriptionTextEdit->setText(toQString(bclMeasure.description())); m_modelerDescriptionTextEdit->setText(toQString(bclMeasure.modelerDescription())); QString measureTypeString; MeasureType measureType = bclMeasure.measureType(); if ( measureType == MeasureType::ModelMeasure){ measureTypeString = "OpenStudio Measure"; }else if ( measureType == MeasureType::EnergyPlusMeasure){ measureTypeString = "EnergyPlus Measure"; }else if ( measureType == MeasureType::UtilityMeasure){ measureTypeString = "Utility Measure"; }else if ( measureType == MeasureType::ReportingMeasure){ measureTypeString = "Reporting Measure"; } int index = m_measureTypeComboBox->findText(measureTypeString); m_measureTypeComboBox->setCurrentIndex(index); QStringList taxonomyParts = toQString(bclMeasure.taxonomyTag()).split('.'); if (taxonomyParts.size() > 0){ index = m_taxonomyFirstLevelComboBox->findText(taxonomyParts[0]); m_taxonomyFirstLevelComboBox->setCurrentIndex(index); firstLevelTaxonomyChanged(m_taxonomyFirstLevelComboBox->currentText()); } if (taxonomyParts.size() > 1){ index = m_taxonomySecondLevelComboBox->findText(taxonomyParts[1]); m_taxonomySecondLevelComboBox->setCurrentIndex(index); } std::vector<std::string> intendedSoftwareTools = bclMeasure.intendedSoftwareTools(); QList<QListWidgetItem *> items = m_intendedSoftwareToolListWidget->findItems(".*", Qt::MatchRegExp); for (QListWidgetItem * item : items){ std::string intendedSoftwareTool = toString(item->text()); if (std::find(intendedSoftwareTools.begin(), intendedSoftwareTools.end(), intendedSoftwareTool) == intendedSoftwareTools.end()){ item->setCheckState(Qt::Unchecked); } else { item->setCheckState(Qt::Checked); } } std::vector<std::string> intendedUseCases = bclMeasure.intendedUseCases(); items = m_intendedUseCaseListWidget->findItems(".*", Qt::MatchRegExp); for (QListWidgetItem * item : items){ std::string intendedUseCase = toString(item->text()); if (std::find(intendedUseCases.begin(), intendedUseCases.end(), intendedUseCase) == intendedUseCases.end()){ item->setCheckState(Qt::Unchecked); } else { item->setCheckState(Qt::Checked); } } }
TEST_F(ProjectFixture, RubyMeasureRecord_BCLMeasure) { // Construct problem with RubyMeasure that points to BCLMeasure Problem problem("Problem",VariableVector(),runmanager::Workflow()); MeasureGroup dvar("Variable",MeasureVector()); problem.push(dvar); openstudio::path measuresPath = resourcesPath() / toPath("/utilities/BCL/Measures"); openstudio::path dir = measuresPath / toPath("SetWindowToWallRatioByFacade"); BCLMeasure measure = BCLMeasure::load(dir).get(); RubyMeasure rpert(measure); dvar.push(rpert); OSArgument arg = OSArgument::makeDoubleArgument("wwr"); arg.setValue(0.4); rpert.setArgument(arg); arg = OSArgument::makeIntegerArgument("typo_arg"); arg.setDefaultValue(1); rpert.setArgument(arg); // Serialize to database { ProjectDatabase database = getCleanDatabase("RubyMeasureRecord_BCLMeasure"); bool didStartTransaction = database.startTransaction(); EXPECT_TRUE(didStartTransaction); // Problem Record ProblemRecord problemRecord = ProblemRecord::factoryFromProblem(problem,database); database.save(); if (didStartTransaction) { EXPECT_TRUE(database.commitTransaction()); } } // Re-open database, de-serialize, verify that RubyMeasure is intact. openstudio::path tempDir1 = measuresPath / toPath(toString(createUUID())); { ProjectDatabase database = getExistingDatabase("RubyMeasureRecord_BCLMeasure"); ASSERT_EQ(1u,ProblemRecord::getProblemRecords(database).size()); ASSERT_EQ(1u,MeasureGroupRecord::getMeasureGroupRecords(database).size()); EXPECT_EQ(1u,RubyMeasureRecord::getRubyMeasureRecords(database).size()); MeasureRecordVector dprs = MeasureGroupRecord::getMeasureGroupRecords(database)[0].measureRecords(false); ASSERT_EQ(1u,dprs.size()); ASSERT_TRUE(dprs[0].optionalCast<RubyMeasureRecord>()); RubyMeasureRecord rpr = dprs[0].cast<RubyMeasureRecord>(); RubyMeasure rp = rpr.rubyMeasure(); EXPECT_TRUE(rp.usesBCLMeasure()); EXPECT_TRUE(rp.measure()); EXPECT_EQ(dir,rp.measureDirectory()); EXPECT_EQ(measure.uuid(),rp.measureUUID()); EXPECT_EQ(measure.versionUUID(),rp.measureVersionUUID()); EXPECT_ANY_THROW(rp.perturbationScript()); EXPECT_EQ(2u,rp.arguments().size()); EXPECT_FALSE(rp.hasIncompleteArguments()); // Update measure and save BCLMeasure newVersion = measure.clone(tempDir1).get(); newVersion.setDescription("Window to wall ratio with sill height configurable."); newVersion.save(); EXPECT_NE(measure.versionUUID(),newVersion.versionUUID()); OSArgumentVector args; args.push_back(OSArgument::makeDoubleArgument("wwr")); args.push_back(OSArgument::makeDoubleArgument("sillHeight")); Problem problemCopy = ProblemRecord::getProblemRecords(database)[0].problem(); problemCopy.updateMeasure(newVersion,args,false); bool didStartTransaction = database.startTransaction(); EXPECT_TRUE(didStartTransaction); // Problem Record ProblemRecord problemRecord = ProblemRecord::factoryFromProblem(problemCopy,database); database.save(); if (didStartTransaction) { EXPECT_TRUE(database.commitTransaction()); } } // Re-open database, check that old argument records are gone, check that de-serialized object ok openstudio::path tempDir2 = measuresPath / toPath(toString(createUUID())); { ProjectDatabase database = getExistingDatabase("RubyMeasureRecord_BCLMeasure"); ASSERT_EQ(1u,ProblemRecord::getProblemRecords(database).size()); EXPECT_EQ(1u,MeasureGroupRecord::getMeasureGroupRecords(database).size()); EXPECT_EQ(1u,RubyMeasureRecord::getRubyMeasureRecords(database).size()); EXPECT_EQ(1u,FileReferenceRecord::getFileReferenceRecords(database).size()); EXPECT_EQ(2u,OSArgumentRecord::getOSArgumentRecords(database).size()); Problem problemCopy = ProblemRecord::getProblemRecords(database)[0].problem(); InputVariableVector vars = problemCopy.variables(); ASSERT_FALSE(vars.empty()); ASSERT_TRUE(vars[0].optionalCast<MeasureGroup>()); MeasureVector dps = vars[0].cast<MeasureGroup>().measures(false); ASSERT_FALSE(dps.empty()); ASSERT_TRUE(dps[0].optionalCast<RubyMeasure>()); RubyMeasure rp = dps[0].cast<RubyMeasure>(); EXPECT_TRUE(rp.usesBCLMeasure()); EXPECT_TRUE(rp.measure()); EXPECT_EQ(tempDir1,rp.measureDirectory()); EXPECT_EQ(measure.uuid(),rp.measureUUID()); EXPECT_NE(measure.versionUUID(),rp.measureVersionUUID()); EXPECT_ANY_THROW(rp.perturbationScript()); ASSERT_EQ(2u,rp.arguments().size()); EXPECT_TRUE(rp.hasIncompleteArguments()); EXPECT_EQ("wwr",rp.arguments()[0].name()); ASSERT_EQ(1u,rp.incompleteArguments().size()); EXPECT_EQ("sillHeight",rp.incompleteArguments()[0].name()); // Set to different measure BCLMeasure measure2 = measure.clone(tempDir2).get(); measure2.changeUID(); measure2.incrementVersionId(); measure2.save(); measure2 = BCLMeasure::load(tempDir2).get(); EXPECT_NE(measure.uuid(),measure2.uuid()); EXPECT_NE(measure.versionUUID(),measure2.versionUUID()); rp.setMeasure(measure2); EXPECT_TRUE(rp.isDirty()); EXPECT_TRUE(problemCopy.isDirty()); bool didStartTransaction = database.startTransaction(); EXPECT_TRUE(didStartTransaction); // Problem Record ProblemRecord problemRecord = ProblemRecord::factoryFromProblem(problemCopy,database); database.save(); if (didStartTransaction) { EXPECT_TRUE(database.commitTransaction()); } } // Re-open database, check that old measure and all argument records are gone { ProjectDatabase database = getExistingDatabase("RubyMeasureRecord_BCLMeasure"); ASSERT_EQ(1u,ProblemRecord::getProblemRecords(database).size()); EXPECT_EQ(1u,MeasureGroupRecord::getMeasureGroupRecords(database).size()); EXPECT_EQ(1u,RubyMeasureRecord::getRubyMeasureRecords(database).size()); EXPECT_EQ(1u,FileReferenceRecord::getFileReferenceRecords(database).size()); EXPECT_EQ(0u,OSArgumentRecord::getOSArgumentRecords(database).size()); Problem problemCopy = ProblemRecord::getProblemRecords(database)[0].problem(); InputVariableVector vars = problemCopy.variables(); ASSERT_FALSE(vars.empty()); ASSERT_TRUE(vars[0].optionalCast<MeasureGroup>()); MeasureVector dps = vars[0].cast<MeasureGroup>().measures(false); ASSERT_FALSE(dps.empty()); ASSERT_TRUE(dps[0].optionalCast<RubyMeasure>()); RubyMeasure rp = dps[0].cast<RubyMeasure>(); EXPECT_TRUE(rp.usesBCLMeasure()); EXPECT_TRUE(rp.measure()); EXPECT_EQ(tempDir2,rp.measureDirectory()); EXPECT_NE(measure.uuid(),rp.measureUUID()); EXPECT_NE(measure.versionUUID(),rp.measureVersionUUID()); EXPECT_ANY_THROW(rp.perturbationScript()); ASSERT_EQ(0u,rp.arguments().size()); EXPECT_FALSE(rp.hasIncompleteArguments()); } boost::filesystem::remove_all(tempDir1); boost::filesystem::remove_all(tempDir2); }
TEST_F(AnalysisDriverFixture,SimpleProject_UpdateMeasure) { // create a new project SimpleProject project = getCleanSimpleProject("SimpleProject_UpdateMeasure"); Problem problem = project.analysis().problem(); // insert a measure into the project, extract and register its arguments openstudio::path measuresDir = resourcesPath() / toPath("/utilities/BCL/Measures"); openstudio::path dir = measuresDir / toPath("SetWindowToWallRatioByFacade"); BCLMeasure measure = BCLMeasure::load(dir).get(); BCLMeasure projectMeasure = project.insertMeasure(measure); OSArgumentVector args = argumentGetter->getArguments(projectMeasure, project.seedModel(), project.seedIdf()); project.registerArguments(projectMeasure,args); EXPECT_EQ(1u,project.measures().size()); // use the measure to create a new variable/ruby measure MeasureGroup dv("New Measure Group",MeasureVector()); EXPECT_TRUE(problem.push(dv)); RubyMeasure rp(projectMeasure); rp.setArguments(args); EXPECT_TRUE(dv.push(rp)); EXPECT_EQ(args.size(),rp.arguments().size()); EXPECT_TRUE(rp.hasIncompleteArguments()); BOOST_FOREACH(const OSArgument& arg,args) { if (arg.name() == "wwr") { OSArgument temp = arg.clone(); temp.setValue(0.6); rp.setArgument(temp); } if (arg.name() == "sillHeight") { OSArgument temp = arg.clone(); temp.setValue(1.0); rp.setArgument(temp); } if (arg.name() == "facade") { OSArgument temp = arg.clone(); temp.setValue("South"); rp.setArgument(temp); } } EXPECT_FALSE(rp.hasIncompleteArguments()); openstudio::path tempDir = measuresDir / toPath(toString(createUUID())); { // create fake new version of the measure BCLMeasure newVersion = measure.clone(tempDir).get(); newVersion.incrementVersionId(); newVersion.save(); OSArgumentVector newArgs = args; newArgs.push_back(OSArgument::makeDoubleArgument("frame_width")); // update the measure project.updateMeasure(newVersion,newArgs); // verify the final state of SimpleProject and RubyMeasure EXPECT_EQ(1u,project.measures().size()); BCLMeasure retrievedMeasure = project.getMeasureByUUID(measure.uuid()).get(); EXPECT_NE(measure.versionUUID(),retrievedMeasure.versionUUID()); EXPECT_EQ(newVersion.versionUUID(),retrievedMeasure.versionUUID()); ASSERT_TRUE(project.hasStoredArguments(retrievedMeasure)); OSArgumentVector retrievedArgs = project.getStoredArguments(retrievedMeasure); EXPECT_EQ(args.size() + 1u,retrievedArgs.size()); EXPECT_EQ(retrievedArgs.size(),rp.arguments().size()); EXPECT_TRUE(rp.hasIncompleteArguments()); } boost::filesystem::remove_all(tempDir); }
TEST_F(AnalysisDriverFixture,SimpleProject_InsertMeasure) { // create a new project SimpleProject project = getCleanSimpleProject("SimpleProject_InsertMeasure"); // open a measure openstudio::path dir = resourcesPath() / toPath("/utilities/BCL/Measures/SetWindowToWallRatioByFacade"); BCLMeasure measure = BCLMeasure::load(dir).get(); // insert it into the project BCLMeasure projectMeasure = project.insertMeasure(measure); // verify that there is a project-specific copy EXPECT_NE(toString(measure.directory()),toString(projectMeasure.directory())); openstudio::path scriptsDir = project.projectDir() / toPath("scripts"); EXPECT_EQ(toString(completeAndNormalize(scriptsDir)), toString(completeAndNormalize(projectMeasure.directory().parent_path()))); EXPECT_EQ(measure.uuid(),projectMeasure.uuid()); EXPECT_EQ(measure.versionUUID(),projectMeasure.versionUUID()); // DLM: should this be not equal? // verify that it can be retrieved from the project, but its arguments cannot ASSERT_TRUE(project.getMeasureByUUID(measure.uuid())); BCLMeasure temp = project.getMeasureByUUID(measure.uuid()).get(); EXPECT_EQ(toString(projectMeasure.directory()),toString(temp.directory())); EXPECT_EQ(projectMeasure.uuid(),temp.uuid()); EXPECT_EQ(projectMeasure.versionUUID(),temp.versionUUID()); EXPECT_EQ(1u,project.measures().size()); // use embedded Ruby to extract the arguments // (see AnalysisDriverFixture.cpp for interpreter set-up) OSArgumentVector args = argumentGetter->getArguments(projectMeasure, project.seedModel(), project.seedIdf()); EXPECT_FALSE(args.empty()); // register and subsequently retrieve those arguments project.registerArguments(measure,args); // doesn't matter which copy of the measure we use EXPECT_TRUE(project.hasStoredArguments(temp)); OSArgumentVector argsCopy = project.getStoredArguments(projectMeasure); ASSERT_EQ(args.size(),argsCopy.size()); for (int i = 0, n = args.size(); i < n; ++i) { EXPECT_EQ(args[i].name(),argsCopy[i].name()); EXPECT_EQ(args[i].type(),argsCopy[i].type()); } // use this measure to create a new variable/ruby measure // now it is important to use the copy in the project MeasureGroup dv("New Measure Group",MeasureVector()); Problem problem = project.analysis().problem(); problem.push(dv); // here, expect this test to pass. // in pat, if it fails, let user know and call problem.erase(dv). EXPECT_TRUE(problem.fileTypesAreCompatible(dv, projectMeasure.inputFileType(), projectMeasure.outputFileType())); EXPECT_TRUE(dv.push(RubyMeasure(projectMeasure))); }
TEST_F(AnalysisFixture, Problem_FileTypesAreCompatible_ExistingMeasureGroup) { // expected behavior when discrete variable already contains measures // test with BCLMeasure first. verify with RubyMeasure. // create problem VariableVector variables; variables.push_back( MeasureGroup("Model Variable 1", MeasureVector(1u,RubyMeasure(toPath("modelUserScript.rb"), FileReferenceType::OSM, FileReferenceType::OSM, true)))); variables.back().cast<MeasureGroup>().insert(0,NullMeasure()); // 2 variables.push_back( MeasureGroup("Translation Variable 1", MeasureVector(1u,RubyMeasure(toPath("translationUserScript.rb"), FileReferenceType::OSM, FileReferenceType::IDF, true)))); // 3 variables.push_back( MeasureGroup("Workspace Variable 1", MeasureVector(1u,RubyMeasure(toPath("workspaceUserScript.rb"), FileReferenceType::IDF, FileReferenceType::IDF, true)))); variables.back().cast<MeasureGroup>().insert(0,NullMeasure()); runmanager::Workflow workflow; workflow.addJob(runmanager::JobType::EnergyPlus); Problem problem("Problem",variables,workflow); // create measure to be pushed onto a variable openstudio::path dir = resourcesPath() / toPath("/utilities/BCL/Measures/v2/SetWindowToWallRatioByFacade"); BCLMeasure bclMeasure = BCLMeasure::load(dir).get(); EXPECT_EQ(FileReferenceType(FileReferenceType::OSM),bclMeasure.inputFileType()); EXPECT_EQ(FileReferenceType(FileReferenceType::OSM),bclMeasure.outputFileType()); RubyMeasure measure(bclMeasure); ASSERT_EQ(3,problem.numVariables()); // can be added to variable 0 (OSM) WorkflowStep step = problem.workflow()[0]; InputVariable var = step.inputVariable(); EXPECT_EQ(2u,var.cast<MeasureGroup>().numMeasures(false)); EXPECT_TRUE(problem.fileTypesAreCompatible(step, measure.inputFileType(), measure.outputFileType())); EXPECT_TRUE(var.cast<MeasureGroup>().push(measure)); EXPECT_EQ(3u,var.cast<MeasureGroup>().numMeasures(false)); // cannot be added to variable 1 (translation) step = problem.workflow()[1]; var = step.inputVariable(); EXPECT_EQ(1u,var.cast<MeasureGroup>().numMeasures(false)); EXPECT_FALSE(problem.fileTypesAreCompatible(step, measure.inputFileType(), measure.outputFileType())); EXPECT_FALSE(var.cast<MeasureGroup>().push(measure)); EXPECT_EQ(1u,var.cast<MeasureGroup>().numMeasures(false)); // cannot be added to variable 2 (IDF) step = problem.variables()[2]; var = step.inputVariable(); EXPECT_EQ(2u,var.cast<MeasureGroup>().numMeasures(false)); EXPECT_FALSE(problem.fileTypesAreCompatible(step, measure.inputFileType(), measure.outputFileType())); EXPECT_FALSE(var.cast<MeasureGroup>().push(measure)); EXPECT_EQ(2u,var.cast<MeasureGroup>().numMeasures(false)); }
TEST_F(AnalysisFixture, Problem_FileTypesAreCompatible_NewMeasureGroup) { // ok to insert null-only discrete variable anywhere in the chain // (between null-model, model-model, idf-idf, idf-workflow) VariableVector variables; // 0 variables.push_back( MeasureGroup("Null Variable 1", MeasureVector(1u,NullMeasure()))); // 1 variables.push_back( MeasureGroup("Model Variable 1", MeasureVector(1u,RubyMeasure(toPath("modelUserScript.rb"), FileReferenceType::OSM, FileReferenceType::OSM, true)))); // 2 variables.push_back( MeasureGroup("Translation Variable 1", MeasureVector(1u,RubyMeasure(toPath("translationUserScript.rb"), FileReferenceType::OSM, FileReferenceType::IDF, true)))); // 3 variables.push_back( MeasureGroup("Workspace Variable 1", MeasureVector(1u,RubyMeasure(toPath("workspaceUserScript.rb"), FileReferenceType::IDF, FileReferenceType::IDF, true)))); runmanager::Workflow workflow; workflow.addJob(runmanager::JobType::EnergyPlus); Problem problem("Problem 1",variables,workflow); MeasureGroup newVar("New Discrete Variable", MeasureVector(1u,NullMeasure())); EXPECT_TRUE(problem.insert(4,newVar.clone().cast<InputVariable>())); ASSERT_EQ(5,problem.numVariables()); EXPECT_EQ("New Discrete Variable",problem.variables()[4].name()); EXPECT_TRUE(problem.insert(3,newVar.clone().cast<InputVariable>())); EXPECT_EQ(6,problem.numVariables()); ASSERT_GE(problem.numVariables(),5); EXPECT_EQ("Translation Variable 1",problem.variables()[2].name()); EXPECT_EQ("New Discrete Variable",problem.variables()[3].name()); EXPECT_EQ("Workspace Variable 1",problem.variables()[4].name()); EXPECT_TRUE(problem.insert(2,newVar.clone().cast<InputVariable>())); EXPECT_TRUE(problem.insert(1,newVar.clone().cast<InputVariable>())); EXPECT_TRUE(problem.insert(0,newVar.clone().cast<InputVariable>())); EXPECT_EQ(9,problem.numVariables()); variables = castVector<Variable>(problem.variables()); for (int i = 0, n = problem.numVariables(); i < n; ++i) { if (i % 2 == 0) { EXPECT_EQ("New Discrete Variable",variables[i].name()); } else { EXPECT_NE("New Discrete Variable",variables[i].name()); } } // (between null-idf, idf-idf, idf-workflow) variables.clear(); // 0 variables.push_back( MeasureGroup("Null Variable 1", MeasureVector(1u,NullMeasure()))); // 1 variables.push_back( MeasureGroup("Workspace Variable 1", MeasureVector(1u,RubyMeasure(toPath("workspaceUserScript.rb"), FileReferenceType::IDF, FileReferenceType::IDF, true)))); // 2 variables.push_back( MeasureGroup("Workspace Variable 2", MeasureVector(1u,RubyMeasure(toPath("workspaceUserScript.rb"), FileReferenceType::IDF, FileReferenceType::IDF, true)))); problem = Problem("Problem 2",variables,workflow); EXPECT_TRUE(problem.insert(3,newVar.clone().cast<InputVariable>())); EXPECT_TRUE(problem.insert(2,newVar.clone().cast<InputVariable>())); EXPECT_TRUE(problem.insert(1,newVar.clone().cast<InputVariable>())); EXPECT_TRUE(problem.insert(0,newVar.clone().cast<InputVariable>())); EXPECT_EQ(7,problem.numVariables()); variables = castVector<Variable>(problem.variables()); for (int i = 0, n = problem.numVariables(); i < n; ++i) { if (i % 2 == 0) { EXPECT_EQ("New Discrete Variable",variables[i].name()); } else { EXPECT_NE("New Discrete Variable",variables[i].name()); } } // expected behavior for then adding first measure // test with BCLMeasure first. verify with RubyMeasure. openstudio::path dir = resourcesPath() / toPath("/utilities/BCL/Measures/v2/SetWindowToWallRatioByFacade"); BCLMeasure bclMeasure = BCLMeasure::load(dir).get(); EXPECT_EQ(FileReferenceType(FileReferenceType::OSM),bclMeasure.inputFileType()); EXPECT_EQ(FileReferenceType(FileReferenceType::OSM),bclMeasure.outputFileType()); RubyMeasure measure(bclMeasure); // have idf-only problem with two null variables at the top // try to add measures to first variable MeasureGroup firstVariable = problem.variables()[0].cast<MeasureGroup>(); ASSERT_TRUE(firstVariable.parent()); WorkflowStep step0 = problem.workflow()[0]; EXPECT_TRUE(firstVariable.parent().get() == step0); EXPECT_EQ(1u,firstVariable.numMeasures(false)); EXPECT_FALSE(problem.fileTypesAreCompatible(firstVariable, measure.inputFileType(), measure.outputFileType())); ASSERT_TRUE(firstVariable.parent()); EXPECT_TRUE(firstVariable.parent().get() == problem.workflow()[0]); EXPECT_TRUE(problem.workflow()[0] == step0); EXPECT_FALSE(firstVariable.push(measure)); EXPECT_EQ(1u,firstVariable.numMeasures(false)); // make second variable a translation variable MeasureGroup secondVariable = problem.variables()[1].cast<MeasureGroup>(); EXPECT_FALSE(secondVariable.push(RubyMeasure(toPath("myTranslationScript.rb"), FileReferenceType::OSM, FileReferenceType::IDF))); secondVariable.erase(secondVariable.measures(false)[0]); EXPECT_TRUE(secondVariable.push(RubyMeasure(toPath("myTranslationScript.rb"), FileReferenceType::OSM, FileReferenceType::IDF))); // now should be able to add OSM measure EXPECT_TRUE(problem.fileTypesAreCompatible(firstVariable, measure.inputFileType(), measure.outputFileType())); EXPECT_TRUE(firstVariable.push(measure)); EXPECT_EQ(2u,firstVariable.numMeasures(false)); }
TEST_F(BCLFixture, PatApplicationMeasures) { std::vector<BCLMeasure> patApplicationMeasures = BCLMeasure::patApplicationMeasures(); ASSERT_EQ(4u, patApplicationMeasures.size()); bool filesUpdated; bool xmlUpdated; BCLMeasure alternativeModelMeasure = BCLMeasure::alternativeModelMeasure(); filesUpdated = alternativeModelMeasure.checkForUpdatesFiles(); ASSERT_FALSE(filesUpdated); // DLM: comment out to update built in PAT measures xmlUpdated = alternativeModelMeasure.checkForUpdatesXML(); ASSERT_FALSE(xmlUpdated); // DLM: comment out to update built in PAT measures if (filesUpdated || xmlUpdated){ alternativeModelMeasure.save(); } BCLMeasure reportRequestMeasure = BCLMeasure::reportRequestMeasure(); filesUpdated = reportRequestMeasure.checkForUpdatesFiles(); ASSERT_FALSE(filesUpdated); // DLM: comment out to update built in PAT measures xmlUpdated = reportRequestMeasure.checkForUpdatesXML(); ASSERT_FALSE(xmlUpdated); // DLM: comment out to update built in PAT measures if (filesUpdated || xmlUpdated){ reportRequestMeasure.save(); } BCLMeasure standardReportMeasure = BCLMeasure::standardReportMeasure(); filesUpdated = standardReportMeasure.checkForUpdatesFiles(); ASSERT_FALSE(filesUpdated); // DLM: comment out to update built in PAT measures xmlUpdated = standardReportMeasure.checkForUpdatesXML(); ASSERT_FALSE(xmlUpdated); // DLM: comment out to update built in PAT measures if (filesUpdated || xmlUpdated){ standardReportMeasure.save(); } BCLMeasure calibrationReportMeasure = BCLMeasure::calibrationReportMeasure(); filesUpdated = calibrationReportMeasure.checkForUpdatesFiles(); ASSERT_FALSE(filesUpdated); // DLM: comment out to update built in PAT measures xmlUpdated = calibrationReportMeasure.checkForUpdatesXML(); ASSERT_FALSE(xmlUpdated); // DLM: comment out to update built in PAT measures if (filesUpdated || xmlUpdated){ calibrationReportMeasure.save(); } }
TEST_F(AnalysisFixture, RubyPerturbation_BCLMeasure) { // construct openstudio::path measuresPath = resourcesPath() / toPath("/utilities/BCL/Measures"); openstudio::path dir = measuresPath / toPath("SetWindowToWallRatioByFacade"); BCLMeasure measure = BCLMeasure::load(dir).get(); RubyPerturbation perturbation(measure); EXPECT_TRUE(perturbation.usesBCLMeasure()); ASSERT_TRUE(perturbation.measure()); EXPECT_TRUE(perturbation.measure().get() == measure); EXPECT_EQ(dir,perturbation.measureDirectory()); EXPECT_TRUE(measure.uuid() == perturbation.measureUUID()); EXPECT_TRUE(measure.versionUUID() == perturbation.measureVersionUUID()); EXPECT_ANY_THROW(perturbation.perturbationScript()); // isUserScript value is ignored in this case EXPECT_TRUE(perturbation.arguments().empty()); EXPECT_FALSE(perturbation.hasIncompleteArguments()); // add arguments to fill in OSArgumentVector args; args.push_back(OSArgument::makeDoubleArgument("wwr")); args.push_back(OSArgument::makeDoubleArgument("sillHeight")); perturbation.setArguments(args); // verify that arguments are incomplete EXPECT_EQ(2u,perturbation.incompleteArguments().size()); // fill in argument values OSArgument arg = OSArgument::makeDoubleArgument("wwr"); EXPECT_TRUE(arg.setValue(0.8)); perturbation.setArgument(arg); EXPECT_EQ(2u,perturbation.arguments().size()); EXPECT_EQ(1u,perturbation.incompleteArguments().size()); EXPECT_TRUE(perturbation.hasIncompleteArguments()); arg = OSArgument::makeDoubleArgument("sillHeight"); arg.setValue("0.1"); perturbation.setArgument(arg); EXPECT_EQ(2u,perturbation.arguments().size()); EXPECT_EQ(0u,perturbation.incompleteArguments().size()); EXPECT_FALSE(perturbation.hasIncompleteArguments()); // update measure openstudio::path tempDir = measuresPath / toPath(toString(createUUID())); { BCLMeasure newVersion = measure.clone(tempDir).get(); newVersion.setDescription("Window to wall ratio by wwr and offset."); newVersion.save(); EXPECT_TRUE(newVersion.uuid() == measure.uuid()); EXPECT_FALSE(newVersion.versionUUID() == measure.versionUUID()); args.pop_back(); args.push_back(OSArgument::makeDoubleArgument("offset")); perturbation.updateMeasure(newVersion,args); EXPECT_TRUE(perturbation.usesBCLMeasure()); ASSERT_TRUE(perturbation.measure()); EXPECT_TRUE(perturbation.measure().get() == newVersion); EXPECT_EQ(tempDir,perturbation.measureDirectory()); EXPECT_TRUE(newVersion.uuid() == perturbation.measureUUID()); EXPECT_TRUE(newVersion.versionUUID() == perturbation.measureVersionUUID()); EXPECT_ANY_THROW(perturbation.perturbationScript()); // verify that arguments updated correctly, values retained EXPECT_EQ(2u,perturbation.arguments().size()); ASSERT_EQ(1u,perturbation.incompleteArguments().size()); EXPECT_TRUE(perturbation.hasIncompleteArguments()); EXPECT_EQ("offset",perturbation.incompleteArguments()[0].name()); EXPECT_EQ("wwr",perturbation.arguments()[0].name()); EXPECT_EQ(0.8,perturbation.arguments()[0].valueAsDouble()); // set measure and verify that arguments cleared perturbation.setMeasure(newVersion); // always goes through setting motions, even if same EXPECT_TRUE(perturbation.usesBCLMeasure()); ASSERT_TRUE(perturbation.measure()); EXPECT_TRUE(perturbation.measure().get() == newVersion); EXPECT_EQ(tempDir,perturbation.measureDirectory()); EXPECT_TRUE(newVersion.uuid() == perturbation.measureUUID()); EXPECT_TRUE(newVersion.versionUUID() == perturbation.measureVersionUUID()); EXPECT_ANY_THROW(perturbation.perturbationScript()); // isUserScript value is ignored in this case EXPECT_TRUE(perturbation.arguments().empty()); EXPECT_FALSE(perturbation.hasIncompleteArguments()); } boost::filesystem::remove_all(tempDir); }
bool RubyMeasure_Impl::updateMeasure(const BCLMeasure& newVersion, std::vector<ruleset::OSArgument> newArguments) { if (!usesBCLMeasure() || (newVersion.uuid() != m_bclMeasureUUID.get())) { return false; } FileReferenceType inputFileType = newVersion.inputFileType(); FileReferenceType outputFileType = newVersion.outputFileType(); if (!fileTypesAreCompatible(inputFileType,outputFileType)) { return false; } m_bclMeasure = newVersion; m_bclMeasureDirectory = newVersion.directory(); OS_ASSERT(m_bclMeasureUUID.get() == newVersion.uuid()); m_bclMeasureVersionUUID = newVersion.versionUUID(); m_inputFileType = inputFileType; m_outputFileType = outputFileType; m_isUserScript = false; // preserve current argument values // otherwise, prefer newArguments definitions and order OSArgumentVector argsToSet; OSArgumentVector currentArgs = arguments(); BOOST_FOREACH(const OSArgument& newArg,newArguments) { OSArgument newArgClone = newArg.clone(); // look for current value NameFinder<OSArgument> finder(newArgClone.name(),true); ruleset::OSArgumentVector::iterator it = std::find_if(currentArgs.begin(), currentArgs.end(), finder); if (it != currentArgs.end()) { // already exists--try to preserve value if (it->hasValue()) { bool setResult(false); switch(it->type().value()) { case OSArgumentType::Boolean : setResult = newArgClone.setValue(it->valueAsBool()); break; case OSArgumentType::Double : setResult = newArgClone.setValue(it->valueAsDouble()); break; case OSArgumentType::Quantity : setResult = newArgClone.setValue(it->valueAsQuantity()); break; case OSArgumentType::Integer : setResult = newArgClone.setValue(it->valueAsInteger()); break; default : break; } if (!setResult) { // try string conversion by default or if failed setResult = newArgClone.setValue(it->valueAsString()); if (!setResult) { LOG(Info,"Unable to preserve argument value for " << *it << " during updateMeasure operation on RubyMeasure named " << name() << " with measure " << newVersion.name() << " and new argument " << newArgClone); } } } } argsToSet.push_back(newArgClone); }