|
| 1 | +// Autor: Héctor Adán |
| 2 | +// GitHub: https://github.com/hectorio23 |
| 3 | + |
| 4 | +#include <iostream> |
| 5 | +#include <string> |
| 6 | +#include <vector> |
| 7 | +#include <map> |
| 8 | +#include <fstream> |
| 9 | +#include <memory> |
| 10 | +#include <stdexcept> |
| 11 | +#include <uuid/uuid.h> |
| 12 | + |
| 13 | +// NOTE: COMPILE the program useing the following instruction: |
| 14 | +// g++ -o run hectorio23.cpp -luuid |
| 15 | + |
| 16 | + |
| 17 | +// Goal class represents a single goal with all necessary attributes. |
| 18 | +class Goal { |
| 19 | +private: |
| 20 | + std::string id; |
| 21 | + std::string description; |
| 22 | + int amount; |
| 23 | + int monthsLimit; |
| 24 | + std::string units; |
| 25 | + |
| 26 | + std::string generateUUID() { |
| 27 | + uuid_t uuid; |
| 28 | + char uuidStr[37]; |
| 29 | + uuid_generate(uuid); |
| 30 | + uuid_unparse(uuid, uuidStr); |
| 31 | + return std::string(uuidStr); |
| 32 | + } |
| 33 | + |
| 34 | +public: |
| 35 | + Goal(const std::string& desc, int amt, int months, const std::string& unit) |
| 36 | + : description(desc), amount(amt), monthsLimit(months), units(unit), id(generateUUID()) { |
| 37 | + if (monthsLimit < 1 || monthsLimit > 12) { |
| 38 | + throw std::out_of_range("Months limit must be between 1 and 12."); |
| 39 | + } |
| 40 | + } |
| 41 | + |
| 42 | + const std::string& getId() const { return id; } |
| 43 | + const std::string& getDescription() const { return description; } |
| 44 | + int getAmount() const { return amount; } |
| 45 | + int getMonthsLimit() const { return monthsLimit; } |
| 46 | + const std::string& getUnits() const { return units; } |
| 47 | +}; |
| 48 | + |
| 49 | +// YearGoals manages a collection of goals and their monthly plans. |
| 50 | +class YearGoals { |
| 51 | +private: |
| 52 | + std::vector<std::shared_ptr<Goal>> goals; |
| 53 | + std::map<std::string, std::vector<std::pair<std::shared_ptr<Goal>, int>>> plan; |
| 54 | + |
| 55 | + const std::vector<std::string> months = { |
| 56 | + "January", "February", "March", "April", "May", "June", |
| 57 | + "July", "August", "September", "October", "November", "December"}; |
| 58 | + |
| 59 | + void initializePlan() { |
| 60 | + for (const auto& month : months) { |
| 61 | + plan[month] = {}; |
| 62 | + } |
| 63 | + } |
| 64 | + |
| 65 | +public: |
| 66 | + YearGoals() { |
| 67 | + initializePlan(); |
| 68 | + } |
| 69 | + |
| 70 | + bool addGoal(const std::shared_ptr<Goal>& goal) { |
| 71 | + if (goals.size() >= 10) { |
| 72 | + std::cerr << "Maximum number of goals reached." << std::endl; |
| 73 | + return false; |
| 74 | + } |
| 75 | + |
| 76 | + goals.push_back(goal); |
| 77 | + distributeGoalAcrossMonths(goal); |
| 78 | + return true; |
| 79 | + } |
| 80 | + |
| 81 | + void distributeGoalAcrossMonths(const std::shared_ptr<Goal>& goal) { |
| 82 | + int remainingAmount = goal->getAmount(); |
| 83 | + int monthsLimit = goal->getMonthsLimit(); |
| 84 | + for (size_t i = 0; i < months.size() && remainingAmount > 0 && monthsLimit > 0; ++i, --monthsLimit) { |
| 85 | + int monthlyAmount = std::min(remainingAmount, 1); |
| 86 | + plan[months[i]].emplace_back(goal, monthlyAmount); |
| 87 | + remainingAmount -= monthlyAmount; |
| 88 | + } |
| 89 | + } |
| 90 | + |
| 91 | + void displayGoals() const { |
| 92 | + if (goals.empty()) { |
| 93 | + std::cout << "No goals added yet.\n"; |
| 94 | + return; |
| 95 | + } |
| 96 | + |
| 97 | + for (const auto& goal : goals) { |
| 98 | + std::cout << "ID: " << goal->getId() << "\n" |
| 99 | + << "Description: " << goal->getDescription() << "\n" |
| 100 | + << "Amount: " << goal->getAmount() << "\n" |
| 101 | + << "Units: " << goal->getUnits() << "\n" |
| 102 | + << "Months Limit: " << goal->getMonthsLimit() << "\n\n"; |
| 103 | + } |
| 104 | + } |
| 105 | + |
| 106 | + void displayPlan() const { |
| 107 | + for (const auto& month : months) { |
| 108 | + std::cout << month << ":\n"; |
| 109 | + const auto& goalsForMonth = plan.at(month); |
| 110 | + for (size_t i = 0; i < goalsForMonth.size(); ++i) { |
| 111 | + const auto& [goal, amount] = goalsForMonth[i]; |
| 112 | + std::cout << " [ ] " << i + 1 << ". " << goal->getDescription() |
| 113 | + << " (" << amount << " " << goal->getUnits() << "/month). Total: " |
| 114 | + << goal->getAmount() << ".\n"; |
| 115 | + } |
| 116 | + std::cout << "\n"; |
| 117 | + } |
| 118 | + } |
| 119 | + |
| 120 | + void savePlanToFile(const std::string& filePath) const { |
| 121 | + std::ofstream file(filePath); |
| 122 | + if (!file.is_open()) { |
| 123 | + std::cerr << "Failed to open file: " << filePath << std::endl; |
| 124 | + return; |
| 125 | + } |
| 126 | + |
| 127 | + for (const auto& month : months) { |
| 128 | + file << month << ":\n"; |
| 129 | + const auto& goalsForMonth = plan.at(month); |
| 130 | + for (size_t i = 0; i < goalsForMonth.size(); ++i) { |
| 131 | + const auto& [goal, amount] = goalsForMonth[i]; |
| 132 | + file << " [ ] " << i + 1 << ". " << goal->getDescription() |
| 133 | + << " (" << amount << " " << goal->getUnits() << "/month). Total: " |
| 134 | + << goal->getAmount() << ".\n"; |
| 135 | + } |
| 136 | + file << "\n"; |
| 137 | + } |
| 138 | + |
| 139 | + file.close(); |
| 140 | + std::cout << "Plan saved to " << filePath << "\n"; |
| 141 | + } |
| 142 | +}; |
| 143 | + |
| 144 | +void displayMenu() { |
| 145 | + std::cout << "\nNew Year Goals Manager\n" |
| 146 | + << "========================\n" |
| 147 | + << "1. Add a Goal\n" |
| 148 | + << "2. View Goals\n" |
| 149 | + << "3. View Detailed Plan\n" |
| 150 | + << "4. Save Plan to File\n" |
| 151 | + << "0. Exit\n" |
| 152 | + << "Select an option: "; |
| 153 | +} |
| 154 | + |
| 155 | +int main() { |
| 156 | + YearGoals yearGoals; |
| 157 | + int option; |
| 158 | + |
| 159 | + do { |
| 160 | + displayMenu(); |
| 161 | + std::cin >> option; |
| 162 | + std::cin.ignore(); |
| 163 | + |
| 164 | + switch (option) { |
| 165 | + case 1: { |
| 166 | + std::string description, units; |
| 167 | + int amount, monthsLimit; |
| 168 | + |
| 169 | + std::cout << "Enter description: "; |
| 170 | + std::getline(std::cin, description); |
| 171 | + |
| 172 | + std::cout << "Enter amount: "; |
| 173 | + std::cin >> amount; |
| 174 | + |
| 175 | + std::cout << "Enter months limit (1-12): "; |
| 176 | + std::cin >> monthsLimit; |
| 177 | + while (monthsLimit < 1 || monthsLimit > 12) { |
| 178 | + std::cout << "Invalid input. Enter months limit (1-12): "; |
| 179 | + std::cin >> monthsLimit; |
| 180 | + } |
| 181 | + |
| 182 | + std::cout << "Enter units: "; |
| 183 | + std::cin.ignore(); |
| 184 | + std::getline(std::cin, units); |
| 185 | + |
| 186 | + try { |
| 187 | + auto goal = std::make_shared<Goal>(description, amount, monthsLimit, units); |
| 188 | + if (yearGoals.addGoal(goal)) { |
| 189 | + std::cout << "Goal added successfully.\n"; |
| 190 | + } else { |
| 191 | + std::cout << "Failed to add goal. Maximum limit reached.\n"; |
| 192 | + } |
| 193 | + } catch (const std::exception& e) { |
| 194 | + std::cerr << e.what() << "\n"; |
| 195 | + } |
| 196 | + |
| 197 | + break; |
| 198 | + } |
| 199 | + case 2: |
| 200 | + yearGoals.displayGoals(); |
| 201 | + break; |
| 202 | + case 3: |
| 203 | + yearGoals.displayPlan(); |
| 204 | + break; |
| 205 | + case 4: { |
| 206 | + std::string filePath; |
| 207 | + std::cout << "Enter file path to save plan: "; |
| 208 | + std::cin.ignore(); |
| 209 | + std::getline(std::cin, filePath); |
| 210 | + yearGoals.savePlanToFile(filePath); |
| 211 | + break; |
| 212 | + } |
| 213 | + case 0: |
| 214 | + std::cout << "Exiting program. Goodbye!\n"; |
| 215 | + break; |
| 216 | + default: |
| 217 | + std::cout << "Invalid option. Please try again.\n"; |
| 218 | + } |
| 219 | + } while (option != 0); |
| 220 | + |
| 221 | + return 0; |
| 222 | +} |
0 commit comments