Personal Task Automation Tool C++

👤 Sharing: AI
```cpp
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <ctime>
#include <chrono>
#include <iomanip>
#include <algorithm>
#include <filesystem> // Requires C++17 or later.  If older, use boost::filesystem or alternative.

#ifdef _WIN32
#include <windows.h> //For sleep on Windows
#else
#include <unistd.h> //For sleep on Linux/macOS
#endif

namespace fs = std::filesystem;  //Makes it easier to refer to the namespace.


// Struct to represent a task
struct Task {
    std::string description;
    std::time_t dueDate;
    int priority; // Higher number = higher priority
    bool completed;
};

// Function prototypes
void addTask(std::vector<Task>& tasks);
void viewTasks(const std::vector<Task>& tasks);
void markTaskCompleted(std::vector<Task>& tasks);
void deleteTask(std::vector<Task>& tasks);
void saveTasksToFile(const std::vector<Task>& tasks, const std::string& filename);
void loadTasksFromFile(std::vector<Task>& tasks, const std::string& filename);
void sortTasksByPriority(std::vector<Task>& tasks);
void displayMenu();
std::time_t parseDateString(const std::string& dateString);
std::string formatDate(std::time_t time);
void snoozeTask(std::vector<Task>& tasks);
void clearScreen();

int main() {
    std::vector<Task> tasks;
    std::string filename = "tasks.txt"; // Default filename

    // Load tasks from file at the beginning
    loadTasksFromFile(tasks, filename);

    int choice;
    do {
        clearScreen();
        displayMenu();

        std::cout << "Enter your choice: ";
        std::cin >> choice;
        std::cin.ignore(); // Consume newline

        switch (choice) {
            case 1:
                addTask(tasks);
                break;
            case 2:
                viewTasks(tasks);
                break;
            case 3:
                markTaskCompleted(tasks);
                break;
            case 4:
                deleteTask(tasks);
                break;
            case 5:
                sortTasksByPriority(tasks);
                break;
            case 6:
                snoozeTask(tasks);
                break;
            case 7:
                saveTasksToFile(tasks, filename);
                std::cout << "Tasks saved to file.\n";
                break;
            case 0:
                saveTasksToFile(tasks, filename); // Save before exiting
                std::cout << "Exiting program.\n";
                break;
            default:
                std::cout << "Invalid choice. Please try again.\n";
        }

        if (choice != 0) {
            std::cout << "Press Enter to continue...";
            std::cin.get();  //Wait for the user to press Enter.
        }

    } while (choice != 0);

    return 0;
}

void displayMenu() {
    std::cout << "Personal Task Automation Tool\n";
    std::cout << "------------------------------\n";
    std::cout << "1. Add Task\n";
    std::cout << "2. View Tasks\n";
    std::cout << "3. Mark Task as Completed\n";
    std::cout << "4. Delete Task\n";
    std::cout << "5. Sort Tasks by Priority\n";
    std::cout << "6. Snooze Task\n";
    std::cout << "7. Save Tasks to File\n";
    std::cout << "0. Exit\n";
    std::cout << "------------------------------\n";
}

void addTask(std::vector<Task>& tasks) {
    Task newTask;

    std::cout << "Enter task description: ";
    std::getline(std::cin, newTask.description);

    std::string dateString;
    std::cout << "Enter due date (YYYY-MM-DD): ";
    std::getline(std::cin, dateString);
    newTask.dueDate = parseDateString(dateString);
    if (newTask.dueDate == -1) {
        std::cout << "Invalid date format. Task added with no due date.\n";
        newTask.dueDate = 0; // or some other sensible default
    }

    std::cout << "Enter priority (1-10, 10 being highest): ";
    std::cin >> newTask.priority;
    std::cin.ignore(); // Consume newline

    newTask.completed = false;

    tasks.push_back(newTask);
    std::cout << "Task added successfully.\n";
}

void viewTasks(const std::vector<Task>& tasks) {
    if (tasks.empty()) {
        std::cout << "No tasks to display.\n";
        return;
    }

    std::cout << "------------------------------\n";
    for (size_t i = 0; i < tasks.size(); ++i) {
        std::cout << i + 1 << ". ";
        std::cout << "Description: " << tasks[i].description << "\n";
        if (tasks[i].dueDate != 0) {
            std::cout << "   Due Date: " << formatDate(tasks[i].dueDate) << "\n";
        } else {
            std::cout << "   Due Date: N/A\n";
        }
        std::cout << "   Priority: " << tasks[i].priority << "\n";
        std::cout << "   Completed: " << (tasks[i].completed ? "Yes" : "No") << "\n";
        std::cout << "------------------------------\n";
    }
}

void markTaskCompleted(std::vector<Task>& tasks) {
    viewTasks(tasks);  // Show the tasks so the user can choose

    if (tasks.empty()) {
        return;
    }

    int taskNumber;
    std::cout << "Enter the number of the task to mark as completed: ";
    std::cin >> taskNumber;
    std::cin.ignore(); // Consume newline

    if (taskNumber >= 1 && taskNumber <= tasks.size()) {
        tasks[taskNumber - 1].completed = true;
        std::cout << "Task marked as completed.\n";
    } else {
        std::cout << "Invalid task number.\n";
    }
}

void deleteTask(std::vector<Task>& tasks) {
    viewTasks(tasks); // Show the tasks so the user can choose

    if (tasks.empty()) {
        return;
    }

    int taskNumber;
    std::cout << "Enter the number of the task to delete: ";
    std::cin >> taskNumber;
    std::cin.ignore(); // Consume newline

    if (taskNumber >= 1 && taskNumber <= tasks.size()) {
        tasks.erase(tasks.begin() + taskNumber - 1);
        std::cout << "Task deleted.\n";
    } else {
        std::cout << "Invalid task number.\n";
    }
}

void saveTasksToFile(const std::vector<Task>& tasks, const std::string& filename) {
    std::ofstream outputFile(filename);

    if (outputFile.is_open()) {
        for (const auto& task : tasks) {
            outputFile << task.description << "\n";
            outputFile << task.dueDate << "\n";
            outputFile << task.priority << "\n";
            outputFile << task.completed << "\n";
        }
        outputFile.close();
    } else {
        std::cerr << "Unable to open file for writing.\n";
    }
}

void loadTasksFromFile(std::vector<Task>& tasks, const std::string& filename) {
    std::ifstream inputFile(filename);
    Task tempTask;
    if (inputFile.is_open()) {
        while (std::getline(inputFile, tempTask.description)) {
            std::string dueDateStr, priorityStr, completedStr;

            std::getline(inputFile, dueDateStr);
            std::getline(inputFile, priorityStr);
            std::getline(inputFile, completedStr);

            try {
                tempTask.dueDate = std::stoll(dueDateStr);
                tempTask.priority = std::stoi(priorityStr);
                tempTask.completed = (completedStr == "1"); //Convert string to bool
            } catch (const std::invalid_argument& e) {
                std::cerr << "Error parsing task data. Skipping task.\n";
                continue; //Skip the rest of the loop and go to the next task
            } catch (const std::out_of_range& e) {
                 std::cerr << "Error parsing task data (out of range). Skipping task.\n";
                 continue;
            }
            tasks.push_back(tempTask);
        }
        inputFile.close();
    } else {
        //If file doesn't exist, it's not necessarily an error. Just means no tasks saved yet.
        //std::cerr << "Unable to open file for reading.  Starting with an empty task list.\n";
        std::cout << "No existing task file found. Starting with an empty task list.\n"; //Less alarming message.
    }
}


// Custom comparison function for sorting tasks by priority
bool compareTasksByPriority(const Task& a, const Task& b) {
    return a.priority > b.priority; // Sort in descending order (highest priority first)
}

void sortTasksByPriority(std::vector<Task>& tasks) {
    std::sort(tasks.begin(), tasks.end(), compareTasksByPriority);
    std::cout << "Tasks sorted by priority.\n";
}

std::time_t parseDateString(const std::string& dateString) {
    std::tm t{};
    std::istringstream ss(dateString);
    ss >> std::get_time(&t, "%Y-%m-%d");
    if (ss.fail()) {
        return -1; // Indicate parsing failure
    }
    return mktime(&t);
}

std::string formatDate(std::time_t time) {
    std::tm t = *std::localtime(&time);
    std::ostringstream oss;
    oss << std::put_time(&t, "%Y-%m-%d");
    return oss.str();
}


void snoozeTask(std::vector<Task>& tasks) {
   viewTasks(tasks);

    if (tasks.empty()) {
        return;
    }

    int taskNumber;
    std::cout << "Enter the number of the task to snooze: ";
    std::cin >> taskNumber;
    std::cin.ignore();

    if (taskNumber >= 1 && taskNumber <= tasks.size()) {
        int snoozeMinutes;
        std::cout << "Enter snooze duration in minutes: ";
        std::cin >> snoozeMinutes;
        std::cin.ignore();

        tasks[taskNumber - 1].dueDate += snoozeMinutes * 60; // Add minutes in seconds

        std::cout << "Task snoozed.  New due date: " << formatDate(tasks[taskNumber - 1].dueDate) << "\n";

    } else {
        std::cout << "Invalid task number.\n";
    }
}

void clearScreen() {
#ifdef _WIN32
    system("cls");  // For Windows
#else
    system("clear"); // For Linux/macOS
#endif
}
```
👁️ Viewed: 122

Comments