#pragma once #include #include #include #include // Prompt: free to accept prompts. // LimitReset: computed - a Wait whose time has passed (can also be set by hand). enum class StatusKind { Prompt, LimitReset, Testing, Wait, Uploading, Frozen, Done }; struct Status { StatusKind kind = StatusKind::Prompt; std::time_t waitUntil = 0; // when the wait ends; set for Wait, and kept on the computed LimitReset }; namespace StatusUtil { Status make(StatusKind kind); // User input such as "testing" or "wait 16:30". A wait time that has already // passed today is taken to mean tomorrow. std::optional parse(const std::string& text, std::time_t now); // Database representation, e.g. "testing" or "wait 2026-10-17T16:30". std::string serialize(const Status& status); std::optional deserialize(const std::string& text); // 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. 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& 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); // Times kept outside a Status (an account's cooldown): "2026-10-17T16:30". std::string timeToText(std::time_t value); std::optional timeFromText(const std::string& text); std::string clockLabel(std::time_t value); // "16:30" // "16:30" for today, "tomorrow 06:40" for the next day, otherwise "2026-10-26 16:30". std::string resetLabel(std::time_t value, std::time_t now); // True when the text is just "wait" (no time given). bool isBareWait(const std::string& text); // One-line list of the accepted statuses, for error messages and help. std::string helpText(); std::string label(const Status& status); // "Prompt", "Limit reset", "Wait 16:30", ... std::string kindName(StatusKind kind); // lowercase token: "prompt", "limit-reset", ... std::vector allKinds(); // Accepts "limit-reset", "limit_reset", "limitreset", "reset"; "available" is an // old name for "prompt". std::optional kindFromName(const std::string& name); int rank(StatusKind kind); // task sort priority, lowest first bool isBusy(StatusKind kind); // keeps its account Busy: Testing, Limit reset, Wait bool isTaken(StatusKind kind); // keeps its account Taken: Prompt } // namespace StatusUtil