C and Python API + Smarter account-based wait times
This commit is contained in:
1 parent
35c568333d
commit
10badb282c
18 files changed
+2204
-429
No files matched your search
@@ -0,0 +1,83 @@
|
||||
#pragma once
|
||||
|
||||
#include <ctime>
|
||||
#include <optional>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#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 (waits, auto-unwait, status
|
||||
// handling...). 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.
|
||||
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<std::string> 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 hits its limit until `until` (or a clock time such as "16:30",
|
||||
// "4:30pm"; a time that has passed today means tomorrow).
|
||||
void setAccountWait(const std::string& name, std::time_t until);
|
||||
void setAccountWaitText(const std::string& name, const std::string& timeText);
|
||||
// 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, without the auto-unwait that an explicit status triggers.
|
||||
void addTask(const std::string& name, const std::optional<std::string>& account,
|
||||
const std::optional<std::string>& statusText);
|
||||
void deleteTask(const std::string& name);
|
||||
void renameTask(const std::string& name, const std::string& newName);
|
||||
void setTaskAccount(const std::string& name, const std::optional<std::string>& account);
|
||||
void setTaskStatus(const std::string& name, const std::string& statusText);
|
||||
// Returns false (and changes nothing) if the notes are the same already.
|
||||
bool setTaskNotes(const std::string& name, const std::string& notes);
|
||||
|
||||
// ---- Computed views -----------------------------------------------------
|
||||
std::vector<TaskInfo> tasks() const;
|
||||
std::vector<AccountInfo> accounts() const;
|
||||
|
||||
private:
|
||||
static void requireName(const std::string& name);
|
||||
Status parseStatus(const std::string& text) const;
|
||||
std::string existingAccount(const std::string& name) const;
|
||||
TaskRow existingTask(const std::string& name) const;
|
||||
std::optional<std::time_t> runningWait(const std::string& account) const;
|
||||
void resumeAccount(const std::string& account);
|
||||
void makeTaskFollowAccount(const TaskRow& task);
|
||||
void noteAccountWait(const std::string& taskName);
|
||||
void note(const std::string& message);
|
||||
|
||||
Database& db_;
|
||||
std::time_t fixedNow_;
|
||||
std::vector<std::string> messages_;
|
||||
};
|
||||
Reference in new issue
Block a user