cs-210/Project3/Items.cpp
2023-04-19 22:29:24 -07:00

230 lines
5.2 KiB
C++

/* 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;
}
}
}