When disaster hits a populated area, the most critical task is to provide immediately affected people with what they need as quickly and as efficiently as possible.
This project completes an application that manages the list of goods that need to be shipped to the disaster area. The client application tracks the quantity of items needed, tracks the quantity on hand, and stores the information in a file for future use.
The types of goods that need to be shipped are of two categories;
- Non-Perishable products, such as blankets and tents, which have no expiry date. We refer to products in this category as Product objects.
- Perishable products, such as food and medicine, that have an expiry date. We refer to products in this category as Perishable.
To complete this project you will need to create several classes that encapsulate your solution.
OVERVIEW OF THE CLASSES TO BE DEVELOPED
The classes used by the client application are:
- Date: A class to be used to hold the expiry date of the perishable items.
- ErrorState: A class to keep track of the error state of client code. Errors may occur during data entry and user interaction.
- Product: A class for managing non-perishable products.
- Perishable: A class for managing perishable products. This class inherits the structure of the "Product" class and manages an expiry date.
- iProduct: An interface to the Product hierarchy. This interface exposes the features of the hierarchy available to the client application. Any "iProduct" class can
- read itself from or write itself to the console
- save itself to or load itself from a text file
- compare itself to a unique C-string identifier
- determine if it is greater than another product in the collating sequence
- report the total cost of the items on hand
- describe itself
- update the quantity of the items on hand
- report its quantity of the items on hand
- report the quantity of items needed
- accept a number of items
- Using this class, the client application can
- save its set of iProducts to a file and retrieve that set later
- read individual item specifications from the keyboard and display them on the screen
- update information regarding the number of each product on hand
THE CLIENT APPLICATION
The client application manages the iProducts and provides the user with options to
- list the Products
- display details of a Product
- add a Product
- add items of a Product
- update the items of a Product
- delete a Product
- sort the set of Products
MILESTONE 3: THE PRODUCT CLASS
The Product class is a concrete class that encapsulates the general information for an AMA product.
Define and implement your Product class in the ama namespace. Store your class definition in a file named Product.h and your implementation in a file named Product.cpp.
NOTE: This milestone does not use the Date class, but uses the ErrorState class.
In the Product.h header file, predefine the following constants as integers:
- max_length_label with the value 30. This is used when accepting data from user or displaying data to user.
- max_length_sku with the value 7. This represents the maximum number of characters in an SKU (stock keeping unit).
- max_length_name with the value 75. This represents the maximum number of characters for the name of the product.
- max_length_unit with the value 10. This represents the maximum number of characters in the user descriptor for a product unit.
- write_condensed with the value 0. This is used to signal what we want the data inserted into a stream in a condensed form.
- write_table with the value 1. This is used to signal what we want the data inserted into a stream in a table form.
- write_human with the value 2. This is used to signal what we want the data inserted into a stream in a human readable form.
In the Product.h header file, predefine the following constant as a floating point number in double precision:
- tax_rate: the current tax rate13%.
PRODUCT CLASS MEMBERS:
Add to the class attributes to store the following information:
- A constant character that indicates the type of the product - for use in the file record. This attribute must be initialized with an initialization list; cannot be initialized in the body of a constructor.
- A character array that holds the product's SKU (stock keeping unit) - the maximum number of characters excluding the null byte is defined by a constant.
- A character array that describes the product's unit - the maximum number of characters excluding the null byte is defined by a constant.
- A pointer that holds the address of a C-style string in dynamic memory containing the name of the product. This the resource that the class must manage!
- An integer that holds the quantity of the product currently on hand (available).
- An integer that holds the quantity of the product needed.
- A double that holds the price of a single unit of the product before any taxes.
- A bool that identifies the taxable status of the product; its value is true if the product is taxable.
- An ErrorState object that holds the error state of the Product object.
Add to the class the following protected functions:
- void message(const char* pText): This function receives the address of a C-style null-terminated string holding an error message and stores that message in the ErrorState object.
- bool isClear() const: This query returns true if the ErrorState attribute contains no error message; false otherwise.
Add to the class the following public functions:
- Zero/One Argument Constructor: This constructor optionally receives a character that identifies the product type. The default value is 'N'. This function stores the character received in an attribute and sets the current object to a safe recognizable empty state.
- A Custom Constructor with 7 arguments: This constructor receives in its seven parameters values in the following order:
- the address of an unmodifiable C-style null terminated string holding the SKU of the product
- the address of an unmodifiable C-style null terminated string holding the name of the product
- the address of an unmodifiable C-style null terminated string holding the unit for the product
- a double holding the product's price before taxes - defaults to zero
- an integer holding the quantity needed of the product - defaults to zero
- an integer holding the quantity of the product on hand - defaults to zero
- a Boolean value indicating the product's taxable status - defaults to true
- This constructor allocates enough memory to hold the name of the product. If the name parameter is null, this constructor sets the object in an empty state. If the name parameter is valid, this constructor stores all parameters in attributes. The type for the product is set to 'N'.
- The Copy Constructor.
- The Destructor.
- The Copy Assignment Operator.
- int operator+=(int cnt): This modifier receives an integer identifying the number of units to be added to the available quantity attribute and returns the updated number of units on hand. If the integer received is positive-valued, this function adds it to the quantity on hand. If the integer is negative-valued or zero, this function does nothing and returns the quantity on hand (without modification).
- bool operator==(const char* sku) const: This query returns true if the string specified in the parameter is the same as the string stored in the SKU attribute of the current instance; false otherwise.
- bool operator> (const char* sku) const: This query returns true if the SKU attribute from the current instance is greater than the string stored at the received address (according to how the string comparison functions define 'greater than'); false otherwise.
- bool operator> (const Product&) const: This query returns true if the name of the current object is greater than the name of the Product received as parameter object (according to how the string comparison functions define 'greater than'); false otherwise.
- int qtyAvailable() const: This query returns the value of the attribute storing how many units of product are available.
- int qtyNeeded() const: This query returns the value of the attribute storing how many units of product are needed.
- double total_cost() const: This query returns the total cost of all available units of product, including tax.
- bool isEmpty() const: this query returns true if the object is in the empty state; false otherwise.
- std::istream& read(std::istream& in, bool interractive): This function reads data from the stream, and stores it in the attributes. Depending on the second parameter, this function prompts the user asking for values, or doesn't interact with the user.
- If the second parameter is false, this function extracts all the information from the stream and doesn't interact with the user. The format of the expected data is the following: SKU,NAME,UNIT,PRICE,TAX,QTY_AVAILABLE,QTY_NEEDED< ENDL>
- That is a sequence of fields, separated by comma. After the last field, there might be a '\n' or the end of the stream.
- If the second parameter is true, this function interacts with the user, asking for data in the following order: see image.
- The text prompted to the user will be displayed in a field of size max_length_label, aligned to the right. The field size includes the space (␣) after the colon (:).
- If there are errors while reading a field, this function stops asking data from the user, sets the failure bit of the first parameter (by calling istr.setstate(ios::failbit)), and sets the ErrorState attribute to one of the following messages, depending on which field encountered the issue:
Only (Y)es or (N)o are acceptable!
Invalid Price Entry!
Invalid Quantity Available Entry!
Invalid Quantity Needed Entry!
- This function accepts the data only if there are no errors reading it.
- std::ostream& write(std::ostream& out, int writeMode) const: This function writes the content of the current instance in the stream received as the first parameter.
- If the object contains an error message, this function prints the error message and exits
- If the current instance is in empty state, this function is not doing anything.
- If the writeMode is set to write_condensed, this function writes the content of the current instance in the following format: TAG,SKU,NAME,UNIT,PRICE,TAX,QTY_AVAILABLE,QTY_NEEDED< ENDL>
- If the writeMode is set to write_table, this function writes the content of the current instance in the following format ( marks a mandatory blank space, not part of the field width):
SKU|NAME|UNIT|PRICE|TAX|QTY_AVAIL|QTY_NEEDED|
Field | Size | Alignment | Observations |
SKU | max_length_sku | Right | |
Name | 16 | Left | If the name is more than 16 characters, write only 13 characters, followed by three dots (...) |
Unit | 10 | Left | |
Price | 7 | Right | Precision is set to 2 |
Tax | 3 | Right | Writes "yes" or "no" |
Quantity Available | 6 | Right | |
Quantity Needed | 6 | Right | |
- If the writeMode is set to write_human, this function writes the content of the current instance in the following format: see image.
- The labels are will be displayed in a field of size max_length_label, aligned to the right. The field size includes the space () after the colon (:).
NOTE: You can add as many private members as your design requires. Do not add extra public/protected members.
NOTE: Some of the functions above change the name of the product; make sure that there are no memory leaks when that happens.
NOTE: Reuse the code whenever possible. Do not duplicate functionality!
NOTE: With the exception of the tag field, what the function write(...) writes in condensed mode, the function read(...) should be able to extract in non-interactive mode.
UTILITIES
In another module, called Utilities, add the following helper functions, in the ama namespace (prototypes in the header, implementations in a source file):
- double& operator+=(double& total, const Product& prod): Adds the total cost of the product into the first parameter and returns the result;
- ostream& operator<<(ostream& out, const Product& prod): Writes into the first parameter, in a human readable format, the content of the second parameter.
- istream& operator>>(istream& in, Product& prod): Reads from the first parameter a product in interactive mode.