Limits are now account-tied rather than task-tied
This commit is contained in:
1 parent
315a2102a7
commit
0af468f47c
9 files changed
+235
-14
No files matched your search
+82
-5
@@ -62,6 +62,11 @@ void Repl::registerCommands() {
|
||||
{ArgKind::Account}, &Repl::cmdAccDel);
|
||||
add("acc rename", "acc rename <name> <new>", "rename an account", 2, 2,
|
||||
{ArgKind::Account, ArgKind::None}, &Repl::cmdAccRename);
|
||||
add("acc wait", "acc wait <name> <time>",
|
||||
"the account hit its limit until <time>: its Prompt/Testing tasks show Wait, then Limit reset",
|
||||
2, kUnlimited, {ArgKind::Account, ArgKind::None}, &Repl::cmdAccWait);
|
||||
add("acc unwait", "acc unwait <name>", "clear an account's wait / limit reset (its tasks show their own status again)",
|
||||
1, 1, {ArgKind::Account}, &Repl::cmdAccUnwait);
|
||||
add("acc ls", "acc ls", "show the account table", 0, 0, {}, &Repl::cmdAccLs);
|
||||
|
||||
add("tsk add", "tsk add <name> [acc] [status]", "create a task", 1, kUnlimited,
|
||||
@@ -277,6 +282,55 @@ bool Repl::cmdAccRename(const Args& args) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void Repl::setAccountWait(const std::string& account, std::time_t until) {
|
||||
db_.setAccountCooldown(account, StatusUtil::timeToText(until));
|
||||
say("Account '" + account + "' waits until " + StatusUtil::clockLabel(until) +
|
||||
": its Prompt and Testing tasks show Wait, then Limit reset (acc unwait " + account + " to clear).");
|
||||
}
|
||||
|
||||
// Tells the user when a task's own status is hidden by its account's wait.
|
||||
void Repl::noteAccountWait(const std::string& taskName) {
|
||||
std::optional<TaskRow> task = db_.getTask(taskName);
|
||||
std::optional<Status> stored = task ? StatusUtil::deserialize(task->status) : std::nullopt;
|
||||
if (!task || !task->account || !stored || !StatusUtil::followsAccountWait(stored->kind)) {
|
||||
return;
|
||||
}
|
||||
std::optional<AccountRow> account = db_.getAccount(*task->account);
|
||||
if (account && account->cooldown) {
|
||||
say("It shows as Wait / Limit reset because account '" + account->id + "' is waiting (acc unwait " +
|
||||
account->id + " to clear).");
|
||||
}
|
||||
}
|
||||
|
||||
bool Repl::cmdAccWait(const Args& args) {
|
||||
std::optional<AccountRow> account = db_.getAccount(args[0]);
|
||||
if (!account) {
|
||||
throw std::runtime_error("No account named '" + args[0] + "'.");
|
||||
}
|
||||
const std::string text = "wait " + StringUtil::join(args, 1, " ");
|
||||
std::optional<Status> status = StatusUtil::parse(text, std::time(nullptr));
|
||||
if (!status) {
|
||||
throw std::runtime_error("Invalid time '" + StringUtil::join(args, 1, " ") +
|
||||
"'. Use e.g. 16:30, 4:30pm or 4pm.");
|
||||
}
|
||||
setAccountWait(account->id, status->waitUntil);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Repl::cmdAccUnwait(const Args& args) {
|
||||
std::optional<AccountRow> account = db_.getAccount(args[0]);
|
||||
if (!account) {
|
||||
throw std::runtime_error("No account named '" + args[0] + "'.");
|
||||
}
|
||||
if (!account->cooldown) {
|
||||
say("Account '" + account->id + "' is not waiting.");
|
||||
return false;
|
||||
}
|
||||
db_.setAccountCooldown(account->id, std::nullopt);
|
||||
say("Wait cleared on '" + account->id + "'.");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Repl::cmdAccLs(const Args&) {
|
||||
Terminal::clearScreen();
|
||||
std::cout << display_.renderAccounts(std::time(nullptr)) << "\n";
|
||||
@@ -311,8 +365,18 @@ bool Repl::cmdTskAdd(const Args& args) {
|
||||
status = parseStatusFrom(args, next);
|
||||
}
|
||||
|
||||
db_.addTask(name, account, StatusUtil::serialize(status));
|
||||
// A wait on a task that has an account is the account's wait; the task itself
|
||||
// stays Prompt and follows it.
|
||||
const bool accountWait = (status.kind == StatusKind::Wait && account);
|
||||
const Status stored = accountWait ? StatusUtil::make(StatusKind::Prompt) : status;
|
||||
|
||||
db_.addTask(name, account, StatusUtil::serialize(stored));
|
||||
say("Task '" + name + "' added.");
|
||||
if (accountWait) {
|
||||
setAccountWait(*account, status.waitUntil);
|
||||
} else {
|
||||
noteAccountWait(name);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -365,13 +429,26 @@ bool Repl::cmdTskReacc(const Args& args) {
|
||||
}
|
||||
|
||||
bool Repl::cmdTskRestat(const Args& args) {
|
||||
std::optional<std::string> name = db_.findTask(args[0]);
|
||||
if (!name) {
|
||||
std::optional<TaskRow> task = db_.getTask(args[0]);
|
||||
if (!task) {
|
||||
throw std::runtime_error("No task named '" + args[0] + "'.");
|
||||
}
|
||||
Status status = parseStatusFrom(args, 1);
|
||||
db_.setTaskStatus(*name, StatusUtil::serialize(status));
|
||||
say("Task '" + *name + "' set to " + StatusUtil::label(status) + ".");
|
||||
|
||||
if (status.kind == StatusKind::Wait && task->account) {
|
||||
// The wait belongs to the account. Keep an active task as it is so it
|
||||
// follows the wait; any other status becomes Prompt.
|
||||
std::optional<Status> current = StatusUtil::deserialize(task->status);
|
||||
if (!current || !StatusUtil::followsAccountWait(current->kind)) {
|
||||
db_.setTaskStatus(task->id, StatusUtil::serialize(StatusUtil::make(StatusKind::Prompt)));
|
||||
}
|
||||
setAccountWait(*task->account, status.waitUntil);
|
||||
return true;
|
||||
}
|
||||
|
||||
db_.setTaskStatus(task->id, StatusUtil::serialize(status));
|
||||
say("Task '" + task->id + "' set to " + StatusUtil::label(status) + ".");
|
||||
noteAccountWait(task->id);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user