Status system reworked
This commit is contained in:
1 parent
33567db5a3
commit
a29ba6e4d2
18 files changed
+326
-345
No files matched your search
@@ -46,8 +46,6 @@ public:
|
||||
void setTaskAccount(const std::string& name, const std::optional<std::string>& account);
|
||||
void setTaskStatus(const std::string& name, const std::string& status);
|
||||
void setTaskNotes(const std::string& name, const std::string& notes);
|
||||
void setTaskWaitOverride(const std::string& name, bool value);
|
||||
void clearWaitOverrides(const std::string& account); // every task of the account follows its wait again
|
||||
|
||||
private:
|
||||
using Param = std::optional<std::string>;
|
||||
|
||||
@@ -8,7 +8,6 @@ struct TaskRow {
|
||||
std::optional<std::string> account;
|
||||
std::string status; // serialized, see StatusUtil::serialize
|
||||
std::string notes; // free text, any length (stored as SQLite TEXT)
|
||||
bool waitOverride = false; // set to Testing / Prompt while its account waits: ignores that wait
|
||||
};
|
||||
|
||||
struct AccountRow {
|
||||
|
||||
+9
-7
@@ -26,14 +26,16 @@ std::optional<Status> parse(const std::string& text, std::time_t now);
|
||||
std::string serialize(const Status& status);
|
||||
std::optional<Status> deserialize(const std::string& text);
|
||||
|
||||
// Prompt and Testing tasks follow their account's wait; Uploading, Frozen and
|
||||
// Done tasks do not.
|
||||
bool followsAccountWait(StatusKind kind);
|
||||
// Prompt and Testing show as they are, with "(account-waiting)" appended while
|
||||
// their account waits. Other statuses are shown without a note.
|
||||
bool showsAccountWaiting(StatusKind kind);
|
||||
|
||||
// The status to show for a task. If its account has a wait, the tasks that
|
||||
// follow it show Wait until then and Limit reset after; otherwise the stored
|
||||
// status is used (see effective).
|
||||
Status resolve(const Status& stored, const std::optional<std::time_t>& accountWait, std::time_t now);
|
||||
// The status to show for a task. A task set to Wait on an account waits for the
|
||||
// account: Wait until the account's wait ends, Limit reset after that (or if the
|
||||
// account is not waiting). `accountWait` is when the account's wait ends (ended).
|
||||
// Everything else shows its stored status (see effective).
|
||||
Status resolve(const Status& stored, bool hasAccount, const std::optional<std::time_t>& accountWait,
|
||||
std::time_t now);
|
||||
|
||||
// The status shown to the user: an expired wait becomes LimitReset.
|
||||
Status effective(const Status& status, std::time_t now);
|
||||
|
||||
+18
-10
@@ -22,10 +22,15 @@ 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.
|
||||
// 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);
|
||||
@@ -43,16 +48,19 @@ public:
|
||||
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).
|
||||
// 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);
|
||||
// Returns false if the account was not waiting.
|
||||
// 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, without the auto-unwait that an explicit status triggers.
|
||||
// nullopt = Prompt. "wait <time>" sets the account's wait too; "wait" alone
|
||||
// joins the account's running wait (and is an error if it is not waiting).
|
||||
void addTask(const std::string& name, const std::optional<std::string>& account,
|
||||
const std::optional<std::string>& statusText);
|
||||
void deleteTask(const std::string& name);
|
||||
@@ -72,8 +80,8 @@ private:
|
||||
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 taskInUse(const std::string& taskName, const std::string& accountName);
|
||||
void makeTaskFollowAccount(const TaskRow& task);
|
||||
void settle();
|
||||
int endAccountWait(const std::string& account, std::time_t endedAt);
|
||||
void note(const std::string& message);
|
||||
|
||||
Database& db_;
|
||||
|
||||
+13
-9
@@ -12,34 +12,38 @@
|
||||
// How taken an account is, judged by its tasks:
|
||||
// Free - only Done, Frozen or Uploading tasks, or no tasks
|
||||
// Taken - has a Prompt task (and nothing Busy)
|
||||
// Busy - has a Testing, Limit reset or Wait task, or a wait nothing else shows
|
||||
// Busy - has a Testing, Limit reset or Wait task, or is waiting itself
|
||||
enum class AccountLevel { Busy, Taken, Free };
|
||||
|
||||
std::string accountLevelName(AccountLevel level); // "busy", "taken", "free"
|
||||
|
||||
enum class WaitState { None, Waiting, LimitReset };
|
||||
// An account waits from the moment it hits its limit until the wait time; after
|
||||
// that it is not waiting any more (its Wait tasks are then Limit reset).
|
||||
enum class WaitState { None, Waiting };
|
||||
|
||||
// A task as the user sees it: the status is computed from the stored status,
|
||||
// the account's wait and the current time.
|
||||
struct TaskInfo {
|
||||
std::string name;
|
||||
std::optional<std::string> account;
|
||||
Status status; // as shown (Wait / Limit reset come from the account)
|
||||
Status status; // as shown (a Wait task becomes Limit reset when its account's wait ends)
|
||||
Status storedStatus; // what is saved underneath
|
||||
// What the panel shows: "Wait 16:30", "Limit reset", "Testing (account-waiting)"...
|
||||
std::string statusLabel;
|
||||
// Prompt / Testing while its account waits: shown as they are, with
|
||||
// "(account-waiting)" appended.
|
||||
bool accountWaiting = false;
|
||||
std::string notes;
|
||||
std::size_t noteLines = 0;
|
||||
// Set to Testing / Prompt while its account waits: it shows its own status
|
||||
// and ignores the wait, while the account's other tasks keep following it.
|
||||
bool overridesWait = false;
|
||||
};
|
||||
|
||||
struct AccountInfo {
|
||||
std::string name;
|
||||
AccountLevel level = AccountLevel::Free;
|
||||
WaitState waitState = WaitState::None;
|
||||
std::time_t waitUntil = 0; // when the wait ends (or ended); 0 if none
|
||||
// True when the account has a wait that none of its tasks shows (it has no
|
||||
// tasks, or only Done / Frozen / Uploading ones). It still makes the account Busy.
|
||||
std::time_t waitUntil = 0; // when the wait ends; 0 if it is not waiting
|
||||
// True when the account is waiting but none of its tasks is set to Wait
|
||||
// (e.g. it has no tasks). It still makes the account Busy.
|
||||
bool waitListed = false;
|
||||
std::vector<std::string> tasks; // tasks at the account's level (Free: its Uploading/Frozen/Done ones)
|
||||
};
|
||||
|
||||
+15
-16
@@ -14,13 +14,13 @@
|
||||
* - Statuses are the text you would type at the prompt: "prompt", "testing",
|
||||
* "uploading", "frozen", "done", "limit-reset", "wait 4:30pm", "wait 16:30"
|
||||
* or just "wait" (only while the task's account is already waiting).
|
||||
* - A wait belongs to the account: setting a task to "wait <time>" sets its
|
||||
* account's wait, and the account's Prompt / Testing tasks then show Wait
|
||||
* until that time and Limit reset after it. A task you explicitly set to
|
||||
* "testing" or "prompt" while the wait is running shows that status instead
|
||||
* (overrides_wait = 1) and the other tasks keep waiting; "wait" makes it follow
|
||||
* the account again. If the wait is already over (Limit reset), setting a task
|
||||
* to testing / prompt clears it: the account is in use again (see the README).
|
||||
* - Waits: an account hits its limit until a time. A task set to "wait" is waiting
|
||||
* for that: "wait <time>" sets the account's wait and marks the task Wait; "wait"
|
||||
* alone marks it Wait while the account is already waiting. When the time passes
|
||||
* the account stops waiting by itself and its Wait tasks show Limit reset (the
|
||||
* conversation can be continued). Prompt / Testing tasks are not waiting: they
|
||||
* keep their status, with "(account-waiting)" added to the label while the
|
||||
* account waits (account_waiting = 1).
|
||||
* - Times are Unix seconds (UTC); clock-time text like "4:30pm" is read in the
|
||||
* local time zone, and a time that has passed today means tomorrow.
|
||||
*
|
||||
@@ -75,8 +75,7 @@ extern "C" {
|
||||
|
||||
/* ---- Account wait states (lls_account_info.wait_state) -------------------- */
|
||||
#define LLS_WAIT_NONE 0
|
||||
#define LLS_WAIT_WAITING 1 /* wait_until is in the future */
|
||||
#define LLS_WAIT_LIMIT_RESET 2 /* wait_until has passed; stays until cleared */
|
||||
#define LLS_WAIT_WAITING 1 /* waiting until wait_until; after that it is NONE again (automatically) */
|
||||
|
||||
typedef struct lls_db lls_db;
|
||||
typedef struct lls_task_list lls_task_list;
|
||||
@@ -86,13 +85,13 @@ typedef struct lls_account_list lls_account_list;
|
||||
typedef struct lls_task_info {
|
||||
const char* name;
|
||||
const char* account; /* NULL when the task has no account */
|
||||
int status; /* LLS_STATUS_*, as shown (Wait / Limit reset come from the account) */
|
||||
const char* status_label; /* "Prompt", "Limit reset", "Wait 16:30", ... */
|
||||
int status; /* LLS_STATUS_*, as shown (Wait becomes Limit reset when the account's wait ends) */
|
||||
const char* status_label; /* "Prompt", "Limit reset", "Wait 16:30", "Testing (account-waiting)", ... */
|
||||
int stored_status; /* LLS_STATUS_*, what is saved underneath */
|
||||
int64_t until; /* for Wait / Limit reset: when the wait ends (ended); else 0 */
|
||||
const char* notes; /* the full text, "" if none (any length) */
|
||||
int notes_lines; /* number of lines in the notes */
|
||||
int overrides_wait; /* 1 if its account waits but this task ignores it (set to Testing / Prompt) */
|
||||
int account_waiting; /* 1 if it is Prompt / Testing while its account waits (the label says so) */
|
||||
} lls_task_info;
|
||||
|
||||
/* An account with its computed state. */
|
||||
@@ -101,8 +100,8 @@ typedef struct lls_account_info {
|
||||
int level; /* LLS_LEVEL_* */
|
||||
const char* level_label; /* "Busy", "Taken", "Free" */
|
||||
int wait_state; /* LLS_WAIT_* */
|
||||
int64_t wait_until; /* when the wait ends (ended); 0 if none */
|
||||
int wait_listed; /* 1 if the wait is not shown by any task (it still makes the account Busy) */
|
||||
int64_t wait_until; /* when the wait ends; 0 if it is not waiting */
|
||||
int wait_listed; /* 1 if it is waiting but no task is set to Wait (it is still Busy) */
|
||||
int task_count;
|
||||
const char* const* tasks; /* the tasks at the account's level (a Free account: its Uploading/Frozen/Done ones) */
|
||||
} lls_account_info;
|
||||
@@ -152,9 +151,9 @@ LLS_API int lls_account_add(lls_db* db, const char* name);
|
||||
LLS_API int lls_account_delete(lls_db* db, const char* name); /* its tasks become unassigned */
|
||||
LLS_API int lls_account_rename(lls_db* db, const char* name, const char* new_name);
|
||||
/* The account hit its limit until a clock time ("16:30", "4:30pm") / until a Unix time. */
|
||||
LLS_API int lls_account_set_wait(lls_db* db, const char* name, const char* time_text);
|
||||
LLS_API int lls_account_set_wait(lls_db* db, const char* name, const char* time_text); /* tasks set to Wait follow it */
|
||||
LLS_API int lls_account_set_wait_at(lls_db* db, const char* name, int64_t until);
|
||||
/* Clears its wait / limit reset. Sets *was_waiting (if not NULL) to 1 or 0. */
|
||||
/* Ends the wait now: its Wait tasks become Limit reset. Sets *was_waiting (if not NULL) to 1 or 0. */
|
||||
LLS_API int lls_account_clear_wait(lls_db* db, const char* name, int* was_waiting);
|
||||
|
||||
/* ---- Tasks ---------------------------------------------------------------- */
|
||||
|
||||
Reference in new issue
Block a user