diff --git a/.github/workflows/buildCSharp.yml b/.github/workflows/buildCSharp.yml
index 67bd5d7d547..ffaeafc2ad7 100644
--- a/.github/workflows/buildCSharp.yml
+++ b/.github/workflows/buildCSharp.yml
@@ -23,9 +23,9 @@ jobs:
name: [Ubuntu, macOS, macOS_arm64, Windows64, Windows32]
include:
- name: Ubuntu
- os: ubuntu-20.04
+ os: ubuntu-22.04
- name: macOS
- os: macos-11
+ os: macos-13
- name: macOS_arm64
os: macos-14
- name: Windows64
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 05fe5faf2f9..2d833b0f85c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -161,7 +161,7 @@ get_directory_property(hasParent PARENT_DIRECTORY)
# TODO: Modify the more specific variables as needed to indicate prerelease, etc
# Keep in beta in-between release cycles. Set to empty string (or comment out) for official)
-set(PROJECT_VERSION_PRERELEASE "rc2")
+set(PROJECT_VERSION_PRERELEASE "rc3")
# OpenStudio version: Only include Major.Minor.Patch, eg "3.0.0", even if you have a prerelease tag
set(OPENSTUDIO_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
@@ -638,11 +638,15 @@ endif()
if(UNIX)
if(APPLE)
+ # TODO: temp for #5281 - Resigned with a different entitlements to avoid an issue when we pip install stuff into the E+ dir with native comps (numpy for eg)
+ set(ENERGYPLUS_REPO "jmarrec")
+ set(ENERGYPLUS_RELEASE_NAME "v24.2.0a-entitlements")
+
if (ARCH MATCHES "arm64")
- set(ENERGYPLUS_EXPECTED_HASH f36afc055a675ae95523d6f41ec478c0)
+ set(ENERGYPLUS_EXPECTED_HASH 29616d6aa23e2fc0f71362da9794ef08)
set(ENERGYPLUS_PLATFORM "Darwin-macOS13-arm64")
else()
- set(ENERGYPLUS_EXPECTED_HASH b2003c461277c0bd4e91a4c003b350ac)
+ set(ENERGYPLUS_EXPECTED_HASH 21bdad40fbc560b4b382469ef9f96936)
set(ENERGYPLUS_PLATFORM "Darwin-macOS12.1-x86_64")
endif()
elseif(LSB_RELEASE_ID_SHORT MATCHES "CentOS")
@@ -843,7 +847,7 @@ if(BUILD_CLI)
set(OPENSTUDIO_GEMS_BASEURL "http://openstudio-resources.s3.amazonaws.com/dependencies")
# TODO: temp
- set(OPENSTUDIO_GEMS_BASEURL "https://github.com/NREL/openstudio-gems/releases/download/v3.9.0-RC2")
+ set(OPENSTUDIO_GEMS_BASEURL "https://github.com/NREL/openstudio-gems/releases/download/v3.9.0-RC3")
# To use the package produced by a PR to https://github.com/NREL/openstudio-gems
set(USE_OPENSTUDIO_GEMS_PR FALSE)
@@ -855,19 +859,19 @@ if(BUILD_CLI)
if(UNIX)
if(APPLE)
if (ARCH MATCHES arm64)
- set(OPENSTUDIO_GEMS_ZIP_FILENAME "openstudio3-gems-20241101-darwin_arm64-3.2.2.tar.gz")
- set(OPENSTUDIO_GEMS_ZIP_EXPECTED_MD5 "c4cf7754444937e5df496f23af6d76ad")
+ set(OPENSTUDIO_GEMS_ZIP_FILENAME "openstudio3-gems-20241112-darwin_arm64-3.2.2.tar.gz")
+ set(OPENSTUDIO_GEMS_ZIP_EXPECTED_MD5 "cb6a884366780c8ba5da2852ca60e98a")
else()
- set(OPENSTUDIO_GEMS_ZIP_FILENAME "openstudio3-gems-20241101-darwin-3.2.2.tar.gz")
- set(OPENSTUDIO_GEMS_ZIP_EXPECTED_MD5 "5754b6ba7cff435d33f6c4dcdcd6bfc4")
+ set(OPENSTUDIO_GEMS_ZIP_FILENAME "openstudio3-gems-20241112-darwin-3.2.2.tar.gz")
+ set(OPENSTUDIO_GEMS_ZIP_EXPECTED_MD5 "ce81fcf1bf707281082cde3d87dac114")
endif()
else()
if (ARCH MATCHES "arm64")
set(OPENSTUDIO_GEMS_ZIP_FILENAME "openstudio3-gems-20240517-linux_arm64-3.2.2.tar.gz")
set(OPENSTUDIO_GEMS_ZIP_EXPECTED_MD5 "f6d094a3bdaf1476ce7911e74276993b")
else()
- set(OPENSTUDIO_GEMS_ZIP_FILENAME "openstudio3-gems-20241101-linux-3.2.2.tar.gz")
- set(OPENSTUDIO_GEMS_ZIP_EXPECTED_MD5 "972a9246fd2a6d43bc7eb23e2ad2b715")
+ set(OPENSTUDIO_GEMS_ZIP_FILENAME "openstudio3-gems-20241112-linux-3.2.2.tar.gz")
+ set(OPENSTUDIO_GEMS_ZIP_EXPECTED_MD5 "7551691c842a86cc8198959b5d0f1ee9")
endif()
if (USE_OPENSTUDIO_GEMS_PR)
set(OPENSTUDIO_GEMS_BASEURL "${OPENSTUDIO_GEMS_BASEURL}/openstudio-gems-linux/${OPENSTUDIO_GEMS_PR_NUMBER}")
@@ -875,8 +879,8 @@ if(BUILD_CLI)
endif()
elseif(WIN32)
# OpenStudio gems are only supported on 64 bit windows
- set(OPENSTUDIO_GEMS_ZIP_FILENAME "openstudio3-gems-20241101-windows-3.2.2.tar.gz")
- set(OPENSTUDIO_GEMS_ZIP_EXPECTED_MD5 "a5f1fde7ab2555e736d3d21ba5beb683")
+ set(OPENSTUDIO_GEMS_ZIP_FILENAME "openstudio3-gems-20241112-windows-3.2.2.tar.gz")
+ set(OPENSTUDIO_GEMS_ZIP_EXPECTED_MD5 "8f1cdcca664a1d3d80908230a00981ef")
if (USE_OPENSTUDIO_GEMS_PR)
set(OPENSTUDIO_GEMS_BASEURL "${OPENSTUDIO_GEMS_BASEURL}/openstudio-gems-windows/${OPENSTUDIO_GEMS_PR_NUMBER}")
endif()
diff --git a/ProjectMacros.cmake b/ProjectMacros.cmake
index cf944fa06a2..3ca827748ed 100644
--- a/ProjectMacros.cmake
+++ b/ProjectMacros.cmake
@@ -532,6 +532,7 @@ macro(MAKE_SWIG_TARGET NAME SIMPLENAME KEY_I_FILE I_FILES PARENT_TARGET PARENT_S
set( model_names
OpenStudioMeasure
+ OpenStudioAlfalfa
OpenStudioModel
OpenStudioModelAirflow
OpenStudioModelAvailabilityManager
diff --git a/csharp/CMakeLists.txt b/csharp/CMakeLists.txt
index 995b65987ff..4bffd5e51ac 100644
--- a/csharp/CMakeLists.txt
+++ b/csharp/CMakeLists.txt
@@ -83,6 +83,7 @@ set(translator_wrappers
set(model_wrappers
csharp_OpenStudioMeasure_wrap.cxx
+ csharp_OpenStudioAlfalfa_wrap.cxx
csharp_OpenStudioModel_wrap.cxx
csharp_OpenStudioModelAirflow_wrap.cxx
csharp_OpenStudioModelAvailabilityManager_wrap.cxx
diff --git a/resources/workflow/invalid_measures/missing_a_measure.osw b/resources/workflow/invalid_measures/missing_a_measure.osw
new file mode 100644
index 00000000000..2f78c0633ba
--- /dev/null
+++ b/resources/workflow/invalid_measures/missing_a_measure.osw
@@ -0,0 +1,19 @@
+{
+ "weather_file": "../../Examples/compact_osw/files/srrl_2013_amy.epw",
+ "seed_file": "../example_model.osm",
+ "measure_paths": ["../measures/"],
+ "steps": [
+ {
+ "measure_dir_name": "FakeModelMeasure",
+ "arguments": {}
+ },
+ {
+ "measure_dir_name": "NON_EXISTING_MEASURE_THIS_SHOULD_BE_CAUGHT",
+ "arguments": {}
+ },
+ {
+ "measure_dir_name": "FakeReport",
+ "arguments": {}
+ }
+ ]
+}
diff --git a/resources/workflow/invalid_measures/unloadable_measure.osw b/resources/workflow/invalid_measures/unloadable_measure.osw
new file mode 100644
index 00000000000..cb5d1c88178
--- /dev/null
+++ b/resources/workflow/invalid_measures/unloadable_measure.osw
@@ -0,0 +1,19 @@
+{
+ "weather_file": "../../Examples/compact_osw/files/srrl_2013_amy.epw",
+ "seed_file": "../example_model.osm",
+ "measure_paths": ["../measures/"],
+ "steps": [
+ {
+ "measure_dir_name": "FakeModelMeasure",
+ "arguments": {}
+ },
+ {
+ "measure_dir_name": "UnloadableMeasure",
+ "arguments": {}
+ },
+ {
+ "measure_dir_name": "FakeReport",
+ "arguments": {}
+ }
+ ]
+}
diff --git a/resources/workflow/invalid_measures/wrong_measure_type_order.osw b/resources/workflow/invalid_measures/wrong_measure_type_order.osw
new file mode 100644
index 00000000000..01b28e49177
--- /dev/null
+++ b/resources/workflow/invalid_measures/wrong_measure_type_order.osw
@@ -0,0 +1,15 @@
+{
+ "weather_file": "../../Examples/compact_osw/files/srrl_2013_amy.epw",
+ "seed_file": "../example_model.osm",
+ "measure_paths": ["../measures/"],
+ "steps": [
+ {
+ "measure_dir_name": "FakeReport",
+ "arguments": {}
+ },
+ {
+ "measure_dir_name": "FakeModelMeasure",
+ "arguments": {}
+ }
+ ]
+}
diff --git a/resources/workflow/measures/FakeModelMeasure/measure.rb b/resources/workflow/measures/FakeModelMeasure/measure.rb
new file mode 100644
index 00000000000..68a978a9096
--- /dev/null
+++ b/resources/workflow/measures/FakeModelMeasure/measure.rb
@@ -0,0 +1,42 @@
+class FakeModelMeasure < OpenStudio::Measure::ModelMeasure
+ # human readable name
+ def name
+ # Measure name should be the title case of the class name.
+ return 'A dumb ModelMeasure'
+ end
+
+ # human readable description
+ def description
+ return 'Does nothing'
+ end
+
+ # human readable description of modeling approach
+ def modeler_description
+ return 'Just for testing'
+ end
+
+ # define the arguments that the user will input
+ def arguments(model)
+ args = OpenStudio::Measure::OSArgumentVector.new
+
+ return args
+ end
+
+ # define what happens when the measure is run
+ def run(model, runner, user_arguments)
+ super(model, runner, user_arguments) # Do **NOT** remove this line
+
+ # use the built-in error checking
+ if !runner.validateUserArguments(arguments(model), user_arguments)
+ return false
+ end
+
+ # report final condition of model
+ runner.registerFinalCondition("The FakeModelMeasure run.")
+
+ return true
+ end
+end
+
+# register the measure to be used by the application
+FakeModelMeasure.new.registerWithApplication
diff --git a/resources/workflow/measures/FakeModelMeasure/measure.xml b/resources/workflow/measures/FakeModelMeasure/measure.xml
new file mode 100644
index 00000000000..a1fd30f66f0
--- /dev/null
+++ b/resources/workflow/measures/FakeModelMeasure/measure.xml
@@ -0,0 +1,44 @@
+
+
+ 3.1
+ fake_model_measure
+ 677b8fd3-2627-4516-b090-f6e47dc99fea
+ 162465e5-b6f6-419f-ab5f-c2fc4bd549e0
+ 2024-11-07T11:55:10Z
+ 82D8F881
+ FakeModelMeasure
+ A dumb ModelMeasure
+ Does nothing
+ Just for testing
+
+
+
+
+ Envelope.Form
+
+
+
+ Measure Type
+ ModelMeasure
+ string
+
+
+ Measure Language
+ Ruby
+ string
+
+
+
+
+
+ OpenStudio
+ 3.9.0
+ 3.9.0
+
+ measure.rb
+ rb
+ script
+ DDA977B0
+
+
+
diff --git a/resources/workflow/measures/UnloadableMeasure/README.md b/resources/workflow/measures/UnloadableMeasure/README.md
new file mode 100644
index 00000000000..4459d7e1aa3
--- /dev/null
+++ b/resources/workflow/measures/UnloadableMeasure/README.md
@@ -0,0 +1 @@
+This doesnt have a xml
diff --git a/resources/workflow/measures/UnloadableMeasure/measure.rb b/resources/workflow/measures/UnloadableMeasure/measure.rb
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/src/alfalfa/Alfalfa.i b/src/alfalfa/Alfalfa.i
index 1c3956b2b5b..ebe639c05a7 100644
--- a/src/alfalfa/Alfalfa.i
+++ b/src/alfalfa/Alfalfa.i
@@ -6,6 +6,8 @@
#endif
%include
+#define ALFALFA_API
+
%include
%import
%import
@@ -13,7 +15,6 @@
%ignore openstudio::alfalfa::detail;
%{
- #include
#include
#include
#include
@@ -33,15 +34,14 @@
using namespace openstudio::alfalfa;
%}
-%ignore openstudio::alfalfa::ComponentBase;
+%ignore openstudio::alfalfa::AlfalfaComponentBase;
%ignore openstudio::alfalfa::AlfalfaActuator::clone;
%ignore openstudio::alfalfa::AlfalfaConstant::clone;
%ignore openstudio::alfalfa::AlfalfaMeter::clone;
%ignore openstudio::alfalfa::AlfalfaGlobalVariable::clone;
%ignore openstudio::alfalfa::AlfalfaOutputVariable::clone;
-%include
-%include
+%include
%include
%include
%include
diff --git a/src/alfalfa/AlfalfaActuator.hpp b/src/alfalfa/AlfalfaActuator.hpp
index 9bc82dccb29..1ce5c05df2c 100644
--- a/src/alfalfa/AlfalfaActuator.hpp
+++ b/src/alfalfa/AlfalfaActuator.hpp
@@ -2,13 +2,13 @@
#define ALFALFA_COMPONENT_ACTUATOR_HPP
#include "AlfalfaAPI.hpp"
-#include "ComponentBase.hpp"
+#include "AlfalfaComponentBase.hpp"
#include "../utilities/idf/IdfObject.hpp"
namespace openstudio {
namespace alfalfa {
- class ALFALFA_API AlfalfaActuator : public ComponentBase
+ class ALFALFA_API AlfalfaActuator : public AlfalfaComponentBase
{
public:
/**
@@ -26,15 +26,15 @@ namespace alfalfa {
Json::Value toJSON() const override;
- ComponentCapability capability() const override {
- return ComponentCapability::Bidirectional;
+ AlfalfaComponentCapability capability() const override {
+ return AlfalfaComponentCapability::Bidirectional;
}
- ComponentType type() const override {
- return ComponentType::Actuator;
+ AlfalfaComponentType type() const override {
+ return AlfalfaComponentType::Actuator;
}
- std::unique_ptr clone() const override {
+ std::unique_ptr clone() const override {
return std::make_unique(*this);
}
diff --git a/src/alfalfa/AlfalfaComponent.cpp b/src/alfalfa/AlfalfaComponent.cpp
index 6b10d5bf702..bde3cae7039 100644
--- a/src/alfalfa/AlfalfaComponent.cpp
+++ b/src/alfalfa/AlfalfaComponent.cpp
@@ -6,11 +6,11 @@ namespace alfalfa {
return m_component->toJSON();
}
- ComponentCapability AlfalfaComponent::capability() const {
+ AlfalfaComponentCapability AlfalfaComponent::capability() const {
return m_component->capability();
}
- ComponentType AlfalfaComponent::type() const {
+ AlfalfaComponentType AlfalfaComponent::type() const {
return m_component->type();
}
diff --git a/src/alfalfa/AlfalfaComponent.hpp b/src/alfalfa/AlfalfaComponent.hpp
index b87b3ef5102..951ed4516f9 100644
--- a/src/alfalfa/AlfalfaComponent.hpp
+++ b/src/alfalfa/AlfalfaComponent.hpp
@@ -5,14 +5,14 @@
#include
#include "AlfalfaAPI.hpp"
-#include "ComponentBase.hpp"
+#include "AlfalfaComponentBase.hpp"
namespace openstudio {
namespace alfalfa {
class ALFALFA_API AlfalfaComponent
{
public:
- template ::value, bool> = true>
+ template ::value, bool> = true>
AlfalfaComponent(T component) : m_component(std::make_unique(std::move(component))) {}
AlfalfaComponent(const AlfalfaComponent& other) : m_component(other.m_component->clone()) {}
@@ -32,9 +32,9 @@ namespace alfalfa {
Json::Value toJSON() const;
- ComponentCapability capability() const;
+ AlfalfaComponentCapability capability() const;
- ComponentType type() const;
+ AlfalfaComponentType type() const;
std::string typeName() const;
@@ -46,7 +46,7 @@ namespace alfalfa {
private:
AlfalfaComponent() = default;
- std::unique_ptr m_component;
+ std::unique_ptr m_component;
};
inline bool operator==(const AlfalfaComponent& lhs, const AlfalfaComponent& rhs) {
diff --git a/src/alfalfa/AlfalfaComponentBase.cpp b/src/alfalfa/AlfalfaComponentBase.cpp
new file mode 100644
index 00000000000..1e114f07ced
--- /dev/null
+++ b/src/alfalfa/AlfalfaComponentBase.cpp
@@ -0,0 +1,15 @@
+#include "AlfalfaComponentBase.hpp"
+
+namespace openstudio {
+namespace alfalfa {
+
+ bool AlfalfaComponentBase::canInput() const {
+ return capability() == AlfalfaComponentCapability::Bidirectional || capability() == AlfalfaComponentCapability::Input;
+ }
+
+ bool AlfalfaComponentBase::canOutput() const {
+ return capability() == AlfalfaComponentCapability::Bidirectional || capability() == AlfalfaComponentCapability::Output;
+ }
+
+} // namespace alfalfa
+} // namespace openstudio
diff --git a/src/alfalfa/ComponentBase.hpp b/src/alfalfa/AlfalfaComponentBase.hpp
similarity index 52%
rename from src/alfalfa/ComponentBase.hpp
rename to src/alfalfa/AlfalfaComponentBase.hpp
index c85ba317886..b5239deb298 100644
--- a/src/alfalfa/ComponentBase.hpp
+++ b/src/alfalfa/AlfalfaComponentBase.hpp
@@ -3,27 +3,23 @@
#include "AlfalfaAPI.hpp"
-#include "../utilities/core/Enum.hpp"
+#include "../utilities/data/DataEnums.hpp"
#include
namespace openstudio {
namespace alfalfa {
- OPENSTUDIO_ENUM(ComponentCapability, ((Input))((Output))((Bidirectional)))
-
- OPENSTUDIO_ENUM(ComponentType, ((Actuator))((Constant))((Meter))((OutputVariable))((GlobalVariable)))
-
- class ALFALFA_API ComponentBase
+ class ALFALFA_API AlfalfaComponentBase
{
public:
- virtual ~ComponentBase() = default;
+ virtual ~AlfalfaComponentBase() = default;
virtual Json::Value toJSON() const = 0;
- virtual ComponentCapability capability() const = 0;
+ virtual AlfalfaComponentCapability capability() const = 0;
- virtual ComponentType type() const = 0;
+ virtual AlfalfaComponentType type() const = 0;
virtual std::string typeName() const {
return type().valueName();
@@ -31,7 +27,7 @@ namespace alfalfa {
virtual std::string deriveName() const = 0;
- virtual std::unique_ptr clone() const = 0;
+ virtual std::unique_ptr clone() const = 0;
virtual bool canInput() const;
diff --git a/src/alfalfa/AlfalfaConstant.hpp b/src/alfalfa/AlfalfaConstant.hpp
index 1d74e8b6226..e07403fe387 100644
--- a/src/alfalfa/AlfalfaConstant.hpp
+++ b/src/alfalfa/AlfalfaConstant.hpp
@@ -3,11 +3,11 @@
#include "AlfalfaAPI.hpp"
-#include "ComponentBase.hpp"
+#include "AlfalfaComponentBase.hpp"
namespace openstudio {
namespace alfalfa {
- class ALFALFA_API AlfalfaConstant : public ComponentBase
+ class ALFALFA_API AlfalfaConstant : public AlfalfaComponentBase
{
public:
/**
@@ -19,15 +19,15 @@ namespace alfalfa {
Json::Value toJSON() const override;
- ComponentCapability capability() const override {
- return ComponentCapability::Output;
+ AlfalfaComponentCapability capability() const override {
+ return AlfalfaComponentCapability::Output;
}
- ComponentType type() const override {
- return ComponentType::Constant;
+ AlfalfaComponentType type() const override {
+ return AlfalfaComponentType::Constant;
}
- std::unique_ptr clone() const override {
+ std::unique_ptr clone() const override {
return std::make_unique(*this);
}
diff --git a/src/alfalfa/AlfalfaGlobalVariable.hpp b/src/alfalfa/AlfalfaGlobalVariable.hpp
index 3f389bb08a4..e62efa171c0 100644
--- a/src/alfalfa/AlfalfaGlobalVariable.hpp
+++ b/src/alfalfa/AlfalfaGlobalVariable.hpp
@@ -3,13 +3,13 @@
#include "AlfalfaAPI.hpp"
-#include "ComponentBase.hpp"
+#include "AlfalfaComponentBase.hpp"
#include "../utilities/idf/IdfObject.hpp"
namespace openstudio {
namespace alfalfa {
- class ALFALFA_API AlfalfaGlobalVariable : public ComponentBase
+ class ALFALFA_API AlfalfaGlobalVariable : public AlfalfaComponentBase
{
public:
/**
@@ -27,15 +27,15 @@ namespace alfalfa {
Json::Value toJSON() const override;
- ComponentCapability capability() const override {
- return ComponentCapability::Bidirectional;
+ AlfalfaComponentCapability capability() const override {
+ return AlfalfaComponentCapability::Bidirectional;
}
- ComponentType type() const override {
- return ComponentType::GlobalVariable;
+ AlfalfaComponentType type() const override {
+ return AlfalfaComponentType::GlobalVariable;
}
- std::unique_ptr clone() const override {
+ std::unique_ptr clone() const override {
return std::make_unique(*this);
}
diff --git a/src/alfalfa/AlfalfaJSON.cpp b/src/alfalfa/AlfalfaJSON.cpp
index 518b09946a7..9fa41f5324e 100644
--- a/src/alfalfa/AlfalfaJSON.cpp
+++ b/src/alfalfa/AlfalfaJSON.cpp
@@ -83,9 +83,9 @@ namespace alfalfa {
Json::Value AlfalfaJSON_Impl::toJSON() const {
Json::Value root;
- for (const auto& point : m_points) {
+ for (Json::ArrayIndex i = 0; const auto& point : points()) {
// No guard here as the toJSON call will throw an exception if the id does not exist.
- root[point.id().get()] = point.toJSON();
+ root[i++] = point.toJSON();
}
return root;
}
diff --git a/src/alfalfa/AlfalfaMeter.hpp b/src/alfalfa/AlfalfaMeter.hpp
index 51001bf47af..8d2593764b0 100644
--- a/src/alfalfa/AlfalfaMeter.hpp
+++ b/src/alfalfa/AlfalfaMeter.hpp
@@ -3,13 +3,13 @@
#include "AlfalfaAPI.hpp"
-#include "ComponentBase.hpp"
+#include "AlfalfaComponentBase.hpp"
#include "../utilities/idf/IdfObject.hpp"
namespace openstudio {
namespace alfalfa {
- class ALFALFA_API AlfalfaMeter : public ComponentBase
+ class ALFALFA_API AlfalfaMeter : public AlfalfaComponentBase
{
public:
/**
@@ -27,15 +27,15 @@ namespace alfalfa {
Json::Value toJSON() const override;
- ComponentCapability capability() const override {
- return ComponentCapability::Output;
+ AlfalfaComponentCapability capability() const override {
+ return AlfalfaComponentCapability::Output;
}
- ComponentType type() const override {
- return ComponentType::Meter;
+ AlfalfaComponentType type() const override {
+ return AlfalfaComponentType::Meter;
}
- std::unique_ptr clone() const override {
+ std::unique_ptr clone() const override {
return std::make_unique(*this);
}
diff --git a/src/alfalfa/AlfalfaOutputVariable.hpp b/src/alfalfa/AlfalfaOutputVariable.hpp
index bf6b010a86b..c8d85d8ea71 100644
--- a/src/alfalfa/AlfalfaOutputVariable.hpp
+++ b/src/alfalfa/AlfalfaOutputVariable.hpp
@@ -3,13 +3,13 @@
#include "AlfalfaAPI.hpp"
-#include "ComponentBase.hpp"
+#include "AlfalfaComponentBase.hpp"
#include "../utilities/idf/IdfObject.hpp"
namespace openstudio {
namespace alfalfa {
- class ALFALFA_API AlfalfaOutputVariable : public ComponentBase
+ class ALFALFA_API AlfalfaOutputVariable : public AlfalfaComponentBase
{
public:
/**
@@ -27,15 +27,15 @@ namespace alfalfa {
Json::Value toJSON() const override;
- ComponentCapability capability() const override {
- return ComponentCapability::Output;
+ AlfalfaComponentCapability capability() const override {
+ return AlfalfaComponentCapability::Output;
}
- ComponentType type() const override {
- return ComponentType::OutputVariable;
+ AlfalfaComponentType type() const override {
+ return AlfalfaComponentType::OutputVariable;
}
- std::unique_ptr clone() const override {
+ std::unique_ptr clone() const override {
return std::make_unique(*this);
}
diff --git a/src/alfalfa/AlfalfaPoint.cpp b/src/alfalfa/AlfalfaPoint.cpp
index b3dfb301187..9ffd9a03c59 100644
--- a/src/alfalfa/AlfalfaPoint.cpp
+++ b/src/alfalfa/AlfalfaPoint.cpp
@@ -7,12 +7,11 @@
#include
#include
+#include
namespace openstudio {
namespace alfalfa {
- static constexpr std::string_view ID_VALID_CHARS_MSG = "IDs can only contain letters, numbers, and the following special characters _-[]():";
-
namespace detail {
AlfalfaPoint_Impl::AlfalfaPoint_Impl(const std::string& display_name) {
@@ -22,11 +21,7 @@ namespace alfalfa {
Json::Value AlfalfaPoint_Impl::toJSON() const {
Json::Value point;
- if (auto id_ = id()) {
- point["id"] = *id_;
- } else {
- throw std::runtime_error(fmt::format("Point requires a valid ID for export. {}", ID_VALID_CHARS_MSG));
- }
+ point["id"] = id();
point["name"] = displayName();
if (auto input_ = input()) {
point["input"]["type"] = input_->typeName();
@@ -80,24 +75,17 @@ namespace alfalfa {
}
void AlfalfaPoint_Impl::setId(const std::string& id) {
- if (isValidId(id)) {
- m_id = id;
- } else {
- throw std::runtime_error(ID_VALID_CHARS_MSG.data());
+ if (id.empty()) {
+ throw std::runtime_error("Id must have non-zero length");
}
+ m_id = toIdString(id);
}
- boost::optional AlfalfaPoint_Impl::id() const {
- boost::optional result = m_id;
- if (!result.is_initialized()) {
- std::string id = toIdString(displayName());
- if (isValidId(id)) {
- result = id;
- } else {
- LOG(Warn, fmt::format("Display name '{}' does not produce a valid point ID. Manually set a valid ID or export will fail.", displayName()));
- }
+ std::string AlfalfaPoint_Impl::id() const {
+ if (m_id.empty()) {
+ return toIdString(displayName());
}
- return result;
+ return m_id;
}
void AlfalfaPoint_Impl::setDisplayName(const std::string& display_name) {
@@ -105,12 +93,6 @@ namespace alfalfa {
throw std::runtime_error("Display name must have non-zero length");
}
m_display_name = display_name;
- if (!m_id.is_initialized()) {
- const std::string id = toIdString(display_name);
- if (!isValidId(id)) {
- LOG(Warn, fmt::format("Display name '{}' does not produce a valid point ID. Manually set a valid ID or export will fail.", display_name));
- }
- }
}
std::string AlfalfaPoint_Impl::displayName() const {
@@ -125,17 +107,13 @@ namespace alfalfa {
return m_optional;
}
- bool AlfalfaPoint_Impl::isValidId(const std::string& id) {
- return !id.empty() && boost::regex_match(id, boost::regex(R"(^[A-Za-z0-9_\-\[\]:()]*$)"));
- }
-
std::string AlfalfaPoint_Impl::toIdString(const std::string& str) {
- return boost::regex_replace(str, boost::regex(" "), "_");
+ std::string id_string = str;
+ std::replace(id_string.begin(), id_string.end(), ' ', '_');
+ return id_string;
}
} // namespace detail
- // AlfalfaPoint::AlfalfaPoint(const AlfalfaPoint& point) : m_impl(point.m_impl) {}
-
AlfalfaPoint::AlfalfaPoint(const std::string& display_name) : m_impl(std::make_shared(display_name)) {}
void AlfalfaPoint::setInput(const AlfalfaComponent& component) {
@@ -162,7 +140,7 @@ namespace alfalfa {
return m_impl->units();
}
- boost::optional AlfalfaPoint::id() const {
+ std::string AlfalfaPoint::id() const {
return m_impl->id();
}
diff --git a/src/alfalfa/AlfalfaPoint.hpp b/src/alfalfa/AlfalfaPoint.hpp
index 3ed3ee51589..1ca63e380a4 100644
--- a/src/alfalfa/AlfalfaPoint.hpp
+++ b/src/alfalfa/AlfalfaPoint.hpp
@@ -69,7 +69,7 @@ namespace alfalfa {
/**
* Get id of point. By default this will be a version of the display name with spaces removed.
*/
- boost::optional id() const;
+ std::string id() const;
/**
* Set id of point. This is the component which will uniquely identify the point in the API.
diff --git a/src/alfalfa/AlfalfaPoint_Impl.hpp b/src/alfalfa/AlfalfaPoint_Impl.hpp
index f6d0810a65c..bc311434e5f 100644
--- a/src/alfalfa/AlfalfaPoint_Impl.hpp
+++ b/src/alfalfa/AlfalfaPoint_Impl.hpp
@@ -32,7 +32,7 @@ namespace alfalfa {
boost::optional units() const;
- boost::optional id() const;
+ std::string id() const;
void setId(const std::string& id);
@@ -47,13 +47,11 @@ namespace alfalfa {
private:
static std::string toIdString(const std::string& str);
- static bool isValidId(const std::string& id);
-
boost::optional m_input;
boost::optional m_output;
std::string m_display_name;
boost::optional m_units;
- boost::optional m_id;
+ std::string m_id;
bool m_optional = true;
// configure logging
diff --git a/src/alfalfa/CMakeLists.txt b/src/alfalfa/CMakeLists.txt
index c87da18b12d..9fe7e350d15 100644
--- a/src/alfalfa/CMakeLists.txt
+++ b/src/alfalfa/CMakeLists.txt
@@ -5,8 +5,8 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR}/)
set(${target_name}_src
AlfalfaAPI.hpp
- ComponentBase.cpp
- ComponentBase.hpp
+ AlfalfaComponentBase.cpp
+ AlfalfaComponentBase.hpp
AlfalfaComponent.hpp
AlfalfaComponent.cpp
AlfalfaConstant.hpp
@@ -58,4 +58,4 @@ if(BUILD_TESTING)
endif()
-MAKE_SWIG_TARGET(OpenStudioAlfalfa alfalfa "${CMAKE_CURRENT_SOURCE_DIR}/Alfalfa.i" "${${target_name}_swig_src}" ${target_name} OpenStudioModel)
+MAKE_SWIG_TARGET(OpenStudioAlfalfa alfalfa "${CMAKE_CURRENT_SOURCE_DIR}/Alfalfa.i" "${${target_name}_swig_src}" ${target_name} OpenStudioOSVersion)
diff --git a/src/alfalfa/ComponentBase.cpp b/src/alfalfa/ComponentBase.cpp
deleted file mode 100644
index 4ed339d05da..00000000000
--- a/src/alfalfa/ComponentBase.cpp
+++ /dev/null
@@ -1,15 +0,0 @@
-#include "ComponentBase.hpp"
-
-namespace openstudio {
-namespace alfalfa {
-
- bool ComponentBase::canInput() const {
- return capability() == ComponentCapability::Bidirectional || capability() == ComponentCapability::Input;
- }
-
- bool ComponentBase::canOutput() const {
- return capability() == ComponentCapability::Bidirectional || capability() == ComponentCapability::Output;
- }
-
-} // namespace alfalfa
-} // namespace openstudio
diff --git a/src/alfalfa/test/AlfalfaJSON_GTest.cpp b/src/alfalfa/test/AlfalfaJSON_GTest.cpp
index 6b5e568871d..6a623d7c409 100644
--- a/src/alfalfa/test/AlfalfaJSON_GTest.cpp
+++ b/src/alfalfa/test/AlfalfaJSON_GTest.cpp
@@ -1,5 +1,6 @@
#include
#include
+#include
#include
#include "../AlfalfaJSON.hpp"
@@ -194,74 +195,46 @@ TEST(AlfalfaJSON, json_serialization) {
const bool parsing_success = Json::parseFromStream(r_builder, ifs, &root, &formatted_errors);
EXPECT_TRUE(parsing_success);
EXPECT_EQ(alfalfa.toJSON(), root);
- for (const AlfalfaPoint& point : alfalfa.points()) {
- EXPECT_EQ(root[point.id().get()], point.toJSON());
+ for (Json::ArrayIndex i = 0; const auto& point : alfalfa.points()) {
+ EXPECT_EQ(root[i++], point.toJSON());
}
}
TEST(AlfalfaJSON, point_exceptions_logging) {
- const std::string ID_VALID_CHARS_MSG = "IDs can only contain letters, numbers, and the following special characters _-[]():";
- const std::string DISPLAY_NAME_VALID_CHARS_MSG = "Display name '{}' does not produce a valid point ID. Manually set a valid ID or export will fail.";
+ const std::string DISPLAY_NAME_EMPTY_ERROR = "Display name must have non-zero length";
+ const std::string ID_EMPTY_ERROR = "Id must have non-zero length";
const std::string LOG_CHANNEL = "openstudio.AlfalfaPoint";
StringStreamLogSink ss;
ss.setLogLevel(Warn);
- const AlfalfaPoint point("Point");
+ AlfalfaPoint point("Point");
ASSERT_EQ(0, ss.logMessages().size());
point.id();
ASSERT_EQ(0, ss.logMessages().size());
//Test logging in constructor
- AlfalfaPoint invalid_point("Point$$$");
- ASSERT_EQ(1, ss.logMessages().size());
- LogMessage invalid_id_msg = ss.logMessages().at(0);
- EXPECT_EQ(invalid_id_msg.logMessage(), fmt::format(fmt::runtime(DISPLAY_NAME_VALID_CHARS_MSG), "Point$$$"));
- EXPECT_EQ(invalid_id_msg.logLevel(), Warn);
- EXPECT_EQ(invalid_id_msg.logChannel(), LOG_CHANNEL);
- ss.resetStringStream();
- ASSERT_EQ(ss.logMessages().size(), 0);
-
- // Test logging when getting id()
- const boost::optional invalid_point_id = invalid_point.id();
- EXPECT_FALSE(invalid_point_id.is_initialized());
- ASSERT_EQ(ss.logMessages().size(), 1);
- invalid_id_msg = ss.logMessages().at(0);
- EXPECT_EQ(invalid_id_msg.logMessage(), fmt::format(fmt::runtime(DISPLAY_NAME_VALID_CHARS_MSG), "Point$$$"));
- EXPECT_EQ(invalid_id_msg.logLevel(), Warn);
- EXPECT_EQ(invalid_id_msg.logChannel(), LOG_CHANNEL);
- ss.resetStringStream();
- ASSERT_EQ(ss.logMessages().size(), 0);
-
- // Test exception handling in setId()
EXPECT_THROW(
{
try {
- invalid_point.setId("Point_123_$$$");
+ const AlfalfaPoint invalid_point("");
} catch (const std::runtime_error& error) {
- EXPECT_EQ(error.what(), ID_VALID_CHARS_MSG);
+ EXPECT_EQ(error.what(), DISPLAY_NAME_EMPTY_ERROR);
throw;
}
},
std::runtime_error);
- ASSERT_EQ(ss.logMessages().size(), 0);
- // Test exception handling in toJSON()
+ // Test exception handling in setId()
EXPECT_THROW(
{
try {
- Json::Value root = invalid_point.toJSON();
+ point.setId("");
} catch (const std::runtime_error& error) {
- EXPECT_EQ(error.what(), "Point requires a valid ID for export. " + ID_VALID_CHARS_MSG);
+ EXPECT_EQ(error.what(), ID_EMPTY_ERROR);
throw;
}
},
std::runtime_error);
- ASSERT_EQ(ss.logMessages().size(), 1);
- invalid_id_msg = ss.logMessages().at(0);
- EXPECT_EQ(invalid_id_msg.logMessage(), fmt::format(fmt::runtime(DISPLAY_NAME_VALID_CHARS_MSG), "Point$$$"));
- EXPECT_EQ(invalid_id_msg.logLevel(), Warn);
- EXPECT_EQ(invalid_id_msg.logChannel(), LOG_CHANNEL);
- ss.resetStringStream();
ASSERT_EQ(ss.logMessages().size(), 0);
//Test Calls work when provided with legal input
@@ -277,8 +250,7 @@ TEST(AlfalfaJSON, point_exceptions_logging) {
// Test that changing display name changes the ID if an ID has not been set.
valid_point.setDisplayName("Another Good Point");
ASSERT_EQ(ss.logMessages().size(), 0);
- ASSERT_TRUE(valid_point.id().is_initialized());
- ASSERT_EQ(valid_point.id().get(), "Another_Good_Point");
+ ASSERT_EQ(valid_point.id(), "Another_Good_Point");
ASSERT_EQ(ss.logMessages().size(), 0);
Json::Value valid_json = valid_point.toJSON();
@@ -288,8 +260,7 @@ TEST(AlfalfaJSON, point_exceptions_logging) {
const std::string new_id = "Another_Valid_Point(123)";
valid_point.setId(new_id);
ASSERT_EQ(ss.logMessages().size(), 0);
- ASSERT_TRUE(valid_point.id().is_initialized());
- ASSERT_EQ(valid_point.id().get(), new_id);
+ ASSERT_EQ(valid_point.id(), new_id);
valid_json = valid_point.toJSON();
ASSERT_EQ(ss.logMessages().size(), 0);
@@ -297,25 +268,25 @@ TEST(AlfalfaJSON, point_exceptions_logging) {
// Test that once an ID is set, setting a new display name won't throw a warning.
valid_point.setDisplayName("Valid Name, but Invalid Id $$$");
ASSERT_EQ(ss.logMessages().size(), 0);
- ASSERT_EQ(valid_point.id().get(), new_id);
+ ASSERT_EQ(valid_point.id(), new_id);
valid_json = valid_point.toJSON();
ASSERT_EQ(ss.logMessages().size(), 0);
}
-class InputComponent : public ComponentBase
+class InputComponent : public AlfalfaComponentBase
{
public:
InputComponent() = default;
- ComponentCapability capability() const override {
- return ComponentCapability::Input;
+ AlfalfaComponentCapability capability() const override {
+ return AlfalfaComponentCapability::Input;
}
- openstudio::alfalfa::ComponentType type() const override {
- return openstudio::alfalfa::ComponentType::Constant;
+ AlfalfaComponentType type() const override {
+ return AlfalfaComponentType::Constant;
}
- std::unique_ptr clone() const override {
+ std::unique_ptr clone() const override {
return std::make_unique(*this);
}
diff --git a/src/cli/CMakeLists.txt b/src/cli/CMakeLists.txt
index 179c35f7a04..e79684fcdfc 100644
--- a/src/cli/CMakeLists.txt
+++ b/src/cli/CMakeLists.txt
@@ -270,6 +270,63 @@ if(BUILD_TESTING)
PASS_REGULAR_EXPRESSION "HI FROM ERB PYTHON PLUGIN[\r\n\t ]*HI FROM JINJA PYTHON PLUGIN"
)
+ # ======================== Workflows should fail ========================
+ add_test(NAME OpenStudioCLI.Run_Validate.MissingAMeasure
+ COMMAND $ run --show-stdout -w missing_a_measure.osw
+ WORKING_DIRECTORY "${PROJECT_BINARY_DIR}/resources/workflow/invalid_measures/"
+ )
+ set_tests_properties(OpenStudioCLI.Run_Validate.MissingAMeasure PROPERTIES
+ WILL_FAIL TRUE
+ RESOURCE_LOCK "invalid_measures"
+ )
+
+ add_test(NAME OpenStudioCLI.Run_Validate.UnloadableMeasure
+ COMMAND $ run --show-stdout -w unloadable_measure.osw
+ WORKING_DIRECTORY "${PROJECT_BINARY_DIR}/resources/workflow/invalid_measures/"
+ )
+ set_tests_properties(OpenStudioCLI.Run_Validate.UnloadableMeasure PROPERTIES
+ WILL_FAIL TRUE
+ RESOURCE_LOCK "invalid_measures"
+ )
+
+ add_test(NAME OpenStudioCLI.Run_Validate.WrongMeasureTypeOrder
+ COMMAND $ run --show-stdout -w wrong_measure_type_order.osw
+ WORKING_DIRECTORY "${PROJECT_BINARY_DIR}/resources/workflow/invalid_measures/"
+ )
+ set_tests_properties(OpenStudioCLI.Run_Validate.WrongMeasureTypeOrder PROPERTIES
+ WILL_FAIL TRUE
+ RESOURCE_LOCK "invalid_measures"
+ )
+
+ # Classic
+ add_test(NAME OpenStudioCLI.Classic.Run_Validate.MissingAMeasure
+ COMMAND $ classic run --show-stdout -w missing_a_measure.osw
+ WORKING_DIRECTORY "${PROJECT_BINARY_DIR}/resources/workflow/invalid_measures/"
+ )
+ set_tests_properties(OpenStudioCLI.Classic.Run_Validate.MissingAMeasure PROPERTIES
+ WILL_FAIL TRUE
+ RESOURCE_LOCK "invalid_measures"
+ )
+
+ add_test(NAME OpenStudioCLI.Classic.Run_Validate.UnloadableMeasure
+ COMMAND $ classic run --show-stdout -w unloadable_measure.osw
+ WORKING_DIRECTORY "${PROJECT_BINARY_DIR}/resources/workflow/invalid_measures/"
+ )
+ set_tests_properties(OpenStudioCLI.Classic.Run_Validate.UnloadableMeasure PROPERTIES
+ WILL_FAIL TRUE
+ RESOURCE_LOCK "invalid_measures"
+ )
+
+ add_test(NAME OpenStudioCLI.Classic.Run_Validate.WrongMeasureTypeOrder
+ COMMAND $ classic run --show-stdout -w wrong_measure_type_order.osw
+ WORKING_DIRECTORY "${PROJECT_BINARY_DIR}/resources/workflow/invalid_measures/"
+ )
+ set_tests_properties(OpenStudioCLI.Classic.Run_Validate.WrongMeasureTypeOrder PROPERTIES
+ WILL_FAIL TRUE
+ RESOURCE_LOCK "invalid_measures"
+ )
+ # ====================== End Workflows should fail ======================
+
if (Pytest_AVAILABLE)
add_test(NAME OpenStudioCLI.test_loglevel
COMMAND ${Python_EXECUTABLE} -m pytest --verbose ${Pytest_XDIST_OPTS} --os-cli-path $ "${CMAKE_CURRENT_SOURCE_DIR}/test/test_loglevel.py"
diff --git a/src/gltf/GltfMaterialData.cpp b/src/gltf/GltfMaterialData.cpp
index 589737fec35..3a7dc4c0263 100644
--- a/src/gltf/GltfMaterialData.cpp
+++ b/src/gltf/GltfMaterialData.cpp
@@ -26,7 +26,7 @@
#include
-#include