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
PROJECT CLASS DIAGRAM
See figure: see image.
FILE STRUCTURE OF THE PROJECT
Each class has its own header (.h) file and its own implementation (.cpp) file. The name of each file is the name of its class.
Example: Class Date is defined in two files: Date.h and Date.cpp
All of the code developed for this application should be enclosed in the ama namespace.
MILESTONE 1: THE DATE CLASS
To kick-start this project, clone/download milestone 1 from the course repository and code the Date class.
The Date class encapsulates a date that is readable by an std::istream and printable by an std::ostream using the following format for both reading and writing: YYYY/MM/DD, where YYYY refers to a four-digit value for the year, MM refers to a two-digit value for the month and DD refers to a two-digit value for the day in the month.
Implement the Date class using following specifications below.
CONSTANTS:
In the Date.h header file, predefine the following constants as integers:
- min_year with the value 2019. This represents the minimum year acceptable for a valid date.
- max_year with the value 2028. This represents the maximum year for a valid date.
- no_error with the value 0. A date object with this status is either in a safe empty state or holds a valid date.
- error_year with the value 1. The client has attempted to set an invalid year for the date object. The object should be in a safe empty state.
- error_mon with the value 2. The client has attempted to set an invalid month for the date object. The object should be in a safe empty state.
- error_day with the value 3. The client has attempted to set an invalid day for the date object. The object should be in a safe empty state.
- error_invalid_operation with the value 4. The client has attempted to perform an invalid operation on the date object. The object should store the same date as before the invalid operation was attempted.
- error_input with the value 5. The date object failed to read data from an input steam (stream data was in the wrong format). The object should be in a safe empty state.
CLASS MEMBERS:
Add to the class attributes to store the following information:
- Year: an integer with a value between the limits defined above.
- Month: an integer with a value between 1 and 12.
- Day of the Month: an integer with a value between and the maximum number of days in the month. Use the function int mdays(int year, int month) to find out how many days are in a given month for a given year. Note that February can have 28 or 29 days depending on the year.
- Status: an integer used by the client to determine if the object contains a valid date. This attribute should have the value no_error or one of the error_* constants defined above.
Add to the class the following private functions:
- void status(int newStatus): This function sets the status of the date object to the value of the parameter.
- int mdays(int year, int month) const: This function returns the number of days in a given month for a given year. Use the implementation below:
int Date::mdays(int year, int mon) const
{
int days[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, -1 };
int month = mon >= 1 && mon <= 12 ? mon : 13;
month--;
return days[month] + int((month == 1)*((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0));
}
Add to the class the following public functions:
- A default constructor: sets the object to an empty state and the status to no_error. Use the date 0000/00/00 as the empty state.
- A custom constructor with three arguments: year, month and day (in this order). If the date specified by the arguments is correct (each number is within range), this constructor should store the arguments in the attributes and set the status to no_error.
- If any of the parameters is not correct, the constructor should set the date object in a safe empty state and set the status to a value that indicates which parameter was invalid (see the constants defined above).
- The parameters should be checked in the following order: year, month, and then day.
- status(...): A query that returns an integer representing the status of the current object.
- clearError(...): A modifier that resets the status of an object to no_error. This function should not update the date stored in the object. This function should return nothing.
- isGood(...): A query that returns true if the object stores a valid date and is not in error mode.
- operator+=(int days): A modifier that adds to the date stored by the object the number of days specified in the parameter.
- If the current object is in error mode or in a safe empty state, this function does not update the stored date and changes the status of the object to error_invalid_operation.
- If adding the number of days specified by the parameter would place the days attribute outside the acceptable limits, this function does not update the stored date and changes the status of the object to error_invalid_operation.
- operator++(): A modifier that adds one day to the date stored by the object (prefix). This function should return the updated current instance.
- If the current object is in error mode or in a safe empty state, this function does not update the stored date and changes the status of the object to error_invalid_operation.
- If adding one day would place the days attribute outside the acceptable limits, this function does not update the stored date and changes the status of the object to error_invalid_operation.
- operator++(int): A modifier that adds one day to the date stored by the object (postfix). This function should return a copy of the instance before it gets updated.
- If the current object is in error mode or in a safe empty state, this function does not update the stored date and changes the status of the current object to error_invalid_operation.
- If adding one day would place the days attribute outside the acceptable limits, this function does not update the stored date and changes the status of the current object to error_invalid_operation.
- operator+(int days): A query that adds to the date stored by the object the number of days specified in the parameter. The result is stored in a new object.
- If the current object is in error mode or in a safe empty state, this function returns a copy of the current object with the status set to error_invalid_operation.
- If adding the number of days specified by the parameter would place the days attribute outside the acceptable limits, this function returns a copy of the current object with the status set to error_invalid_operation.
- operator==(const Date& rhs): A query that returns true if two date objects store the same date (does not check status of either object).
- operator!=(const Date& rhs): A query that returns true if two date objects store different dates (does not check status of either object).
- operator<(const Date& rhs): A query that returns true if the current object stores a date that is before the date stored in rhs (does not check status of either object).
- operator>(const Date& rhs): A query that returns true if the current object stores a date that is after the date stored in rhs (does not check status of either object).
- operator<=(const Date& rhs): A query that returns true if the current object stores a date that is before or equal to the date stored in rhs (does not check status of either object).
- operator>=(const Date& rhs): A query that returns true if the current object stores a date that is after or equal to the date stored in rhs (does not check status of either object).
- istream& Date::read(istream& is): A query that reads from an input stream a date in the following format: YYYY?MM?DD (three integers separated by a single character). This function does not prompt the user.
- If the reading fails at any point (when the reading fails, the function is.fail() returns true), this function sets the object in a safe state and updates the state attribute to error_input.
- If this function reads the numbers successfully, and the read values are valid, it stores them into the instance variables and sets the status to no_error.
- Regardless of the result of the input process, your function returns a reference to the std::istream object.
- ostream& Date::write(ostream& os): A query that writes the date to an std::ostream object in the following format: YYYY/MM/DD, and then returns a reference to the std::ostream object.
Add to the following free helper function functions:
- operator<<: Prints the date to the first parameter (use Date::write()).
- operator>>: Reads the date from the first parameter (use Date::read()).
You can add as many private members as your design requires. Do not add extra public members.