| Milestone | Revision | Approximate Workload (days) |
Overview | Comments |
|---|---|---|---|---|
| MS1 | V0.9 | 5 | Watch | |
| MS2 | V1.0 | 9 | Watch | |
| MS3 | V0.9 | 10 | Watch | |
| V0.91 | Fixed few typos | |||
| V1.0 | Moved m_displayType to protected section for MS4 | |||
| V1.1 | corrected operator== definition | |||
| V1.2 | missing itemType function name is added | |||
| MS4 | V0.9 | 4 | Watch | |
| V1.0 | The write oveload logic corrected | |||
| MS5 | 14 | Watch | Tester data explained | |
| m51-V1.1 | Total Asset Calculation Precision | |||
| m52-V1.0 | ||||
| m53-V1.0 | ||||
| m54-V1.0 | ||||
| m55-V1.0 |
Your task for the project for this semester is to create simple Point of Sale (POS) application that keeps track of a small inventory of Goods to sell and can sell them at the cashier, issuing a bill of sale.
This project will be done in 5 milestones and each milestone will have its due date. The due date of each milestone is stated below, and it is based on the amount of work to be done for that milestone.
| Milestone | Mark | Due date | Submission Policy |
|---|---|---|---|
| MS1 | 10% | Mar 10 | gets full mark even if 1 week late. gets 0% afterwards |
| MS2 | 10% | Mar 20 | gets full mark even if 1 week late. gets 0% afterwards |
| MS3 | 10% | Mar 29 | gets full mark even if 1 week late. gets 0% afterwards |
| MS4 | 10% | Apr 2 | gets full mark even if 1 week late. gets 0% afterwards |
| MS5 | 60% | Apr 16 | See below |
To make the final submission of the project easier and to make it possible to partially submit a project we have divided the submission of milestone 5 into five small ones. Each submission is worth 12% of the project mark. Your project will be marked only if you have all four milestones and at least have one of the five submissions of milestone 5.
| Milestone 5 Divided into five submission |
Mark | Due date | Submission Policy |
|---|---|---|---|
| m51 | 12% | Apr 16th | 10% penalty for each day being late up to 5 days |
| m52 | 12% | Apr 16th | 10% penalty for each day being late up to 5 days |
| m53 | 12% | Apr 16th | 10% penalty for each day being late up to 5 days |
| m54 | 12% | Apr 16th | 10% penalty for each day being late up to 5 days |
| m55 | 12% | Apr 16th | 10% penalty for each day being late up to 5 days |
The first 4 milestones will not be marked based on the code, but their success and their timely submissions. You may modify or debug your previous code as you are going through the milestones. The only milestone that is going to scrutinized based your code will be milestone 5. If you require any feedback on your first four milestones you need to ask your professor to do so.
⚠️ The first four milestones must be submitted successfully even if they are very late.
Your project will receive a mark of zero if any of the first 4 milestones are not submitted by the rejection date (Apr 21) . For your project to be marked, you must submit all the 4 milestones and at least one of the 5 submissions of Milestone 5 (Rejection date for milestone 5 is also Apr 21)
You can check the due date of each milestone using the -due flag in the submission command:
~profname.proflastname/submit 2??/prj/m? -due- replace 2?? with the subject code
- replace m? with the milestone number
Different sections may have different due dates based on their section's progress. Always check the due date using this command. The due date returned by this command always have priority over the due dates stated above.
When submitting your work, all the files submitted should carry full student information along with the "citation and sources" information. See the following example:
If you have multiple submissions of the same milestone, please update the Revision History in each submission so your professor knows what changes to look for.
/* Citation and Sources...
Final Project Milestone ?
Module: Whatever
Filename: Whatever.cpp
Version 1.0
Author John Doe
Revision History
-----------------------------------------------------------
Date Reason
2020/?/? Preliminary release
2020/?/? Debugged DMA
-----------------------------------------------------------
I have done all the coding by myself and only copied the code
that my professor provided to complete my project milestones.
-----------------------------------------------------------
OR
-----------------------------------------------------------
Write exactly which part of the code is given to you as help and
who gave it to you, or from what source you acquired it.
-----------------------------------------------------------*/Failing to include the above citation to any of the files containing your work will cause the rejection of your project submission
If the file contains only your work or the work provided to you by your professor, add the following message as a comment at the top of the file:
I have done all the coding by myself and only copied the code that my professor provided to complete my project milestones.
If the file contains work that is not yours (you found it online or somebody provided it to you), write exactly which part of the assignment is given to you as help, who gave it to you, or which source you received it from. By doing this you will only lose the mark for the parts you got help for, and the person helping you will be clear of any wrongdoing.
⚠️ This Submission Policy only applies to the project. All other assessments in this subject have their own submission policies.
If you have helped someone with your code. Let them know of these regulations and in an email write exactly which part of your code was copied and who was the recipient of this code.
By doing this you will be clear of any wrongdoing if the recipient of the code does not honour these regulations.
All your code should be compiled using this command on matrix:
g++ -Wall -std=c++11 -g -o ms file1.cpp file2.cpp ...-Wall: the compiler will report all warnings-std=c++11: the code will be compiled using the C++11 standard-g: the executable file will contain debugging symbols, allowing valgrind to create better reports-o ms: the compiled application will be namedms
After compiling and testing your code, run your program as follows to check for possible memory leaks (assuming your executable name is ms):
valgrind --show-error-list=yes --leak-check=full --show-leak-kinds=all --track-origins=yes ms--show-error-list=yes: show the list of detected errors--leak-check=full: check for all types of memory problems--show-leak-kinds=all: show all types of memory leaks identified (enabled by the previous flag)--track-origins=yes: tracks the origin of uninitialized values (g++must use-gflag for compilation, so the information displayed here is meaningful).
To check the output, use a program that can compare text files. Search online for such a program for your platform, or use diff available on matrix.
You can add the following two lines to the end of your .bash_profile file in your matrix home directory to create two aliases for the above C++ compilation and valgrind testing so you don't have to type such a long command to compile and execute your programs:
alias msc++="g++ -Wall -std=c++11 -g -o ms"
alias vrun="valgrind --show-error-list=yes --leak-check=full --show-leak-kinds=all --track-origins=yes"By adding the above to the '.bash_profile' (you must logoff and log back it so it takes effect) you can compile your c++ files as follows:
msc++ file1.cpp file2.cpp file3.cpp...<ENTER>The above will compile your files and if successful it will create an executable called ms.
vrun ms<ENTER>The above will execute your ms executable under the tester valgrind for detailed test on leaks and runtime errors.
Make sure that all the debugging code and debugging comments are removed before submission.
-
All the code written in this project should be within the namespace sdds.
-
You are free and encouraged to add any attributes(member variables), functions and methods (member functions) you find necessary to complete your code. If you are not sure about your strategy for adding functionalities and properties to your classes, ask your professor for advice.
-
If any methods are being added and they are not called outside the scope of the class, make sure they are private.
-
Unless you are asked for a specific definition, name the variables, and functions yourself. Use proper names and follow the naming conventions instructed by your professor. Having meaningless and misleading names will attract a penalty.
-
When creating methods (member functions) make sure to make them constant if in their logic, they are not modifying their class.
-
If an Empty state is required for an object, it is considered to be an “invalid” empty state, and objects in this state should be rendered unusable.
-
A module called Utils is added to the project that can be used for your custom functions and classes in your implementation. Leave this module empty if you don't have any custom functionalities.
You can add any custom code/class of your own to the Utils module to be used throughout the project. -
Throughout the project, if any class is capable of printing, displaying or writing itself, the member function will always have the following signature:
The function will return a reference of an ostream and will receive a reference on an ostream as an optional argument. If this argument is not provided, the object “cout” will be passed instead. -
Throughout the project, if any class is capable of reading or receiving its content from a stream, the member function will always have the following signature:
The function will return a reference of an istream and will receive a reference on an istream as an optional argument. If this argument is not provided, the object “cin” will be passed instead. -
When passing an object or variable by address or reference, if they are not to be modified, make sure they are passed as constant pointers and references.
-
You may reuse and copy any code your professor provided for your workshops or functions you may have from previous work in this subject or other subjects and place it in the Utils module.
We will start the development of the project by creating its user interface (MS1, PosApp module). Through this, we will create a mockup application that represents what the application will look like and act without actually doing anything. In short, we are creating a prototype of the application (in MS1) then coding its engine (in MS2, MS3 and MS4) and finally adding functionality to the POS system (MS1) to make it fully functional (in ms5, parts 1 to 5).
This Module contains one Module called PosApp. This module is responsible to offer the user a menu of features provided by the POS system.
The user, then, can select an option representing the feature and execute it. After the execution is complete, the system displays the menu again, until the user selects to exit the application.
- List Items
- Add Item
- Remove Item
- Stock Item
- Point Of Sale
For milestone 1 you are responsible to create a mockup module for the Point Of Sale that will demonstrate how the system is going to run (eventually) by only printing the name of the actions, instead of executing them. In later stages of development, you will replace these messages with the proper logic to actually perform the action.
Note that the signature of many of the methods created now will be changed to accommodate what needs to be done.
In module PosApp create a class with the same name (PosApp) having the following mandatory methods:
This method will display the menu of the system, and receive the user's choice (in a foolproof way and return the choice). See below:
The Sene-Store
1- List items
2- Add item
3- Remove item
4- Stock item
5- Point of Sale
0- exit program
> a
Invalid Integer, try again: -1
[0<=value<=5], retry: > 6
[0<=value<=5], retry: > 1
Running listItems()
Create the following 7 methods that only print Running and their names.
- addItem()
- removeItem()
- stockItem()
- listItems()
- POS()
- saveRecs()
- loadRecs()
PosApp is created by receiving the name of a file that is stored in character cString with a maximum length of 255 characters.
PosApp Can neither get copied nor assigned to another PosApp object. Your code must prevent such actions.
implement the following actions calling the corresponding mockup methods
This method first loads all the records and then displays the menu waiting for the user to make the selection. After the (foolproof) selection the proper action is executed and again the menu is displayed until the option exit is selected. In the latter case, all the records are saved and a Goodbye! message is displayed.
See the correct_output.txt file for sample execution.
The tester file for this output is main.cpp
PosApp.cpp
PosApp.h
Utils.cpp
Utils.h
main.cpp
abc
-1
6
1
2
3
4
5
0
If you would like to successfully complete the project and be on time, start early and try to meet all the due dates of the milestones.
Upload your source code and the tester program to your matrix account. Compile and run your code using the g++ compiler as shown in the introduction and make sure that everything works properly.
Then, run the following command from your account (replace profname.proflastname with your professor’s Seneca userid):
~profname.proflastname/submit 2??/prj/m1
and follow the instructions.
- 2?? is replaced with your subject code
~prof_name.prof_lastname/submit DeliverableName [-submission options]<ENTER>
[-submission option] acceptable values:
"-due":
Shows due dates only
This option cannot be used in combination with any other option.
"-skip_spaces":
Do the submission regardless of incorrect horizontal spacing.
This option may attract penalty.
"-skip_blank_lines":
Do the submission regardless of incorrect vertical spacing.
This option may attract penalty.
"-feedback":
Check the program execution without submission.Start the second milestone by creating a general header file for the constant values needed throughout the development of the project.
The name of this file is POS.h
Add the following constant values:
TAX: 0.13
MAX_SKU_LEN: 7
MIN_YEAR: 2000
MAX_YEAR: 2030
MAX_STOCK_NUMBER: 99
MAX_NO_ITEMS: 2000
We may add more values to this header file later. If you need any constant value for your code, add it here.
Create a class called Error. This class will be used as a smart flag in our future classes to keep track of the erroneous state of the object and the error message associated with it.
The Error class has only a character pointer as an attribute that holds the description of the error (the error message) in a dynamic C-string. (We will call this pointer the error message pointer from now on).
Note: naturally if the error message pointer is null, then the object is in a No Error state and if the error message is not null, then there is an error and the description of the Error is pointed by the error message.
- The Error class by default is in a "No Error" state. (its pointer is null)
- The Error class can also get created using an error message (a C-string). In this case, the Error object will be in an erroneous state.
The Error class can be copied and assigned to another Error object safely and must get destructed with no memory leak.
An Error object should be able to be assigned to a C-string. This will set the error message to the content of the C-string dynamically or nullptr if the C-String is null or empty.
If an Error object is casted to a bool, it should return true if the message is not null and false if it is null.
Error err;
...
...
if(err){
// there is an error
}
else{
// there is no error
}This method clears the error message and returns the reference of the current Error object. After this, the Error object should be in an "no Error" state with the message set to nullptr;
The Error message should be able to be inserted into an ostream object using the operator<<. If the Error object is not in an error state nothing will be inserted into the ostream object.
DO NOT use friend to implement this.
Implement and add any other method or operations you find necessary to accomplish the above tasks (make them private if they don't need to be publicly accessible)
- The date class encapsulates date and time properties in five integer attributes (year, month, day, hour and minute).
- Date also has a flag for using date only (no hour or minutes)
- Finally, Date has an Error attribute to keep track of the success of operations.
During the implementation of the Date class whenever validation is needed the attributes of the date are all checked in the following order and the Error object is set to the corresponding error message stated below.
The valid range of values for the year is defined in POS.h. Month values are between 1 and 12 and day values are between 1 and the return value of the daysOfMonth function
The valid range for time value is 0 t 23 for the hour and 0 to 59 for the minute.
Note that as soon as a validation fails, the Error object is set, and the rest of the validations will not take place
- If the year is invalid, then the Error object is set to
"Invalid Year" - If the month is invalid, then the Error object is set to
"Invalid Month" - If the day is invalid, then the Error object is set to
"Invalid Day" - If the hour is invalid, then the Error object is set to
"Invalid Hour" - If the minute is invalid, then the Error object is set to
"Invalid Minute"
The following functions are already implemented to help you with implementing different functionalities in the Date class. Use them (or their logic) wherever you find fit or necessary.
The following function retrieves the current date and time of the system and returns them through the argument list.
#define _CRT_SECURE_NO_WARNINGS
#include <ctime>
void getSystemDate(int& year, int& mon, int& day, int& hour, int& min, bool dateOnly) {
time_t t = time(NULL);
tm lt = *localtime(&t);
day = lt.tm_mday;
mon = lt.tm_mon + 1;
year = lt.tm_year + 1900;
if(dateOnly) {
hour = min = 0;
} else {
hour = lt.tm_hour;
min = lt.tm_min;
}
}The following function assigns a unique integer value to a date-time value. Using this value you can compare two dates. (i.e if the unique value of one date is greater than the unique value of another date, then the first date is larger than the second one)
int uniqueDateValue(int year, int mon, int day, int hour, int min) {
return year * 535680 + mon * 44640 + day * 1440 + hour * 60 + min;
}To find out what is the maximum valid value for a calendar day in a month you can use this function. This function gets the year and the month and gives you the correct value for the number of days in that month (considering the leap year).
int daysOfMonth(int year, int month){
int days[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, -1 };
int mon = month >= 1 && month <= 12 ? month : 13;
mon--;
return days[mon] + int((mon == 1) * ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0));
}- By default date is created and set to the current system date and will be set not to be date-only (it will include the hour and the minute)
- A date can get created by receiving the date; (year, month and day values only). In this case, the Date object will be set to date-only mode. After the attributes are set, they are validated.
- A date can get created using date and time; (year, month, day, hour and minute). In this case, the Date object will not be set to date-only mode. After the attributes are set, they are validated.
Overload all the comparison operator overloads to compare two date objects and return a boolean.
(==, != , < , > , <= , >=)
Make sure the references and methods are constant if they don't change the state of their objects and classes.
Create a method called dateOnly that receives a boolean and returns the reference of the current date class.
This method should set the date-only flag to the value received from the argument of the function. However, if the function argument is "true" which sets the object to date only, then the hour and minute attributes of the date should be set to zero.
In any case, the reference of the current object is returned.
Overload the bool type conversion operator and return the opposite of the state of the error attribute.
Create a method called error that returns a constant reference of the error attribute object. This query does not change the state of the Date class.
Implement and add any other method or operations you find necessary to accomplish the above tasks (make them private if they don't need to be publicly accessible)
Overload the insertion operator to insert a Date into the ostream object. the result of the insertion should be as follows:
If the Date is in the date-only more, print the date in the following format: YYYY/MM/DD
If the Date is not in the date-only mode, print the date and time in the following format: YYYY/MM/DD, HH:MM
Insert the error attribute into ostream to print the error message held in the error attribute then print the date and time exactly as shown before but surrounding them with parenthesis.
Date A(2023,10,20);
Date B(2023,10,20,14,30);
Date C(2023,10,20,26,72);
cout << A << endl << B << endl << C << endl;
/* output:
2023/10/20
2023/10/20, 14:30
Invalid Hour(2023/10/20, 26:72)
*/DO NOT use friend to implement this. implement member functions to access the data instead.
Overload the extraction operator to read a date from istream in the same format it is printed.
First, clear the error object to make sure the date is not in an erroneous state and set all the date and time attributes to zero.
Then read the date values by reading the five integers (if date and time) or the three integers (if date only), and ignoring the delimiters in the data entry.
Note that you do not need to verify the delimiters to be exactly what the printed format is.
For example, the following three date Entries are all valid:
2023/10/20, 26:72 <<- date and time
2023-10-20*26-72 <<- date and time
2023_10_20 <<- date only
After reading each integer, check the status of istream, if it is not in a fail state, ignore the next character and read the next integer. If the istream is in a fail state, set the error object to the corresponding error message (see below) and skip the rest of the entries. If all the integers were read successfully validate the date values.
"Cannot read year entry"
"Cannot read month entry"
"Cannot read day entry"
"Cannot read hour entry"
"Cannot read minute entry"
2023/10/abc, 20:20
The Error message should be set to "Cannot read day entry" and extration is stopped having istream left in error sate
Note if the Date is in read-only mode, after reading the three date integers, set hour and minute to zero.
In any case, at the end return the reference of istream.
Check each state of your program with the following testers. The main tester at submission combines all these tests.
- 01-ErrorTester.cpp - output
- 02-constantValueTests.cpp - output
- 03-DateConstructorTests.cpp - output
- 04-DateLogicalOperators.cpp - output
- 05-DateValidation.cpp - output
If you would like to successfully complete the project and be on time, start early and try to meet all the due dates of the milestones.
Upload your source code and the tester programs to your matrix account. Compile and run your code using the g++ compiler as shown in the introduction and make sure that everything works properly.
Then, run the following command from your account (replace profname.proflastname with your professor’s Seneca userid):
~profname.proflastname/submit 2??/prj/m2
and follow the instructions.
- 2?? is replaced with your subject code
~prof_name.prof_lastname/submit DeliverableName [-submission options]<ENTER>
[-submission option] acceptable values:
"-due":
Shows due dates only
This option cannot be used in combination with any other option.
"-skip_spaces":
Do the submission regardless of incorrect horizontal spacing.
This option may attract penalty.
"-skip_blank_lines":
Do the submission regardless of incorrect vertical spacing.
This option may attract penalty.
"-feedback":
Check the program execution without submission.Before starting milestone 3, add the following constant values to POS.h header file:
MAX_NAME_LEN: 40
POS_LIST: 1
POS_FORM: 2
ERROR_POS_SKU: "SKU too long"
ERROR_POS_NAME: "Item name too long"
ERROR_POS_PRICE: "Invalid price value"
ERROR_POS_TAX: "Invalid tax status"
ERROR_POS_QTY: "Invalid quantity value"
ERROR_POS_STOCK: "Item out of stock"
ERROR_POS_EMPTY: "Invalid Empty Item"
For the third milestone of the project, you will create two classes: PosIO and Item. Milestone 3 is dependent on the Error class only. (You do not need the other classes created in milestones 1 and 2 at this stage)
Create a class called PosIO as an interface for console and file input and output operations. This class will only define 4 pure virtual methods and a virtual empty destructor.
Receives and returns references of ostream. This method does not modify its owner.
Receives and returns references of istream.
Receives and returns references of ofstream. This method does not modify its owner.
Receives and returns references of ifstream.
Implement two insertion operator<< operator overloads that invoke the write and save pure virtual methods to work with ostream and ofstream.
Implement two extraction operator>> operator overloads that invoke the read and load pure virtual methods to work with istream and ifstream.
Create a class called Item to encapsulate an Item to be sold by the POS system.
The Item class has the following mandatory attributes:
A C-string to keep an SKU code up to MAX_SKU_LEN characters.
A dynamically allocated C-string to keep the name of the Item up to MAX_NAME_LEN characters.
A double value
A boolean that indicates if the Item is taxable or not.
An integer value for the stock number of the Item. (number of items in the shop)
An integer flag that can be either POS_LIST to display the Item in List mode or POS_FORM to display the Item in Form mode.
An Error object to keep the error status of the Item.
Item is instantiated using no arguments. In this case, an Item is set to an invalid Empty state (we will refer to this as empty from now on).
An Item can be copied or assigned to another item safely and is destroyed with no memory leak.
Compares an Item to a C-string and returns true if the C-sting is a match to the SKU code of the Item.
Compares two items alphabetically based on their names.
Adds an integer value (right-hand operand) to the quantity and returns the quantity. If the sum of the value and the quantity exceeds the MAX_STOCK_NUMBER then the quantity will be set to MAX_STOCK_NUMBER and the Item error will be set to ERROR_POS_QTY.
Reduces the quantity by the right-hand value and returns the quantity. If the value is more than the quantity then the quantity will be set to zero and the Item error will be set to ERROR_POS_STOCK.
Returns the opposite of the status of the error attribute. This method does not modify the object.
Overload the operator+= to receive a double reference as the left-hand operand and a constant reference of Item as the right-hand operator. This operator should add the product of cost() by quantity() of the Item to the double operand and then return the value.
This pure virtual method returns a character as the type indicator of the item in future descendants of the Item. This method does not modify the object.
Receives an integer (POS_LIST or POS_FORM) and sets the corresponding attribute. This method returns the reference of the current object.
Returns the cost of the Item; that is the price of the item (plus tax if the item is taxable). This method does not modify the object.
Returns the quantity of the Item. This method does not modify the object.
Clears the error status of the object and then returns the reference of the current object.
Implement the four pure virtual methods of the base class as follows:
- If in POS_LIST mode, it will print the object as follows:
1234 |Screw Driver | 12.32| X | 90| 1252.94|
4567 |Tape Measure - Level| 112.30| | 10| 1123.00|
- Name: if longer than 20 characters, only the first 20 will be printed
- Taxed: if true
Xis printed or else space - After the line is printed, no newlines are printed.
- If in POS_FORM mode, it will print as follows:
=============v
Name: Screw Driver
Sku: 1234
Price: 12.32
Price + tax: 13.92
Stock Qty: 90
=============v
Name: Tape Measure - Level - Laser - Combo
Sku: 4567
Price: 112.30
Price + tax: N/A
Stock Qty: 10
- At the end, a newline is printed.
- If the Item is erroneous only the error object is printed (with no newline after).
In the end, the ostream reference is returned.
Save the data in a comma-separated format as follows:
First, the itemType is printed and then all the attributes are saved separated by commas. No newline is saved at the end.
In the following example, we assume the derived class's itemType function is returning 'T'.
T,1234,Screw Driver,12.32,1,89
T,4567,Tape Measure - Level - Laser - Combo,112.30,0,9
If the Item is erroneous the error object is inserted into cerr and not the ofstream (with a newline after).
In the end, the ofstream reference is returned.
Performs fool-proof data entry.
The attributes are read in the following order:
SKU, Name, Price, Taxed or not and Quantity.
After each data entry, the value is validated, if invalid the proper error message is printed and in the next line at the prompt (>) the value is re-entered. This repeats until a valid value is entered. See Execution Sample.
In the end, the reference of istream is returned.
Sku
> 12345
Name
> Hammer
Price
> 23.99
Taxed?
(Y)es/(N)o: y
Quantity
> 35
First, the error status will be cleared
Then reads all the values from the ifstream object in a comma-separated format (assuming the data begins with the SKU) in local variables (not directly into the attributes of the item).
If after the reading the ifstream is not in a failure state, it will validate the values one by one and if any of the validation fails, the error message is set to the proper message and validation stops.
At the end of the validation process, if there is no error, the attributes are set to the validated values.
The reference of the ifstream object is returned at the end.
This function will receive and return the ostream object. The bill print function will only print the Name, taxed price, and if the item is taxed or not:
| Screw Driver | 13.92 | T |
| Tape Measure - Level| 112.30 | |
- Name: only the first 20 characters are printed
- Taxed: if the item is taxed,
Tand otherwise, a space is printed.
POS.h
Error.cpp
Error.h
PosIO.cpp
PosIO.h
Item.cpp
Item.h
Utils.cpp
Utils.h
main.cpp
If you would like to successfully complete the project and be on time, start early and try to meet all the due dates of the milestones.
Upload your source code and the tester program to your matrix account. Compile and run your code using the g++ compiler as shown in the introduction and make sure that everything works properly.
Then, run the following command from your account (replace profname.proflastname with your professor’s Seneca userid):
~profname.proflastname/submit 2??/prj/m3
and follow the instructions.
- 2?? is replaced with your subject code
~prof_name.prof_lastname/submit DeliverableName [-submission options]<ENTER>
[-submission option] acceptable values:
"-due":
Shows due dates only
This option cannot be used in combination with any other option.
"-skip_spaces":
Do the submission regardless of incorrect horizontal spacing.
This option may attract penalty.
"-skip_blank_lines":
Do the submission regardless of incorrect vertical spacing.
This option may attract penalty.
"-feedback":
Check the program execution without submission.Inherit a concrete class called NonPerishable from the Item class.
Override the pure virtual function itemType and return the character 'N' to identify this Item to be non-perishable.
Override the write function to complete the writing of an Item in POS_LIST and POS_FORM.
To accomplish this first call the write of the Base class and then if the Object is in a good state do the following:
If the display type is LIST then print the following to indicate this Item does not have an expiry date:
" N / A |"
If the display type is FORM close the data display by printing the following line and printing newline:
"=============^"
If the object is not in a good state, nothing extra is printed.
Inherit a concrete class called Perishable from the Item class.
Add a Date attribute for the expiry date of the perishable item.
Override the pure virtual function itemType and return the character 'P' to identify this Item to be perishable.
Override all the Input and output functions of the Base class as follows:
Invoke the read of the Base class.
If the object is not in a good state or istream has failed, do nothing, otherwise, if the object and the istream are in a good state, create a local instance of Date and set it to date only. then prompt the user as follows:
Expiry date(YYYY/MM/DD)
> _
and extract the date from the istream. If the date is in a good state, set the expiry date to the extracted date, if not, set the error object of the Item to the error of the Date.
Invoke the write of the base class.
If the object is not in a good state, do nothing otherwise, If the object is in POS_LIST display mode print the date as follows:
- space
- date
- space
'|'
If the object is in POS_FORM display mode print the date as follows:
"Expiry date: "- Date
- newline
"=============^"- newline
Invoke the load of the Base class.
If the object is not in a good state or ifstream has failed, do nothing, otherwise, if the object and the ifstream are in a good state, create a local instance of Date and set it to date only. Ignore one character to pass the comma. Then extract the date from the ifstream. If the date is in a good state, set the expiry date to the extracted date, if not, set the error object of the Item to the error of the Date.
Invoke the save of the Base class.
If the object is in a good state, insert a comma and then the expiry date into ofstream, otherwise, do nothing.
POS.h
Date.cpp
Date.h
Error.h
Error.cpp
PosIO.h
PosIO.cpp
Item.h
Item.cpp
NonPerishable.h
NonPerishable.cpp
Perishable.h
Perishable.cpp
Utils.h
Utils.cpp
main.cpp
nonPerInput.csv
perishableInput.csv
If you would like to successfully complete the project and be on time, start early and try to meet all the due dates of the milestones.
Upload your source code and the tester program to your matrix account. Compile and run your code using the g++ compiler as shown in the introduction and make sure that everything works properly.
Then, run the following command from your account (replace profname.proflastname with your professor’s Seneca userid):
~profname.proflastname/submit 2??/prj/m4
and follow the instructions.
- 2?? is replaced with your subject code
~prof_name.prof_lastname/submit DeliverableName [-submission options]<ENTER>
[-submission option] acceptable values:
"-due":
Shows due dates only
This option cannot be used in combination with any other option.
"-skip_spaces":
Do the submission regardless of incorrect horizontal spacing.
This option may attract penalty.
"-skip_blank_lines":
Do the submission regardless of incorrect vertical spacing.
This option may attract penalty.
"-feedback":
Check the program execution without submission.Each submission tests one menu option of the PosApp and requires some of the functions of the PosApp of MS1 to be completed (implemented).
After completion of each section upload your updates to the matrix and issue the submission command for that part:
~profname.proflastname/submit 2??/prj/m5#
??is replaced with your subject code (00or44)#is replaced with the menu option number (1to5)
The tester program for all MS5 submissions is the same main.cpp but each menu option has test data of its own.
The file posdataOrigin.csv contains some sample data that is added to help you debug your code. The data in this file overwrites the data file the main.cpp uses every time it runs, to make sure you always start your program with the same data set, so you can debug your code more easily.
Also, the content of the data file is displayed before and after the POS test is done so you can track the data changes and make sure your program works correctly.
Note that the content of the initial data may and probably will change when you are submitting your project milestones (by the submitter program). Each data set will have the information needed to check the logic that is being tested at the time.
Create a file called reflect.txt and add the following:
- Citation, for any part of the code that is not yours.
- Any additional (extra) work done that needs your professor's attention.
- Your overall reflection on the project and work done in the milestones (can be done only in your last submissions of milestone 5)
The bill class is fully implemented and uses the bprint method of the item to print a bill.
Study the Bill class and understand how it works.
Complete the code of the PosApp as follows
A C-string (max 128 chars) to keep the data file name of items
An array of Item pointers with the size MAX_NO_ITEMS (MAX_NO_ITEMS set to be 200 in POS.h; modify it if it is not 200)
we will call this array
Iptrfrom now on
An attribute to hold the number of items in the PosApp. This number indicates how many of the Iptr pointers are used in the array to keep the items in the Inventory.
we will call this number
nptrfrom now on
Every time an action title is requested print the following:
- print
">>>> " - print the title in 73 spaces, left justified filled with
'.'character.
Implement the loadRecs method to load all the records of the data file into the Iptr array. Each Iptr pointer should point to a dynamically allocated Item (Perishable or NonPerishable).
- Print the action title
Loading Items. - open the data file in an
ifstreamobject (we will call thisinputhere). - if opening the file was not successful create the file by opening and closing it using an
ofstreamobject. - Empty the
PosAppclass (make sure there are no Items in theIptr) - while the
inputis in a good state and theIptrarray is not full,- read one character
- create a dynamic Item (either
Perishable, orNonPershable) based on the character beingPorNand keep the address in the next availableIptrpointer - extract the Item from the
inputand add one to thenptr
Implement the saveRecs to save all the items pointed by Iptr array in the data file.
- Print the action title
Saving Data. - Create an instance of ofstream using the data filename.
- loop through the Items pointed by the
Iptrpointers and insert them into the ofstream instance up tonptr.
- Print the action title
Listing Items. - Sort all the Items in
Iptrarray based on their name in ascending order. - Print the Title/Header of the list:
Row | SKU | Item Name | Price |TX |Qty | Total | Expiry Date |
-----|--------|--------------------|-------|---|----|---------|-------------|
- Loop through the items up to
nptrand display the row and theItemsinPOS_LISTformat, calculating the total asset value of theItems. Total asset is the sum of (cost() * quantity) of each item. see Total asset calculation - Print the footer and the total asset as follows:
-----^--------^--------------------^-------^---^----^---------^-------------^
Total Asset: $ | 9999.99|
-----------------------------------------------^--------------^
Note: to make sure not to have a different outcome for the total asset because of the
doubletype's imprecise operations, add this method to your item to calculate the cost of an item, havingm_pricebeing the price of the item andm_taxedthe flag for the item being taxed or not:
double Item::cost()const {
return m_price * (1 + m_taxed * TAX);
}1
0
~profname.proflastname/submit 2??/prj/m51
Complete the implementation of addItem to add a new item to the inventory
- Print the action title
Adding Item to the store. - if the number of items is at maximum, print
"Inventory Full!"and exit the function. - if not, create a pointer to an item and ask the user if the item is perishable
- Based on the user's answer dynamically create an instance of an Item (Perishable or NonPerishable) and keep the address in the Item pointer
- In a loop extract the item from cin
- if the item is not in a good state
- clear cin
- flush keyboard
- insert the item into cout
- insert
", try again...\n" - repeat the loop
- if the item is in a good state add the item address to the next available element of
Iptrand increase thenptr. - Print the action title
DONE!.
2
y
1111
Orange
3.99
n
20
2023/04/21
2
n
2222
Tea
12.22
y
10
0
~profname.proflastname/submit 2??/prj/m52
To be able to remove an item, you must first provide the facility to select an Item.
Implement a method called selectItem() to list the items EXACTLY like the listItems function (except that the total asset is not shown) and then ask the user to select an Item by entering the row number, and then return that row number.
- Print the action title
Item Selection by row number. - Then pause so the user can see what action is being taken by printing this prompt:
Press <ENTER> to start.... - Print the action title
Listing Items. - List the items (see hint below)
- Prompt:
Enter the row number: - perform a fool-proof entry of an integer between 1 and the number of
Items listed. - return the integer
hint: It would be nice to have your
listItemsmethod receive a bool argument to turn the total asset display on and off so you can reuse the function here.
Assuming there are only 7 items in the system:
>>>> Item Selection by row number............................................
Press <ENTER> to start....
>>>> Listing Items...........................................................
Row | SKU | Item Name | Price |TX |Qty | Total | Expiry Date |
-----|--------|--------------------|-------|---|----|---------|-------------|
1 | 5228 |7up 12 pack | 6.49| X | 20| 146.67| 2017/05/31 |
2 | 7913 |Banana | 0.44| | 99| 43.56| 2017/05/21 |
3 | 3854 |Beefsteak Pie | 5.29| X | 40| 239.11| 2017/05/25 |
4 | 3456 |Bic Pen(Blue) | 1.49| X | 80| 134.70| N / A |
5 | 6458 |Blueberries | 3.99| | 30| 119.70| 2017/05/18 |
6 | 4567 |Butter | 4.56| X | 9| 46.38| 2017/05/15 |
7 | 3815 |Chicken Alfredo | 4.49| X | 20| 101.47| 2017/05/23 |
-----^--------^--------------------^-------^---^----^---------^-------------^
Enter the row number: abc
Invalid Integer, try again: -1
[1<=value<=7], retry: Enter the row number: 8
[1<=value<=7], retry: Enter the row number: 5
The function will return 5
Prompt the user and remove an item by letting the user select the item from the list of items.
- Print the action title
Remove Item. - call the selectItem to get the row number of the Item (row number is index + 1 in
Iptrarray) - print
Removing....and show the item that is about to be removed inPOS_FROMformat. - deallocate and remove the item from the
Iptrarray (see illustration) - Print the action title
DONE!.
>>>> Remove Item.............................................................
>>>> Item Selection by row number............................................
Press <ENTER> to start....
>>>> Listing Items...........................................................
Row | SKU | Item Name | Price |TX |Qty | Total | Expiry Date |
-----|--------|--------------------|-------|---|----|---------|-------------|
1 | 5228 |7up 12 pack | 6.49| X | 20| 146.67| 2017/05/31 |
2 | 7913 |Banana | 0.44| | 99| 43.56| 2017/05/21 |
3 | 3854 |Beefsteak Pie | 5.29| X | 40| 239.11| 2017/05/25 |
4 | 3456 |Bic Pen(Blue) | 1.49| X | 80| 134.70| N / A |
5 | 6458 |Blueberries | 3.99| | 30| 119.70| 2017/05/18 |
6 | 4567 |Butter | 4.56| X | 9| 46.38| 2017/05/15 |
7 | 3815 |Chicken Alfredo | 4.49| X | 20| 101.47| 2017/05/23 |
-----^--------^--------------------^-------^---^----^---------^-------------^
Enter the row number: 5
Removing....
=============v
Name: Blueberries
Sku: 6458
Price: 3.99
Price + tax: N/A
Stock Qty: 30
Expiry date: 2017/05/18
=============^
>>>> DONE!.................................................................
In this illustration user has selected item number 4.
3
<ENTER>
abc
-1
27
5
0
~profname.proflastname/submit 2??/prj/m53
When this option is selected, user will select an Item from the Items list and then the Item will be displayed on the screen in POS_FORM format. Then the user will be asked to add the number of items to be added to the quantity of the Item. This value can be between 1 and the current number of items minus the MAX_STOCK_NUMBER.
After the user enters the number, it will be added to the quantity of the Item.
- Print the action title
Select an item to stock. - call the seletItem method and get the row number
- Print
Selected Item:\n - display the select Item
- Prompt
Enter quantity to add: - get and integer (fool-proof)
- Add the quantity to the item
- Print the action title
DONE!.
>>>> Select an item to stock.................................................
>>>> Item Selection by row number............................................
Press <ENTER> to start....
>>>> Listing Items...........................................................
Row | SKU | Item Name | Price |TX |Qty | Total | Expiry Date |
-----|--------|--------------------|-------|---|----|---------|-------------|
1 | 5228 |7up 12 pack | 6.49| X | 20| 146.67| 2017/05/31 |
2 | 7913 |Banana | 0.44| | 99| 43.56| 2017/05/21 |
3 | 3854 |Beefsteak Pie | 5.29| X | 40| 239.11| 2017/05/25 |
4 | 3456 |Bic Pen(Blue) | 1.49| X | 80| 134.70| N / A |
5 | 6458 |Blueberries | 3.99| | 30| 119.70| 2017/05/18 |
6 | 4567 |Butter | 4.56| X | 9| 46.38| 2017/05/15 |
7 | 3815 |Chicken Alfredo | 4.49| X | 20| 101.47| 2017/05/23 |
-----^--------^--------------------^-------^---^----^---------^-------------^
Enter the row number: 5
Selected Item:
=============v
Name: Blueberries
Sku: 6458
Price: 3.99
Price + tax: N/A
Stock Qty: 30
Expiry date: 2017/05/18
=============^
Enter quantity to add: abc
Invalid Integer, try again: 0
[1<=value<=69], retry: Enter quantity to add: 70
[1<=value<=69], retry: Enter quantity to add: 10
>>>> DONE!.................................................................
4
<ENTER>
abc
-1
27
5
abc
0
70
10
0
~profname.proflastname/submit 2??/prj/m54
The
posdataOrigin.csvfile is updated to accommodate the testing of this section, make sure to pull the change.
To finalize your project implement the POS() method of the PosApp Module.
In this method, you are to ask the user for the SKU of items to sell and if the SKU is found and the item is available (Quantity > 0) then reduce the quantity by one and add the item to the Bill and print the total price of the bill so far.
If instead of entering the SKU user just hits enter with no data entry, then you will finalize the sale by printing the Bill.
>>>> Starting Point of Sale..................................................
Enter SKU or <ENTER> only to end sale...
> 1627
=============v
Name: Peaches
Sku: 1627
Price: 1.44
Price + tax: N/A
Stock Qty: 13
Expiry date: 2017/06/01
=============^
>>>>> Added to bill
>>>>> Total: 1.44
Enter SKU or <ENTER> only to end sale...
> 4297
=============v
Name: Lays Chips S&V
Sku: 4297
Price: 3.69
Price + tax: 4.17
Stock Qty: 0
Expiry date: 2017/05/26
=============^
>>>>> Added to bill
>>>>> Total: 5.61
Enter SKU or <ENTER> only to end sale...
> 4297
Item out of stock
Enter SKU or <ENTER> only to end sale...
> 1111
!!!!! Item Not Found !!!!!
Enter SKU or <ENTER> only to end sale...
>
v---------------------------------------v
| 2023/03/31, 10:44 |
+---------------------v-----------v-----+
| Item | Price | Tax +
+---------------------v-----------v-----+
| Peaches | 1.44 | |
| Lays Chips S&V | 4.17 | T |
+---------------------^-----------^-----+
| total: 5.61 |
^---------------------------------^
To accomplish this we suggest the creation of a relatively simple method called search first. This method receives the SKU and returns the address of the item in the Iptr array if the matching SKU is found in the array, or otherwise nullptr.
Having this function to implement the POS() method do the following:
- Print the action title
Starting Point of Sale.
Keep getting the SKU (up to MAX_SKU_LEN characters) in a local C-string Until the SKU is empty and in the loop:
- if SKU is not empty end the istream is not in a fail state
- Search for the item
- if found reduce the quantity by one and print the item in
POS_FORMformat.- If reduction was successful add the item to the bill and print
>>>>> Added to bill>>>>> Total: <bill total so far> - if the reduction was not successful, clear the error state of the item
- If reduction was successful add the item to the bill and print
- if not found print:
!!!!! Item Not Found !!!!!
- if istream is in a fail state print:
SKU too long
and clear and flush the istream.
After the loop print the bill.
5
1111
9318
9318
4297
4297
1212
<ENTER>
0
~profname.proflastname/submit 2??/prj/m55
