diff options
Diffstat (limited to 'core/src/Model')
27 files changed, 570 insertions, 299 deletions
diff --git a/core/src/Model/Filter.hpp b/core/src/Model/Filter.hpp index 53995c1..1b923e1 100644 --- a/core/src/Model/Filter.hpp +++ b/core/src/Model/Filter.hpp @@ -1,5 +1,6 @@ #pragma once -class TableRowsFilter { +class TableRowsFilter +{ // TODO }; diff --git a/core/src/Model/GlobalStates.cpp b/core/src/Model/GlobalStates.cpp index 0c4e58e..4004f4a 100644 --- a/core/src/Model/GlobalStates.cpp +++ b/core/src/Model/GlobalStates.cpp @@ -16,11 +16,13 @@ namespace fs = std::filesystem; static std::unique_ptr<GlobalStates> globalStateInstance; static fs::path globalDataPath; -void GlobalStates::Init() { +void GlobalStates::Init() +{ Init(StandardDirectories::UserData() / "cplt"); } -void GlobalStates::Init(std::filesystem::path userDataDir) { +void GlobalStates::Init(std::filesystem::path userDataDir) +{ globalStateInstance = std::make_unique<GlobalStates>(); globalDataPath = userDataDir; fs::create_directories(globalDataPath); @@ -51,31 +53,37 @@ void GlobalStates::Init(std::filesystem::path userDataDir) { }(); } -void GlobalStates::Shutdown() { +void GlobalStates::Shutdown() +{ if (!globalStateInstance) return; if (globalStateInstance->mDirty) { globalStateInstance->WriteToDisk(); } } -GlobalStates& GlobalStates::GetInstance() { +GlobalStates& GlobalStates::GetInstance() +{ return *globalStateInstance; } -const std::filesystem::path& GlobalStates::GetUserDataPath() { +const std::filesystem::path& GlobalStates::GetUserDataPath() +{ return globalDataPath; } -const std::vector<GlobalStates::RecentProject>& GlobalStates::GetRecentProjects() const { +const std::vector<GlobalStates::RecentProject>& GlobalStates::GetRecentProjects() const +{ return mRecentProjects; } -void GlobalStates::ClearRecentProjects() { +void GlobalStates::ClearRecentProjects() +{ mRecentProjects.clear(); MarkDirty(); } -void GlobalStates::AddRecentProject(const Project& project) { +void GlobalStates::AddRecentProject(const Project& project) +{ mRecentProjects.push_back(RecentProject{ .path = project.GetPath(), .cachedUtf8String = project.GetPath().string(), @@ -83,7 +91,8 @@ void GlobalStates::AddRecentProject(const Project& project) { MarkDirty(); } -void GlobalStates::MoveProjectToTop(const Project& project) { +void GlobalStates::MoveProjectToTop(const Project& project) +{ for (auto it = mRecentProjects.begin(); it != mRecentProjects.end(); ++it) { if (it->path == project.GetPath()) { std::rotate(it, it + 1, mRecentProjects.end()); @@ -94,14 +103,16 @@ void GlobalStates::MoveProjectToTop(const Project& project) { AddRecentProject(project); } -void GlobalStates::RemoveRecentProject(int idx) { +void GlobalStates::RemoveRecentProject(int idx) +{ assert(idx >= 0 && idx < mRecentProjects.size()); mRecentProjects.erase(mRecentProjects.begin() + idx); MarkDirty(); } -void GlobalStates::WriteToDisk() const { +void GlobalStates::WriteToDisk() const +{ Json::Value root; auto& recentProjects = root["RecentProjects"] = Json::Value(Json::arrayValue); @@ -115,11 +126,13 @@ void GlobalStates::WriteToDisk() const { mDirty = false; } -bool GlobalStates::IsDirty() const { +bool GlobalStates::IsDirty() const +{ return mDirty; } -void GlobalStates::MarkDirty() { +void GlobalStates::MarkDirty() +{ mDirty = true; OnModified(); } diff --git a/core/src/Model/GlobalStates.hpp b/core/src/Model/GlobalStates.hpp index 8375569..d88f752 100644 --- a/core/src/Model/GlobalStates.hpp +++ b/core/src/Model/GlobalStates.hpp @@ -7,7 +7,8 @@ #include <string> #include <vector> -class GlobalStates { +class GlobalStates +{ public: static void Init(); static void Init(std::filesystem::path userDataDir); @@ -16,7 +17,8 @@ public: static GlobalStates& GetInstance(); static const std::filesystem::path& GetUserDataPath(); - struct RecentProject { + struct RecentProject + { std::filesystem::path path; std::string cachedUtf8String; }; diff --git a/core/src/Model/Items.cpp b/core/src/Model/Items.cpp index 02a4516..9d2abc6 100644 --- a/core/src/Model/Items.cpp +++ b/core/src/Model/Items.cpp @@ -1,29 +1,36 @@ #include "Items.hpp" -const std::string& ProductItem::GetDescription() const { +const std::string& ProductItem::GetDescription() const +{ return mDescription; } -void ProductItem::SetDescription(std::string description) { +void ProductItem::SetDescription(std::string description) +{ mDescription = std::move(description); } -int ProductItem::GetPrice() const { +int ProductItem::GetPrice() const +{ return mPrice; } -void ProductItem::SetPrice(int price) { +void ProductItem::SetPrice(int price) +{ mPrice = price; } -int ProductItem::GetStock() const { +int ProductItem::GetStock() const +{ return mStock; } -void ProductItem::SetStock(int stock) { +void ProductItem::SetStock(int stock) +{ mStock = stock; } -Json::Value ProductItem::Serialize() const { +Json::Value ProductItem::Serialize() const +{ Json::Value elm; elm["Description"] = mDescription; elm["Price"] = mPrice; @@ -31,64 +38,77 @@ Json::Value ProductItem::Serialize() const { return elm; } -void ProductItem::Deserialize(const Json::Value& elm) { +void ProductItem::Deserialize(const Json::Value& elm) +{ mDescription = elm["Description"].asString(); mPrice = elm["Price"].asInt(); mStock = elm["Stock"].asInt(); } -const std::string& FactoryItem::GetDescription() const { +const std::string& FactoryItem::GetDescription() const +{ return mDescription; } -void FactoryItem::SetDescription(std::string description) { +void FactoryItem::SetDescription(std::string description) +{ mDescription = std::move(description); } -const std::string& FactoryItem::GetEmail() const { +const std::string& FactoryItem::GetEmail() const +{ return mEmail; } -void FactoryItem::SetEmail(std::string email) { +void FactoryItem::SetEmail(std::string email) +{ mEmail = std::move(email); } -Json::Value FactoryItem::Serialize() const { +Json::Value FactoryItem::Serialize() const +{ Json::Value elm; elm["Description"] = mDescription; elm["Email"] = mEmail; return elm; } -void FactoryItem::Deserialize(const Json::Value& elm) { +void FactoryItem::Deserialize(const Json::Value& elm) +{ mDescription = elm["Description"].asString(); mEmail = elm["Email"].asString(); } -const std::string& CustomerItem::GetDescription() const { +const std::string& CustomerItem::GetDescription() const +{ return mDescription; } -void CustomerItem::SetDescription(std::string description) { +void CustomerItem::SetDescription(std::string description) +{ mDescription = std::move(description); } -const std::string& CustomerItem::GetEmail() const { +const std::string& CustomerItem::GetEmail() const +{ return mEmail; } -void CustomerItem::SetEmail(std::string email) { +void CustomerItem::SetEmail(std::string email) +{ mEmail = std::move(email); } -Json::Value CustomerItem::Serialize() const { +Json::Value CustomerItem::Serialize() const +{ Json::Value elm; elm["Description"] = mDescription; elm["Email"] = mEmail; return elm; } -void CustomerItem::Deserialize(const Json::Value& elm) { +void CustomerItem::Deserialize(const Json::Value& elm) +{ mDescription = elm["Description"].asString(); mEmail = elm["Email"].asString(); } diff --git a/core/src/Model/Items.hpp b/core/src/Model/Items.hpp index 1289be6..859aedf 100644 --- a/core/src/Model/Items.hpp +++ b/core/src/Model/Items.hpp @@ -15,14 +15,16 @@ #include <vector> template <class T> -class ItemList { +class ItemList +{ private: std::vector<T> mStorage; tsl::array_map<char, size_t> mNameLookup; public: template <class... Args> - T& Insert(std::string name, Args... args) { + T& Insert(std::string name, Args... args) + { auto iter = mNameLookup.find(name); if (iter != mNameLookup.end()) { throw std::runtime_error("Duplicate key."); @@ -42,21 +44,25 @@ public: return mStorage[id]; } - void Remove(size_t index) { + void Remove(size_t index) + { auto& item = mStorage[index]; mNameLookup.erase(item.GetName()); mStorage[index] = T(*this); } - T* Find(size_t id) { + T* Find(size_t id) + { return &mStorage[id]; } - const T* Find(size_t id) const { + const T* Find(size_t id) const + { return &mStorage[id]; } - const T* Find(std::string_view name) const { + const T* Find(std::string_view name) const + { auto iter = mNameLookup.find(name); if (iter != mNameLookup.end()) { return &mStorage[iter.value()]; @@ -65,7 +71,8 @@ public: } } - Json::Value Serialize() const { + Json::Value Serialize() const + { Json::Value items(Json::arrayValue); for (auto& item : mStorage) { if (!item.IsInvalid()) { @@ -85,7 +92,8 @@ public: ItemList() = default; - ItemList(const Json::Value& root) { + ItemList(const Json::Value& root) + { constexpr const char* kMessage = "Failed to load item list from JSON."; auto& itemCount = root["MaxItemId"]; @@ -110,19 +118,23 @@ public: } } - typename decltype(mStorage)::iterator begin() { + typename decltype(mStorage)::iterator begin() + { return mStorage.begin(); } - typename decltype(mStorage)::iterator end() { + typename decltype(mStorage)::iterator end() + { return mStorage.end(); } - typename decltype(mStorage)::const_iterator begin() const { + typename decltype(mStorage)::const_iterator begin() const + { return mStorage.begin(); } - typename decltype(mStorage)::const_iterator end() const { + typename decltype(mStorage)::const_iterator end() const + { return mStorage.end(); } @@ -130,14 +142,16 @@ private: template <class TSelf> friend class ItemBase; - void UpdateItemName(const T& item, const std::string& newName) { + void UpdateItemName(const T& item, const std::string& newName) + { mNameLookup.erase(item.GetName()); mNameLookup.insert(newName, item.GetId()); } }; template <class TSelf> -class ItemBase { +class ItemBase +{ private: ItemList<TSelf>* mList; size_t mId; @@ -147,32 +161,39 @@ public: ItemBase(ItemList<TSelf>& list, size_t id = std::numeric_limits<size_t>::max(), std::string name = "") : mList{ &list } , mId{ id } - , mName{ std::move(name) } { + , mName{ std::move(name) } + { } - bool IsInvalid() const { + bool IsInvalid() const + { return mId == std::numeric_limits<size_t>::max(); } - ItemList<TSelf>& GetList() const { + ItemList<TSelf>& GetList() const + { return *mList; } - size_t GetId() const { + size_t GetId() const + { return mId; } - const std::string& GetName() const { + const std::string& GetName() const + { return mName; } - void SetName(std::string name) { + void SetName(std::string name) + { mList->UpdateItemName(static_cast<TSelf&>(*this), name); mName = std::move(name); } }; -class ProductItem : public ItemBase<ProductItem> { +class ProductItem : public ItemBase<ProductItem> +{ private: std::string mDescription; int mPrice = 0; @@ -195,7 +216,8 @@ public: void Deserialize(const Json::Value& elm); }; -class FactoryItem : public ItemBase<FactoryItem> { +class FactoryItem : public ItemBase<FactoryItem> +{ private: std::string mDescription; std::string mEmail; @@ -212,7 +234,8 @@ public: void Deserialize(const Json::Value& elm); }; -class CustomerItem : public ItemBase<CustomerItem> { +class CustomerItem : public ItemBase<CustomerItem> +{ private: std::string mDescription; std::string mEmail; diff --git a/core/src/Model/Project.cpp b/core/src/Model/Project.cpp index e762efb..74e7142 100644 --- a/core/src/Model/Project.cpp +++ b/core/src/Model/Project.cpp @@ -11,7 +11,8 @@ namespace fs = std::filesystem; template <class T> -void ReadItemList(ItemList<T>& list, const fs::path& filePath) { +void ReadItemList(ItemList<T>& list, const fs::path& filePath) +{ std::ifstream ifs(filePath); if (ifs) { Json::Value root; @@ -24,7 +25,8 @@ void ReadItemList(ItemList<T>& list, const fs::path& filePath) { Project::Project(const fs::path& rootPath) : mRootPath{ rootPath } , mRootPathString{ mRootPath.string() } - , mDb(*this) { + , mDb(*this) +{ // TODO better diagnostic const char* kInvalidFormatErr = "Failed to load project: invalid format."; @@ -63,34 +65,42 @@ Project::Project(std::filesystem::path rootPath, std::string name) : mRootPath{ std::move(rootPath) } , mRootPathString{ mRootPath.string() } , mName{ std::move(name) } - , mDb(*this) { + , mDb(*this) +{ } -const fs::path& Project::GetPath() const { +const fs::path& Project::GetPath() const +{ return mRootPath; } -const std::string& Project::GetPathString() const { +const std::string& Project::GetPathString() const +{ return mRootPathString; } -const std::string& Project::GetName() const { +const std::string& Project::GetName() const +{ return mName; } -void Project::SetName(std::string name) { +void Project::SetName(std::string name) +{ mName = std::move(name); } -const TransactionModel& Project::GetTransactionsModel() const { +const TransactionModel& Project::GetTransactionsModel() const +{ return mDb; } -TransactionModel& Project::GetTransactionsModel() { +TransactionModel& Project::GetTransactionsModel() +{ return mDb; } -Json::Value Project::Serialize() { +Json::Value Project::Serialize() +{ Json::Value root(Json::objectValue); root["Name"] = mName; @@ -99,12 +109,14 @@ Json::Value Project::Serialize() { } template <class T> -static void WriteItemList(ItemList<T>& list, const fs::path& filePath) { +static void WriteItemList(ItemList<T>& list, const fs::path& filePath) +{ std::ofstream ofs(filePath); ofs << list.Serialize(); } -void Project::WriteToDisk() { +void Project::WriteToDisk() +{ std::ofstream ofs(mRootPath / "cplt_project.json"); ofs << this->Serialize(); diff --git a/core/src/Model/Project.hpp b/core/src/Model/Project.hpp index 748ca82..998befb 100644 --- a/core/src/Model/Project.hpp +++ b/core/src/Model/Project.hpp @@ -7,7 +7,8 @@ #include <filesystem> #include <string> -class Project { +class Project +{ public: ItemList<ProductItem> Products; ItemList<FactoryItem> Factories; diff --git a/core/src/Model/TransactionsModel.cpp b/core/src/Model/TransactionsModel.cpp index 914191d..6d0989e 100644 --- a/core/src/Model/TransactionsModel.cpp +++ b/core/src/Model/TransactionsModel.cpp @@ -9,26 +9,28 @@ namespace fs = std::filesystem; SalesTable::SalesTable(TransactionModel& db) // language=SQLite - : GetRowCountStatement(db.GetSQLite(), "SELECT Count(*) FROM Sales") + : GetRowCount(db.GetSQLite(), "SELECT Count(*) FROM Sales") // language=SQLite - , GetRowsStatement(db.GetSQLite(), "SELECT * FROM Sales WHERE rowid >= ? AND rowid < ?") - // language=SQLite - // TODO - , FilterRowsStatement(db.GetSQLite(), R"""( -)""") { + , GetRows(db.GetSQLite(), "SELECT * FROM Sales WHERE rowid >= ? AND rowid < ?") +{ } PurchasesTable::PurchasesTable(TransactionModel& db) // language=SQLite - : GetRowCountStatement(db.GetSQLite(), "SELECT Count(*) FROM Purchases") + : GetRowCount(db.GetSQLite(), "SELECT Count(*) FROM Purchases") // language=SQLite - , GetRowsStatement(db.GetSQLite(), "SELECT * FROM Purchases WHERE rowid >= ? AND rowid < ?") { + , GetRows(db.GetSQLite(), "SELECT * FROM Purchases WHERE rowid >= ? AND rowid < ?") +{ } -DeliveryTable::DeliveryTable(TransactionModel& db) { +DeliveryTable::DeliveryTable(TransactionModel& db) + // language=SQLite + : FilterByTypeAndId(db.GetSQLite(), "SELECT * FROM Deliveries WHERE AssociatedOrder == ? AND Outgoing = ?") +{ } -static std::string GetDatabaseFilePath(const Project& project) { +static std::string GetDatabaseFilePath(const Project& project) +{ auto dbsDir = project.GetPath() / "databases"; fs::create_directories(dbsDir); @@ -38,8 +40,8 @@ static std::string GetDatabaseFilePath(const Project& project) { /// Wrapper for SQLite::Database that creates the default tables TransactionModel::DatabaseWrapper::DatabaseWrapper(TransactionModel& self) - : mSqlite(GetDatabaseFilePath(*self.mProject), SQLite::OPEN_READWRITE) { - + : mSqlite(GetDatabaseFilePath(*self.mProject), SQLite::OPEN_READWRITE) +{ // If this table doesn't exist, the database probably just got initialized if (mSqlite.tableExists("Sales")) { return; @@ -56,8 +58,8 @@ TransactionModel::DatabaseWrapper::DatabaseWrapper(TransactionModel& self) // - DeliveryTime: the time this order was completed (through a set of deliveries) // 'Deliveries' schema - // - SendTime: unix epoch time of sending to delivery - // - ArriveTime: unix epoch time of delivery arrived at warehouse; 0 if not arrived yet + // - ShipmentTime: unix epoch time of sending to delivery + // - ArrivalTime: unix epoch time of delivery arrived at warehouse; 0 if not arrived yet // - AssociatedOrder: rowid of the order that this delivery is completing (which table: Outgoing=true -> Sales, Outgoing=false -> Purchases) // - Outgoing: true if the delivery is from warehouse to customer; false if the delivery is from factory to warehouse @@ -76,28 +78,28 @@ CREATE TABLE IF NOT EXISTS SalesItems( ); CREATE TABLE IF NOT EXISTS Purchases( - INT PRIMARY KEY, - Factory INT, - OrderTime DATETIME, - DeliveryTime DATETIME + INT PRIMARY KEY, + Factory INT, + OrderTime DATETIME, + DeliveryTime DATETIME ); CREATE TABLE IF NOT EXISTS PurchasesItems( - PurchaseId INT, - ItemId INT, - Count INT + PurchaseId INT, + ItemId INT, + Count INT ); CREATE TABLE IF NOT EXISTS Deliveries( - INT PRIMARY KEY, - SendTime DATETIME, - ArriveTime DATETIME, - AssociatedOrder INT, - Outgoing BOOLEAN + INT PRIMARY KEY, + ShipmentTime DATETIME, + ArrivalTime DATETIME, + AssociatedOrder INT, + Outgoing BOOLEAN ); CREATE TABLE IF NOT EXISTS DeliveriesItems( - DeliveryId INT, - ItemId INT, - Count INT + DeliveryId INT, + ItemId INT, + Count INT ); )"""); } @@ -107,37 +109,46 @@ TransactionModel::TransactionModel(Project& project) , mDbWrapper(*this) , mSales(*this) , mPurchases(*this) - , mDeliveries(*this) { + , mDeliveries(*this) +{ } -const SQLite::Database& TransactionModel::GetSQLite() const { +const SQLite::Database& TransactionModel::GetSQLite() const +{ return mDbWrapper.mSqlite; } -SQLite::Database& TransactionModel::GetSQLite() { +SQLite::Database& TransactionModel::GetSQLite() +{ return mDbWrapper.mSqlite; } -const SalesTable& TransactionModel::GetSales() const { +const SalesTable& TransactionModel::GetSales() const +{ return mSales; } -SalesTable& TransactionModel::GetSales() { +SalesTable& TransactionModel::GetSales() +{ return mSales; } -const PurchasesTable& TransactionModel::GetPurchases() const { +const PurchasesTable& TransactionModel::GetPurchases() const +{ return mPurchases; } -PurchasesTable& TransactionModel::GetPurchases() { +PurchasesTable& TransactionModel::GetPurchases() +{ return mPurchases; } -const DeliveryTable& TransactionModel::GetDeliveries() const { +const DeliveryTable& TransactionModel::GetDeliveries() const +{ return mDeliveries; } -DeliveryTable& TransactionModel::GetDeliveries() { +DeliveryTable& TransactionModel::GetDeliveries() +{ return mDeliveries; } diff --git a/core/src/Model/TransactionsModel.hpp b/core/src/Model/TransactionsModel.hpp index 7a71fca..86611cf 100644 --- a/core/src/Model/TransactionsModel.hpp +++ b/core/src/Model/TransactionsModel.hpp @@ -6,34 +6,41 @@ #include <SQLiteCpp/Statement.h> #include <cstdint> -class SalesTable { +class SalesTable +{ public: - SQLite::Statement GetRowCountStatement; - SQLite::Statement GetRowsStatement; - SQLite::Statement FilterRowsStatement; + SQLite::Statement GetRowCount; + SQLite::Statement GetRows; public: SalesTable(TransactionModel& db); }; -class PurchasesTable { +class PurchasesTable +{ public: - SQLite::Statement GetRowCountStatement; - SQLite::Statement GetRowsStatement; + SQLite::Statement GetRowCount; + SQLite::Statement GetRows; public: PurchasesTable(TransactionModel& db); }; -class DeliveryTable { +class DeliveryTable +{ +public: + SQLite::Statement FilterByTypeAndId; + public: DeliveryTable(TransactionModel& db); }; // TODO fuck SQLite::Statement has move ctor but not move assignment operator -class TransactionModel { +class TransactionModel +{ private: - class DatabaseWrapper { + class DatabaseWrapper + { public: SQLite::Database mSqlite; DatabaseWrapper(TransactionModel& self); diff --git a/core/src/Model/Workflow/Evaluation.cpp b/core/src/Model/Workflow/Evaluation.cpp index ff3edf4..f6472dd 100644 --- a/core/src/Model/Workflow/Evaluation.cpp +++ b/core/src/Model/Workflow/Evaluation.cpp @@ -2,14 +2,16 @@ #include <queue> -const char* WorkflowEvaluationError::FormatMessageType(enum MessageType messageType) { +const char* WorkflowEvaluationError::FormatMessageType(enum MessageType messageType) +{ switch (messageType) { case Error: return "Error"; case Warning: return "Warning"; } } -const char* WorkflowEvaluationError::FormatPinType(enum PinType pinType) { +const char* WorkflowEvaluationError::FormatPinType(enum PinType pinType) +{ switch (pinType) { case NoPin: return nullptr; case InputPin: return "Input pin"; @@ -17,7 +19,8 @@ const char* WorkflowEvaluationError::FormatPinType(enum PinType pinType) { } } -std::string WorkflowEvaluationError::Format() const { +std::string WorkflowEvaluationError::Format() const +{ // TODO convert to std::format std::string result; @@ -37,32 +40,38 @@ std::string WorkflowEvaluationError::Format() const { } namespace { -enum class EvaluationStatus { +enum class EvaluationStatus +{ Unevaluated, Success, Failed, }; } // namespace -struct WorkflowEvaluationContext::RuntimeNode { +struct WorkflowEvaluationContext::RuntimeNode +{ EvaluationStatus Status = EvaluationStatus::Unevaluated; }; -struct WorkflowEvaluationContext::RuntimeConnection { +struct WorkflowEvaluationContext::RuntimeConnection +{ std::unique_ptr<BaseValue> Value; - bool IsAvailableValue() const { + bool IsAvailableValue() const + { return Value != nullptr; } }; WorkflowEvaluationContext::WorkflowEvaluationContext(Workflow& workflow) - : mWorkflow{ &workflow } { + : mWorkflow{ &workflow } +{ mRuntimeNodes.resize(workflow.mNodes.size()); mRuntimeConnections.resize(workflow.mConnections.size()); } -BaseValue* WorkflowEvaluationContext::GetConnectionValue(size_t id, bool constant) { +BaseValue* WorkflowEvaluationContext::GetConnectionValue(size_t id, bool constant) +{ if (constant) { return mWorkflow->GetConstantById(id); } else { @@ -70,7 +79,8 @@ BaseValue* WorkflowEvaluationContext::GetConnectionValue(size_t id, bool constan } } -BaseValue* WorkflowEvaluationContext::GetConnectionValue(const WorkflowNode::InputPin& inputPin) { +BaseValue* WorkflowEvaluationContext::GetConnectionValue(const WorkflowNode::InputPin& inputPin) +{ if (inputPin.IsConnected()) { return GetConnectionValue(inputPin.Connection, inputPin.IsConstantConnection()); } else { @@ -78,17 +88,20 @@ BaseValue* WorkflowEvaluationContext::GetConnectionValue(const WorkflowNode::Inp } } -void WorkflowEvaluationContext::SetConnectionValue(size_t id, std::unique_ptr<BaseValue> value) { +void WorkflowEvaluationContext::SetConnectionValue(size_t id, std::unique_ptr<BaseValue> value) +{ mRuntimeConnections[id].Value = std::move(value); } -void WorkflowEvaluationContext::SetConnectionValue(const WorkflowNode::OutputPin& outputPin, std::unique_ptr<BaseValue> value) { +void WorkflowEvaluationContext::SetConnectionValue(const WorkflowNode::OutputPin& outputPin, std::unique_ptr<BaseValue> value) +{ if (outputPin.IsConnected()) { SetConnectionValue(outputPin.Connection, std::move(value)); } } -void WorkflowEvaluationContext::Run() { +void WorkflowEvaluationContext::Run() +{ int evaluatedCount = 0; int erroredCount = 0; @@ -118,7 +131,8 @@ void WorkflowEvaluationContext::Run() { } } -void WorkflowEvaluationContext::ReportError(std::string message, const WorkflowNode& node, int pinId, bool inputPin) { +void WorkflowEvaluationContext::ReportError(std::string message, const WorkflowNode& node, int pinId, bool inputPin) +{ mErrors.push_back(WorkflowEvaluationError{ .Message = std::move(message), .NodeId = node.GetId(), @@ -128,7 +142,8 @@ void WorkflowEvaluationContext::ReportError(std::string message, const WorkflowN }); } -void WorkflowEvaluationContext::ReportError(std::string message, const WorkflowNode& node) { +void WorkflowEvaluationContext::ReportError(std::string message, const WorkflowNode& node) +{ mErrors.push_back(WorkflowEvaluationError{ .Message = std::move(message), .NodeId = node.GetId(), @@ -138,7 +153,8 @@ void WorkflowEvaluationContext::ReportError(std::string message, const WorkflowN }); } -void WorkflowEvaluationContext::ReportWarning(std::string message, const WorkflowNode& node, int pinId, bool inputPin) { +void WorkflowEvaluationContext::ReportWarning(std::string message, const WorkflowNode& node, int pinId, bool inputPin) +{ mErrors.push_back(WorkflowEvaluationError{ .Message = std::move(message), .NodeId = node.GetId(), @@ -148,7 +164,8 @@ void WorkflowEvaluationContext::ReportWarning(std::string message, const Workflo }); } -void WorkflowEvaluationContext::ReportWarning(std::string message, const WorkflowNode& node) { +void WorkflowEvaluationContext::ReportWarning(std::string message, const WorkflowNode& node) +{ mErrors.push_back(WorkflowEvaluationError{ .Message = std::move(message), .NodeId = node.GetId(), diff --git a/core/src/Model/Workflow/Evaluation.hpp b/core/src/Model/Workflow/Evaluation.hpp index d068c45..4d78872 100644 --- a/core/src/Model/Workflow/Evaluation.hpp +++ b/core/src/Model/Workflow/Evaluation.hpp @@ -7,14 +7,17 @@ #include <string> #include <vector> -class WorkflowEvaluationError { +class WorkflowEvaluationError +{ public: - enum MessageType : int16_t { + enum MessageType : int16_t + { Error, Warning, }; - enum PinType : int16_t { + enum PinType : int16_t + { NoPin, InputPin, OutputPin, @@ -34,7 +37,8 @@ public: std::string Format() const; }; -class WorkflowEvaluationContext { +class WorkflowEvaluationContext +{ private: struct RuntimeNode; struct RuntimeConnection; diff --git a/core/src/Model/Workflow/Nodes/DocumentNodes.cpp b/core/src/Model/Workflow/Nodes/DocumentNodes.cpp index 255d446..b858b49 100644 --- a/core/src/Model/Workflow/Nodes/DocumentNodes.cpp +++ b/core/src/Model/Workflow/Nodes/DocumentNodes.cpp @@ -3,13 +3,16 @@ #include "Model/Workflow/Evaluation.hpp" #include "Model/Workflow/Values/BasicValues.hpp" -bool DocumentTemplateExpansionNode::IsInstance(const WorkflowNode* node) { +bool DocumentTemplateExpansionNode::IsInstance(const WorkflowNode* node) +{ return node->GetKind() == KD_DocumentTemplateExpansion; } DocumentTemplateExpansionNode::DocumentTemplateExpansionNode() - : WorkflowNode(KD_DocumentTemplateExpansion) { + : WorkflowNode(KD_DocumentTemplateExpansion) +{ } -void DocumentTemplateExpansionNode::Evaluate(WorkflowEvaluationContext& ctx) { +void DocumentTemplateExpansionNode::Evaluate(WorkflowEvaluationContext& ctx) +{ } diff --git a/core/src/Model/Workflow/Nodes/DocumentNodes.hpp b/core/src/Model/Workflow/Nodes/DocumentNodes.hpp index 3b775ec..85bba9e 100644 --- a/core/src/Model/Workflow/Nodes/DocumentNodes.hpp +++ b/core/src/Model/Workflow/Nodes/DocumentNodes.hpp @@ -2,7 +2,8 @@ #include "Model/Workflow/Workflow.hpp" -class DocumentTemplateExpansionNode : public WorkflowNode { +class DocumentTemplateExpansionNode : public WorkflowNode +{ public: static bool IsInstance(const WorkflowNode* node); DocumentTemplateExpansionNode(); diff --git a/core/src/Model/Workflow/Nodes/NumericNodes.cpp b/core/src/Model/Workflow/Nodes/NumericNodes.cpp index f054421..138b35d 100644 --- a/core/src/Model/Workflow/Nodes/NumericNodes.cpp +++ b/core/src/Model/Workflow/Nodes/NumericNodes.cpp @@ -8,7 +8,8 @@ #include <cassert> #include <utility> -WorkflowNode::Kind NumericOperationNode::OperationTypeToNodeKind(OperationType type) { +WorkflowNode::Kind NumericOperationNode::OperationTypeToNodeKind(OperationType type) +{ switch (type) { case Addition: return KD_NumericAddition; case Subtraction: return KD_NumericSubtraction; @@ -18,7 +19,8 @@ WorkflowNode::Kind NumericOperationNode::OperationTypeToNodeKind(OperationType t } } -NumericOperationNode::OperationType NumericOperationNode::NodeKindToOperationType(Kind kind) { +NumericOperationNode::OperationType NumericOperationNode::NodeKindToOperationType(Kind kind) +{ switch (kind) { case KD_NumericAddition: return Addition; case KD_NumericSubtraction: return Subtraction; @@ -28,13 +30,15 @@ NumericOperationNode::OperationType NumericOperationNode::NodeKindToOperationTyp } } -bool NumericOperationNode::IsInstance(const WorkflowNode* node) { +bool NumericOperationNode::IsInstance(const WorkflowNode* node) +{ return node->GetKind() >= KD_NumericAddition && node->GetKind() <= KD_NumericDivision; } NumericOperationNode::NumericOperationNode(OperationType type) : WorkflowNode(OperationTypeToNodeKind(type)) - , mType{ type } { + , mType{ type } +{ mInputs.resize(2); mInputs[0].MatchingType = BaseValue::KD_Numeric; mInputs[1].MatchingType = BaseValue::KD_Numeric; @@ -43,7 +47,8 @@ NumericOperationNode::NumericOperationNode(OperationType type) mOutputs[0].MatchingType = BaseValue::KD_Numeric; } -void NumericOperationNode::Evaluate(WorkflowEvaluationContext& ctx) { +void NumericOperationNode::Evaluate(WorkflowEvaluationContext& ctx) +{ auto lhsVal = dyn_cast<NumericValue>(ctx.GetConnectionValue(mInputs[0])); if (!lhsVal) return; double lhs = lhsVal->GetValue(); @@ -74,13 +79,16 @@ void NumericOperationNode::Evaluate(WorkflowEvaluationContext& ctx) { ctx.SetConnectionValue(mOutputs[0], std::move(value)); } -bool NumericExpressionNode::IsInstance(const WorkflowNode* node) { +bool NumericExpressionNode::IsInstance(const WorkflowNode* node) +{ return node->GetKind() == KD_NumericExpression; } NumericExpressionNode::NumericExpressionNode() - : WorkflowNode(KD_NumericExpression) { + : WorkflowNode(KD_NumericExpression) +{ } -void NumericExpressionNode::Evaluate(WorkflowEvaluationContext& ctx) { +void NumericExpressionNode::Evaluate(WorkflowEvaluationContext& ctx) +{ } diff --git a/core/src/Model/Workflow/Nodes/NumericNodes.hpp b/core/src/Model/Workflow/Nodes/NumericNodes.hpp index 32610f6..56c0313 100644 --- a/core/src/Model/Workflow/Nodes/NumericNodes.hpp +++ b/core/src/Model/Workflow/Nodes/NumericNodes.hpp @@ -7,9 +7,11 @@ #include <variant> #include <vector> -class NumericOperationNode : public WorkflowNode { +class NumericOperationNode : public WorkflowNode +{ public: - enum OperationType { + enum OperationType + { Addition, Subtraction, Multiplication, @@ -31,7 +33,8 @@ public: virtual void Evaluate(WorkflowEvaluationContext& ctx) override; }; -class NumericExpressionNode : public WorkflowNode { +class NumericExpressionNode : public WorkflowNode +{ public: static bool IsInstance(const WorkflowNode* node); NumericExpressionNode(); diff --git a/core/src/Model/Workflow/Nodes/TextNodes.cpp b/core/src/Model/Workflow/Nodes/TextNodes.cpp index 72bd666..944fc07 100644 --- a/core/src/Model/Workflow/Nodes/TextNodes.cpp +++ b/core/src/Model/Workflow/Nodes/TextNodes.cpp @@ -11,10 +11,12 @@ #include <variant> #include <vector> -class TextFormatterNode::Impl { +class TextFormatterNode::Impl +{ public: template <class TFunction> - static void ForArguments(std::vector<Element>::iterator begin, std::vector<Element>::iterator end, const TFunction& func) { + static void ForArguments(std::vector<Element>::iterator begin, std::vector<Element>::iterator end, const TFunction& func) + { for (auto it = begin; it != end; ++it) { auto& elm = *it; if (auto arg = std::get_if<Argument>(&elm)) { @@ -24,7 +26,8 @@ public: } /// Find the pin index that the \c elmIdx -th element should have, based on the elements coming before it. - static int FindPinForElement(const std::vector<Element>& vec, int elmIdx) { + static int FindPinForElement(const std::vector<Element>& vec, int elmIdx) + { for (int i = elmIdx; i >= 0; --i) { auto& elm = vec[i]; if (auto arg = std::get_if<Argument>(&elm)) { @@ -35,7 +38,8 @@ public: } }; -BaseValue::Kind TextFormatterNode::ArgumentTypeToValueKind(TextFormatterNode::ArgumentType arg) { +BaseValue::Kind TextFormatterNode::ArgumentTypeToValueKind(TextFormatterNode::ArgumentType arg) +{ switch (arg) { case NumericArgument: return BaseValue::KD_Numeric; case TextArgument: return BaseValue::KD_Text; @@ -44,23 +48,28 @@ BaseValue::Kind TextFormatterNode::ArgumentTypeToValueKind(TextFormatterNode::Ar } } -bool TextFormatterNode::IsInstance(const WorkflowNode* node) { +bool TextFormatterNode::IsInstance(const WorkflowNode* node) +{ return node->GetKind() == KD_TextFormatting; } TextFormatterNode::TextFormatterNode() - : WorkflowNode(KD_TextFormatting) { + : WorkflowNode(KD_TextFormatting) +{ } -int TextFormatterNode::GetElementCount() const { +int TextFormatterNode::GetElementCount() const +{ return mElements.size(); } -const TextFormatterNode::Element& TextFormatterNode::GetElement(int idx) const { +const TextFormatterNode::Element& TextFormatterNode::GetElement(int idx) const +{ return mElements[idx]; } -void TextFormatterNode::SetElement(int idx, std::string text) { +void TextFormatterNode::SetElement(int idx, std::string text) +{ assert(idx >= 0 && idx < mElements.size()); std::visit( @@ -74,7 +83,8 @@ void TextFormatterNode::SetElement(int idx, std::string text) { mElements[idx] = std::move(text); } -void TextFormatterNode::SetElement(int idx, ArgumentType argument) { +void TextFormatterNode::SetElement(int idx, ArgumentType argument) +{ assert(idx >= 0 && idx < mElements.size()); std::visit( @@ -106,7 +116,8 @@ void TextFormatterNode::SetElement(int idx, ArgumentType argument) { mElements[idx]); } -void TextFormatterNode::InsertElement(int idx, std::string text) { +void TextFormatterNode::InsertElement(int idx, std::string text) +{ assert(idx >= 0); if (idx >= mElements.size()) AppendElement(std::move(text)); @@ -114,7 +125,8 @@ void TextFormatterNode::InsertElement(int idx, std::string text) { mElements.insert(mElements.begin() + idx, std::move(text)); } -void TextFormatterNode::InsertElement(int idx, ArgumentType argument) { +void TextFormatterNode::InsertElement(int idx, ArgumentType argument) +{ assert(idx >= 0); if (idx >= mElements.size()) AppendElement(argument); @@ -133,12 +145,14 @@ void TextFormatterNode::InsertElement(int idx, ArgumentType argument) { }); } -void TextFormatterNode::AppendElement(std::string text) { +void TextFormatterNode::AppendElement(std::string text) +{ mMinOutputChars += text.size(); mElements.push_back(std::move(text)); } -void TextFormatterNode::AppendElement(ArgumentType argument) { +void TextFormatterNode::AppendElement(ArgumentType argument) +{ int pinIdx = mInputs.size(); // Create pin mInputs.push_back(InputPin{}); @@ -150,7 +164,8 @@ void TextFormatterNode::AppendElement(ArgumentType argument) { }); } -void TextFormatterNode::RemoveElement(int idx) { +void TextFormatterNode::RemoveElement(int idx) +{ assert(idx >= 0 && idx < mElements.size()); PreRemoveElement(idx); @@ -160,7 +175,8 @@ void TextFormatterNode::RemoveElement(int idx) { mElements.erase(mElements.begin() + idx); } -void TextFormatterNode::Evaluate(WorkflowEvaluationContext& ctx) { +void TextFormatterNode::Evaluate(WorkflowEvaluationContext& ctx) +{ std::string result; result.reserve((size_t)(mMinOutputChars * 1.5f)); @@ -201,7 +217,8 @@ void TextFormatterNode::Evaluate(WorkflowEvaluationContext& ctx) { } } -void TextFormatterNode::PreRemoveElement(int idx) { +void TextFormatterNode::PreRemoveElement(int idx) +{ auto& elm = mElements[idx]; if (auto arg = std::get_if<Argument>(&elm)) { RemoveInputPin(arg->PinIdx); diff --git a/core/src/Model/Workflow/Nodes/TextNodes.hpp b/core/src/Model/Workflow/Nodes/TextNodes.hpp index 278db32..1beb145 100644 --- a/core/src/Model/Workflow/Nodes/TextNodes.hpp +++ b/core/src/Model/Workflow/Nodes/TextNodes.hpp @@ -7,9 +7,11 @@ #include <variant> #include <vector> -class TextFormatterNode : public WorkflowNode { +class TextFormatterNode : public WorkflowNode +{ public: - enum ArgumentType { + enum ArgumentType + { NumericArgument, TextArgument, DateTimeArgument, @@ -18,7 +20,8 @@ public: private: class Impl; - struct Argument { + struct Argument + { ArgumentType ArgumentType; int PinIdx; }; diff --git a/core/src/Model/Workflow/Nodes/UserInputNodes.cpp b/core/src/Model/Workflow/Nodes/UserInputNodes.cpp index 435cf6d..3a30631 100644 --- a/core/src/Model/Workflow/Nodes/UserInputNodes.cpp +++ b/core/src/Model/Workflow/Nodes/UserInputNodes.cpp @@ -3,24 +3,30 @@ #include "Model/Workflow/Evaluation.hpp" #include "Model/Workflow/Values/BasicValues.hpp" -bool FormInputNode::IsInstance(const WorkflowNode* node) { +bool FormInputNode::IsInstance(const WorkflowNode* node) +{ return node->GetKind() == KD_FormInput; } FormInputNode::FormInputNode() - : WorkflowNode(KD_FormInput) { + : WorkflowNode(KD_FormInput) +{ } -void FormInputNode::Evaluate(WorkflowEvaluationContext& ctx) { +void FormInputNode::Evaluate(WorkflowEvaluationContext& ctx) +{ } -bool DatabaseRowsInputNode::IsInstance(const WorkflowNode* node) { +bool DatabaseRowsInputNode::IsInstance(const WorkflowNode* node) +{ return node->GetKind() == KD_DatabaseRowsInput; } DatabaseRowsInputNode::DatabaseRowsInputNode() - : WorkflowNode(KD_DatabaseRowsInput) { + : WorkflowNode(KD_DatabaseRowsInput) +{ } -void DatabaseRowsInputNode::Evaluate(WorkflowEvaluationContext& ctx) { +void DatabaseRowsInputNode::Evaluate(WorkflowEvaluationContext& ctx) +{ } diff --git a/core/src/Model/Workflow/Nodes/UserInputNodes.hpp b/core/src/Model/Workflow/Nodes/UserInputNodes.hpp index fe66cb4..10ea95d 100644 --- a/core/src/Model/Workflow/Nodes/UserInputNodes.hpp +++ b/core/src/Model/Workflow/Nodes/UserInputNodes.hpp @@ -2,7 +2,8 @@ #include "Model/Workflow/Workflow.hpp" -class FormInputNode : public WorkflowNode { +class FormInputNode : public WorkflowNode +{ public: static bool IsInstance(const WorkflowNode* node); FormInputNode(); @@ -11,7 +12,8 @@ public: virtual void Evaluate(WorkflowEvaluationContext& ctx) override; }; -class DatabaseRowsInputNode : public WorkflowNode { +class DatabaseRowsInputNode : public WorkflowNode +{ public: static bool IsInstance(const WorkflowNode* node); DatabaseRowsInputNode(); diff --git a/core/src/Model/Workflow/Value.hpp b/core/src/Model/Workflow/Value.hpp index 2748e16..6cd42f3 100644 --- a/core/src/Model/Workflow/Value.hpp +++ b/core/src/Model/Workflow/Value.hpp @@ -3,9 +3,11 @@ #include <iosfwd> #include <memory> -class BaseValue { +class BaseValue +{ public: - enum Kind { + enum Kind + { KD_Numeric, KD_Text, KD_DateTime, diff --git a/core/src/Model/Workflow/Value_Main.cpp b/core/src/Model/Workflow/Value_Main.cpp index 2e64987..fdd2fd5 100644 --- a/core/src/Model/Workflow/Value_Main.cpp +++ b/core/src/Model/Workflow/Value_Main.cpp @@ -1,19 +1,24 @@ #include "Value.hpp" BaseValue::BaseValue(Kind kind) - : mKind{ kind } { + : mKind{ kind } +{ } -BaseValue::Kind BaseValue::GetKind() const { +BaseValue::Kind BaseValue::GetKind() const +{ return mKind; } -bool BaseValue::SupportsConstant() const { +bool BaseValue::SupportsConstant() const +{ return false; } -void BaseValue::ReadFrom(std::istream& stream) { +void BaseValue::ReadFrom(std::istream& stream) +{ } -void BaseValue::WriteTo(std::ostream& stream) { +void BaseValue::WriteTo(std::ostream& stream) +{ } diff --git a/core/src/Model/Workflow/Value_RTTI.cpp b/core/src/Model/Workflow/Value_RTTI.cpp index 2a1ac39..a660557 100644 --- a/core/src/Model/Workflow/Value_RTTI.cpp +++ b/core/src/Model/Workflow/Value_RTTI.cpp @@ -3,7 +3,8 @@ #include "Model/Workflow/Values/BasicValues.hpp" #include "Utils/Macros.hpp" -const char* BaseValue::FormatKind(Kind kind) { +const char* BaseValue::FormatKind(Kind kind) +{ switch (kind) { case KD_Numeric: return "Numeric"; case KD_Text: return "Text"; @@ -12,7 +13,8 @@ const char* BaseValue::FormatKind(Kind kind) { } } -std::unique_ptr<BaseValue> BaseValue::CreateByKind(BaseValue::Kind kind) { +std::unique_ptr<BaseValue> BaseValue::CreateByKind(BaseValue::Kind kind) +{ switch (kind) { case KD_Numeric: return std::make_unique<NumericValue>(); case KD_Text: return std::make_unique<TextValue>(); diff --git a/core/src/Model/Workflow/Values/BasicValues.cpp b/core/src/Model/Workflow/Values/BasicValues.cpp index 11d30b7..3f58de8 100644 --- a/core/src/Model/Workflow/Values/BasicValues.cpp +++ b/core/src/Model/Workflow/Values/BasicValues.cpp @@ -3,16 +3,19 @@ #include <charconv> #include <limits> -bool NumericValue::IsInstance(const BaseValue* value) { +bool NumericValue::IsInstance(const BaseValue* value) +{ return value->GetKind() == KD_Numeric; } NumericValue::NumericValue() - : BaseValue(BaseValue::KD_Numeric) { + : BaseValue(BaseValue::KD_Numeric) +{ } template <class T> -static std::string NumberToString(T value) { +static std::string NumberToString(T value) +{ constexpr auto kSize = std::numeric_limits<T>::max_digits10; char buf[kSize]; @@ -24,55 +27,68 @@ static std::string NumberToString(T value) { } } -std::string NumericValue::GetTruncatedString() const { +std::string NumericValue::GetTruncatedString() const +{ return ::NumberToString((int64_t)mValue); } -std::string NumericValue::GetRoundedString() const { +std::string NumericValue::GetRoundedString() const +{ return ::NumberToString((int64_t)std::round(mValue)); } -std::string NumericValue::GetString() const { +std::string NumericValue::GetString() const +{ return ::NumberToString(mValue); } -int64_t NumericValue::GetInt() const { +int64_t NumericValue::GetInt() const +{ return static_cast<int64_t>(mValue); } -double NumericValue::GetValue() const { +double NumericValue::GetValue() const +{ return mValue; } -void NumericValue::SetValue(double value) { +void NumericValue::SetValue(double value) +{ mValue = value; } -bool TextValue::IsInstance(const BaseValue* value) { +bool TextValue::IsInstance(const BaseValue* value) +{ return value->GetKind() == KD_Text; } TextValue::TextValue() - : BaseValue(BaseValue::KD_Text) { + : BaseValue(BaseValue::KD_Text) +{ } -const std::string& TextValue::GetValue() const { +const std::string& TextValue::GetValue() const +{ return mValue; } -void TextValue::SetValue(const std::string& value) { +void TextValue::SetValue(const std::string& value) +{ mValue = value; } -bool DateTimeValue::IsInstance(const BaseValue* value) { +bool DateTimeValue::IsInstance(const BaseValue* value) +{ return value->GetKind() == KD_DateTime; } DateTimeValue::DateTimeValue() - : BaseValue(BaseValue::KD_DateTime) { + : BaseValue(BaseValue::KD_DateTime) +{ } -std::string DateTimeValue::GetString() const { +std::string DateTimeValue::GetString() const +{ namespace chrono = std::chrono; auto t = chrono::system_clock::to_time_t(mValue); @@ -82,10 +98,12 @@ std::string DateTimeValue::GetString() const { return std::string(data); } -const std::chrono::time_point<std::chrono::system_clock>& DateTimeValue::GetValue() const { +const std::chrono::time_point<std::chrono::system_clock>& DateTimeValue::GetValue() const +{ return mValue; } -void DateTimeValue::SetValue(const std::chrono::time_point<std::chrono::system_clock>& value) { +void DateTimeValue::SetValue(const std::chrono::time_point<std::chrono::system_clock>& value) +{ mValue = value; } diff --git a/core/src/Model/Workflow/Values/BasicValues.hpp b/core/src/Model/Workflow/Values/BasicValues.hpp index e2e990d..795876e 100644 --- a/core/src/Model/Workflow/Values/BasicValues.hpp +++ b/core/src/Model/Workflow/Values/BasicValues.hpp @@ -6,7 +6,8 @@ #include <cstdint> #include <string> -class NumericValue : public BaseValue { +class NumericValue : public BaseValue +{ private: double mValue; @@ -23,7 +24,8 @@ public: void SetValue(double value); }; -class TextValue : public BaseValue { +class TextValue : public BaseValue +{ private: std::string mValue; @@ -35,7 +37,8 @@ public: void SetValue(const std::string& value); }; -class DateTimeValue : public BaseValue { +class DateTimeValue : public BaseValue +{ private: std::chrono::time_point<std::chrono::system_clock> mValue; diff --git a/core/src/Model/Workflow/Workflow.hpp b/core/src/Model/Workflow/Workflow.hpp index 139a96e..f26fff9 100644 --- a/core/src/Model/Workflow/Workflow.hpp +++ b/core/src/Model/Workflow/Workflow.hpp @@ -14,16 +14,19 @@ #include <variant> #include <vector> -class WorkflowConnection { +class WorkflowConnection +{ public: static constexpr auto kInvalidId = std::numeric_limits<size_t>::max(); - enum Direction { + enum Direction + { ManyToOne, OneToMany, }; - struct ConnectionPoint { + struct ConnectionPoint + { size_t Node; int Pin; @@ -48,17 +51,20 @@ public: void WriteTo(std::ostream& stream); }; -class WorkflowNode { +class WorkflowNode +{ public: static constexpr auto kInvalidId = std::numeric_limits<size_t>::max(); - enum Type { + enum Type + { InputType, TransformType, OutputType, }; - enum Kind { + enum Kind + { KD_NumericAddition, KD_NumericSubtraction, KD_NumericMultiplication, @@ -74,7 +80,8 @@ public: }; protected: - struct InputPin { + struct InputPin + { size_t Connection = WorkflowConnection::kInvalidId; BaseValue::Kind MatchingType = BaseValue::InvalidKind; bool ConnectionToConst = false; @@ -87,7 +94,8 @@ protected: WorkflowConnection::Direction GetSupportedDirection() const; }; - struct OutputPin { + struct OutputPin + { size_t Connection = WorkflowConnection::kInvalidId; BaseValue::Kind MatchingType = BaseValue::InvalidKind; bool AllowsMultipleConnections = false; @@ -165,7 +173,8 @@ protected: void OnDetach() {} }; -class Workflow { +class Workflow +{ private: friend class WorkflowEvaluationContext; @@ -208,12 +217,18 @@ public: /* Graph rebuild */ - struct GraphUpdate_Success {}; - struct GraphUpdate_NoWorkToDo {}; - struct GraphUpdate_UnsatisfiedDependencies { + struct GraphUpdate_Success + { + }; + struct GraphUpdate_NoWorkToDo + { + }; + struct GraphUpdate_UnsatisfiedDependencies + { std::vector<size_t> UnsatisfiedNodes; }; - struct GraphUpdate_UnreachableNodes { + struct GraphUpdate_UnreachableNodes + { std::vector<size_t> UnreachableNodes; }; @@ -228,7 +243,8 @@ public: /* Serialization */ - enum ReadResult { + enum ReadResult + { ReadSuccess, ReadInvalidVersion, }; diff --git a/core/src/Model/Workflow/Workflow_Main.cpp b/core/src/Model/Workflow/Workflow_Main.cpp index 84b4557..c3e3791 100644 --- a/core/src/Model/Workflow/Workflow_Main.cpp +++ b/core/src/Model/Workflow/Workflow_Main.cpp @@ -14,42 +14,49 @@ namespace ImNodes = ax::NodeEditor; WorkflowConnection::WorkflowConnection() : MultiConnections{} , SingleConnection{ WorkflowNode::kInvalidId, -1 } - , ConnectionDirection{ OneToMany } { + , ConnectionDirection{ OneToMany } +{ } -bool WorkflowConnection::IsValid() const { +bool WorkflowConnection::IsValid() const +{ return SingleConnection.Node != WorkflowNode::kInvalidId; } -std::span<WorkflowConnection::ConnectionPoint> WorkflowConnection::GetSourcePoints() { +std::span<WorkflowConnection::ConnectionPoint> WorkflowConnection::GetSourcePoints() +{ switch (ConnectionDirection) { case ManyToOne: return MultiConnections; case OneToMany: return { &SingleConnection, 1 }; } } -std::span<const WorkflowConnection::ConnectionPoint> WorkflowConnection::GetSourcePoints() const { +std::span<const WorkflowConnection::ConnectionPoint> WorkflowConnection::GetSourcePoints() const +{ switch (ConnectionDirection) { case ManyToOne: return MultiConnections; case OneToMany: return { &SingleConnection, 1 }; } } -std::span<WorkflowConnection::ConnectionPoint> WorkflowConnection::GetDestinationPoints() { +std::span<WorkflowConnection::ConnectionPoint> WorkflowConnection::GetDestinationPoints() +{ switch (ConnectionDirection) { case ManyToOne: return { &SingleConnection, 1 }; case OneToMany: return MultiConnections; } } -std::span<const WorkflowConnection::ConnectionPoint> WorkflowConnection::GetDestinationPoints() const { +std::span<const WorkflowConnection::ConnectionPoint> WorkflowConnection::GetDestinationPoints() const +{ switch (ConnectionDirection) { case ManyToOne: return { &SingleConnection, 1 }; case OneToMany: return MultiConnections; } } -static void DrawConnectionPoints(const std::vector<WorkflowConnection::ConnectionPoint>& points, const char* pinHint) { +static void DrawConnectionPoints(const std::vector<WorkflowConnection::ConnectionPoint>& points, const char* pinHint) +{ ImGui::Indent(32.0f); for (auto& pt : points) { ImGui::Text("{ Node = %llu, Pin (%s) = %d }", pt.Node, pinHint, pt.Pin); @@ -60,13 +67,15 @@ static void DrawConnectionPoints(const std::vector<WorkflowConnection::Connectio ImGui::Unindent(); } -static void DrawConnectionPoint(const WorkflowConnection::ConnectionPoint& point, const char* pinHint) { +static void DrawConnectionPoint(const WorkflowConnection::ConnectionPoint& point, const char* pinHint) +{ ImGui::Indent(32.0f); ImGui::Text("{ Node = %llu, Pin (%s) = %d }", point.Node, pinHint, point.Pin); ImGui::Unindent(); } -void WorkflowConnection::DrawDebugInfo() const { +void WorkflowConnection::DrawDebugInfo() const +{ ImGui::BeginTooltip(); switch (ConnectionDirection) { case ManyToOne: { @@ -88,14 +97,16 @@ void WorkflowConnection::DrawDebugInfo() const { ImGui::EndTooltip(); } -static WorkflowConnection::ConnectionPoint ReadConnectionPoint(std::istream& stream) { +static WorkflowConnection::ConnectionPoint ReadConnectionPoint(std::istream& stream) +{ WorkflowConnection::ConnectionPoint pt; stream >> pt.Node; stream >> pt.Pin; return pt; } -void WorkflowConnection::ReadFrom(std::istream& stream) { +void WorkflowConnection::ReadFrom(std::istream& stream) +{ int n; stream >> n; ConnectionDirection = (Direction)n; @@ -109,12 +120,14 @@ void WorkflowConnection::ReadFrom(std::istream& stream) { } } -static void WriteConnectionPoint(std::ostream& stream, const WorkflowConnection::ConnectionPoint& pt) { +static void WriteConnectionPoint(std::ostream& stream, const WorkflowConnection::ConnectionPoint& pt) +{ stream << pt.Node; stream << pt.Pin; } -void WorkflowConnection::WriteTo(std::ostream& stream) { +void WorkflowConnection::WriteTo(std::ostream& stream) +{ stream << (int)ConnectionDirection; ::WriteConnectionPoint(stream, SingleConnection); stream << (size_t)MultiConnections.size(); @@ -123,60 +136,74 @@ void WorkflowConnection::WriteTo(std::ostream& stream) { } } -bool WorkflowNode::InputPin::IsConstantConnection() const { +bool WorkflowNode::InputPin::IsConstantConnection() const +{ return ConnectionToConst && IsConnected(); } -bool WorkflowNode::InputPin::IsConnected() const { +bool WorkflowNode::InputPin::IsConnected() const +{ return Connection != WorkflowConnection::kInvalidId; } -BaseValue::Kind WorkflowNode::InputPin::GetMatchingType() const { +BaseValue::Kind WorkflowNode::InputPin::GetMatchingType() const +{ return MatchingType; } -WorkflowConnection::Direction WorkflowNode::InputPin::GetSupportedDirection() const { +WorkflowConnection::Direction WorkflowNode::InputPin::GetSupportedDirection() const +{ return AllowsMultipleConnections ? WorkflowConnection::ManyToOne : WorkflowConnection::OneToMany; } -bool WorkflowNode::OutputPin::IsConnected() const { +bool WorkflowNode::OutputPin::IsConnected() const +{ return Connection != WorkflowConnection::kInvalidId; } -BaseValue::Kind WorkflowNode::OutputPin::GetMatchingType() const { +BaseValue::Kind WorkflowNode::OutputPin::GetMatchingType() const +{ return MatchingType; } -WorkflowConnection::Direction WorkflowNode::OutputPin::GetSupportedDirection() const { +WorkflowConnection::Direction WorkflowNode::OutputPin::GetSupportedDirection() const +{ return AllowsMultipleConnections ? WorkflowConnection::OneToMany : WorkflowConnection::ManyToOne; } WorkflowNode::WorkflowNode(Kind kind) : mKind{ kind } - , mDepth{ -1 } { + , mDepth{ -1 } +{ } -Vec2i WorkflowNode::GetPosition() const { +Vec2i WorkflowNode::GetPosition() const +{ return mPosition; } -void WorkflowNode::SetPosition(const Vec2i& position) { +void WorkflowNode::SetPosition(const Vec2i& position) +{ mPosition = position; } -size_t WorkflowNode::GetId() const { +size_t WorkflowNode::GetId() const +{ return mId; } -WorkflowNode::Kind WorkflowNode::GetKind() const { +WorkflowNode::Kind WorkflowNode::GetKind() const +{ return mKind; } -int WorkflowNode::GetDepth() const { +int WorkflowNode::GetDepth() const +{ return mDepth; } -WorkflowNode::Type WorkflowNode::GetType() const { +WorkflowNode::Type WorkflowNode::GetType() const +{ if (IsInputNode()) { return InputType; } else if (IsOutputNode()) { @@ -186,39 +213,48 @@ WorkflowNode::Type WorkflowNode::GetType() const { } } -bool WorkflowNode::IsInputNode() const { +bool WorkflowNode::IsInputNode() const +{ return mInputs.size() == 0; } -bool WorkflowNode::IsOutputNode() const { +bool WorkflowNode::IsOutputNode() const +{ return mOutputs.size() == 0; } -void WorkflowNode::ConnectInput(int nodeId, WorkflowNode& output, int outputNodeId) { +void WorkflowNode::ConnectInput(int nodeId, WorkflowNode& output, int outputNodeId) +{ mWorkflow->Connect(*this, nodeId, output, outputNodeId); } -void WorkflowNode::DisconnectInput(int nodeId) { +void WorkflowNode::DisconnectInput(int nodeId) +{ mWorkflow->DisconnectByDestination(*this, nodeId); } -bool WorkflowNode::IsInputConnected(int nodeId) const { +bool WorkflowNode::IsInputConnected(int nodeId) const +{ return mInputs[nodeId].IsConnected(); } -void WorkflowNode::ConnectOutput(int nodeId, WorkflowNode& input, int inputNodeId) { +void WorkflowNode::ConnectOutput(int nodeId, WorkflowNode& input, int inputNodeId) +{ mWorkflow->Connect(input, inputNodeId, *this, nodeId); } -void WorkflowNode::DisconnectOutput(int nodeId) { +void WorkflowNode::DisconnectOutput(int nodeId) +{ mWorkflow->DisconnectBySource(*this, nodeId); } -bool WorkflowNode::IsOutputConnected(int nodeId) const { +bool WorkflowNode::IsOutputConnected(int nodeId) const +{ return mOutputs[nodeId].IsConnected(); } -void WorkflowNode::Draw() { +void WorkflowNode::Draw() +{ for (size_t i = 0; i < mInputs.size(); ++i) { auto& pin = mInputs[i]; ImNodes::BeginPin(i, ImNodes::PinKind::Input); @@ -233,7 +269,8 @@ void WorkflowNode::Draw() { } } -void WorkflowNode::DrawDebugInfo() const { +void WorkflowNode::DrawDebugInfo() const +{ ImGui::BeginTooltip(); ImGui::Text("Node kind: %s", FormatKind(mKind)); ImGui::Text("Node type: %s", FormatType(GetType())); @@ -243,17 +280,20 @@ void WorkflowNode::DrawDebugInfo() const { ImGui::EndTooltip(); } -void WorkflowNode::ReadFrom(std::istream& stream) { +void WorkflowNode::ReadFrom(std::istream& stream) +{ stream >> mId; stream >> mPosition.x >> mPosition.y; } -void WorkflowNode::WriteTo(std::ostream& stream) { +void WorkflowNode::WriteTo(std::ostream& stream) +{ stream << mId; stream << mPosition.x << mPosition.y; } -WorkflowNode::InputPin& WorkflowNode::InsertInputPin(int atIdx) { +WorkflowNode::InputPin& WorkflowNode::InsertInputPin(int atIdx) +{ assert(atIdx >= 0 && atIdx < mInputs.size()); mInputs.push_back(InputPin{}); @@ -264,7 +304,8 @@ WorkflowNode::InputPin& WorkflowNode::InsertInputPin(int atIdx) { return mInputs[atIdx]; } -void WorkflowNode::RemoveInputPin(int pin) { +void WorkflowNode::RemoveInputPin(int pin) +{ DisconnectInput(pin); for (int i = 0, end = (int)mInputs.size() - 1; i < end; ++i) { SwapInputPin(i, i + 1); @@ -272,7 +313,8 @@ void WorkflowNode::RemoveInputPin(int pin) { mInputs.resize(mInputs.size() - 1); } -void WorkflowNode::SwapInputPin(int a, int b) { +void WorkflowNode::SwapInputPin(int a, int b) +{ auto& pinA = mInputs[a]; auto& pinB = mInputs[b]; @@ -300,7 +342,8 @@ void WorkflowNode::SwapInputPin(int a, int b) { std::swap(pinA, pinB); } -WorkflowNode::OutputPin& WorkflowNode::InsertOutputPin(int atIdx) { +WorkflowNode::OutputPin& WorkflowNode::InsertOutputPin(int atIdx) +{ assert(atIdx >= 0 && atIdx < mOutputs.size()); mOutputs.push_back(OutputPin{}); @@ -311,7 +354,8 @@ WorkflowNode::OutputPin& WorkflowNode::InsertOutputPin(int atIdx) { return mOutputs[atIdx]; } -void WorkflowNode::RemoveOutputPin(int pin) { +void WorkflowNode::RemoveOutputPin(int pin) +{ DisconnectOutput(pin); for (int i = 0, end = (int)mOutputs.size() - 1; i < end; ++i) { SwapInputPin(i, i + 1); @@ -319,7 +363,8 @@ void WorkflowNode::RemoveOutputPin(int pin) { mOutputs.resize(mOutputs.size() - 1); } -void WorkflowNode::SwapOutputPin(int a, int b) { +void WorkflowNode::SwapOutputPin(int a, int b) +{ auto& pinA = mOutputs[a]; auto& pinB = mOutputs[b]; @@ -346,51 +391,63 @@ void WorkflowNode::SwapOutputPin(int a, int b) { std::swap(pinA, pinB); } -const std::vector<WorkflowConnection>& Workflow::GetConnections() const { +const std::vector<WorkflowConnection>& Workflow::GetConnections() const +{ return mConnections; } -std::vector<WorkflowConnection>& Workflow::GetConnections() { +std::vector<WorkflowConnection>& Workflow::GetConnections() +{ return mConnections; } -const std::vector<std::unique_ptr<WorkflowNode>>& Workflow::GetNodes() const { +const std::vector<std::unique_ptr<WorkflowNode>>& Workflow::GetNodes() const +{ return mNodes; } -std::vector<std::unique_ptr<WorkflowNode>>& Workflow::GetNodes() { +std::vector<std::unique_ptr<WorkflowNode>>& Workflow::GetNodes() +{ return mNodes; } -const std::vector<std::unique_ptr<BaseValue>>& Workflow::GetConstants() const { +const std::vector<std::unique_ptr<BaseValue>>& Workflow::GetConstants() const +{ return mConstants; } -std::vector<std::unique_ptr<BaseValue>>& Workflow::GetConstants() { +std::vector<std::unique_ptr<BaseValue>>& Workflow::GetConstants() +{ return mConstants; } -WorkflowConnection* Workflow::GetConnectionById(size_t id) { +WorkflowConnection* Workflow::GetConnectionById(size_t id) +{ return &mConnections[id]; } -WorkflowNode* Workflow::GetStepById(size_t id) { +WorkflowNode* Workflow::GetStepById(size_t id) +{ return mNodes[id].get(); } -BaseValue* Workflow::GetConstantById(size_t id) { +BaseValue* Workflow::GetConstantById(size_t id) +{ return mConstants[id].get(); } -const std::vector<std::vector<size_t>>& Workflow::GetDepthGroups() const { +const std::vector<std::vector<size_t>>& Workflow::GetDepthGroups() const +{ return mDepthGroups; } -bool Workflow::DoesDepthNeedsUpdate() const { +bool Workflow::DoesDepthNeedsUpdate() const +{ return mDepthsDirty; } -void Workflow::AddStep(std::unique_ptr<WorkflowNode> step) { +void Workflow::AddStep(std::unique_ptr<WorkflowNode> step) +{ auto [storage, id] = AllocWorkflowStep(); storage = std::move(step); storage->OnAttach(*this, id); @@ -398,7 +455,8 @@ void Workflow::AddStep(std::unique_ptr<WorkflowNode> step) { storage->mId = id; } -void Workflow::RemoveStep(size_t id) { +void Workflow::RemoveStep(size_t id) +{ auto& step = mNodes[id]; if (step == nullptr) return; @@ -407,7 +465,8 @@ void Workflow::RemoveStep(size_t id) { step->mId = WorkflowNode::kInvalidId; } -void Workflow::RemoveConnection(size_t id) { +void Workflow::RemoveConnection(size_t id) +{ auto& conn = mConnections[id]; if (!conn.IsValid()) return; @@ -426,7 +485,8 @@ void Workflow::RemoveConnection(size_t id) { mDepthsDirty = true; } -bool Workflow::Connect(WorkflowNode& sourceNode, int sourcePin, WorkflowNode& destinationNode, int destinationPin) { +bool Workflow::Connect(WorkflowNode& sourceNode, int sourcePin, WorkflowNode& destinationNode, int destinationPin) +{ auto& src = sourceNode.mOutputs[sourcePin]; auto& dst = destinationNode.mInputs[destinationPin]; @@ -496,7 +556,8 @@ bool Workflow::Connect(WorkflowNode& sourceNode, int sourcePin, WorkflowNode& de // TODO cleanup these two implementation -bool Workflow::DisconnectBySource(WorkflowNode& sourceNode, int sourcePin) { +bool Workflow::DisconnectBySource(WorkflowNode& sourceNode, int sourcePin) +{ auto& sp = sourceNode.mOutputs[sourcePin]; if (!sp.IsConnected()) return false; @@ -530,7 +591,8 @@ bool Workflow::DisconnectBySource(WorkflowNode& sourceNode, int sourcePin) { return true; } -bool Workflow::DisconnectByDestination(WorkflowNode& destinationNode, int destinationPin) { +bool Workflow::DisconnectByDestination(WorkflowNode& destinationNode, int destinationPin) +{ auto& dp = destinationNode.mInputs[destinationPin]; if (!dp.IsConnected()) return false; if (dp.IsConstantConnection()) { @@ -569,7 +631,8 @@ bool Workflow::DisconnectByDestination(WorkflowNode& destinationNode, int destin return true; } -Workflow::GraphUpdateResult Workflow::UpdateGraph(bool getInfo) { +Workflow::GraphUpdateResult Workflow::UpdateGraph(bool getInfo) +{ if (!mDepthsDirty) { return GraphUpdate_NoWorkToDo{}; } @@ -578,7 +641,8 @@ Workflow::GraphUpdateResult Workflow::UpdateGraph(bool getInfo) { // - Dependency = nodes its input pins are connected to // - Dependents = nodes its output pins are connected to - struct WorkingNode { + struct WorkingNode + { // The max depth out of all dependency nodes, maintained during the traversal and committed as the actual depth // when all dependencies of this node has been resolved. Add 1 to get the depth that will be assigned to the node. int MaximumDepth = 0; @@ -688,7 +752,8 @@ Workflow::GraphUpdateResult Workflow::UpdateGraph(bool getInfo) { return GraphUpdate_Success{}; } -Workflow::ReadResult Workflow::ReadFrom(std::istream& stream) { +Workflow::ReadResult Workflow::ReadFrom(std::istream& stream) +{ auto DeserializeV0 = [&]() { size_t connectionsStorage, nodesStorage, constantsStorage; stream >> connectionsStorage >> nodesStorage >> constantsStorage; @@ -738,7 +803,8 @@ Workflow::ReadResult Workflow::ReadFrom(std::istream& stream) { return ReadSuccess; } -void Workflow::WriteTo(std::ostream& stream) { +void Workflow::WriteTo(std::ostream& stream) +{ // Version stream << (uint64_t)0; @@ -774,7 +840,8 @@ void Workflow::WriteTo(std::ostream& stream) { } } -std::pair<WorkflowConnection&, size_t> Workflow::AllocWorkflowConnection() { +std::pair<WorkflowConnection&, size_t> Workflow::AllocWorkflowConnection() +{ for (size_t idx = 0; idx < mConnections.size(); ++idx) { auto& elm = mConnections[idx]; if (!elm.IsValid()) { @@ -786,7 +853,8 @@ std::pair<WorkflowConnection&, size_t> Workflow::AllocWorkflowConnection() { return { mConnections.emplace_back(WorkflowConnection{}), id }; } -std::pair<std::unique_ptr<WorkflowNode>&, size_t> Workflow::AllocWorkflowStep() { +std::pair<std::unique_ptr<WorkflowNode>&, size_t> Workflow::AllocWorkflowStep() +{ for (size_t idx = 0; idx < mNodes.size(); ++idx) { auto& elm = mNodes[idx]; if (elm == nullptr) { diff --git a/core/src/Model/Workflow/Workflow_RTTI.cpp b/core/src/Model/Workflow/Workflow_RTTI.cpp index e3fafdb..0f8fd2e 100644 --- a/core/src/Model/Workflow/Workflow_RTTI.cpp +++ b/core/src/Model/Workflow/Workflow_RTTI.cpp @@ -8,7 +8,8 @@ #include <memory> -const char* WorkflowNode::FormatKind(Kind kind) { +const char* WorkflowNode::FormatKind(Kind kind) +{ switch (kind) { case KD_NumericAddition: return "NumericOperation (addition)"; case KD_NumericSubtraction: return "NumericOperation (subtraction)"; @@ -24,7 +25,8 @@ const char* WorkflowNode::FormatKind(Kind kind) { } } -const char* WorkflowNode::FormatType(Type type) { +const char* WorkflowNode::FormatType(Type type) +{ switch (type) { case InputType: return "input"; case TransformType: return "transform"; @@ -32,7 +34,8 @@ const char* WorkflowNode::FormatType(Type type) { } } -std::unique_ptr<WorkflowNode> WorkflowNode::CreateByKind(WorkflowNode::Kind kind) { +std::unique_ptr<WorkflowNode> WorkflowNode::CreateByKind(WorkflowNode::Kind kind) +{ switch (kind) { case KD_NumericAddition: return std::make_unique<NumericOperationNode>(NumericOperationNode::Addition); case KD_NumericSubtraction: return std::make_unique<NumericOperationNode>(NumericOperationNode::Subtraction); |