diff options
Diffstat (limited to 'core/src/Model/Items.hpp')
-rw-r--r-- | core/src/Model/Items.hpp | 253 |
1 files changed, 0 insertions, 253 deletions
diff --git a/core/src/Model/Items.hpp b/core/src/Model/Items.hpp deleted file mode 100644 index 859aedf..0000000 --- a/core/src/Model/Items.hpp +++ /dev/null @@ -1,253 +0,0 @@ -#pragma once - -#include "cplt_fwd.hpp" - -#include <json/reader.h> -#include <json/value.h> -#include <json/writer.h> -#include <tsl/array_map.h> -#include <cstddef> -#include <limits> -#include <stdexcept> -#include <string> -#include <string_view> -#include <utility> -#include <vector> - -template <class T> -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) - { - auto iter = mNameLookup.find(name); - if (iter != mNameLookup.end()) { - throw std::runtime_error("Duplicate key."); - } - - for (size_t i = 0; i < mStorage.size(); ++i) { - if (mStorage[i].IsInvalid()) { - mStorage[i] = T(*this, i, std::move(name), std::forward<Args>(args)...); - mNameLookup.insert(name, i); - return mStorage[i]; - } - } - - size_t id = mStorage.size(); - mNameLookup.insert(name, id); - mStorage.emplace_back(*this, id, std::move(name), std::forward<Args>(args)...); - return mStorage[id]; - } - - void Remove(size_t index) - { - auto& item = mStorage[index]; - mNameLookup.erase(item.GetName()); - mStorage[index] = T(*this); - } - - T* Find(size_t id) - { - return &mStorage[id]; - } - - const T* Find(size_t id) const - { - return &mStorage[id]; - } - - const T* Find(std::string_view name) const - { - auto iter = mNameLookup.find(name); - if (iter != mNameLookup.end()) { - return &mStorage[iter.value()]; - } else { - return nullptr; - } - } - - Json::Value Serialize() const - { - Json::Value items(Json::arrayValue); - for (auto& item : mStorage) { - if (!item.IsInvalid()) { - auto elm = item.Serialize(); - elm["Id"] = item.GetId(); - elm["Name"] = item.GetName(); - items.append(elm); - } - } - - Json::Value root; - root["MaxItemId"] = mStorage.size(); - root["Items"] = std::move(items); - - return root; - } - - ItemList() = default; - - ItemList(const Json::Value& root) - { - constexpr const char* kMessage = "Failed to load item list from JSON."; - - auto& itemCount = root["MaxItemId"]; - if (!itemCount.isIntegral()) throw std::runtime_error(kMessage); - - mStorage.resize(itemCount.asInt64(), T(*this)); - - auto& items = root["Items"]; - if (!items.isArray()) throw std::runtime_error(kMessage); - - for (auto& elm : items) { - if (!elm.isObject()) throw std::runtime_error(kMessage); - - auto& id = elm["Id"]; - if (!id.isIntegral()) throw std::runtime_error(kMessage); - auto& name = elm["Name"]; - if (!name.isString()) throw std::runtime_error(kMessage); - - size_t iid = id.asInt64(); - mStorage[iid] = T(*this, iid, name.asString()); - mStorage[iid].Deserialize(elm); - } - } - - typename decltype(mStorage)::iterator begin() - { - return mStorage.begin(); - } - - typename decltype(mStorage)::iterator end() - { - return mStorage.end(); - } - - typename decltype(mStorage)::const_iterator begin() const - { - return mStorage.begin(); - } - - typename decltype(mStorage)::const_iterator end() const - { - return mStorage.end(); - } - -private: - template <class TSelf> - friend class ItemBase; - - void UpdateItemName(const T& item, const std::string& newName) - { - mNameLookup.erase(item.GetName()); - mNameLookup.insert(newName, item.GetId()); - } -}; - -template <class TSelf> -class ItemBase -{ -private: - ItemList<TSelf>* mList; - size_t mId; - std::string mName; - -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) } - { - } - - bool IsInvalid() const - { - return mId == std::numeric_limits<size_t>::max(); - } - - ItemList<TSelf>& GetList() const - { - return *mList; - } - - size_t GetId() const - { - return mId; - } - - const std::string& GetName() const - { - return mName; - } - - void SetName(std::string name) - { - mList->UpdateItemName(static_cast<TSelf&>(*this), name); - mName = std::move(name); - } -}; - -class ProductItem : public ItemBase<ProductItem> -{ -private: - std::string mDescription; - int mPrice = 0; - int mStock = 0; - -public: - using ItemBase::ItemBase; - - const std::string& GetDescription() const; - void SetDescription(std::string description); - /// Get the price of this item in US cents. - int GetPrice() const; - void SetPrice(int price); - /// Get the current number of this product in warehouse. - /// This is a housekeeping field and shouldn't be editable by the user from the UI. - int GetStock() const; - void SetStock(int stock); - - Json::Value Serialize() const; - void Deserialize(const Json::Value& elm); -}; - -class FactoryItem : public ItemBase<FactoryItem> -{ -private: - std::string mDescription; - std::string mEmail; - -public: - using ItemBase::ItemBase; - - const std::string& GetDescription() const; - void SetDescription(std::string description); - const std::string& GetEmail() const; - void SetEmail(std::string email); - - Json::Value Serialize() const; - void Deserialize(const Json::Value& elm); -}; - -class CustomerItem : public ItemBase<CustomerItem> -{ -private: - std::string mDescription; - std::string mEmail; - -public: - using ItemBase::ItemBase; - - const std::string& GetDescription() const; - void SetDescription(std::string description); - const std::string& GetEmail() const; - void SetEmail(std::string email); - - Json::Value Serialize() const; - void Deserialize(const Json::Value& elm); -}; |