diff --git a/include/cse.h b/include/cse.h index 3d416b49a..ac7c114b1 100644 --- a/include/cse.h +++ b/include/cse.h @@ -361,6 +361,28 @@ int cse_manipulator_slave_set_real( size_t nv, const double values[]); +/** + * Resets any previously overridden values of real variables for one slave. + * + * \param [in] manipulator + * The manipulator. + * \param [in] slaveIndex + * The slave. + * \param [in] variables + * A pointer to an array of length `nv` that contains the (slave-specific) + * indices of variables to reset. + * \param [in] nv + * The length of the `variables` array. + * + * \returns + * 0 on success and -1 on error. + */ +int cse_manipulator_slave_reset_real( + cse_manipulator* manipulator, + cse_slave_index slaveIndex, + const cse_variable_index variables[], + size_t nv); + /** * Retrieves the values of real variables for one slave. * @@ -438,6 +460,28 @@ int cse_manipulator_slave_set_integer( size_t nv, const int values[]); +/** + * Resets the values of any previously overridden integer variables for one slave. + * + * \param [in] manipulator + * The manipulator. + * \param [in] slaveIndex + * The slave. + * \param [in] variables + * A pointer to an array of length `nv` that contains the (slave-specific) + * indices of variables to reset. + * \param [in] nv + * The length of the `variables` array. + * + * \returns + * 0 on success and -1 on error. + */ +int cse_manipulator_slave_reset_integer( + cse_manipulator* manipulator, + cse_slave_index slaveIndex, + const cse_variable_index variables[], + size_t nv); + /** * Retrieves the values of integer variables for one slave. * @@ -660,9 +704,9 @@ cse_manipulator* cse_scenario_manager_create(); /// Loads and executes a scenario from file. int cse_execution_load_scenario( - cse_execution* execution, - cse_manipulator* manipulator, - const char* scenarioFile); + cse_execution* execution, + cse_manipulator* manipulator, + const char* scenarioFile); /// Checks if a scenario is running int cse_scenario_is_running(cse_manipulator* manipulator); diff --git a/include/cse/manipulator.hpp b/include/cse/manipulator.hpp index 90ac32b9f..2abab0cb1 100644 --- a/include/cse/manipulator.hpp +++ b/include/cse/manipulator.hpp @@ -75,12 +75,24 @@ class override_manipulator : public manipulator void override_real_variable(simulator_index, variable_index, double value); void override_integer_variable(simulator_index, variable_index, int value); void override_boolean_variable(simulator_index, variable_index, bool value); - void override_string_variable(simulator_index, variable_index, std::string value); + void override_string_variable(simulator_index, variable_index, const std::string& value); + void reset_real_variable(simulator_index, variable_index); + void reset_integer_variable(simulator_index, variable_index); + void reset_boolean_variable(simulator_index, variable_index); + void reset_string_variable(simulator_index, variable_index); ~override_manipulator() noexcept override; private: + void add_action( + simulator_index index, + variable_index variable, + variable_type type, + const scenario::manipulators& m); + std::unordered_map simulators_; + std::vector actions_; + std::mutex lock_; }; } // namespace cse diff --git a/include/cse/scenario.hpp b/include/cse/scenario.hpp index ff6747e0c..fe403c4bb 100644 --- a/include/cse/scenario.hpp +++ b/include/cse/scenario.hpp @@ -15,60 +15,38 @@ namespace cse namespace scenario { -struct real_input_manipulator +struct real_manipulator { std::function f; }; -struct real_output_manipulator -{ - std::function f; -}; - -struct integer_input_manipulator -{ - std::function f; -}; - -struct integer_output_manipulator +struct integer_manipulator { std::function f; }; -struct boolean_input_manipulator +struct boolean_manipulator { std::function f; }; -struct boolean_output_manipulator -{ - std::function f; -}; - -struct string_input_manipulator +struct string_manipulator { std::function f; }; -struct string_output_manipulator -{ - std::function f; -}; +using manipulators = std::variant< + real_manipulator, + integer_manipulator, + boolean_manipulator, + string_manipulator>; struct variable_action { simulator_index simulator; variable_index variable; - std::variant< - real_input_manipulator, - real_output_manipulator, - integer_input_manipulator, - integer_output_manipulator, - boolean_input_manipulator, - boolean_output_manipulator, - string_input_manipulator, - string_output_manipulator> - manipulator; + manipulators manipulator; + bool is_input; }; struct event diff --git a/src/c/cse.cpp b/src/c/cse.cpp index 2e712ad1e..2939a2f17 100644 --- a/src/c/cse.cpp +++ b/src/c/cse.cpp @@ -588,7 +588,7 @@ int cse_observer_start_observing(cse_observer* observer, cse_slave_index slave, if (!timeSeriesObserver) { throw std::invalid_argument("Invalid observer! The provided observer must be a time_series_observer."); } - const auto variableId = cse::variable_id {slave, to_variable_type(type), index}; + const auto variableId = cse::variable_id{slave, to_variable_type(type), index}; timeSeriesObserver->start_observing(variableId); return success; } catch (...) { @@ -603,7 +603,7 @@ int cse_observer_stop_observing(cse_observer* observer, cse_slave_index slave, c if (!timeSeriesObserver) { throw std::invalid_argument("Invalid observer! The provided observer must be a time_series_observer."); } - const auto variableId = cse::variable_id {slave, to_variable_type(type), index}; + const auto variableId = cse::variable_id{slave, to_variable_type(type), index}; timeSeriesObserver->stop_observing(variableId); return success; } catch (...) { @@ -706,6 +706,48 @@ int cse_manipulator_slave_set_integer( } } +int cse_manipulator_slave_reset_real( + cse_manipulator* manipulator, + cse_slave_index slaveIndex, + const cse_variable_index variables[], + size_t nv) +{ + try { + const auto man = std::dynamic_pointer_cast(manipulator->cpp_manipulator); + if (!man) { + throw std::invalid_argument("Invalid manipulator!"); + } + for (size_t i = 0; i < nv; i++) { + man->reset_real_variable(slaveIndex, variables[i]); + } + return success; + } catch (...) { + handle_current_exception(); + return failure; + } +} + +int cse_manipulator_slave_reset_integer( + cse_manipulator* manipulator, + cse_slave_index slaveIndex, + const cse_variable_index variables[], + size_t nv) +{ + try { + const auto man = std::dynamic_pointer_cast(manipulator->cpp_manipulator); + if (!man) { + throw std::invalid_argument("Invalid manipulator!"); + } + for (size_t i = 0; i < nv; i++) { + man->reset_integer_variable(slaveIndex, variables[i]); + } + return success; + } catch (...) { + handle_current_exception(); + return failure; + } +} + cse_manipulator* cse_scenario_manager_create() { auto manipulator = std::make_unique(); diff --git a/src/cpp/override_manipulator.cpp b/src/cpp/override_manipulator.cpp index b64884994..8898e7427 100644 --- a/src/cpp/override_manipulator.cpp +++ b/src/cpp/override_manipulator.cpp @@ -6,7 +6,19 @@ namespace cse namespace { -cse::variable_causality find_variable_causality(const std::vector& variables, +template +struct visitor : Functors... +{ + visitor(const Functors&... functors) + : Functors(functors)... + { + } + + using Functors::operator()...; +}; + +cse::variable_causality find_variable_causality( + const std::vector& variables, const cse::variable_type type, const cse::variable_index index) { @@ -18,9 +30,28 @@ cse::variable_causality find_variable_causality(const std::vector lock(lock_); + if (!actions_.empty()) { + for (const auto& a : actions_) { + auto sim = simulators_.at(a.simulator); + std::visit( + visitor( + [=](scenario::real_manipulator m) { + if (a.is_input) { + sim->expose_for_setting(variable_type::real, a.variable); + sim->set_real_input_manipulator(a.variable, m.f); + } else { + sim->expose_for_getting(variable_type::real, a.variable); + sim->set_real_output_manipulator(a.variable, m.f); + } + }, + [=](scenario::integer_manipulator m) { + if (a.is_input) { + sim->expose_for_setting(variable_type::integer, a.variable); + sim->set_integer_input_manipulator(a.variable, m.f); + } else { + sim->expose_for_getting(variable_type::integer, a.variable); + sim->set_integer_output_manipulator(a.variable, m.f); + } + }, + [=](scenario::boolean_manipulator m) { + if (a.is_input) { + sim->expose_for_setting(variable_type::boolean, a.variable); + sim->set_boolean_input_manipulator(a.variable, m.f); + } else { + sim->expose_for_getting(variable_type::boolean, a.variable); + sim->set_boolean_output_manipulator(a.variable, m.f); + } + }, + [=](scenario::string_manipulator m) { + if (a.is_input) { + sim->expose_for_setting(variable_type::string, a.variable); + sim->set_string_input_manipulator(a.variable, m.f); + } else { + sim->expose_for_getting(variable_type::string, a.variable); + sim->set_string_output_manipulator(a.variable, m.f); + } + }), + a.manipulator); + } + actions_.clear(); + } +} + +void override_manipulator::add_action( + simulator_index index, + variable_index variable, + variable_type type, + const scenario::manipulators& m) +{ + auto sim = simulators_.at(index); + auto causality = find_variable_causality(sim->model_description().variables, type, variable); + bool input = is_input(causality); + + std::lock_guard lock(lock_); + actions_.emplace_back(scenario::variable_action{index, variable, m, input}); } -void override_manipulator::override_real_variable(simulator_index index, variable_index variable, double value) +void override_manipulator::override_real_variable( + simulator_index index, + variable_index variable, + double value) { auto f = [value](double /*original*/) { return value; }; - auto sim = simulators_.at(index); - auto causality = find_variable_causality(sim->model_description().variables, variable_type::real, variable); - switch (causality) { - case input: - case parameter: - sim->expose_for_setting(variable_type::real, variable); - sim->set_real_input_manipulator(variable, f); - break; - case calculated_parameter: - case output: - sim->expose_for_getting(variable_type::real, variable); - sim->set_real_output_manipulator(variable, f); - break; - default: - throw std::invalid_argument("No support for manipulating a variable with this causality"); - } + add_action(index, variable, variable_type::real, scenario::real_manipulator{f}); } -void override_manipulator::override_integer_variable(simulator_index index, variable_index variable, int value) +void override_manipulator::override_integer_variable( + simulator_index index, + variable_index variable, + int value) { auto f = [value](int /*original*/) { return value; }; - auto sim = simulators_.at(index); - auto causality = find_variable_causality(sim->model_description().variables, variable_type::integer, variable); - switch (causality) { - case input: - case parameter: - sim->expose_for_setting(variable_type::integer, variable); - sim->set_integer_input_manipulator(variable, f); - break; - case calculated_parameter: - case output: - sim->expose_for_getting(variable_type::integer, variable); - sim->set_integer_output_manipulator(variable, f); - break; - default: - throw std::invalid_argument("No support for manipulating a variable with this causality"); - } + add_action(index, variable, variable_type::integer, scenario::integer_manipulator{f}); } -void override_manipulator::override_boolean_variable(simulator_index index, variable_index variable, bool value) + +void override_manipulator::override_boolean_variable( + simulator_index index, + variable_index variable, + bool value) { auto f = [value](bool /*original*/) { return value; }; - auto sim = simulators_.at(index); - auto causality = find_variable_causality(sim->model_description().variables, variable_type::boolean, variable); - switch (causality) { - case input: - case parameter: - sim->expose_for_setting(variable_type::boolean, variable); - sim->set_boolean_input_manipulator(variable, f); - break; - case calculated_parameter: - case output: - sim->expose_for_getting(variable_type::boolean, variable); - sim->set_boolean_output_manipulator(variable, f); - break; - default: - throw std::invalid_argument("No support for manipulating a variable with this causality"); - } + add_action(index, variable, variable_type::boolean, scenario::boolean_manipulator{f}); } -void override_manipulator::override_string_variable(simulator_index index, variable_index variable, std::string value) + +void override_manipulator::override_string_variable( + simulator_index index, + variable_index variable, + const std::string& value) { auto f = [value](std::string_view /*original*/) { return value; }; - auto sim = simulators_.at(index); - auto causality = find_variable_causality(sim->model_description().variables, variable_type::string, variable); - switch (causality) { - case input: - case parameter: - sim->expose_for_setting(variable_type::string, variable); - sim->set_string_input_manipulator(variable, f); - break; - case calculated_parameter: - case output: - sim->expose_for_getting(variable_type::string, variable); - sim->set_string_output_manipulator(variable, f); - break; - default: - throw std::invalid_argument("No support for manipulating a variable with this causality"); - } + add_action(index, variable, variable_type::string, scenario::string_manipulator{f}); +} + +void override_manipulator::reset_real_variable( + simulator_index index, + variable_index variable) +{ + add_action(index, variable, variable_type::real, scenario::real_manipulator{nullptr}); +} + +void override_manipulator::reset_integer_variable( + simulator_index index, + variable_index variable) +{ + add_action(index, variable, variable_type::integer, scenario::integer_manipulator{nullptr}); +} + +void override_manipulator::reset_boolean_variable( + simulator_index index, + variable_index variable) +{ + add_action(index, variable, variable_type::boolean, scenario::boolean_manipulator{nullptr}); +} + +void override_manipulator::reset_string_variable( + simulator_index index, + variable_index variable) +{ + add_action(index, variable, variable_type::string, scenario::string_manipulator{nullptr}); } override_manipulator::~override_manipulator() = default; -} // namespace cse \ No newline at end of file +} // namespace cse diff --git a/src/cpp/scenario_manager.cpp b/src/cpp/scenario_manager.cpp index 44fdc0038..8749d72be 100644 --- a/src/cpp/scenario_manager.cpp +++ b/src/cpp/scenario_manager.cpp @@ -123,37 +123,41 @@ class scenario_manager::impl { std::visit( visitor( - [=](scenario::real_input_manipulator m) { - sim->expose_for_setting(variable_type::real, a.variable); - sim->set_real_input_manipulator(a.variable, m.f); + [=](scenario::real_manipulator m) { + if (a.is_input) { + sim->expose_for_setting(variable_type::real, a.variable); + sim->set_real_input_manipulator(a.variable, m.f); + } else { + sim->expose_for_getting(variable_type::real, a.variable); + sim->set_real_output_manipulator(a.variable, m.f); + } }, - [=](scenario::real_output_manipulator m) { - sim->expose_for_getting(variable_type::real, a.variable); - sim->set_real_output_manipulator(a.variable, m.f); + [=](scenario::integer_manipulator m) { + if (a.is_input) { + sim->expose_for_setting(variable_type::integer, a.variable); + sim->set_integer_input_manipulator(a.variable, m.f); + } else { + sim->expose_for_getting(variable_type::integer, a.variable); + sim->set_integer_output_manipulator(a.variable, m.f); + } }, - [=](scenario::integer_input_manipulator m) { - sim->expose_for_setting(variable_type::integer, a.variable); - sim->set_integer_input_manipulator(a.variable, m.f); + [=](scenario::boolean_manipulator m) { + if (a.is_input) { + sim->expose_for_setting(variable_type::boolean, a.variable); + sim->set_boolean_input_manipulator(a.variable, m.f); + } else { + sim->expose_for_getting(variable_type::boolean, a.variable); + sim->set_boolean_output_manipulator(a.variable, m.f); + } }, - [=](scenario::integer_output_manipulator m) { - sim->expose_for_getting(variable_type::integer, a.variable); - sim->set_integer_output_manipulator(a.variable, m.f); - }, - [=](scenario::boolean_input_manipulator m) { - sim->expose_for_setting(variable_type::boolean, a.variable); - sim->set_boolean_input_manipulator(a.variable, m.f); - }, - [=](scenario::boolean_output_manipulator m) { - sim->expose_for_getting(variable_type::boolean, a.variable); - sim->set_boolean_output_manipulator(a.variable, m.f); - }, - [=](scenario::string_input_manipulator m) { - sim->expose_for_setting(variable_type::string, a.variable); - sim->set_string_input_manipulator(a.variable, m.f); - }, - [=](scenario::string_output_manipulator m) { - sim->expose_for_getting(variable_type::string, a.variable); - sim->set_string_output_manipulator(a.variable, m.f); + [=](scenario::string_manipulator m) { + if (a.is_input) { + sim->expose_for_setting(variable_type::string, a.variable); + sim->set_string_input_manipulator(a.variable, m.f); + } else { + sim->expose_for_getting(variable_type::string, a.variable); + sim->set_string_output_manipulator(a.variable, m.f); + } }), a.manipulator); } @@ -175,36 +179,40 @@ class scenario_manager::impl { std::visit( visitor( - [=](scenario::real_input_manipulator /*m*/) { - sim->set_real_input_manipulator(a.variable, nullptr); - }, - [=](scenario::real_output_manipulator /*m*/) { - sim->set_real_output_manipulator(a.variable, nullptr); - }, - [=](scenario::integer_input_manipulator /*m*/) { - sim->set_integer_input_manipulator(a.variable, nullptr); - }, - [=](scenario::integer_output_manipulator /*m*/) { - sim->set_integer_output_manipulator(a.variable, nullptr); - }, - [=](scenario::boolean_input_manipulator /*m*/) { - sim->set_boolean_input_manipulator(a.variable, nullptr); + [=](scenario::real_manipulator /*m*/) { + if (a.is_input) { + sim->set_real_input_manipulator(a.variable, nullptr); + } else { + sim->set_real_output_manipulator(a.variable, nullptr); + } }, - [=](scenario::boolean_output_manipulator /*m*/) { - sim->set_boolean_output_manipulator(a.variable, nullptr); + [=](scenario::integer_manipulator /*m*/) { + if (a.is_input) { + sim->set_integer_input_manipulator(a.variable, nullptr); + } else { + sim->set_integer_output_manipulator(a.variable, nullptr); + } }, - [=](scenario::string_input_manipulator /*m*/) { - sim->set_string_input_manipulator(a.variable, nullptr); + [=](scenario::boolean_manipulator /*m*/) { + if (a.is_input) { + sim->set_boolean_input_manipulator(a.variable, nullptr); + } else { + sim->set_boolean_output_manipulator(a.variable, nullptr); + } }, - [=](scenario::string_output_manipulator /*m*/) { - sim->set_string_output_manipulator(a.variable, nullptr); + [=](scenario::string_manipulator /*m*/) { + if (a.is_input) { + sim->set_string_input_manipulator(a.variable, nullptr); + } else { + sim->set_string_output_manipulator(a.variable, nullptr); + } }), a.manipulator); } - void cleanup(std::unordered_map executedEvents) + void cleanup(const std::unordered_map& executedEvents) { - for(const auto& entry : executedEvents) { + for (const auto& entry : executedEvents) { auto e = entry.second; cleanup_action(simulators_[e.action.simulator], e.action); } @@ -223,27 +231,37 @@ scenario_manager::scenario_manager() { } -void scenario_manager::load_scenario(const scenario::scenario& s, time_point currentTime) +void scenario_manager::load_scenario( + const scenario::scenario& s, + time_point currentTime) { pimpl_->load_scenario(s, currentTime); } -void scenario_manager::load_scenario(const boost::filesystem::path& scenarioFile, time_point currentTime) +void scenario_manager::load_scenario( + const boost::filesystem::path& scenarioFile, + time_point currentTime) { pimpl_->load_scenario(scenarioFile, currentTime); } -void scenario_manager::step_commencing(time_point currentTime) +void scenario_manager::step_commencing( + time_point currentTime) { pimpl_->step_commencing(currentTime); } -void scenario_manager::simulator_added(simulator_index index, simulator* sim, time_point /*currentTime*/) +void scenario_manager::simulator_added( + simulator_index index, + simulator* sim, + time_point /*currentTime*/) { pimpl_->simulator_added(index, sim); } -void scenario_manager::simulator_removed(simulator_index index, time_point) +void scenario_manager::simulator_removed( + simulator_index index, + time_point) { pimpl_->simulator_removed(index); } diff --git a/src/cpp/scenario_parser.cpp b/src/cpp/scenario_parser.cpp index 2b08d0bb2..5f92bcc17 100644 --- a/src/cpp/scenario_parser.cpp +++ b/src/cpp/scenario_parser.cpp @@ -16,7 +16,9 @@ namespace cse namespace { -std::pair find_simulator(const std::unordered_map& simulators, const std::string& model) +std::pair find_simulator( + const std::unordered_map& simulators, + const std::string& model) { for (const auto& [idx, simulator] : simulators) { if (simulator->name() == model) { @@ -58,7 +60,23 @@ cse::variable_causality find_causality(const nlohmann::json& j) throw std::invalid_argument("Can't process unknown variable type"); } -cse::variable_index find_variable_index(const std::vector& variables, +bool is_input(cse::variable_causality causality) +{ + switch (causality) { + case input: + case parameter: + return true; + case calculated_parameter: + case output: + return false; + default: + throw std::invalid_argument( + "No support for manipulating a variable with this causality"); + } +} + +cse::variable_index find_variable_index( + const std::vector& variables, const std::string& name, const cse::variable_type type, const cse::variable_causality causality) @@ -72,7 +90,9 @@ cse::variable_index find_variable_index(const std::vector& } template -std::function generate_manipulator(const std::string& kind, const nlohmann::json& event) +std::function generate_manipulator( + const std::string& kind, + const nlohmann::json& event) { if ("reset" == kind) { return nullptr; @@ -86,44 +106,24 @@ std::function generate_manipulator(const std::string& kind, const nlohmann throw std::invalid_argument("Can't process unknown modifier kind"); } -cse::scenario::variable_action get_real_action(const std::function& f, cse::variable_causality causality, cse::simulator_index sim, cse::variable_index variable) -{ - switch (causality) { - case input: - case parameter: - return cse::scenario::variable_action{sim, variable, cse::scenario::real_input_manipulator{f}}; - case calculated_parameter: - case output: - return cse::scenario::variable_action{sim, variable, cse::scenario::real_output_manipulator{f}}; - default: - throw std::invalid_argument("No support for manipulating a variable with this causality"); - } -} - -cse::scenario::variable_action get_integer_action(const std::function& f, cse::variable_causality causality, cse::simulator_index sim, cse::variable_index variable) -{ - switch (causality) { - case input: - case parameter: - return cse::scenario::variable_action{sim, variable, cse::scenario::integer_input_manipulator{f}}; - case calculated_parameter: - case output: - return cse::scenario::variable_action{sim, variable, cse::scenario::integer_output_manipulator{f}}; - default: - throw std::invalid_argument("No support for manipulating a variable with this causality"); - } -} - -cse::scenario::variable_action generate_action(const nlohmann::json& event, const std::string& mode, cse::simulator_index sim, cse::variable_type type, cse::variable_causality causality, cse::variable_index var) +cse::scenario::variable_action generate_action( + const nlohmann::json& event, + const std::string& mode, + cse::simulator_index sim, + cse::variable_type type, + bool isInput, + cse::variable_index var) { switch (type) { case cse::variable_type::real: { auto f = generate_manipulator(mode, event); - return get_real_action(f, causality, sim, var); + return cse::scenario::variable_action{ + sim, var, cse::scenario::real_manipulator{f}, isInput}; } case cse::variable_type::integer: { auto f = generate_manipulator(mode, event); - return get_integer_action(f, causality, sim, var); + return cse::scenario::variable_action{ + sim, var, cse::scenario::integer_manipulator{f}, isInput}; } default: throw std::invalid_argument("No support for this variable type"); @@ -139,7 +139,9 @@ struct defaults std::optional action; }; -std::optional parse_element(const nlohmann::json& j, const std::string& name) +std::optional parse_element( + const nlohmann::json& j, + const std::string& name) { if (j.count(name)) { return j.at(name).get(); @@ -162,7 +164,10 @@ defaults parse_defaults(const nlohmann::json& scenario) return defaults{}; } -std::string specified_or_default(const nlohmann::json& j, const std::string& name, std::optional defaultOption) +std::string specified_or_default( + const nlohmann::json& j, + const std::string& name, + std::optional defaultOption) { if (j.count(name)) { return j.at(name).get(); @@ -184,7 +189,10 @@ std::optional parse_end_time(const nlohmann::json& j) } // namespace -scenario::scenario parse_scenario(const boost::filesystem::path& scenarioFile, const std::unordered_map& simulators) +scenario::scenario parse_scenario( + const boost::filesystem::path& scenarioFile, + const std::unordered_map& simulators) { boost::filesystem::ifstream i(scenarioFile); nlohmann::json j; @@ -198,14 +206,20 @@ scenario::scenario parse_scenario(const boost::filesystem::path& scenarioFile, c auto triggerTime = trigger.get(); auto time = to_time_point(triggerTime); - const auto& [index, simulator] = find_simulator(simulators, specified_or_default(event, "model", defaultOpts.model)); - variable_type type = find_variable_type(specified_or_default(event, "type", defaultOpts.type)); - variable_causality causality = find_causality(specified_or_default(event, "causality", defaultOpts.causality)); - auto varName = specified_or_default(event, "variable", defaultOpts.variable); - variable_index varIndex = find_variable_index(simulator->model_description().variables, varName, type, causality); + const auto& [index, simulator] = + find_simulator(simulators, specified_or_default(event, "model", defaultOpts.model)); + variable_type type = + find_variable_type(specified_or_default(event, "type", defaultOpts.type)); + variable_causality causality = + find_causality(specified_or_default(event, "causality", defaultOpts.causality)); + auto varName = + specified_or_default(event, "variable", defaultOpts.variable); + variable_index varIndex = + find_variable_index(simulator->model_description().variables, varName, type, causality); auto mode = specified_or_default(event, "action", defaultOpts.action); - scenario::variable_action a = generate_action(event, mode, index, type, causality, varIndex); + bool isInput = is_input(causality); + scenario::variable_action a = generate_action(event, mode, index, type, isInput, varIndex); events.emplace_back(scenario::event{time, a}); } diff --git a/test/cpp/scenario_manager_test.cpp b/test/cpp/scenario_manager_test.cpp index 5e49d3298..2105c0675 100644 --- a/test/cpp/scenario_manager_test.cpp +++ b/test/cpp/scenario_manager_test.cpp @@ -41,24 +41,27 @@ int main() observer->start_observing(cse::variable_id{simIndex, cse::variable_type::integer, 0}); observer->start_observing(cse::variable_id{simIndex, cse::variable_type::integer, 1}); - auto realManipulator1 = cse::scenario::real_input_manipulator{[](double original) { return original + 1.001; }}; - auto realAction1 = cse::scenario::variable_action{simIndex, 1, realManipulator1}; + constexpr bool input = true; + constexpr bool output = false; + + auto realManipulator1 = cse::scenario::real_manipulator{[](double original) { return original + 1.001; }}; + auto realAction1 = cse::scenario::variable_action{simIndex, 1, realManipulator1, input}; auto realEvent1 = cse::scenario::event{cse::to_time_point(0.5), realAction1}; - auto realManipulator2 = cse::scenario::real_output_manipulator{[](double /*original*/) { return -1.0; }}; - auto realAction2 = cse::scenario::variable_action{simIndex, 0, realManipulator2}; + auto realManipulator2 = cse::scenario::real_manipulator{[](double /*original*/) { return -1.0; }}; + auto realAction2 = cse::scenario::variable_action{simIndex, 0, realManipulator2, output}; auto realEvent2 = cse::scenario::event{cse::to_time_point(0.2), realAction2}; - auto realManipulator3 = cse::scenario::real_output_manipulator{nullptr}; - auto realAction3 = cse::scenario::variable_action{simIndex, 0, realManipulator3}; + auto realManipulator3 = cse::scenario::real_manipulator{nullptr}; + auto realAction3 = cse::scenario::variable_action{simIndex, 0, realManipulator3, output}; auto realEvent3 = cse::scenario::event{cse::to_time_point(0.3), realAction3}; - auto intManipulator1 = cse::scenario::integer_input_manipulator{[](int /*original*/) { return 2; }}; - auto intAction1 = cse::scenario::variable_action{simIndex, 1, intManipulator1}; + auto intManipulator1 = cse::scenario::integer_manipulator{[](int /*original*/) { return 2; }}; + auto intAction1 = cse::scenario::variable_action{simIndex, 1, intManipulator1, input}; auto intEvent1 = cse::scenario::event{cse::to_time_point(0.65), intAction1}; - auto intManipulator2 = cse::scenario::integer_output_manipulator{[](int /*original*/) { return 5; }}; - auto intAction2 = cse::scenario::variable_action{simIndex, 0, intManipulator2}; + auto intManipulator2 = cse::scenario::integer_manipulator{[](int /*original*/) { return 5; }}; + auto intAction2 = cse::scenario::variable_action{simIndex, 0, intManipulator2, output}; auto intEvent2 = cse::scenario::event{cse::to_time_point(0.8), intAction2}; auto events = std::vector();