APCS Final Project

BiographySummaryUMLCodeImplementations

Code

Jump to file:

Pasta.java

Pasta.java

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 import java.util.ArrayList; public class Pasta extends ItalianDish implements Cookable { //#9 - Class Design: Big Three--instance variables (20 pts.) //#25 - Meaningful variable names (10 pts.) private ArrayList<Ingredient> ingredients = new ArrayList<>(); private ArrayList<Double> caloricInfo = new ArrayList<>(); //#13 - ArrayList w/ Wrapper class (10 pts.) private String shape; // e.g., spaghetti, linguini, bucattini, etc. private int timeToCookMinutes; //#3 - Primitive Data Types (2 pts.) private boolean vegetarian; private int difficulty; //#9 - Class Design: Big Three--constructor (20 pts.) public Pasta( String name, String shape, int timeToCookMinutes, String[] flavorProfiles, boolean authenticItalian, String cityOfOrigin, boolean vegetarian, int difficulty ) { //#21 - "is-a" relationship -- calling the parent constructor. super(name, cityOfOrigin, flavorProfiles, 0.0, authenticItalian); this.shape = shape; this.timeToCookMinutes = timeToCookMinutes; this.difficulty = difficulty; if (timeToCookMinutes < 0) { //#1 - Relational Operators (5 pts.) throw new IllegalArgumentException("timeToCookMinutes must be greater than 0"); } } //#9 - Class Design: Big Three--zero arg constructor (20 pts.) public Pasta() { //#21 - "is-a" relationship -- calling the parent constructor. super("Carbonara", "Rome", new String[]{ "Cream", "Cheese", "Egg", "Pepper" }, 0.0, true); shape = "Spaghetti"; timeToCookMinutes = 15; addIngredient(new Ingredient("Spaghetti", 5, 100, "Costco", 500)); addIngredient(new Ingredient("Parmesan Cheese", 15, 20, "Safeway", 90)); } //#9 - Class Design: Processor method (20 pts.) //#10 - Student designed methods: other methods (5 pts.) public int getNumIngredients() { return ingredients.size(); } //#9 - Class Design: Processor method (20 pts.) //#10 - Student designed methods: other methods (5 pts.) public void addIngredient(Ingredient ingredient) { ingredients.add(ingredient); //#20 - Interaction between classes/interfaces (20 pts.) -- calling // a method from the Ingredient class. caloricInfo.add(ingredient.getCalories()); // Reclaculate the calories of the dish. calculateCalories(); } //#9 - Class Design: Processor method (20 pts.) //#10 - Student designed methods: other methods (5 pts.) private void calculateCalories() { double total = 0; //#13 - ArrayList: traversal with for-each (10 pts.) for (double calories : caloricInfo) { //#4 - For-each loop (5 pts.) total += calories; } // is a method from the parent class. setCalories(total); } //#14 - method that finds max/min (10 pts.) private Ingredient getMostCaloricallyDenseIngredient() { Ingredient mostDense = ingredients.get(0); for (Ingredient ingredient : ingredients) { //#20 - Interaction between classes/interfaces (20 pts.) -- calling // a method from the Ingredient class. if (ingredient.getCalories() > mostDense.getCalories()) { mostDense = ingredient; } } return mostDense; } //#9 - Class Design: Big Three--toString (20 pts.) public String toString() { String formattedCalories = "" + getCalories(); if (getCalories() == 0.0) { //#7 - String methods--substring (5 pts.) formattedCalories = formattedCalories.substring(formattedCalories.length()-2); } String out; out = "Name: " + getName() + "\nShape: " + shape + "\nAuthentically Italian: " + getAuthenticItalian() + "\nTime to Cook: " + timeToCookMinutes + " minutes" + "\nCalories: " + getCalories() + "\n"; out += "Flavor profiles: "; //#12 - Array: Traverse via for-loop (10 pts. ) for (int index = 0; index < getFlavorProfiles().length; index++) { //#4 - for-loop (5 pts.) String flavor = getFlavorProfiles()[index]; //#12 - Array: Accessed inside a for-loop (10 pts.) out += flavor; if (index < getFlavorProfiles().length - 1) { //#2 - if-else (5 pts.) out += " "; } } out += "\n"; out += "Ingredients: \n"; for (int index = 0; index < ingredients.size(); index++) { out += " - " + ingredients.get(index); if (index < ingredients.size() - 1) { //#1 – Relational Operators (5 pts.) out += "\n"; } } return out; } //#20 - Interaction between classes/interfaces (20 pts.) -- implementing methods from another interface. //#22 - interface implementation (10 pts.) -- implementing the Cookable methods. public double getTimeToCook() { return timeToCookMinutes; } public int getDifficulty() { return difficulty; } public boolean isVegetarian() { return vegetarian; } //#24 - Utilize a sorting method (10 pts.) -- uses merge sort to return a list of ingredients // sorted by price. this is my own implementation of mergesort, for fun. public ArrayList<Ingredient> getIngredients() { return getIngredientsHelper(ingredients, 0, ingredients.size() - 1); } // Helper method for getIngredientsSorted -- used for recursion public ArrayList<Ingredient> getIngredientsHelper( ArrayList<Ingredient> array, int low, int high ) { ArrayList<Ingredient> merged = new ArrayList<>(); // Base case. if (low == high) { merged.add(array.get(low)); return merged; } // Recurse. ArrayList<Ingredient> left = getIngredientsHelper(array, low, (low + high)/2); ArrayList<Ingredient> right = getIngredientsHelper(array, (low + high)/2 + 1, high); // Merge. int leftIdx = 0; int rightIdx = 0; for (int index = 0; index < (high - low + 1); index++) { if (leftIdx > ((low + high) / 2 - low)) { merged.add(right.get(rightIdx)); rightIdx++; } else if ( rightIdx > (high - (low + high)/2 -1) || left.get(leftIdx).getPrice() < right.get(rightIdx).getPrice() ) { merged.add(left.get(leftIdx)); leftIdx++; } else { merged.add(right.get(rightIdx)); rightIdx++; } } // Return merged array. return merged; } }

ItalianDish.java

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 //#21 - Inheritance hierarchy (20 pts.) -- ItalianDish is the parent class. public class ItalianDish implements Nameable { // Private instance variables. //#25 - Meaningful variable names (10 pts.) private String name; private String cityOfOrigin; private String[] flavorProfiles; //#12 - Array (10 pts.) private double calories; private boolean authenticItalian; //#3 - Primitive Data Types (2 pts.) // Multi-arg constructor. public ItalianDish(String name, String cityOfOrigin, String[] flavorProfiles, double calories, boolean authenticItalian) { this.name = name; this.cityOfOrigin = cityOfOrigin; this.flavorProfiles = flavorProfiles; this.calories = calories; this.authenticItalian = authenticItalian; } //#9 - Class Design: Setter method (20 pts.) //#10 - Student designed methods: Setter method (5 pts.) //#20 - Interaction between classes/interfaces (20 pts.) - implements // a method from the Nameable interface. public void setName(String name) { this.name = name; } //#9 - Class Design: Getter method (20 pts.) //#10 - Student designed methods: Getter method (5 pts.) //#20 - Interaction between classes/interfaces (20 pts.) - implements // a method from the Nameable interface. public String getName() { return name; } // Getter for city of origin. public String getCityOfOrigin() { return cityOfOrigin; } // Getter for flavor profiles. public String[] getFlavorProfiles() { return flavorProfiles; } // Setter for calories. public void setCalories(double calories) { this.calories = calories; } // Getter for calories. public double getCalories() { return calories; } // Getter for authentic italian. public boolean getAuthenticItalian() { return authenticItalian; } }

Ingredient.java

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 public class Ingredient implements Nameable { //#9 - Class Design: Big Three--instance variables (20 pts.) //#25 - Meaningful variable names (10 pts.) private String name; private double price; //#3 - Primitive Data Types (2 pts.) private double weightGrams; private String storeName; private double calories; //#9 - Class Design: Big Three--constructor (20 pts.) public Ingredient( String name, double price, double weightGrams, String storeName, double calories ) { this.name = name; this.price = price; this.weightGrams = weightGrams; this.storeName = storeName; this.calories = calories; //#7 - String methods--length (5 pts.) if (weightGrams < 0 || storeName.length() == 0) { //#1 - Logical Operators (5 pts.) // #2 - if-else with throw (5 pts.) throw new IllegalArgumentException("weight must be greater than 0, and storeName must be non-empty"); } } //#9 - Class Design: Big Three--zero arg constructor (20 pts.) public Ingredient() { name = "Salt"; price = 5; weightGrams = 1; storeName = "Costco"; calories = 5; } //#20 - Interaction between classes/interfaces (20 pts.) -- implements // a method from another interface, Nameable. public String getName() { return name; } //#20 - Interaction between classes/interfaces (20 pts.) -- implements // a method from another interface, Nameable. public void setName(String name) { this.name = name; } //#9 - Class Design: Getter method (20 pts.) public double getCalories() { return calories; } //#9 - Class Design: Setter method (20 pts.) //#10 - Student Designed Methods: Overloaded methods (10 pts.) public void setCalories(double calories) { this.calories = calories; } //#10 - Student Designed Methods: Overloaded methods (10 pts.) public void setCalories(int calories) { this.calories = (double) calories; //#8 Casting } // Getter for price. public double getPrice() { return price; } //#9 - Class Design: Processor method (20 pts.) public double calculateVolumeOfIngredient(double density) { // D = m/v --> v = m/D --> v = m * (D ^ -1) return weightGrams * Math.pow(density, -1.0); //#6 - Math.pow() (5 pts.) } public String toString() { return weightGrams + "g of " + name + " for $" + price + " from " + storeName + "."; } }

Cookable.java

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import java.util.ArrayList; //#20 - Interaction between classes/interfaces (20 pts.) - Cookable // interacts with, in this case extends, another interface, Nameable //#22 - interface (10 pts.) -- is-a relationship. public interface Cookable extends Nameable { // Returns time, in minutes, this cookable takes to cook. public double getTimeToCook(); // Returns the difficulty of cooking this cookable. public int getDifficulty(); // Returns whether or not the dish is vegetarian. public boolean isVegetarian(); // Returns a list of ingredients. public ArrayList<Ingredient> getIngredients(); }

Nameable.java

1 2 3 4 5 6 7 //#22 - Interface (10 pts). -- Not such an interesting interface, but // ends up being useful because lots of classes in this project need to be named. public interface Nameable { public void setName(String name); public String getName(); }

PastaDriver.java

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 import java.util.ArrayList; import java.util.Scanner; //#11 - Class Composition: Driver class (10 pts.) class PastaDriver { public static void main(String[] args) { // Scanner is used throughout the main method //#17 – Scanner (10 pts.) //#25 - Meaningful variable names (10 pts.) Scanner input = new Scanner(System.in); //#23 - Polymorphism (10 pts.) -- The Pasta objects are polymorphed as Cookables. ArrayList<Cookable> recipes = new ArrayList<>(); // Main-loop, can perform 5 different things boolean done = false; while (!done) { //#4 - while-loop (5 pts.) System.out.println("1: Add a new pasta recipe"); System.out.println("2: Display pasta recipes"); System.out.println("3: Display grocery list"); System.out.println("4: Change the name of a recipe"); System.out.println("5: Exit program"); System.out.print("Enter the number of which action you would like to do: "); int action = input.nextInt(); input.nextLine(); // Switch on action to see which action to perform switch (action) { //#5 - switch statement (5 pts.) case 1: // Take user input to create a Pasta Object //#25 - Meaningful variable names (10 pts.) System.out.println(); System.out.println("What is the name of your dish? "); String name = input.nextLine(); System.out.println("What pasta shape does your dish use? "); String shape = input.nextLine(); System.out.println("How long in minutes does your dish take to cook?"); int timeToCook = input.nextInt(); System.out.println("Is your dish authentically Italian? (true/false) "); boolean authenticItalian = input.nextBoolean(); input.nextLine(); System.out.println("What city in Italy does your dish originate from? "); String cityOfOrigin = input.nextLine(); System.out.println("Is your dish vegetarian? (true/false) "); boolean vegetarian = input.nextBoolean(); System.out.println("On a scale of 1-5, how difficult is this dish to cook? "); int difficulty = input.nextInt(); System.out.println("How many flavor profiles does your dish have? "); int numProfiles = input.nextInt(); String[] profiles = new String[numProfiles]; System.out.println("What are your flavor profiles? (Seperate by space) "); for (int profile = 0; profile < profiles.length; profile++) { profiles[profile] = input.next(); } Pasta dish = new Pasta(name, shape, timeToCook, profiles, authenticItalian, cityOfOrigin, vegetarian, difficulty); input.nextLine(); //#25 - Meaningful variable names (10 pts.) boolean addingIngredients = true; while (addingIngredients) { System.out.println("Your current dish has " + dish.getNumIngredients() + " ingredients."); String moreIngredients = ""; boolean validatingInput = true; // Use a while loop to validate input and continue asking until it is valid while (validatingInput) { System.out.println("Would you like to add another ingredient? (y/n) "); moreIngredients = input.nextLine(); if (moreIngredients.equals("y") || moreIngredients.equals("n")) { //#1 - Logical Operators (5 pts.) validatingInput = false; } } //#7 - String methods--equals (5 pts.) if (moreIngredients.equals("y")) { //#25 - Meaningful variable names (10 pts.) System.out.print("Name of ingredient: "); String ingredientName = input.nextLine(); System.out.print("Price of ingredient: "); double price = input.nextDouble(); System.out.print("Weight (grams) of ingredient: "); double weight = input.nextDouble(); input.nextLine(); System.out.print("Name of store that the ingredient is from: "); String storeName = input.nextLine(); if ((int) (Math.random() * 100.0) + 1 < 10) { //#6 - One use of Math.random() (5 pts.) System.out.println("Sorry, that store is out of stock of your ingredient."); System.out.print("Name a different store: "); storeName = input.nextLine(); } System.out.print("Calories of ingredient: "); double calories = input.nextDouble(); input.nextLine(); //#20 - Interaction between classes/interfaces (20 pts.) dish.addIngredient(new Ingredient(ingredientName, price, weight, storeName, calories)); } else { addingIngredients = false; } } recipes.add(dish); System.out.println(); System.out.println("Here is your new recipe: " + dish + " "); break; case 2: // Loop through and print recipes. System.out.println(); System.out.println("Here are your pasta recipes: "); for (Cookable recipe : recipes) { System.out.println(recipe); System.out.println(); } break; case 3: // Use a nested for loop to print out the ingredients. ArrayList<Ingredient> ingredients; for (int pastaIndex = 0; pastaIndex < recipes.size(); pastaIndex++) { //#20 - Interaction between classes/interfaces (20 pts.) ingredients = recipes.get(pastaIndex).getIngredients(); for (int ingredient = 0; ingredient < ingredients.size(); ingredient++) { System.out.println(" - " + ingredients.get(ingredient)); } } System.out.println(); break; case 4: System.out.println(); int index = -1; // Use do-while to continue asking until a valid name was given. do { //#4 - do-while loop (5 pts.) System.out.println("Here are the names of your current recipes: "); for (Cookable recipe : recipes) { System.out.println(" - " + recipe.getName()); } System.out.println(); System.out.println("Which recipe would you like to change the name of? "); String oldName = input.nextLine(); for (int recipeIndex = 0; recipeIndex < recipes.size(); recipeIndex++) { if (recipes.get(recipeIndex).getName().equals(oldName)) { index = recipeIndex; break; } } } while (index == -1); System.out.println("What would you like to rename this recipe to? "); String newName = input.nextLine(); //#20 - Interaction between classes/interfaces (20 pts.) recipes.get(index).setName(newName); System.out.println(); break; case 5: done = true; break; default: System.out.println("That is not a valid action."); break; } } } }