This project will allow you to write a program to get more practice with the sta
ID: 3675839 • Letter: T
Question
This project will allow you to write a program to get more practice with the stack and queue data structures, as well as more practice with object-oriented ideas that we explored in the previous projects.
In this assignment you will be writing a simulation of an order-fulfillment system for a company like Amazon.com. These companies take orders for products and ship them to customers based on what they have in inventory. For this assignment you will be performing a scaled-back version of this task – you will write a program that will read an order from a text file, turn that order into a list of products, determine which products can be shipped now and which must be delayed until later, and then produce two reports – one showing what will be shipped now, and one showing what portions of the order remain “on hold” for a later date.
In the order-fulfillment system we are simulating, orders are fulfilled using either First-In, First-Out processing (for orders that can be fulfilled immediately). However, orders that must be delayed are prioritized in the reverse order they were made – more recent orders should be fulfilled first – and so follow Last-In, First-Out processing. Products that can be filled immediately should be reported in the order they appear in the file. Products that must be delayed should appear in the report in the reverse order that they appear in the input file. To perform this processing and receive full credit you must use queues and stacks to perform this processing as discussed below.
For this program you will be writing a Product class to contain the data about each individual product in the database. You may write this class from scratch, or you may use the Product class you built in Lab 2 as a base for this lab. However, the Product class for this lab has some new requirements, so read below carefully and make sure you modify your class to implement these changes.
Before beginning to code, think carefully about what you need to do to implement the requirements discussed below. Also consider how you will break the portions of this assignment that are not class-based down into smaller methods. Remember that monolithic solutions to this problem will lose points regardless of whether they produce the correct output or not.
Objectives
Practice with programming fundamentals
Review of various Java fundamentals (branching, loops, variables, methods, etc.)
Review of Java File I/O concepts
Practice with Java ArrayList concepts
Practice with object-oriented programming and design
Practice with Java interfaces
Practice with stack and queue data structures
Project 04 Instructions
Create a new Project folder named Project03, then look at the instructions below.
Part I - The Product class
For this assignment you must design a class named SimpleProduct. This class must implement the Product interface given below. You must download this file and import it into your Project03 source code folder before you can start to implement your own SimpleMusicTrack class.
Product.java
It is up to you how to represent the member variables of your SimpleProduct class, but it must implement all of the methods given in the interface. Note in particular that it must implement thereadNextProduct(Scanner in) method that reads a single entry from a Scanner object (used with the input datafile).
In addition, your SimpleProduct class must implement the following methods not provided in the interface, but are inherited from the Object class:
equals(Object obj) – should return a true value if the name and type of the Product are the same.
toString() – should return a string that contains the name of the product, the type of the product, the price and the quantity of the product as a comma-separated list enclosed in parentheses.
As you write this class, write a test program to go along with it. Test each method as you write it, as we have discussed in class. You will need to start with a skeleton of your SimpleProduct code that has each method in the interface written as a "stub" as seen in the Closed Lab code you have modified (i.e. code that does nothing but return a default value to allow the class to compile), and then you should modify your stub code one method at a time, testing each change you make. You will not need to submit this test program, but using it will make your code development much, much easier.
The file format that the readNextProduct method should use is a simple one. An input file for a single Product entry would use this format:
A sample input file for a single product might look like this:
A sample input file for three products might look like this:
Note that you can read a boolean value using the Scanner's nextBoolean() method. This works like nextDouble() or nextInt(), so be careful about using nextLine() appropriately to set yourself up for the next item in the file.
Part II - The Order Reporting Program
The program performs the following actions:
Ask the user to enter the name of the file that contains the order database.
Input the customer and product information from the file. See below for the file format information for the order fulfillment system - it contains more information than what you set up above. Customer information may be stored in any format you choose (though see below about creating a Customer class). Each individual product should be stored in its own Product object.
Create two Collection objects – a FIFO queue of orders to be fulfilled and a stack of orders to be delayed. Use the inStock attribute of each Product to determine which Collection they below to. Items that are in stock should be placed in the FIFO queue, while items that are out of stock should be pushed onto the stack.
For the orders that can be fulfilled now, calculate the shipping cost and the sales tax. Sales tax information is in the customer block of the input data file (see below for the file format). Shipping cost is based on how much is ordered. Basic shipping is 15% of the total cost of the order. If there is at least $10 worth of product being shipped at a time, then the shipping cost is reduced to 5%. If there is at least $25 worth of product being shipped at a time, then the shipping cost is reduced to 0% (i.e. free shipping). Sales tax should be computed before adding in the cost of shipping, and shipping costs and sales tax should ONLY be calculated for orders actually being fulfilled, not for everything in the file.
Output two well-formatted reports as outlined below. The first report is the report of orders to be fulfilled and should list the products that are able to be fulfilled now in FIFO order (i.e. in the order they appear in the file). The second report is the report of orders to be delayed, and should list the products that remain to be fulfilled in LIFO order (i.e. in the reverse of the order they appear in the file). Both reports should include a total dollar amount for the items in the order, and the fulfilled order report should include lines for shipping as well as sales tax.
The input file format for this order fulfillment system is:
Note the inclusion of a block of customer information at the top of the file. After the customer information is finished, the product blocks continue just as the file format described in Part I above. A sample input file might look like this:
An example of the two reports that this file would generate is given below. Note that you will need to make use of Java's formatted output methods to get the report to output properly.
Extra Credit
For up to 1 point of extra lab credit, you can implement a Customer class for this assignment. The Customer class should hold all of the Customer data described above, have at least one constructor method defined, and have accessor and mutator methods defined for all of the member variables. The sales tax member variable should be input constrained to not drop below zero and not be allowed to be set greater than 1.0. If you choose to implement this, make sure to include the Customer class in your submission bundle. Make sure to also note in the header comments of Lab4.java that you have chosen to implement this portion of the extra credit.
For up to 1 point of extra lab credit, you can choose to output a database file containing the orders to be delayed. The format of this file should be exactly the same as the input data file, except that it should only contain the product that could not be fulfilled (i.e. the products you placed into the stack). Crucially, the order of the products in the new file MUST match the order they had in the original file (hint: consider using a second stack to get the order correct). If you choose to implement this, you should ask the user for an output file name and should test to make sure that it is not the same as the input file name (i.e. give an error and keep asking until the user gives a different file name). Then use that file name for output. Make sure you indicate in the header comments of Lab4.java that you have chosen to implement this portion of the extra credit.
Explanation / Answer
/********************************* lab04.java ******************************************/
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
import java.util.Stack;
public class lab04 {
private Customer customer;
private ArrayList<SimpleProduct> productList = new ArrayList<SimpleProduct>();
private SimpleProduct product;
private Queue<SimpleProduct> stockedQueue = new LinkedList<SimpleProduct>();
private Stack<SimpleProduct> unstockedStack = new Stack<SimpleProduct>();
private double subtotal;
private double preShipTotal;
private double shipTotal;
private double shippingPercent;
private boolean safeToAdd;
/**
* Customer constructor
* gets file information and distributes reports appropriately
*
*/
public lab04() {
//Get file from user
String fileName = getUserFile();
//place file contents in correct data structures
allocateFileContents(fileName);
//print reports
reportOne();
reportTwo();
}
/**
* @return String file name that contains order database.
*/
private String getUserFile(){
System.out.println("Please enter database file name? ");
Scanner inFile = new Scanner(System.in);
String fileName = inFile.nextLine();
return fileName;
}
/**
* @param fileName
* appropriately allocates contents of file to customer info, stocked queue, and unstocked stack
*/
private void allocateFileContents(String fileName){
Scanner input = null;
int i = 0;
try {
input = new Scanner(new File(fileName));
if((i == 0) && (! input.hasNext())){
System.out.println("Error: Empty text file. Exiting system.");
System.exit(0);
}
while (input.hasNextLine()) {
//if scanner has read past customer info
if (i >= 7) {
product = new SimpleProduct(input);
this.safeToAdd = true;
for (int p = 0; p < productList.size(); p++){
if (product.equals(productList.get(p).getName(), productList.get(p).getType())){
this.safeToAdd = false;
}
}
if (this.safeToAdd == true){
productList.add(product);
// in stock?
if (product.getInStock() == true) {
// add to FIFO queue
stockedQueue.add(product);
} else {
// add to stack
unstockedStack.push(product);
}
i = i + 5;
}
//if customer info
} else {
customer = new Customer(input);
i = i + 7;
}
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
System.out.println("Error: file not found. Exiting System. ");
System.exit(0);
}
}
/**
* prints report with in-stock items to be shipped
*/
private void reportOne(){
System.out.println("");
System.out.println("-------------------------------------------------");
System.out.println("");
System.out.println("Shipping to:");
//print address
generateAddress();
System.out.println("-------------------------------------------------");
System.out.println("");
//print queue info
printQueueInfo();
System.out.println("");
System.out.println("-------------------------------------------------");
System.out.println("");
System.out.format("Subtotal: $%.2f%n", this.subtotal);
System.out.format("Sales tax (%.2f): $%.2f%n", customer.getTax(),
(customer.getTax() * this.subtotal));
//get shipping
calculateShippingTotal();
System.out.format("Shipping: $%.2f%n", this.shipTotal);
System.out.println("");
System.out.println("-------------------------------------------------");
System.out.println("");
System.out.format("Total: $%.2f%n", (this.shipTotal + this.preShipTotal));
System.out.println("");
System.out.println("-------------------------------------------------");
}
/**
* Print queue product information and
* @return subtotal
*/
public double printQueueInfo(){
this.subtotal = 0;
int stockedQueueSize = stockedQueue.size();
SimpleProduct current;
for (int i = 0; i < stockedQueueSize; i++) {
//pop from queue, assign local variable, and get info
current = stockedQueue.remove();
double sub = current.getQuantity() * current.getPrice();
System.out.println(current.getQuantity() + " x "
+ current.getName() + " (" + current.getType() + ") "
+ current.getPrice());
this.subtotal = sub + this.subtotal;
}
return this.subtotal;
}
/**
* calculate total cost with shipping
*/
public void calculateShippingTotal(){
this.preShipTotal = (this.subtotal * customer.getTax()) + this.subtotal;
if (this.preShipTotal > 25) {
this.shippingPercent = 0;
} else if (this.preShipTotal > 10) {
this.shippingPercent = .05;
} else {
this.shippingPercent = .15;
}
this.shipTotal = this.shippingPercent * this.preShipTotal;
}
/**
* prints report with items that are on hold, along with outstanding balance
*/
private void reportTwo(){
System.out.println("");
System.out.println("Orders Outstanding For:");
//print address
generateAddress();
System.out.println("-------------------------------------------------");
System.out.println("");
//print stack info
printStackInfo();
System.out.println("");
System.out.println("-------------------------------------------------");
System.out.println("");
System.out.format("Outstanding balance: $%.2f%n", this.subtotal);
System.out.println("");
System.out.println("-------------------------------------------------");
System.out.println("");
}
/**
* prints on-hold items with product info
*/
public void printStackInfo(){
this.subtotal = 0;
int unstockedStackSize = unstockedStack.size();
SimpleProduct unstocked;
double sub;
for (int i = 0; i < unstockedStackSize; i++) {
unstocked = unstockedStack.pop();
sub = unstocked.getQuantity() * unstocked.getPrice();
System.out.println(unstocked.getQuantity() + " x "
+ unstocked.getName() + " (" + unstocked.getType() + ") "
+ unstocked.getPrice());
this.subtotal = sub + this.subtotal;
}
}
/**
* prints out customer address
*/
public void generateAddress(){
System.out.println("");
System.out.println(customer.getFirst() + " " + customer.getLast());
System.out.println(customer.getStreet());
System.out.println(customer.getCity() + ", " + customer.getState()
+ " " + customer.getZip());
System.out.println("");
}
public static void main(String[] args) {
lab04 lab = new lab04();
}
}
/******************************* Product.java ******************************************/
import java.util.Scanner;
public interface Product {
/*
* setName
* @param name - new name for the product
*/
public void setName(String name);
/*
* getName
* @return the name of the product
*/
public String getName();
/*
* setType
* @param type - the type of the product
*/
public void setType(String type);
/*
* getType
* @return - the product type
*/
public String getType();
/*
* setPrice
* @param price - the price of the product
*/
public void setPrice(double price);
/*
* getPrice
* @return the price of the product
*/
public double getPrice();
/*
* setQuantity
* @param quantity - the number of this product in inventory
*/
public void setQuantity(int quantity);
/*
* getQuantity
* @return the number of this product in inventory
*/
public int getQuantity();
/*
* setInStock
* @param inStock - true if this product is in stock
*/
public void setInStock(boolean inStock);
/*
* getQuantity
* @return true if this product is in stock
*/
public boolean getInStock();
/*
* readNextProduct
* @param inFile - a Scanner containing product entries
* @return false if the product cannot be completely read,
* true otherwise
*/
public boolean readNextProduct(Scanner inFile);
}
/*****************************************************SimpleProduct.java ********************/
import java.util.Scanner;
public class SimpleProduct implements Product {
// private member variables
private String name;
private String type;
private double price;
private int quantity;
private boolean inStock;
// constructor
public SimpleProduct(Scanner inFile) {
readNextProduct(inFile);
}
/*
* setName
*
* @param name - new name for the product
*/
public void setName(String name) {
this.name = name;
}
/*
* getName
*
* @return the name of the product
*/
public String getName() {
return this.name;
}
/*
* setType
*
* @param type - the type of the product
*/
public void setType(String type) {
this.type = type;
}
/*
* getType
*
* @return - the product type
*/
public String getType() {
return this.type;
}
/*
* setPrice
*
* @param price - the price of the product
*/
public void setPrice(double price) {
this.price = price;
}
/*
* getPrice
*
* @return the price of the product
*/
public double getPrice() {
return this.price;
}
/*
* setQuantity
*
* @param quantity - the number of this product in inventory
*/
public void setQuantity(int quantity) {
this.quantity = quantity;
}
/*
* getQuantity
*
* @return the number of this product in inventory
*/
public int getQuantity() {
return this.quantity;
}
/*
* setInStock
*
* @param inStock - true if this product is in stock
*/
public void setInStock(boolean inStock) {
this.inStock = inStock;
}
/*
* getQuantity
*
* @return true if this product is in stock
*/
public boolean getInStock() {
return this.inStock;
}
/*
* readNextProduct
*
* @param inFile - a Scanner containing product entries
*
* @return false if the product cannot be completely read, true otherwise
*/
public boolean readNextProduct(Scanner input) {
int i = 0;
while (input.hasNextLine()) {
if (i > 4) {
return false;
}
String line = input.nextLine().trim();
if (line.length() <=0){
System.out.println("Error: empty product field(s) in text file. Exiting program.");
System.exit(0);
}
if (i == 0) {
setName(line);
} else if (i == 1) {
setType(line);
} else if (i == 2) {
// convert string to double
try{
double price = Double.parseDouble(line);
setPrice(price);
} catch (Exception e) {
System.out.println("Error: invalid text entry. Prices must be in numeric format. Exiting system.");
System.exit(0);
}
} else if (i == 3) {
// convert string to int
try{
int quantity = Integer.parseInt(line);
setQuantity(quantity);
} catch (Exception e) {
System.out.println("Error: invalid text entry. Quantities must be entered as integers. Exiting system.");
System.exit(0);
}
} else if (i == 4) {
// convert string to boolean
if (line.equalsIgnoreCase("true")
|| line.equalsIgnoreCase("false")) {
setInStock(Boolean.valueOf(line));
} else {
System.out.println("Error: invalid text file entry. Products must be listed as stocked(true) or not(false). Exiting system.");
System.exit(0);
}
}
i++;
}
return true;
}
/**
* @param obj
* @return true value if the name and type of the Product are the same.
*/
public boolean equals(String name, String type) {
return (this.name.equals(name) && this.type.equals(type));
}
/**
* @return string that contains the name of the product, the type of the
* product, the price and the quantity of the product as a
* comma-separated list enclosed in parentheses.
*/
public String toString() {
return ("(" + getName() + ", " + getType() + ", " + getPrice() + ", " + getQuantity()+ ")");
}
}
/**************************** Customer.java ****************************************/
import java.util.Scanner;
public class Customer {
private String last;
private String first;
private String street;
private String city;
private String state;
private String zip;
private double tax;
/**
* Customer constructor
* sets customer information
*
*/
public Customer(Scanner inFile) {
readNextCustomerInfo(inFile);
}
/**
*
* @return last name
*/
public String getLast(){
return this.last;
}
/**
*
* @param String last
* set last name
*/
public void setLast(String last){
this.last = last;
}
/**
*
* @return first name
*/
public String getFirst(){
return this.first;
}
/**
*
* @param first name (set)
*/
public void setFirst(String first){
this.first = first;
}
/**
*
* @return city
*/
public String getCity(){
return this.city;
}
/**
*
* @param city (set)
*/
public void setCity(String city){
this.city = city;
}
/**
*
* @return street
*/
public String getStreet(){
return this.street;
}
/**
*
* @param street (set)
*/
public void setStreet(String street){
this.street = street;
}
/**
*
* @return state
*/
public String getState(){
return this.state;
}
/**
*
* @param state (set)
*/
public void setState(String state){
this.state = state;
}
/**
*
* @return zip
*/
public String getZip(){
return this.zip;
}
/**
*
* @param zip (set)
*/
public void setZip(String zip){
this.zip = zip;
}
/**
*
* @return tax
*/
public double getTax(){
return this.tax;
}
/**
*
* @param tax (set)
*/
public void setTax(double tax){
// The sales tax member variable should be input constrained to not drop below
// zero and not be allowed to be set greater than 1.0.
if ((tax >=0) && (tax <= 1)){
this.tax = tax;
} else {
throw new IllegalArgumentException("Sales tax must be between 0 and 1.0, exclusive.");
}
}
/**
*
* @param Scanner input
* set customer member variables
* @return boolean false if lines remain
*/
public boolean readNextCustomerInfo(Scanner input) {
int i = 0;
while (input.hasNextLine()) {
if (i > 6) {
return false;
}
String line = input.nextLine().trim();
if (line.length() <=0){
System.out.println("Error: empty customer field(s) in text file. Exiting program.");
System.exit(0);
}
if (i == 0) {
setLast(line);
} else if (i == 1) {
setFirst(line);
} else if (i == 2) {
setStreet(line);
} else if (i == 3) {
setCity(line);
} else if (i == 4) {
setState(line);
} else if (i == 5) {
setZip(line);
} else if (i == 6){
// convert string to double
try{
double tax = Double.parseDouble(line);
setTax(tax);
} catch (Exception e) {
System.out.println("Error: invalid text entry. Tax must be in numeric format. Exiting system.");
System.exit(0);
}
}
i++;
}
return true;
}
}
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.