From 35bca4cc31625689343aed75e87b8a4652e7287c Mon Sep 17 00:00:00 2001 From: tobiglaser <76131623+tobiglaser@users.noreply.github.com> Date: Tue, 26 Jul 2022 12:59:56 +0200 Subject: [PATCH] almost worksheet 3, some weirdness though --- CMakeLists.txt | 9 ++- include/BackgroundControl.h | 5 ++ include/ComHandler.h | 61 ++++++++++++++++++ include/ComState.h | 10 +++ include/IComListener.h | 11 ++++ include/Rover.h | 12 ++++ include/RoverHandler.h | 17 +++++ src/CommandType.h | 38 +++++++++++ src/ControlModel.h | 121 ++++++++++++++++++++++++++++++++++++ src/ControlModelRegistry.h | 45 ++++++++++++++ src/IControlModelListener.h | 9 +++ src/testControlModel.cpp | 41 ++++++++++++ 12 files changed, 377 insertions(+), 2 deletions(-) create mode 100644 include/BackgroundControl.h create mode 100644 include/ComHandler.h create mode 100644 include/ComState.h create mode 100644 include/IComListener.h create mode 100644 include/Rover.h create mode 100644 include/RoverHandler.h create mode 100644 src/CommandType.h create mode 100644 src/ControlModel.h create mode 100644 src/ControlModelRegistry.h create mode 100644 src/IControlModelListener.h create mode 100644 src/testControlModel.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index a2eb145..2b50d64 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,12 +8,17 @@ set(CMAKE_C_STANDARD 17) set(CMAKE_CXX_STANDARD 20) -add_executable("Info3_Praktikum-test" +add_executable("Test_Command_List" src/testCommandList.cpp ) +# Add include directory +target_include_directories("Test_Command_List" PUBLIC include/) +add_executable("Test_Control_Model" +src/testControlModel.cpp +) # Add include directory -target_include_directories("Info3_Praktikum-test" PUBLIC include/) +target_include_directories("Test_Control_Model" PUBLIC include/) add_executable("Class-Member-Variable-demo" diff --git a/include/BackgroundControl.h b/include/BackgroundControl.h new file mode 100644 index 0000000..938308d --- /dev/null +++ b/include/BackgroundControl.h @@ -0,0 +1,5 @@ +#pragma once + +class BackgroundControl +{ +}; diff --git a/include/ComHandler.h b/include/ComHandler.h new file mode 100644 index 0000000..a973c57 --- /dev/null +++ b/include/ComHandler.h @@ -0,0 +1,61 @@ +#pragma once +#include "IComListener.h" +#include "ComState.h" +#include "BackgroundControl.h" +#include "commandlib.h" +#include "Rover.h" +#include <memory> +#include <vector> + + +class ComHandler +{ +private: + std::optional<IComListener *> comListener; + BackgroundControl backgroundControl; + ComHandler() {} + +public: + static ComHandler &getInstance(); + void registerComListener(IComListener *cl); + void unregisterComListener(IComListener *cl); + bool start(std::vector<std::shared_ptr<Command>> commands, std::optional<Rover> rover); + bool stop() { return true; } +}; + +ComHandler& ComHandler::getInstance() +{ + static ComHandler instance = ComHandler(); + return instance; +} + +void ComHandler::registerComListener(IComListener *cl) +{ + comListener = cl; +} + +void ComHandler::unregisterComListener(IComListener *cl) +{ + if (comListener == cl) + comListener.reset(); +} + +bool ComHandler::start(std::vector<std::shared_ptr<Command>> commands, std::optional<Rover> rover) +{ + if (rover) + { + //* Funtionality unknown + std::cout << "Many robot, such wow!\nSimuliere stattdessen:\n"; + start(commands, std::nullopt); + } + else + { + std::cout << "Simuliere Ausführung durch Listeneraufrufe.\n"; + for (auto &&i : commands) + { + if (comListener) + comListener.value()->commandPerformed(i, ComState::connection_error); + } + } + return rover ? true : false; +} \ No newline at end of file diff --git a/include/ComState.h b/include/ComState.h new file mode 100644 index 0000000..39f4493 --- /dev/null +++ b/include/ComState.h @@ -0,0 +1,10 @@ +#pragma once + +enum class ComState +{ + connection_error, + rover_finish_ICommand, + rover_in_use, + rover_running_ICommand, + send_ICommand +}; diff --git a/include/IComListener.h b/include/IComListener.h new file mode 100644 index 0000000..57fcf06 --- /dev/null +++ b/include/IComListener.h @@ -0,0 +1,11 @@ +#pragma once +#include "commandlib.h" +#include "ComState.h" +#include <optional> +#include <memory> + +class IComListener +{ +public: + virtual void commandPerformed(std::optional<std::shared_ptr<Command>>, ComState _state) = 0; +}; \ No newline at end of file diff --git a/include/Rover.h b/include/Rover.h new file mode 100644 index 0000000..cde39cc --- /dev/null +++ b/include/Rover.h @@ -0,0 +1,12 @@ +#pragma once +#include <string> + +class Rover +{ +private: + std::string id; + +public: + std::string getId() { return id; } + std::string toString() { return getId(); } +}; \ No newline at end of file diff --git a/include/RoverHandler.h b/include/RoverHandler.h new file mode 100644 index 0000000..102121c --- /dev/null +++ b/include/RoverHandler.h @@ -0,0 +1,17 @@ +#pragma once +#include <vector> +#include "Rover.h" + +class RoverHandler +{ +public: + /** + * @brief Dummy/Placeholder not implemented! + * Maybe don't use References, so nobody has to guarantee any lifetimes. + * @returns an empty Vector or - in future - a Vector of Rover references. + */ + static inline std::vector<Rover> getFreeRover() + { + return std::vector<Rover>(); + }; +}; \ No newline at end of file diff --git a/src/CommandType.h b/src/CommandType.h new file mode 100644 index 0000000..c091d35 --- /dev/null +++ b/src/CommandType.h @@ -0,0 +1,38 @@ +#pragma once +#include "Command.h" +#include "Gear.h" +#include "Direction.h" +#include "Pause.h" +#include <memory> +#include <string> + +class CommandType +{ +private: + std::string name; + +public: + CommandType(std::string _name); + + std::string getName() { return name; } + std::string toString() { return getName(); } + std::shared_ptr<Command> createInstance(); +}; + +CommandType::CommandType(std::string _name) +{ + name = _name; +} + + +std::shared_ptr<Command> CommandType::createInstance() +{ + if (name == IGear::gear) + return std::make_shared<Gear>(0, 0); + else if (name == IDirection::direction) + return std::make_shared<Direction>(0); + else if (name == IPause::pause) + return std::make_shared<Pause>(0); + else + return nullptr; +} diff --git a/src/ControlModel.h b/src/ControlModel.h new file mode 100644 index 0000000..37b54d2 --- /dev/null +++ b/src/ControlModel.h @@ -0,0 +1,121 @@ +#pragma once +#include <iostream> +#include <array> +#include "commandlib.h" +#include "IComListener.h" +#include "ControlModelRegistry.h" +#include "CommandType.h" +#include "CommandListOWN.h" +#include "Rover.h" +#include "RoverHandler.h" +#include "ComHandler.h" +#include "ComState.h" + +class ControlModel : public ControlModelRegistry, IComListener +{ +private: + ControlModel(); + ~ControlModel(); + std::array<CommandType, 3> cT = { + CommandType(IDirection::direction), + CommandType(IGear::gear), + CommandType(IPause::pause)}; + CommandList list; + std::optional<Rover> selectedRover; + +public: + static ControlModel& getInstance(); + void commandPerformed(std::optional<std::shared_ptr<Command>> _command, ComState _state); + bool start(); + bool stop(); + + // Possible Lifetime concerns + CommandList &getCommandList() { return list; } + // Possible Lifetime concerns + std::array<CommandType, 3> &getCommandTypes() { return cT; } + + void setSelectedRover() + { + //? is RoverHandler static? Where does it belong? ControlModel? + std::vector<Rover> rovers = RoverHandler::getFreeRover(); + if (!rovers.empty()) + selectedRover = rovers.front(); + } + + std::optional<std::string> getSelectedRoverId() + { + if (selectedRover) + return selectedRover.value().getId(); + else + return std::nullopt; + } +}; + +ControlModel::ControlModel() +{ + ComHandler::getInstance().registerComListener(this); +} + +ControlModel::~ControlModel() +{ + ComHandler::getInstance().unregisterComListener(this); +} + +ControlModel& ControlModel::getInstance() +{ + static ControlModel instance = ControlModel(); + return instance; +} + +void ControlModel::commandPerformed(std::optional<std::shared_ptr<Command>> _command, ComState _state) +{ + std::string commandPart = ""; + if (_command) + commandPart = _command.value()->getConfig(); + else + commandPart = "no Command"; + + std::string statePart = ""; + switch (_state) + { + case ComState::connection_error: + statePart = "Connection Error"; + break; + case ComState::rover_finish_ICommand: + statePart = "Rover finish ICommand"; + break; + case ComState::rover_in_use: + statePart = "Rover in Use"; + break; + case ComState::rover_running_ICommand: + statePart = "Rover running ICommand"; + break; + case ComState::send_ICommand: + statePart = "Send ICommand"; + break; + default: + statePart = ""; + break; + } + notifyMessageChanged("Command: " + commandPart + " - State: " + statePart); +} + +bool ControlModel::start() +{ + std::vector<std::shared_ptr<Command>> commands; + uint size = list.getSize(); + //0 is root element + // iterator would help greatly with of by one errors + for (int i = 1; i <= size; ++i) + { + //? Wie hier was sammeln und übergeben? + commands.push_back(list.getCommand(i)); + } + + return ComHandler::getInstance().start(commands, selectedRover); +} + +bool ControlModel::stop() +{ + return ComHandler::getInstance().stop(); +} \ No newline at end of file diff --git a/src/ControlModelRegistry.h b/src/ControlModelRegistry.h new file mode 100644 index 0000000..7cb01e2 --- /dev/null +++ b/src/ControlModelRegistry.h @@ -0,0 +1,45 @@ +#pragma once +#include "IControlModelListener.h" +#include <string> +#include <memory> +#include <vector> + +class ControlModelRegistry +{ +private: + //? maybe should be https://en.cppreference.com/w/cpp/memory/weak_ptr + std::vector<std::shared_ptr<IControlModelListener>> registry; + +public: + void addControlModelListener(std::shared_ptr<IControlModelListener> _listener); + void removeControlModelListener(std::shared_ptr<IControlModelListener> _listener); + void notifyMessageChanged(std::string _message); + void notifyRoverChanged(); +}; + +void ControlModelRegistry::addControlModelListener(std::shared_ptr<IControlModelListener> _listener) +{ + registry.push_back(_listener); +} + +void ControlModelRegistry::removeControlModelListener(std::shared_ptr<IControlModelListener> _listener) +{ + // https://en.cppreference.com/w/cpp/container/vector/erase2 + std::erase(registry, _listener); +} + +void ControlModelRegistry::notifyMessageChanged(std::string _message) +{ + for (auto &&i : registry) + { + i->messageUpdated(_message); + } +} + +void ControlModelRegistry::notifyRoverChanged() +{ + for (auto &&i : registry) + { + i->roverUpdated(); + } +} \ No newline at end of file diff --git a/src/IControlModelListener.h b/src/IControlModelListener.h new file mode 100644 index 0000000..51c6bb9 --- /dev/null +++ b/src/IControlModelListener.h @@ -0,0 +1,9 @@ +#pragma once +#include <string> + +class IControlModelListener +{ +public: + virtual void messageUpdated(std::string _message) = 0; + virtual void roverUpdated() = 0; +}; \ No newline at end of file diff --git a/src/testControlModel.cpp b/src/testControlModel.cpp new file mode 100644 index 0000000..53d1957 --- /dev/null +++ b/src/testControlModel.cpp @@ -0,0 +1,41 @@ +#include <iostream> + +#include "Gear.h" +#include "Direction.h" +#include "Pause.h" +#include "IControlModelListener.h" +#include "ControlModel.h" + +class Listener : public IControlModelListener +{ + void messageUpdated(std::string _message) + { + std::cout << "Got Message: " << _message << '\n'; + } + void roverUpdated() + { + std::cout << "Rover was updated\n"; + } +}; + +int main() +{ + ControlModel &model = ControlModel::getInstance(); + std::shared_ptr<Listener> listener = std::make_shared<Listener>(); + model.addControlModelListener(listener); + + + std::shared_ptr<Command> a = model.getCommandTypes()[0].createInstance(); + std::cout << a->getConfig() << '\n'; + //! model.getCommandList().add(a); + // model.getCommandList().add(model.getCommandTypes()[0].createInstance()); + // model.getCommandList().add(model.getCommandTypes()[1].createInstance()); + // model.getCommandList().add(model.getCommandTypes()[2].createInstance()); + model.getCommandList().add(Gear(1, 1.0)); + model.getCommandList().add(Direction(30)); + model.getCommandList().add(Pause(0.5)); + + model.start(); + + model.setSelectedRover(); +} \ No newline at end of file -- GitLab