// Writing skeleton: 8:12 - 8:25am // pseudocode 8:03 - 8:20pm // implementation 4:20 - 5:30 // unit test 5:30 - 5:50 // enhancements 6:10 - 7:18 // LOC 110 import java.util.*; import java.io.*; public class UpcReceiptCalc { public static void main(String args[]) { (new UpcReceiptCalc()).calculateSalesReceipt(); } public void calculateSalesReceipt() { purchaseList = new HashMap(); invalidList = new ArrayList(); readProductDB(); processUPCs(); assembleSalesReceipt(); System.out.println(salesReceipt); showInvalidList(); } public void readProductDB() { productDB = new HashMap(); try { //open "productDB.txt" file Scanner fileReader = new Scanner(new FileReader("productDB.txt")); String currentLine = null; String[] splitLine = null; String nameAndPrice = null; String delims = "[{\",]+"; //FOR each line in input file LOOP while (fileReader.hasNextLine()) { currentLine = fileReader.nextLine(); // parse the input line splitLine = currentLine.split(delims); nameAndPrice = splitLine[2] + "," + splitLine[4]; Product newItem = new Product(); newItem.upc = splitLine[1]; newItem.productName = splitLine[2]; newItem.price = dollarsToInt(splitLine[4]); //Add line to product db productDB.put(newItem.upc, newItem); } //END LOOP } catch (FileNotFoundException ex) { ex.printStackTrace(); System.exit(1); } } private int dollarsToInt(String amount) { return Integer.parseInt(amount.replaceAll(",|\\.", "")); } public void processUPCs() { console = new Scanner(System.in); //WHILE more upc's exist LOOP while (console.hasNextLine()) { //READ upc rawUPC = console.nextLine(); product = null; lookupProduct(); //IF product found in DB THEN if (product != null) { // increase count and total countProduct(); computeTotal(); } //END IF } //END LOOP } public void assembleSalesReceipt() { salesReceipt = new StringBuffer(); // FOR each item in purchase list LOOP for (String upc : purchaseList.keySet()) { ProductCount purchase = purchaseList.get(upc); // compute the subtotal as itemcount * price. subtotal = purchase.itemCount * purchase.item.price; // format a line with product name, itemcount, subtotal String lineout = String.format("%-30s",purchase.item.productName) +"\t("+ String.format("%3d",purchase.itemCount) +")\t" + String.format("%3.2f",subtotal/100.0)+"\n"; // append the line to the receipt salesReceipt.append(lineout); } // END LOOP // Append the total price as the last line of the receipt salesReceipt.append(String.format("%30s","TOTAL") + "\t("+ String.format("%3d",totalItems) +")\t" + String.format("%3.2f",totalPrice/100.0)+"\n"); } public void showInvalidList() { //Display each item in invalidlist for (InvalidItem item : invalidList) { System.out.print(item.upc + " "); System.out.println(item.message); } } public void lookupProduct() { verifiedUPC = null; verifyUPC(); //IF (verifiedUPC exists) THEN if (verifiedUPC != null) { product = productDB.get(verifiedUPC); //IF productDB does not contain (upc) THEN if (product == null) { // create an invalid item from upc and "not in DB" InvalidItem baditem = new InvalidItem(); baditem.upc = verifiedUPC; baditem.message = "product doesn't exist in the database"; // add invalid item to the invalid list. invalidList.add(baditem); } } // END IF } public void verifyUPC() { //Given a raw upc apply the Check Digit algorithm provided. boolean verified = checkDigit(rawUPC); //IF not verified THEN if (!verified) { // create an invalid item from upc and "invalid check digit" InvalidItem baditem = new InvalidItem(); baditem.upc = rawUPC; baditem.message = "check digit doesn't match"; // add invalid item to the invalid list. invalidList.add(baditem); } //ELSE else { // set verifiedUPC from upc verifiedUPC = rawUPC; } //END } public boolean checkDigit(String upc) { int checkDigit; //calc sum of odd-numbered positions & multiply by 3 int oddNumberedPos = (Character.getNumericValue(upc.charAt(0)) + Character.getNumericValue(upc.charAt(2)) + Character.getNumericValue(upc.charAt(4)) + Character.getNumericValue(upc.charAt(6)) + Character.getNumericValue(upc.charAt(8)) + Character.getNumericValue(upc.charAt(10))) * 3; int evenNumberedSum = Character.getNumericValue(upc.charAt(1)) + Character.getNumericValue(upc.charAt(3)) + Character.getNumericValue(upc.charAt(5)) + Character.getNumericValue(upc.charAt(7)) + Character.getNumericValue(upc.charAt(9)); Integer result = new Integer(oddNumberedPos + evenNumberedSum); String strResult = result.toString(); int lastDigit = Character.getNumericValue(strResult.charAt(strResult.length() - 1)); //if lastDigit == 0 if (lastDigit == 0) checkDigit = 0; else checkDigit = 10 - lastDigit; return checkDigit == Character.getNumericValue(upc.charAt(11)); } public void countProduct() { //Given a product, increment the itemcount in purchase list. ProductCount pc = purchaseList.get(verifiedUPC); // If this is the first purchase of this product if (pc == null) { pc = new ProductCount(); pc.item = product; pc.itemCount = 1; purchaseList.put(verifiedUPC, pc); } // update the count for a previously purchased product else { pc.itemCount++; purchaseList.put(verifiedUPC, pc); } } public void computeTotal() { //Given a product, increment the total price with the price of this product. totalPrice += product.price; totalItems++; } // Data Structures // List of products. Map productDB; // List of products and itemcounts, in order of arrival. Map purchaseList; // List of invalid items, in order of arrival. List invalidList; String rawUPC; String verifiedUPC; Product product; String productName; String price; int quantityPurchased; int subtotal; int totalPrice; int totalItems; StringBuffer salesReceipt; Scanner console; } class Product { String upc; String productName; int price; // in cents } class ProductCount { Product item; int itemCount; } class InvalidItem { String upc; String message; }