#pragma once #include #include #include #include #include #include "Database.h" #include "Views.h" enum class ErrorCode { Invalid, NotFound, Exists, Database }; // What went wrong, with a message that can be shown to the user as it is. class TrackerError : public std::runtime_error { public: TrackerError(ErrorCode code, const std::string& message); ErrorCode code() const; private: ErrorCode code_; }; // All the rules for changing accounts and tasks. The prompt and the C API are // both thin layers over this class. Each change appends human-readable notes // (what the prompt prints), which takeMessages() hands over. // // How waits work: an account hits its limit until a time ("acc wait"). A task set // to Wait is waiting for that: it shows Wait until then, and when the time passes // the account stops waiting by itself and the task shows Limit reset (the // conversation can be continued). Prompt / Testing tasks are not waiting: they // show as they are, with "(account-waiting)" appended while the account waits. class Tracker { public: explicit Tracker(Database& db); const Database& database() const; // For tests and simulations: pretend the time is `fixedNow`. 0 = real clock. void setClock(std::time_t fixedNow); std::time_t now() const; std::vector takeMessages(); // ---- Accounts ----------------------------------------------------------- void addAccount(const std::string& name); void deleteAccount(const std::string& name); void renameAccount(const std::string& name, const std::string& newName); // The account hit its limit until `until` (or a clock time such as "16:30", // "4:30pm"; a time that has passed today means tomorrow). Tasks set to Wait // follow the new time. void setAccountWait(const std::string& name, std::time_t until); void setAccountWaitText(const std::string& name, const std::string& timeText); // Ends the wait now: its Wait tasks become Limit reset. Returns false if the // account was not waiting. bool clearAccountWait(const std::string& name); // ---- Tasks -------------------------------------------------------------- // `statusText` is what the user would type: "testing", "wait 4pm", "wait"... // nullopt = Prompt. "wait