diff --git a/lib/3rd_party_adapters/nlohmann/JsonGenerator.cpp b/lib/3rd_party_adapters/nlohmann/JsonGenerator.cpp index b064ae8bc..8f3a01ce8 100644 --- a/lib/3rd_party_adapters/nlohmann/JsonGenerator.cpp +++ b/lib/3rd_party_adapters/nlohmann/JsonGenerator.cpp @@ -4,6 +4,7 @@ #include #include #include +#include /** * Indentation used by default for formating JSON. @@ -38,10 +39,17 @@ std::string toJsonString(const task_tracker_sy return jsonObject.dump(defaultJsonIndent); } +void to_json(nlohmann::json &jsonObject, const device::TaskCollection::value_type &object) +{ + jsonObject["id"] = object.first; + jsonObject["label"] = object.second.getLabel(); + jsonObject["duration"] = object.second.getLastRecordedDuration().count(); +} + template <> -std::string toJsonString(const task_tracker_systems::TaskList &object) +std::string toJsonString(const device::TaskCollection &container) { - nlohmann::json jsonObject(object); + nlohmann::json jsonObject(container); return jsonObject.dump(defaultJsonIndent); } diff --git a/lib/application_business_rules/serial_interface/Protocol.cpp b/lib/application_business_rules/serial_interface/Protocol.cpp index 845f9f22f..9ac06bb48 100644 --- a/lib/application_business_rules/serial_interface/Protocol.cpp +++ b/lib/application_business_rules/serial_interface/Protocol.cpp @@ -9,10 +9,12 @@ namespace cli = command_line_interpreter; // --- define commands ------ // -------------------------- #include "JsonGenerator.hpp" +#include #include #include #include #include +#include using namespace task_tracker_systems; @@ -24,25 +26,62 @@ static const auto info = []() { static const auto infoCmd = cli::makeCommand("info", std::function(info)); // command for list -static const auto list = []() { - const TaskList dummyList = { - {.id = 1, .label = "first", .duration = 100U}, - {.id = 2, .label = "second", .duration = 200U}, - }; - serial_port::cout << toJsonString(dummyList) << std::endl; }; +static const auto list = []() { serial_port::cout << toJsonString(device::tasks) << std::endl; }; static const auto listCmd = cli::makeCommand("list", std::function(list)); // command for edit -static const auto edit = [](const unsigned int id, const std::basic_string label, const std::chrono::seconds::rep duration) { - const TaskObject task = {.id = id, .label = label, .duration = duration}; - serial_port::cout << toJsonString(task) << std::endl; +static const auto edit = [](const TaskId id, const std::basic_string label, const Task::Duration::rep duration) { + try + { + auto &task = device::tasks.at(id); + task.setLabel(label); + task.setRecordedDuration(std::chrono::seconds(duration)); + const TaskObject taskObject = {.id = id, .label = task.getLabel(), .duration = task.getLastRecordedDuration().count()}; + serial_port::cout << toJsonString(taskObject) << std::endl; + } + catch (std::out_of_range &e) + { + serial_port::cout << "ERROR: Task not found." << std::endl; + } }; -static const cli::Option id = {.labels = {"--id"}, .defaultValue = 0}; +static const cli::Option id = {.labels = {"--id"}, .defaultValue = 0}; static const cli::Option> label = {.labels = {"--name"}, .defaultValue = "foo"}; -static const cli::Option duration = {.labels = {"--duration"}, .defaultValue = 0}; +static const cli::Option duration = {.labels = {"--duration"}, .defaultValue = 0}; static const auto editCmd = cli::makeCommand("edit", std::function(edit), std::make_tuple(&id, &label, &duration)); -static const std::array *, 3> commands = {&listCmd, &editCmd, &infoCmd}; +// command for create/add +static const auto add = [](const TaskId id, const std::basic_string label, const Task::Duration::rep duration) { + try + { + const auto &[element, created] = device::tasks.try_emplace(id, label, std::chrono::seconds(duration)); + const auto &task = element->second; + const TaskObject taskObject = {.id = element->first, .label = task.getLabel(), .duration = task.getLastRecordedDuration().count()}; + serial_port::cout << toJsonString(taskObject) << std::endl; + if (!created) + { + serial_port::cout << "ERROR: Task with the specified ID already exists." << std::endl; + } + } + catch (std::out_of_range &e) + { + serial_port::cout << "ERROR: Task not found." << std::endl; + } +}; +static const auto addCmd = cli::makeCommand("add", std::function(add), std::make_tuple(&id, &label, &duration)); + +// command for delete/remove +static const auto del = [](const TaskId id) { + const bool deleted = device::tasks.erase(id) > 0; + const DeletedTaskObject taskObject{.id = id}; + serial_port::cout << toJsonString(taskObject) << std::endl; + if (!deleted) + { + serial_port::cout << "ERROR: No task deleted." << std::endl; + } +}; +static const auto delCmd = cli::makeCommand("delete", std::function(del), std::make_tuple(&id)); + +static const std::array *, 5> commands = {&listCmd, &editCmd, &infoCmd, &addCmd, &delCmd}; bool ProtocolHandler::execute(const CharType *const commandLine) { diff --git a/lib/application_business_rules/tasks/Task.cpp b/lib/application_business_rules/tasks/Task.cpp index 1c97d0d47..b8742943d 100644 --- a/lib/application_business_rules/tasks/Task.cpp +++ b/lib/application_business_rules/tasks/Task.cpp @@ -47,4 +47,14 @@ Task::Duration Task::getRecordedDuration() return std::chrono::round(recordedDuration); } -std::map device::tasks; +device::TaskCollection device::tasks; + +void Task::setRecordedDuration(Duration newDuration) +{ + recordedDuration = newDuration; +} + +Task::Duration Task::getLastRecordedDuration() const +{ + return std::chrono::round(recordedDuration); +} diff --git a/lib/application_business_rules/tasks/Task.hpp b/lib/application_business_rules/tasks/Task.hpp index 54c6288c3..7ff20204d 100644 --- a/lib/application_business_rules/tasks/Task.hpp +++ b/lib/application_business_rules/tasks/Task.hpp @@ -65,6 +65,16 @@ class Task * \returns the accumulated duration */ Duration getRecordedDuration(); + + Duration getLastRecordedDuration() const; + + /** + * Sets the recorded duration. + * + * Useful for example if the task has been recorded outside the device. + * @param newDuration new duration to apply + */ + void setRecordedDuration(Duration newDuration); bool isRunning() const; private: @@ -87,8 +97,10 @@ class Task namespace device { +typedef std::map TaskCollection; + /** * *The* collection of tasks to be used by the device application. */ -extern std::map tasks; +extern TaskCollection tasks; } // namespace device