Shipping Account

• Create a functioning C++ program using multiple functions.

• Write if and switch statements to control what code is run.

• Create loops to perform the same action multiple times.

• Write expressions to calculate values.

• Divide code into header and source files.

• Write tests to determine if the output of the program is correct.

• Provide appropriate documentation for a file and its functions in the Doxygen format.

Overview

This project has you create a program that generates a summary report on a company’s shipping accounts. The program will read through a file that contains a list of accounts and their associated shipping activity and then process that data.

 

Important Note: Do not put spaces in the file name of your file. The file needs to end in .cpp (not .c, .CPP, etc.) to compile correctly.

 

Project Specifications

1. The company Ship2U is running a report to look at which companies they are shipping to and to do a simple ranking of those companies. The rankings are based on the amount of money they have spent on shipping and on the relative distance of those companies to Ship2U’s location (closer is better).

To build this report, each company’s location will need to be categorized (a shipping type) based on their location code and the amount of money spent on shipping will need to be summed.

Based on this information, a shipping status will be calculated. Companies that have a higher amount spent and are closer to Ship2U will have a higher status.

 

Your job is to take the data for each account and determine the shipping type, the amount spent on shipping and the shipping status. This information will then be put into a readable report.

 

To do this you will need to do the following

a. Get the input file name.

 

i. If it does not exist, the program should produce an error message and end.

 

b. Get the output file name.

 

c. Go through the input file line by line and process the data. This is done by:

 

i. Getting the company id.

 

ii. Getting the location code.

 

iii. Determining the shipping type (local, national, international).

 

iv. Summing the amount spent on shipping.

 

d. If a line is read incorrectly, the shipping status should be calculated and the resulting data should be printed to the output file, formatted correctly.

 

File Format

Input File

The input files contain a list of the companies and their information. Each line represents a separate account. The basic format for each line is:

 

<company id> <location code> <amount> …

 

The <company id> is the id of the company on this account. Company ids do not have spaces.

 

The <location code> is the location of the company. Location codes do not have spaces in them. This will be used to compute the shipping type.

 

At the end of each line is 0 or more amounts for this account. These are double values.

 

The first 2 values are required and must be there for the line to be valid. There do not have to be any amounts listed.

Examples:

ARY16741 az-2229 8079.07 6796.97

 

<company id> = ARY16741, <location code> = az-2229 ARY16741 has two amounts: 8079.07 6796.97.

BXW44833 ne-3061 5908.6 7246.26 8067.51 9577.39 6454.73 6978.08 5511.99 6718.03

 

<company id> = BXW44833, <location code> = ne-3061

 

BXW44833 has 8 amounts: 5908.6, 7246.26, 8067.51, 9577.39, 6454.73, 6978.08, 5511.99, and 6718.03.

 

See the provided files for additional examples.

 

Output File

The output file (the shipping account report) will have lines formatted as follows:

 

<company id> <shipping type> <total amount> <status graph> The <company id> is the id of the company on this account.

The <shipping type> is a text description of the shipping type (see getShippingString below). The <total amount> is a sum of all of the amounts spent on shipping for the account.

The <status graph> is a bar graph of '*' characters. The number of '*'s corresponds to the shipping status of the account (see getStatus below).

 

The report starts with a header that looks like: Shipment Activity

Each line in the report should look something like:

 

Examples

ARY16741 Local 14876.04 ***

 

<company id> = ARY16741, <shipping type> = Local, <total amount> = 14876.04, <status graph> = *** BXW44833 Non-Local 56462.59 **

<company id> = BXW44833, <shipping type> = Non-Local, <total amount> = 56462.59, <status graph>

= **

 

See the provided files for additional examples.

Activities

1. To implement this program, you will need to implement (and test) 10 functions. Each function will solve part of the problem and some of the functions will require other of your functions to work correctly. Each function will also need to be documented.

 

2. This project will use separate compilation. Your function declarations should be in a header file called p2.h.

 

Your function definitions should be in a .cpp file.

 

3. You are required to test your work. See each function for a description of what is required. You can use the main function to test individual functions. See the testing section below for some hints on how to test your code.

 

4. Create an enum called ShippingType. This should be declared in the header file. Use the newer form of C++ enums (the one that uses the keyword class in the declaration). The values for the enum should be (in order):

 

a. LOCAL

b. NATIONAL

c. INTERNATIONAL

Important Note: The order and spelling of the enum and its values are important, and errors here will cause the program not to compile on my end

 

Note: To document an enum with Doxygen, just add a /** */ above the enum and describe its purpose.

5. Implement the following functions. Test them and document them as you go. Think about where you can use these functions to help implement some of the others.

 

a. Create a function called isFileThere that takes a string (a file name) as a parameter. It should return a bool (true if the file exists and false if it does not). In the function, open the file and determine if the file was successfully opened. (You probably want to use the good function here.) If it was, return true. Otherwise, return false.

 

Make sure you use an ifstream and not an ofstream; ofstreams create the file if they do not exist.

 

There are no required tests for this function but it would be useful to test this in main.

 

b. Create a function called getShippingType that takes a string parameter (a location code) and returns a ShippingType (your enum type). This function will take a location code

 

and determine which shipping type is associated with that location. The first 2 characters of the location code can be used to determine this. See the table below.

 

To get the first 2 characters of the file name, use the substr member function. You must have at least 3 tests for this function. Put the inputs and expected outputs in the documentation for the function.

c. Create a function called getShippingString that takes a ShippingType (your enum) and

returns a string (the shipping type as text).

 

The text for the shipping type can be found using the following table. Use a switch statement to implement this functionality.

 

You must have at least 3 tests for this function. Put the inputs and expected outputs in the documentation for the function.

d. Create a function called getStatus that takes a double (the amount of money spent on shipping) and a ShippingType (your enum; where it is being shipped to) and returns an  int (the shipping status).

 

This function determines the shipping status based on the amount of money the company has spent on shipping and its location. More money and closer locations mean a better (higher) shipping status (which leads to better customer service, etc.).

 

First, determine the shipping status value based on the amount spent on shipping. Use the table below to determine the value.

 

Next, check the shipping type. If the shipping type is LOCAL, increase the status by 1. If the shipping type is INTERNATIONAL and the level is as least 2, decrease the status by 1.

 

You must have at least 4 tests for this function. Put the inputs and expected outputs in the documentation for the function.

 

e. Create a function called dupChar that takes a char (the character that will be in the string) and an int (the number of characters in the string). It should return a string (the created string).

 

Create a string of the desired length made up of the char parameter. Use a for loop to repeatedly add the char to a string until it is the right length.

 

You must use a for loop here.

If the desired length is 0 or negative, this will return an empty string (i.e., ""). Example:

If the char is '=' and the length is 3, you will get "===" as a result.

You must have at least 3 tests for this function. Put the inputs and expected outputs in the documentation for the function.

f. Create a function called sumAmounts that takes an istream as a parameter (the input to read from) and returns a double (the sum of all of the amounts in that input).

 

Valid amounts are greater than 0. If an amount is less than 0, do not sum it.

 

Using a loop, read doubles from the input and sum them if they are greater than 0. (This should be a pretty short loop.)

 

Return the sum when you are done.

 

You must have at least 3 tests for this function. Put the inputs and expected outputs in the documentation for the function.

g. Create a function called processAccountInfo. It should take an istream (input to read from), a string (the company id), a double (the amount spent on shipping) and a ShippingType (your enum). It should return a bool (true if the shipping account info was successfully read and false if it was not).

Because the caller wants the company id, amount, and shipping type, those parameters should be passed by reference. (There are better ways of doing this, but this will work for the moment.)

Each line of the file should contain the information for a shipping account. However, because of a bug in the code that generated the input files, not all of the lines have all the required data. You will need to check for this and return false if some of the data is missing.

To read in the data,

 

i. Read in one complete line from the input stream (the parameter).

 

ii. Use that line to create a stringstream. You will use this stringstream to get the shipping account’s information from that line.

 

1. Do not use the istream parameter any more in this function. All of the rest of reading should be done with the stringstream.

 

i.

ii.

iii. Read in the company id. This will not have any spaces in it.

 

iv. Read in the location code. This will be a string without any spaces in it.

 

v. At this point, all of the required data has been read in. If the stringstream (not the parameter) is not valid, return false. This indicates that the something failed as it was being read in.

 

vi. If the stringstream is still good, read in and sum the amounts for this shipping account (use one of your functions for this). This will be the amount spent on shipping you report for this account.

 

vii. Use the location code to determine the shipping type for this account. Use one of your functions to do this.

 

viii. Make sure that all of the parameters (company id, amount and shipping type) have the new values that were read in/calculated and return true.

You must have at least 3 tests for this function. Put the inputs and expected outputs in the documentation for the function. See the input file format for what the input should look like.

h. Create a function called printAccountInfo. It should take an ostream (output to write to), a string (the company id), a double (the amount spent on shipping) and a ShippingType (the shipping type for this company). It should return nothing.

Using the parameters, print to the output stream the company id, the shipping type (as text), the amount and a bar graph of '*' characters that indicate the shipping status of the account (see below).

Use one of your functions to get the shipping type as text from the ShippingType parameter.

Use another of your functions to get the shipping status of the account.

With the shipping status, create a bar graph of '*' characters. The number of '*'s in the graph should equal the value of the shipping status (i.e., if the status is 2, then the graph is: "**"; if it is 4, then the graph is: "****", etc.). Use another one of your functions to do this.

The company id should be left aligned with a width of at least 20.

The shipping type (as text) should be left aligned with a width of at least 12.

The amount should be right aligned with a width of at least 15 and exactly 2 decimal points.

Make sure there are spaces between the values. Add a line feed at the end.

 

h. There are no required tests for this function, but it would be useful to test this in main.

See the sample output files for examples.

 

i. Create a function called processReport that takes two strings as parameters (the input file name and the output file name). It should return nothing. This function will create the report for the shipping accounts.

In the function, open the input and output file. If both are good, create a title for the shipping accounts report and write it to the output file. The title of the report should be "Shipment Activity". See the sample output files for examples.

After writing the title to the file, read through the entire input file. Get the shipping account information from the input file and write it to the output file. Use your functions for this.

Only print the shipping account information if the data was read correctly from the input file (how would you know that?).

If there is an invalid line, that line should be skipped, and the rest of the file should still be processed. Do not stop your loop if something is invalid.

Make sure you close your files at the end.

 

There are no required tests for this function, but it would be useful to test this in main.

J. Create a function called runReport that takes an istream (input to read from) and an

ostream (output to write to). It should return nothing.

 

In the function, prompt for and read in a file name for the input file.

 

If the file exists (use one of your functions), prompt for and read in a file name for the

output file.

 

Once you have the input and output file names, create the shipping account report (use one of your functions).

 

If the input file does not exist, print an error message.

 

There are no required tests for this function, but it would be useful to test this in main.

 

 

Testing

 

Test your code a little at a time as you write it. Use the examples from class to help you.

 

You may use the main function to test your code. At the simplest level, you can just call runReport with cin and cout. So, something like:

 

runReport(cin, cout);

Sample input and output files have been provided to test your work against. You can also test your functions directly like:

cout << getShippingString(ShippingType::NATIONAL) << "\n"; //should produce "Non-Local"

Or

cout << "getStatus\n" << getStatus(5000.0, ShippingType::INTERNATIONAL) << " == 1\n"

<< getStatus (312345.89, ShippingType::LOCAL) << " == 4\n";

If you don’t want to run your tests interactively using cin and cout, you can also use stringstreams (or

files)

Need a custom answer at your budget?

This assignment has been answered 3 times in private sessions.

© 2021 Codify Tutor. All rights reserved