/* Cody Cook 2023/04/13 CS-210 Project 3 */ #include "Items.h" // constructors // default constructor; parses default file name Items::Items() { if (!ParseInputFile()) { // try getting a new file RequestNewFile(); } } // constructor with a custom input option Items::Items(string p_inputFile = defaultItemFileName) { SetInputFile(p_inputFile); if (!ParseInputFile()) { // try geting a new file RequestNewFile(); } } // destructors // run a set of functions when the class closes Items::~Items() { if (r_input.is_open()) { r_input.close(); } } // getters // prints and returns the inventory for a named item int Items::GetInventory(string p_item) { // search the string in the map auto it = r_mapping.find(p_item); // if there were results if (it != r_mapping.end()) { string times; // allow for more natural responses with the word "time" // if there is only one item, it is only there "one time" if (it->second == 1) { times = " time."; } else { // if it is 0 or 2 or more, then it is "times" times = " times."; } // output the quantity purchased cout << c_red << it->first << c_normal << " were purchased "; cout << c_red << it->second << c_normal; cout << times << endl; return it->second; } else { // because there wasn't quantity, explain it wasn't purchased. cerr << c_red << p_item << c_normal << " were not purchased." << endl; return 0; } } // return the string for the inputFile string Items::GetInputFile() { return r_inputFile; } char Items::GetStar() { return r_star; } // setters // update the filename of the input file void Items::SetInputFile(string p_inputFile) { r_inputFile = p_inputFile; } // change the star used in the histogram void Items::SetStar(char p_star) { r_star = p_star; } // methods // ParseInputFile reads the input file and stores the data in a map; it also runs a backup of the data bool Items::ParseInputFile() { // try opening the file r_input.open(r_inputFile); // if the file could not be opened if (!r_input.is_open()) { // error out cout << "Error opening file " << c_red << r_inputFile << c_normal << endl; return false; } clog << endl << "Parsing " << c_red << r_inputFile << c_normal << "... "; string line; // while we go through each line of the file while (getline(r_input, line)) { // Increment the frequency of the current line into the map r_mapping[line]++; } // close the file r_input.close(); // run a backup of this data and return true SaveInventory(); return true; } // output the inventory based on the config void Items::PrintInventory(int p_type) { // find the length of the longest item to help align the output size_t longest = 0; for (const auto &entry : r_mapping) { if (entry.first.length() > longest) { longest = entry.first.length(); } } // output the inventory for (const auto &entry : r_mapping) { // output the item name with the longest item name as the width cout << setw(longest) << entry.first << " "; // see the quantity as a number if (p_type == 1) { cout << c_red << entry.second << c_normal << endl; } // see the quantity as a histogram else if (p_type == 2) { cout << c_red << string(entry.second, r_star) << c_normal << endl; } } } // SaveInventory creates a backup of the data in the map bool Items::SaveInventory() { // open file for backup ofstream file(r_database); // if the file isn't open if (!file.is_open()) { // then there was a opening the file; so warn the user and exit the function cerr << "Error opening " << c_red << r_database << c_normal << " for backup. Please check your permissions."; return false; } // iterate through the mappings and save them to the file for (const auto &entry : r_mapping) { file << entry.first << " " << entry.second << endl; } // save and close the file file.close(); // output a successful save and return true cout << "Backup file " << c_red << r_database << c_normal << " updated." << endl; cout << endl; return true; } void Items::RequestNewFile() { string newFile; bool moveOn = false; while (!moveOn) { cout << endl; cout << "Type " << c_red << "exit" << c_normal << " to quit, or enter the filename to import: "; cout << c_red; cin >> newFile; cout << c_normal; if (newFile == "exit") { exit(0); } SetInputFile(newFile); if (ParseInputFile()) { moveOn = true; } } }