From 35dfb3b63a03ba8e3fd609f9958273bb1ac053a8 Mon Sep 17 00:00:00 2001 From: shyye Date: Mon, 19 Aug 2024 15:21:09 +0200 Subject: [PATCH 01/93] Add domain model --- .../java/com/booleanuk/core/domain-model.md | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 src/main/java/com/booleanuk/core/domain-model.md diff --git a/src/main/java/com/booleanuk/core/domain-model.md b/src/main/java/com/booleanuk/core/domain-model.md new file mode 100644 index 000000000..2c6cb7400 --- /dev/null +++ b/src/main/java/com/booleanuk/core/domain-model.md @@ -0,0 +1,69 @@ +# Domain Model + +## Enums +| Classes | Variables | Methods | Scenario | Output | +|-----------|-----------|---------|----------|--------| +| `SKU` | | | | | +| `COFFEE` | | | | | +| `BAGEL` | | | | | +| `FILLING` | | | | | + +## Inventory +| Classes | Variables | Methods | Scenario | Output | +|-------------|-------------------------------|-----------------------------------------------------|--------------------------------------------|------------| +| `Inventory` | `ArrayList products` | | | | +| | | `-addProduct(float price, enum name, enum variant)` | Add product to inventory. | - | +| | | ?? or ?? | | | +| | | `-addCoffee(float price, enum variant)` | -^ | | +| | | `-addBagel(float price, enum varint)` | -^ | | +| | | `-addFilling(float price enum variant)` | -^ | | +| | | ??? | | | +| | | `-fillInventory()` | Initialize inventory with specified items. | | +| | | `-getAllCoffee()` | Get a list of all coffee products. | List | +| | | `-getAllBagels()` | Get a list of all bagel products. | List | +| | | `-getAllFillings()` | Get a list of all filling products. | List | +| | | `+printMeny()` | Print meny of all items in inventory. | Print text | + +## Basket +| Classes | Variables | Methods | Scenario | Output | +|----------|------------------------------|----------------------------------------|---------------------------------------------------------------------------------------------------------------|-----------------| +| `Basket` | `static int idCount` | | "Fake autoincrement id". Counter which will be increased everytime a new product is added to the basket. | | +| | `HashMap products` | `addCoffee(enum variant)` | Add coffee with specified variant. Then run printBasket(). | | +| | | | Can't add coffee. | throw exception | +| | | `addBagel(enum variant, enum filling)` | Add bagel with specified variant and filling. At the moment just one filling can be added. run printBasket(). | | +| | | | Can't add bagel. | throw exception | +| | | `remove(int ProduktId)` | Product is in basket and can be removed. | Show message | +| | | | Product is not in basket and can not be removed. | throw exception | +| | `int maxCapacity` | `changeCapacity(int newCapacity)` | If newCapacity is more than 0. | true | +| | | | If newCapacity is less than 1. | false | +| | `float totalCost` | | | | +| | | `getTotalCost()` | Get total cost of all products. | float | +| | | `printBasket()` | Prints the content of the basket. | Print text | + +## Product +| Classes | Variables | Methods | Scenario | Output | +|-----------|----------------|--------------|------------------------------------|--------| +| `Product` | `int id` | | | | +| | `enum SKU` | | | | +| | `float price` | | | | +| | `enum name` | | | | +| | `enum variant` | | | | +| | | `setSKU()` | Set SKU based on name and variant. | - | +| | | `getPrice()` | Get price for this product. | float | + +## Coffee extends Product (Inherit) +| Classes | Variables | Methods | Scenario | Output | +|---------|-----------|----------------------|-------------------------------------|--------| +| `Coffe` | | `@override setSKU()` | | | + +## Bagel extends Product (Inherit) +| Classes | Variables | Methods | Scenario | Output | +|---------|-----------|-----------------------|-------------------------------------|--------| +| `Bagel` | | `@override setSKU()` | | | + +## Filling extends Product (Inherit) +| Classes | Variables | Methods | Scenario | Output | +|-----------|-----------|-----------------------|-------------------------------------|--------| +| `Filling` | | `@override setSKU()` | | | + + From 634a27a6001ac6bf100c4e16464723c77b547b4b Mon Sep 17 00:00:00 2001 From: shyye Date: Mon, 19 Aug 2024 15:31:10 +0200 Subject: [PATCH 02/93] Fix spelling error --- src/main/java/com/booleanuk/core/domain-model.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/booleanuk/core/domain-model.md b/src/main/java/com/booleanuk/core/domain-model.md index 2c6cb7400..fdbe3f050 100644 --- a/src/main/java/com/booleanuk/core/domain-model.md +++ b/src/main/java/com/booleanuk/core/domain-model.md @@ -22,7 +22,7 @@ | | | `-getAllCoffee()` | Get a list of all coffee products. | List | | | | `-getAllBagels()` | Get a list of all bagel products. | List | | | | `-getAllFillings()` | Get a list of all filling products. | List | -| | | `+printMeny()` | Print meny of all items in inventory. | Print text | +| | | `+printMenu()` | Print meny of all items in inventory. | Print text | ## Basket | Classes | Variables | Methods | Scenario | Output | From a9569d287c8bf7adc1350aecedb20577300efb09 Mon Sep 17 00:00:00 2001 From: shyye Date: Mon, 19 Aug 2024 15:59:12 +0200 Subject: [PATCH 03/93] Update domain model --- .../java/com/booleanuk/core/domain-model.md | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/booleanuk/core/domain-model.md b/src/main/java/com/booleanuk/core/domain-model.md index fdbe3f050..a7d8f600c 100644 --- a/src/main/java/com/booleanuk/core/domain-model.md +++ b/src/main/java/com/booleanuk/core/domain-model.md @@ -25,20 +25,20 @@ | | | `+printMenu()` | Print meny of all items in inventory. | Print text | ## Basket -| Classes | Variables | Methods | Scenario | Output | -|----------|------------------------------|----------------------------------------|---------------------------------------------------------------------------------------------------------------|-----------------| -| `Basket` | `static int idCount` | | "Fake autoincrement id". Counter which will be increased everytime a new product is added to the basket. | | -| | `HashMap products` | `addCoffee(enum variant)` | Add coffee with specified variant. Then run printBasket(). | | -| | | | Can't add coffee. | throw exception | -| | | `addBagel(enum variant, enum filling)` | Add bagel with specified variant and filling. At the moment just one filling can be added. run printBasket(). | | -| | | | Can't add bagel. | throw exception | -| | | `remove(int ProduktId)` | Product is in basket and can be removed. | Show message | -| | | | Product is not in basket and can not be removed. | throw exception | -| | `int maxCapacity` | `changeCapacity(int newCapacity)` | If newCapacity is more than 0. | true | -| | | | If newCapacity is less than 1. | false | -| | `float totalCost` | | | | -| | | `getTotalCost()` | Get total cost of all products. | float | -| | | `printBasket()` | Prints the content of the basket. | Print text | +| Classes | Variables | Methods | Scenario | Output | +|----------|-------------------------------|----------------------------------------|---------------------------------------------------------------------------------------------------------------|-----------------| +| `Basket` | `static int idCount` | | "Fake autoincrement id". Counter which will be increased everytime a new product is added to the basket. | | +| | `ArrayList products` | `addCoffee(enum variant)` | Add coffee with specified variant. Then run printBasket(). | | +| | | | Can't add coffee. | throw exception | +| | | `addBagel(enum variant, enum filling)` | Add bagel with specified variant and filling. At the moment just one filling can be added. run printBasket(). | | +| | | | Can't add bagel. | throw exception | +| | | `remove(int ProduktId)` | Product is in basket and can be removed. | Show message | +| | | | Product is not in basket and can not be removed. | throw exception | +| | `int maxCapacity` | `changeCapacity(int newCapacity)` | If newCapacity is more than 0. | true | +| | | | If newCapacity is less than 1. | false | +| | `float totalCost` | `setTotalCost(float newTotalCost)` | | | +| | | `getTotalCost()` | Get total cost of all products. | float | +| | | `printBasket()` | Prints the content of the basket. | Print text | ## Product | Classes | Variables | Methods | Scenario | Output | From 91e5a148ed154cae441f6cedbae9882e0c98fc8a Mon Sep 17 00:00:00 2001 From: shyye Date: Mon, 19 Aug 2024 16:04:27 +0200 Subject: [PATCH 04/93] Update domain model --- src/main/java/com/booleanuk/core/domain-model.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/com/booleanuk/core/domain-model.md b/src/main/java/com/booleanuk/core/domain-model.md index a7d8f600c..a7f2b8b29 100644 --- a/src/main/java/com/booleanuk/core/domain-model.md +++ b/src/main/java/com/booleanuk/core/domain-model.md @@ -66,4 +66,10 @@ |-----------|-----------|-----------------------|-------------------------------------|--------| | `Filling` | | `@override setSKU()` | | | +# Class Diagram +## Diagram +![]() + +## Code +TODO: ..... From 2c21df1c48bc05357d5568d4bd4f0a4ac38bbc46 Mon Sep 17 00:00:00 2001 From: shyye Date: Mon, 19 Aug 2024 16:08:09 +0200 Subject: [PATCH 05/93] Update domain model with class diagram --- assets/images/gleek_class-diagram.png | Bin 0 -> 243267 bytes .../java/com/booleanuk/core/domain-model.md | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 assets/images/gleek_class-diagram.png diff --git a/assets/images/gleek_class-diagram.png b/assets/images/gleek_class-diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..5e7dae46741ee2b10e7962b00466a32fe6f8cb58 GIT binary patch literal 243267 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 DKgo`u literal 0 HcmV?d00001 diff --git a/src/main/java/com/booleanuk/core/domain-model.md b/src/main/java/com/booleanuk/core/domain-model.md index a7f2b8b29..4ad0591a5 100644 --- a/src/main/java/com/booleanuk/core/domain-model.md +++ b/src/main/java/com/booleanuk/core/domain-model.md @@ -68,7 +68,7 @@ # Class Diagram ## Diagram -![]() +![Class Diagram](/assets/images/gleek_class-diagram.png) ## Code TODO: ..... From 7f7b549fd803d3df03de83df1556bc5bc48da810 Mon Sep 17 00:00:00 2001 From: shyye Date: Mon, 19 Aug 2024 18:21:45 +0200 Subject: [PATCH 06/93] Update domain model --- .../java/com/booleanuk/core/domain-model.md | 67 +++++++++---------- 1 file changed, 33 insertions(+), 34 deletions(-) diff --git a/src/main/java/com/booleanuk/core/domain-model.md b/src/main/java/com/booleanuk/core/domain-model.md index 4ad0591a5..3ff72a1d3 100644 --- a/src/main/java/com/booleanuk/core/domain-model.md +++ b/src/main/java/com/booleanuk/core/domain-model.md @@ -1,44 +1,42 @@ # Domain Model ## Enums -| Classes | Variables | Methods | Scenario | Output | -|-----------|-----------|---------|----------|--------| -| `SKU` | | | | | -| `COFFEE` | | | | | -| `BAGEL` | | | | | -| `FILLING` | | | | | +| Classes | Variables | Methods | Scenario | Output | +|------------------|-----------|---------|----------|--------| +| `ProductSKU` | | | | | +| `CoffeeVariant` | | | | | +| `BagelVariant` | | | | | +| `FillingVariant` | | | | | ## Inventory -| Classes | Variables | Methods | Scenario | Output | -|-------------|-------------------------------|-----------------------------------------------------|--------------------------------------------|------------| -| `Inventory` | `ArrayList products` | | | | -| | | `-addProduct(float price, enum name, enum variant)` | Add product to inventory. | - | -| | | ?? or ?? | | | -| | | `-addCoffee(float price, enum variant)` | -^ | | -| | | `-addBagel(float price, enum varint)` | -^ | | -| | | `-addFilling(float price enum variant)` | -^ | | -| | | ??? | | | -| | | `-fillInventory()` | Initialize inventory with specified items. | | -| | | `-getAllCoffee()` | Get a list of all coffee products. | List | -| | | `-getAllBagels()` | Get a list of all bagel products. | List | -| | | `-getAllFillings()` | Get a list of all filling products. | List | -| | | `+printMenu()` | Print meny of all items in inventory. | Print text | +| Classes | Variables | Methods | Scenario | Output | +|-------------|---------------------------------|-----------------------------------------------------------------|--------------------------------------------------------|------------| +| `Inventory` | `- ArrayList products` | | | | +| | | `-addProduct(String SKU, float price, Enum name, Enum variant)` | Add product to inventory. | - | +| | | `-fillInventory()` | Initialize inventory with specified items. | | +| | | `-getAllCoffee()` | Get a list of all coffee products. | List | +| | | `-getAllBagels()` | Get a list of all bagel products. | List | +| | | `-getAllFillings()` | Get a list of all filling products. | List | +| | | `-calculateSKU(String productName, String productVariant)` | Calculate SKU based on productName and productVariant. | String | +| | | `+getPrice(Enum productName, Enum productVariant)` | Get price by providing SKU | float | +| | | `+printMenu()` | Print meny of all items in inventory. | Print text | ## Basket -| Classes | Variables | Methods | Scenario | Output | -|----------|-------------------------------|----------------------------------------|---------------------------------------------------------------------------------------------------------------|-----------------| -| `Basket` | `static int idCount` | | "Fake autoincrement id". Counter which will be increased everytime a new product is added to the basket. | | -| | `ArrayList products` | `addCoffee(enum variant)` | Add coffee with specified variant. Then run printBasket(). | | -| | | | Can't add coffee. | throw exception | -| | | `addBagel(enum variant, enum filling)` | Add bagel with specified variant and filling. At the moment just one filling can be added. run printBasket(). | | -| | | | Can't add bagel. | throw exception | -| | | `remove(int ProduktId)` | Product is in basket and can be removed. | Show message | -| | | | Product is not in basket and can not be removed. | throw exception | -| | `int maxCapacity` | `changeCapacity(int newCapacity)` | If newCapacity is more than 0. | true | -| | | | If newCapacity is less than 1. | false | -| | `float totalCost` | `setTotalCost(float newTotalCost)` | | | -| | | `getTotalCost()` | Get total cost of all products. | float | -| | | `printBasket()` | Prints the content of the basket. | Print text | +| Classes | Variables | Methods | Scenario | Output | +|----------|---------------------------------|----------------------------------------|---------------------------------------------------------------------------------------------------------------|-----------------| +| `Basket` | `- static int idCount` | | "Fake autoincrement id". Counter which will be increased everytime a new product is added to the basket. | | +| | `- ArrayList products` | `addCoffee(enum variant)` | Add coffee with specified variant. Then run printBasket(). | | +| | | | Can't add coffee. | throw exception | +| | | `addBagel(enum variant, enum filling)` | Add bagel with specified variant and filling. At the moment just one filling can be added. run printBasket(). | | +| | | | Can't add bagel. | throw exception | +| | | `remove(int ProduktId)` | Product is in basket and can be removed. | Show message | +| | | | Product is not in basket and can not be removed. | throw exception | +| | `int maxCapacity` | `changeCapacity(int newCapacity)` | If newCapacity is more than 0. | true | +| | | | If newCapacity is less than 1. | false | +| | `float totalCost` | `setTotalCost(float newTotalCost)` | | | +| | | `getTotalCost()` | Get total cost of all products. | float | +| | | `printBasket()` | Prints the content of the basket. | Print text | +| | | `getAll()` | Get all products in basket. | List | ## Product | Classes | Variables | Methods | Scenario | Output | @@ -68,6 +66,7 @@ # Class Diagram ## Diagram +TODO: UPDATE.... ![Class Diagram](/assets/images/gleek_class-diagram.png) ## Code From a7f7d371e221d60f9cfeddd855cff6e230e65835 Mon Sep 17 00:00:00 2001 From: shyye Date: Mon, 19 Aug 2024 18:28:31 +0200 Subject: [PATCH 07/93] Add checkInventoryInitialization test --- src/test/java/com/booleanuk/core/InventoryTest.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/test/java/com/booleanuk/core/InventoryTest.java diff --git a/src/test/java/com/booleanuk/core/InventoryTest.java b/src/test/java/com/booleanuk/core/InventoryTest.java new file mode 100644 index 000000000..4613d7244 --- /dev/null +++ b/src/test/java/com/booleanuk/core/InventoryTest.java @@ -0,0 +1,13 @@ +package com.booleanuk.core; + +import org.junit.jupiter.api.Test; + +public class InventoryTest { + Inventory inventory; + + @Test + public void checkInventoryInitialization() { + this.inventory = new Inventory(); + inventory.printMenu(); + } +} From aba887001bece66e7964d2779900287bf72cdbfd Mon Sep 17 00:00:00 2001 From: shyye Date: Tue, 20 Aug 2024 07:28:26 +0200 Subject: [PATCH 08/93] Update checkInventoryInitialization test --- src/test/java/com/booleanuk/core/InventoryTest.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/test/java/com/booleanuk/core/InventoryTest.java b/src/test/java/com/booleanuk/core/InventoryTest.java index 4613d7244..cc5d23798 100644 --- a/src/test/java/com/booleanuk/core/InventoryTest.java +++ b/src/test/java/com/booleanuk/core/InventoryTest.java @@ -7,7 +7,11 @@ public class InventoryTest { @Test public void checkInventoryInitialization() { + + // TODO: How to test print statements this.inventory = new Inventory(); inventory.printMenu(); } + + // TODO: Add more tests } From d941db0c26bc2ae86d09319c28da4c274a0bef1f Mon Sep 17 00:00:00 2001 From: shyye Date: Tue, 20 Aug 2024 07:32:08 +0200 Subject: [PATCH 09/93] Add code for Inventory and corresponding classes --- src/main/java/com/booleanuk/core/Bagel.java | 8 ++ .../java/com/booleanuk/core/BagelVariant.java | 8 ++ src/main/java/com/booleanuk/core/Coffee.java | 7 ++ .../com/booleanuk/core/CoffeeVariant.java | 8 ++ src/main/java/com/booleanuk/core/Filling.java | 7 ++ .../com/booleanuk/core/FillingVariant.java | 10 ++ .../java/com/booleanuk/core/Inventory.java | 115 ++++++++++++++++++ src/main/java/com/booleanuk/core/Product.java | 53 ++++++++ .../java/com/booleanuk/core/ProductName.java | 7 ++ 9 files changed, 223 insertions(+) create mode 100644 src/main/java/com/booleanuk/core/Bagel.java create mode 100644 src/main/java/com/booleanuk/core/BagelVariant.java create mode 100644 src/main/java/com/booleanuk/core/Coffee.java create mode 100644 src/main/java/com/booleanuk/core/CoffeeVariant.java create mode 100644 src/main/java/com/booleanuk/core/Filling.java create mode 100644 src/main/java/com/booleanuk/core/FillingVariant.java create mode 100644 src/main/java/com/booleanuk/core/Inventory.java create mode 100644 src/main/java/com/booleanuk/core/Product.java create mode 100644 src/main/java/com/booleanuk/core/ProductName.java diff --git a/src/main/java/com/booleanuk/core/Bagel.java b/src/main/java/com/booleanuk/core/Bagel.java new file mode 100644 index 000000000..60c60772c --- /dev/null +++ b/src/main/java/com/booleanuk/core/Bagel.java @@ -0,0 +1,8 @@ +package com.booleanuk.core; + +public class Bagel extends Product{ + + public Bagel(int id, String SKU, float price, Enum name, Enum variant) { + super(id, SKU, price, name, variant); + } +} diff --git a/src/main/java/com/booleanuk/core/BagelVariant.java b/src/main/java/com/booleanuk/core/BagelVariant.java new file mode 100644 index 000000000..87cf5cb80 --- /dev/null +++ b/src/main/java/com/booleanuk/core/BagelVariant.java @@ -0,0 +1,8 @@ +package com.booleanuk.core; + +public enum BagelVariant { + ONION, + PLAIN, + EVERYTHING, + SESAME, +} diff --git a/src/main/java/com/booleanuk/core/Coffee.java b/src/main/java/com/booleanuk/core/Coffee.java new file mode 100644 index 000000000..51abd6f00 --- /dev/null +++ b/src/main/java/com/booleanuk/core/Coffee.java @@ -0,0 +1,7 @@ +package com.booleanuk.core; + +public class Coffee extends Product{ + public Coffee(int id, String SKU, float price, Enum name, Enum variant) { + super(id, SKU, price, name, variant); + } +} \ No newline at end of file diff --git a/src/main/java/com/booleanuk/core/CoffeeVariant.java b/src/main/java/com/booleanuk/core/CoffeeVariant.java new file mode 100644 index 000000000..17304f424 --- /dev/null +++ b/src/main/java/com/booleanuk/core/CoffeeVariant.java @@ -0,0 +1,8 @@ +package com.booleanuk.core; + +public enum CoffeeVariant { + BLACK, + WHITE, + CAPUCCINO, + LATTE, +} diff --git a/src/main/java/com/booleanuk/core/Filling.java b/src/main/java/com/booleanuk/core/Filling.java new file mode 100644 index 000000000..e250195d6 --- /dev/null +++ b/src/main/java/com/booleanuk/core/Filling.java @@ -0,0 +1,7 @@ +package com.booleanuk.core; + +public class Filling extends Product { + public Filling(int id, String SKU, float price, Enum name, Enum variant) { + super(id, SKU, price, name, variant); + } +} diff --git a/src/main/java/com/booleanuk/core/FillingVariant.java b/src/main/java/com/booleanuk/core/FillingVariant.java new file mode 100644 index 000000000..24d26a706 --- /dev/null +++ b/src/main/java/com/booleanuk/core/FillingVariant.java @@ -0,0 +1,10 @@ +package com.booleanuk.core; + +public enum FillingVariant { + BACON, + EGG, + CHEESE, + CREAM_CHEESE, + SMOKED_SALMON, + HAM, +} diff --git a/src/main/java/com/booleanuk/core/Inventory.java b/src/main/java/com/booleanuk/core/Inventory.java new file mode 100644 index 000000000..ede99ab63 --- /dev/null +++ b/src/main/java/com/booleanuk/core/Inventory.java @@ -0,0 +1,115 @@ +package com.booleanuk.core; + +import java.util.ArrayList; + +public class Inventory { + private ArrayList products; + + public Inventory() { + this.products = new ArrayList<>(); + fillInventory(); + } + + public void printMenu() { + ArrayList coffee = getAllCoffee(); + ArrayList bagels = getAllBagels(); + ArrayList fillings = getAllFillings(); + + System.out.println("========== Coffee Menu =========="); + System.out.println("\t Coffe \t:\t Variant / Price "); + System.out.println("----------------------------------"); + for (Coffee c : coffee) { + System.out.println("\t\t\t\t " + c.getVariant() + "\t $" + c.getPrice()); + } + System.out.println(); + + System.out.println("========== Bagel Menu =========="); + System.out.println("\t Bagels \t:\t Variant / Price "); + System.out.println("----------------------------------"); + for (Bagel b : bagels) { + System.out.println("\t\t\t\t " + b.getVariant() + "\t $" + b.getPrice()); + } + System.out.println(); + + System.out.println("\t Fillings \t:\t Variant / Price "); + System.out.println("----------------------------------"); + for (Filling f : fillings) { + System.out.println("\t\t\t\t " + f.getVariant() + "\t $" + f.getPrice()); + } + System.out.println(); + } + + private String calulcateSKU(String name, String variant) { + // TODO: This can now override SKU if it calculates the same value, fix this. + // TODO: Not as in example, this takes the whole words + return name + variant; + } + + private void addProduct(float price, Enum name, Enum variant) { + String SKU = calulcateSKU(name.toString(), variant.toString()); + + // TODO: Change to switch statement + if (ProductName.COFFEE == name) { + this.products.add(new Coffee(0, SKU, price, name, variant)); + } else if (ProductName.BAGEL == name) { + this.products.add(new Bagel(0, SKU, price, name, variant)); + } else if (ProductName.FILLING == name) { + this.products.add(new Filling(0, SKU, price, name, variant)); + } + } + + private void fillInventory() { + this.addProduct(0.49f, ProductName.BAGEL, BagelVariant.ONION); + this.addProduct(0.39f, ProductName.BAGEL, BagelVariant.PLAIN); + this.addProduct(0.49f, ProductName.BAGEL, BagelVariant.EVERYTHING); + this.addProduct(0.49f, ProductName.BAGEL, BagelVariant.SESAME); + + this.addProduct(0.99f, ProductName.COFFEE, CoffeeVariant.BLACK); + this.addProduct(1.19f, ProductName.COFFEE, CoffeeVariant.WHITE); + this.addProduct(1.29f, ProductName.COFFEE, CoffeeVariant.CAPUCCINO); + this.addProduct(1.29f, ProductName.COFFEE, CoffeeVariant.LATTE); + + this.addProduct(0.12f, ProductName.FILLING, FillingVariant.BACON); + this.addProduct(0.12f, ProductName.FILLING, FillingVariant.EGG); + this.addProduct(0.12f, ProductName.FILLING, FillingVariant.CHEESE); + this.addProduct(0.12f, ProductName.FILLING, FillingVariant.CREAM_CHEESE); + this.addProduct(0.12f, ProductName.FILLING, FillingVariant.SMOKED_SALMON); + this.addProduct(0.12f, ProductName.FILLING, FillingVariant.HAM); + } + + // TODO: duplication code not good. + private ArrayList getAllCoffee() { + ArrayList coffeList = new ArrayList<>(); + + for (Product product : products) { + if (product.getName() == ProductName.COFFEE) { + coffeList.add((Coffee) product); + } + } + return coffeList; + } + + // TODO: duplication code not good. + private ArrayList getAllBagels() { + ArrayList bagelList = new ArrayList<>(); + + for (Product product : products) { + if (product.getName() == ProductName.BAGEL) { + bagelList.add((Bagel) product); + } + } + return bagelList; + } + + // TODO: duplication code not good. + private ArrayList getAllFillings() { + ArrayList fillingsList = new ArrayList<>(); + + for (Product product : products) { + if (product.getName() == ProductName.FILLING) { + fillingsList.add((Filling) product); + } + } + return fillingsList; + } +} diff --git a/src/main/java/com/booleanuk/core/Product.java b/src/main/java/com/booleanuk/core/Product.java new file mode 100644 index 000000000..a0b77a5a6 --- /dev/null +++ b/src/main/java/com/booleanuk/core/Product.java @@ -0,0 +1,53 @@ +package com.booleanuk.core; + +public class Product { + private int id; + private String SKU; + private float price; + private Enum name; + private Enum variant; + + public Product(int id, String SKU, float price, Enum name, Enum variant) { + this.id = id; + this.SKU = SKU; + this.price = price; + this.name = name; + this.variant = variant; + } + + public int getId() { + return this.id; + } + + public String getSKU() { + return this.SKU; + } + + public void setSKU(String SKU) { + this.SKU = SKU; + } + + public float getPrice() { + return this.price; + } + + public void setPrice(float price) { + this.price = price; + } + + public Enum getName() { + return this.name; + } + + public void setName(Enum name) { + this.name = name; + } + + public Enum getVariant() { + return variant; + } + + public void setVariant(Enum variant) { + this.variant = variant; + } +} diff --git a/src/main/java/com/booleanuk/core/ProductName.java b/src/main/java/com/booleanuk/core/ProductName.java new file mode 100644 index 000000000..021e3dce6 --- /dev/null +++ b/src/main/java/com/booleanuk/core/ProductName.java @@ -0,0 +1,7 @@ +package com.booleanuk.core; + +public enum ProductName { + COFFEE, + BAGEL, + FILLING, +} \ No newline at end of file From f306d6ace342ce35b9dc356102d08ecd56c9a52e Mon Sep 17 00:00:00 2001 From: shyye Date: Tue, 20 Aug 2024 10:57:30 +0200 Subject: [PATCH 10/93] Add addCoffee test --- .../java/com/booleanuk/core/BasketTest.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 src/test/java/com/booleanuk/core/BasketTest.java diff --git a/src/test/java/com/booleanuk/core/BasketTest.java b/src/test/java/com/booleanuk/core/BasketTest.java new file mode 100644 index 000000000..9923fa0ed --- /dev/null +++ b/src/test/java/com/booleanuk/core/BasketTest.java @@ -0,0 +1,17 @@ +package com.booleanuk.core; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class BasketTest { + Inventory inventory; + Basket basket; + + @Test + public void addCoffee() { + this.inventory = new Inventory(); + this.basket = new Basket(); + Product coffee = basket.addCoffee(CoffeeVariant.CAPUCCINO); + Assertions.assertTrue(basket.getAll().contains(coffee)); + } +} From cf697ec9dc9b8525a3c538000fe77ffe5098dfbf Mon Sep 17 00:00:00 2001 From: shyye Date: Wed, 21 Aug 2024 07:42:16 +0200 Subject: [PATCH 11/93] Update checkInventoryInitialization test --- src/test/java/com/booleanuk/core/InventoryTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/java/com/booleanuk/core/InventoryTest.java b/src/test/java/com/booleanuk/core/InventoryTest.java index cc5d23798..7094283a7 100644 --- a/src/test/java/com/booleanuk/core/InventoryTest.java +++ b/src/test/java/com/booleanuk/core/InventoryTest.java @@ -5,6 +5,7 @@ public class InventoryTest { Inventory inventory; + @Test public void checkInventoryInitialization() { From 038f717d449f38abfceb5ba4f3be82a71dbc4b57 Mon Sep 17 00:00:00 2001 From: shyye Date: Wed, 21 Aug 2024 07:45:00 +0200 Subject: [PATCH 12/93] Add inventory and initalization functions --- src/main/java/com/booleanuk/core/Bagel.java | 10 +- src/main/java/com/booleanuk/core/Coffee.java | 11 +- src/main/java/com/booleanuk/core/Filling.java | 10 +- .../java/com/booleanuk/core/Inventory.java | 289 ++++++++++++------ src/main/java/com/booleanuk/core/Product.java | 25 +- .../java/com/booleanuk/core/ProductName.java | 1 + 6 files changed, 237 insertions(+), 109 deletions(-) diff --git a/src/main/java/com/booleanuk/core/Bagel.java b/src/main/java/com/booleanuk/core/Bagel.java index 60c60772c..1bdf0bac9 100644 --- a/src/main/java/com/booleanuk/core/Bagel.java +++ b/src/main/java/com/booleanuk/core/Bagel.java @@ -2,7 +2,13 @@ public class Bagel extends Product{ - public Bagel(int id, String SKU, float price, Enum name, Enum variant) { - super(id, SKU, price, name, variant); + + public Bagel(float price, Enum variant) { + super(price, variant); + } + + @Override + public ProductName setName() { + return ProductName.BAGEL; } } diff --git a/src/main/java/com/booleanuk/core/Coffee.java b/src/main/java/com/booleanuk/core/Coffee.java index 51abd6f00..d529bd178 100644 --- a/src/main/java/com/booleanuk/core/Coffee.java +++ b/src/main/java/com/booleanuk/core/Coffee.java @@ -1,7 +1,14 @@ package com.booleanuk.core; public class Coffee extends Product{ - public Coffee(int id, String SKU, float price, Enum name, Enum variant) { - super(id, SKU, price, name, variant); + + + public Coffee(float price, Enum variant) { + super(price, variant); + } + + @Override + public ProductName setName() { + return ProductName.COFFEE; } } \ No newline at end of file diff --git a/src/main/java/com/booleanuk/core/Filling.java b/src/main/java/com/booleanuk/core/Filling.java index e250195d6..63a0d7761 100644 --- a/src/main/java/com/booleanuk/core/Filling.java +++ b/src/main/java/com/booleanuk/core/Filling.java @@ -1,7 +1,13 @@ package com.booleanuk.core; public class Filling extends Product { - public Filling(int id, String SKU, float price, Enum name, Enum variant) { - super(id, SKU, price, name, variant); + + public Filling(float price, Enum variant) { + super(price, variant); + } + + @Override + public ProductName setName() { + return ProductName.FILLING; } } diff --git a/src/main/java/com/booleanuk/core/Inventory.java b/src/main/java/com/booleanuk/core/Inventory.java index ede99ab63..1532df4bc 100644 --- a/src/main/java/com/booleanuk/core/Inventory.java +++ b/src/main/java/com/booleanuk/core/Inventory.java @@ -1,115 +1,224 @@ package com.booleanuk.core; import java.util.ArrayList; +import java.util.HashMap; public class Inventory { - private ArrayList products; + private HashMap inventoryItems; public Inventory() { - this.products = new ArrayList<>(); + this.inventoryItems = new HashMap<>(); fillInventory(); } - public void printMenu() { - ArrayList coffee = getAllCoffee(); - ArrayList bagels = getAllBagels(); - ArrayList fillings = getAllFillings(); - - System.out.println("========== Coffee Menu =========="); - System.out.println("\t Coffe \t:\t Variant / Price "); - System.out.println("----------------------------------"); - for (Coffee c : coffee) { - System.out.println("\t\t\t\t " + c.getVariant() + "\t $" + c.getPrice()); - } - System.out.println(); - - System.out.println("========== Bagel Menu =========="); - System.out.println("\t Bagels \t:\t Variant / Price "); - System.out.println("----------------------------------"); - for (Bagel b : bagels) { - System.out.println("\t\t\t\t " + b.getVariant() + "\t $" + b.getPrice()); - } - System.out.println(); + private void fillInventory() { - System.out.println("\t Fillings \t:\t Variant / Price "); - System.out.println("----------------------------------"); - for (Filling f : fillings) { - System.out.println("\t\t\t\t " + f.getVariant() + "\t $" + f.getPrice()); + // TODO: Weird to have them here, should move + // Initialize list with inventory products + ArrayList products = new ArrayList<>(); + + products.add(new Bagel(0.49f, BagelVariant.ONION)); + products.add(new Bagel(0.39f, BagelVariant.PLAIN)); + products.add(new Bagel(0.49f, BagelVariant.EVERYTHING)); + products.add(new Bagel(0.49f, BagelVariant.SESAME)); + + products.add(new Coffee(0.99f, CoffeeVariant.BLACK)); + products.add(new Coffee(1.19f, CoffeeVariant.WHITE)); + products.add(new Coffee(1.29f, CoffeeVariant.CAPUCCINO)); + products.add(new Coffee(1.29f, CoffeeVariant.LATTE)); + + products.add(new Filling(0.12f, FillingVariant.BACON)); + products.add(new Filling(0.12f, FillingVariant.EGG)); + products.add(new Filling(0.12f, FillingVariant.CHEESE)); + products.add(new Filling(0.12f, FillingVariant.CREAM_CHEESE)); + products.add(new Filling(0.12f, FillingVariant.SMOKED_SALMON)); + products.add(new Filling(0.12f, FillingVariant.HAM)); + + // Add products to HashMap + for (Product p : products) { + inventoryItems.put(p.getSKU(), p); } - System.out.println(); - } - - private String calulcateSKU(String name, String variant) { - // TODO: This can now override SKU if it calculates the same value, fix this. - // TODO: Not as in example, this takes the whole words - return name + variant; } - private void addProduct(float price, Enum name, Enum variant) { - String SKU = calulcateSKU(name.toString(), variant.toString()); - - // TODO: Change to switch statement - if (ProductName.COFFEE == name) { - this.products.add(new Coffee(0, SKU, price, name, variant)); - } else if (ProductName.BAGEL == name) { - this.products.add(new Bagel(0, SKU, price, name, variant)); - } else if (ProductName.FILLING == name) { - this.products.add(new Filling(0, SKU, price, name, variant)); + public void printMenu() { + // Variables for e.g. "%-15s %-15s %n", keep blank space + String centerSmall = "%4s "; + String center = "%7s "; + String skuAlign = "%-8s "; + String leftAlign = "%-16s "; + String newLine = "%n"; + String divider = "-------------------------------"; + + // TODO: Unnecassary looping + // TODO: Duplicate code + System.out.println(); + System.out.printf(centerSmall + centerSmall + centerSmall + newLine,"", "=== Bob's Bagels ===", ""); + System.out.printf(center + center + center + newLine,"", " ~ Menu ~ ", ""); + System.out.println(divider); + + // Coffee menu + System.out.printf(center + center + center + newLine,"", " COFFEE ", ""); + for (Product item : inventoryItems.values()) { + if (item.getName() == ProductName.COFFEE) { + System.out.printf( + skuAlign + leftAlign + leftAlign + newLine, + item.getSKU()+" | ", item.getVariant().toString(), "$" + item.getPrice() + ); + } } - } - - private void fillInventory() { - this.addProduct(0.49f, ProductName.BAGEL, BagelVariant.ONION); - this.addProduct(0.39f, ProductName.BAGEL, BagelVariant.PLAIN); - this.addProduct(0.49f, ProductName.BAGEL, BagelVariant.EVERYTHING); - this.addProduct(0.49f, ProductName.BAGEL, BagelVariant.SESAME); - - this.addProduct(0.99f, ProductName.COFFEE, CoffeeVariant.BLACK); - this.addProduct(1.19f, ProductName.COFFEE, CoffeeVariant.WHITE); - this.addProduct(1.29f, ProductName.COFFEE, CoffeeVariant.CAPUCCINO); - this.addProduct(1.29f, ProductName.COFFEE, CoffeeVariant.LATTE); - - this.addProduct(0.12f, ProductName.FILLING, FillingVariant.BACON); - this.addProduct(0.12f, ProductName.FILLING, FillingVariant.EGG); - this.addProduct(0.12f, ProductName.FILLING, FillingVariant.CHEESE); - this.addProduct(0.12f, ProductName.FILLING, FillingVariant.CREAM_CHEESE); - this.addProduct(0.12f, ProductName.FILLING, FillingVariant.SMOKED_SALMON); - this.addProduct(0.12f, ProductName.FILLING, FillingVariant.HAM); - } - - // TODO: duplication code not good. - private ArrayList getAllCoffee() { - ArrayList coffeList = new ArrayList<>(); + System.out.println(); - for (Product product : products) { - if (product.getName() == ProductName.COFFEE) { - coffeList.add((Coffee) product); + // Bagel Menu Bagels + System.out.printf(center + center + center + newLine,"", " Bagels ", ""); + for (Product item : inventoryItems.values()) { + if (item.getName() == ProductName.BAGEL) { + System.out.printf( + skuAlign + leftAlign + leftAlign + newLine, + item.getSKU()+" | ", item.getVariant().toString(), "$" + item.getPrice() + ); } } - return coffeList; - } - - // TODO: duplication code not good. - private ArrayList getAllBagels() { - ArrayList bagelList = new ArrayList<>(); + System.out.println(); - for (Product product : products) { - if (product.getName() == ProductName.BAGEL) { - bagelList.add((Bagel) product); + // Bagel Menu Bagels + System.out.printf(center + center + center + newLine,"", "Bagel Fillings", ""); + for (Product item : inventoryItems.values()) { + if (item.getName() == ProductName.FILLING) { + System.out.printf( + skuAlign + leftAlign + leftAlign + newLine, + item.getSKU()+" | ", item.getVariant().toString(), "$" + item.getPrice() + ); } } - return bagelList; + System.out.println(); +// System.out.printf(leftAlign + leftAlign + newLine, "hello", "world"); } - // TODO: duplication code not good. - private ArrayList getAllFillings() { - ArrayList fillingsList = new ArrayList<>(); - for (Product product : products) { - if (product.getName() == ProductName.FILLING) { - fillingsList.add((Filling) product); - } - } - return fillingsList; - } + /** + * Return a String that can be used as key for the HashMap inventoryIten + * @param product + * @return + */ +// private String hash(Product product) { +// String productCode = product.getName().toString().substring(0,2); +// String variantCode = product.getVariant().toString().substring(0,2); +// String hashCode = productCode + variantCode; +// return hashCode.toUpperCase(); +// } + + + + + + + + + + + + + +// public void printMenu() { +// ArrayList coffee = getAllCoffee(); +// ArrayList bagels = getAllBagels(); +// ArrayList fillings = getAllFillings(); +// +// System.out.println("========== Coffee Menu =========="); +// System.out.println("\t Coffe \t:\t Variant / Price "); +// System.out.println("----------------------------------"); +// for (Coffee c : coffee) { +// System.out.println("\t\t\t\t " + c.getVariant() + "\t $" + c.getPrice()); +// } +// System.out.println(); +// +// System.out.println("========== Bagel Menu =========="); +// System.out.println("\t Bagels \t:\t Variant / Price "); +// System.out.println("----------------------------------"); +// for (Bagel b : bagels) { +// System.out.println("\t\t\t\t " + b.getVariant() + "\t $" + b.getPrice()); +// } +// System.out.println(); +// +// System.out.println("\t Fillings \t:\t Variant / Price "); +// System.out.println("----------------------------------"); +// for (Filling f : fillings) { +// System.out.println("\t\t\t\t " + f.getVariant() + "\t $" + f.getPrice()); +// } +// System.out.println(); +// } +// +// private String calulcateSKU(String name, String variant) { +// // TODO: This can now override SKU if it calculates the same value, fix this. +// // TODO: Not as in example, this takes the whole words +// return name + variant; +// } +// +// private void addProduct(float price, Enum name, Enum variant) { +// String SKU = calulcateSKU(name.toString(), variant.toString()); +// +// // TODO: Change to switch statement +// if (ProductName.COFFEE == name) { +// this.products.add(new Coffee(0, SKU, price, name, variant)); +// } else if (ProductName.BAGEL == name) { +// this.products.add(new Bagel(0, SKU, price, name, variant)); +// } else if (ProductName.FILLING == name) { +// this.products.add(new Filling(0, SKU, price, name, variant)); +// } +// } +// +// private void fillInventory() { +// this.addProduct(0.49f, ProductName.BAGEL, BagelVariant.ONION); +// this.addProduct(0.39f, ProductName.BAGEL, BagelVariant.PLAIN); +// this.addProduct(0.49f, ProductName.BAGEL, BagelVariant.EVERYTHING); +// this.addProduct(0.49f, ProductName.BAGEL, BagelVariant.SESAME); +// +// this.addProduct(0.99f, ProductName.COFFEE, CoffeeVariant.BLACK); +// this.addProduct(1.19f, ProductName.COFFEE, CoffeeVariant.WHITE); +// this.addProduct(1.29f, ProductName.COFFEE, CoffeeVariant.CAPUCCINO); +// this.addProduct(1.29f, ProductName.COFFEE, CoffeeVariant.LATTE); +// +// this.addProduct(0.12f, ProductName.FILLING, FillingVariant.BACON); +// this.addProduct(0.12f, ProductName.FILLING, FillingVariant.EGG); +// this.addProduct(0.12f, ProductName.FILLING, FillingVariant.CHEESE); +// this.addProduct(0.12f, ProductName.FILLING, FillingVariant.CREAM_CHEESE); +// this.addProduct(0.12f, ProductName.FILLING, FillingVariant.SMOKED_SALMON); +// this.addProduct(0.12f, ProductName.FILLING, FillingVariant.HAM); +// } +// +// // TODO: duplication code not good. +// private ArrayList getAllCoffee() { +// ArrayList coffeList = new ArrayList<>(); +// +// for (Product product : products) { +// if (product.getName() == ProductName.COFFEE) { +// coffeList.add((Coffee) product); +// } +// } +// return coffeList; +// } +// +// // TODO: duplication code not good. +// private ArrayList getAllBagels() { +// ArrayList bagelList = new ArrayList<>(); +// +// for (Product product : products) { +// if (product.getName() == ProductName.BAGEL) { +// bagelList.add((Bagel) product); +// } +// } +// return bagelList; +// } +// +// // TODO: duplication code not good. +// private ArrayList getAllFillings() { +// ArrayList fillingsList = new ArrayList<>(); +// +// for (Product product : products) { +// if (product.getName() == ProductName.FILLING) { +// fillingsList.add((Filling) product); +// } +// } +// return fillingsList; +// } } diff --git a/src/main/java/com/booleanuk/core/Product.java b/src/main/java/com/booleanuk/core/Product.java index a0b77a5a6..b2a7e5824 100644 --- a/src/main/java/com/booleanuk/core/Product.java +++ b/src/main/java/com/booleanuk/core/Product.java @@ -1,30 +1,29 @@ package com.booleanuk.core; public class Product { - private int id; private String SKU; private float price; - private Enum name; + private ProductName name; private Enum variant; - public Product(int id, String SKU, float price, Enum name, Enum variant) { - this.id = id; - this.SKU = SKU; + public Product(float price, Enum variant) { this.price = price; - this.name = name; + this.name = setName(); this.variant = variant; + this.SKU = setSKU(name, variant); } - public int getId() { - return this.id; - } public String getSKU() { return this.SKU; } - public void setSKU(String SKU) { - this.SKU = SKU; + public String setSKU(ProductName name, Enum variant) { + String productCode = name.toString().substring(0,2); + String variantCode = variant.toString().substring(0,2); + String hashCode = productCode + variantCode; + + return hashCode.toUpperCase(); } public float getPrice() { @@ -39,8 +38,8 @@ public Enum getName() { return this.name; } - public void setName(Enum name) { - this.name = name; + public ProductName setName() { + return ProductName.DEFAULT; } public Enum getVariant() { diff --git a/src/main/java/com/booleanuk/core/ProductName.java b/src/main/java/com/booleanuk/core/ProductName.java index 021e3dce6..700b833b9 100644 --- a/src/main/java/com/booleanuk/core/ProductName.java +++ b/src/main/java/com/booleanuk/core/ProductName.java @@ -1,6 +1,7 @@ package com.booleanuk.core; public enum ProductName { + DEFAULT, COFFEE, BAGEL, FILLING, From f082ddc13a1fa8a724552062b29e6878af4af52a Mon Sep 17 00:00:00 2001 From: shyye Date: Wed, 21 Aug 2024 08:21:04 +0200 Subject: [PATCH 13/93] Update setSKU function --- src/main/java/com/booleanuk/core/Product.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/booleanuk/core/Product.java b/src/main/java/com/booleanuk/core/Product.java index b2a7e5824..882da9ad5 100644 --- a/src/main/java/com/booleanuk/core/Product.java +++ b/src/main/java/com/booleanuk/core/Product.java @@ -19,8 +19,8 @@ public String getSKU() { } public String setSKU(ProductName name, Enum variant) { - String productCode = name.toString().substring(0,2); - String variantCode = variant.toString().substring(0,2); + String productCode = name.toString().substring(0,3); + String variantCode = variant.toString().substring(0,1); String hashCode = productCode + variantCode; return hashCode.toUpperCase(); From bf6356d4b116d77c1ac0f7f582d8011c1fcd0ff4 Mon Sep 17 00:00:00 2001 From: shyye Date: Wed, 21 Aug 2024 11:09:26 +0200 Subject: [PATCH 14/93] Add test comment --- .../java/com/booleanuk/core/InventoryTest.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/booleanuk/core/InventoryTest.java b/src/test/java/com/booleanuk/core/InventoryTest.java index 7094283a7..6ab8d93eb 100644 --- a/src/test/java/com/booleanuk/core/InventoryTest.java +++ b/src/test/java/com/booleanuk/core/InventoryTest.java @@ -1,5 +1,6 @@ package com.booleanuk.core; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; public class InventoryTest { @@ -14,5 +15,18 @@ public void checkInventoryInitialization() { inventory.printMenu(); } - // TODO: Add more tests + @Test + public void getProductBasedOnSKU() { + this.inventory = new Inventory(); + + Coffee coffee = inventory.getCoffeeProduct("COFC"); + Assertions.assertEquals(ProductName.COFFEE, coffee.getName()); + + Bagel bagel = inventory.getBagelProduct("BAGE"); + Assertions.assertEquals(ProductName.BAGEL, bagel.getName()); + + Filling filling = inventory.getFillingProduct("FILB"); + Assertions.assertEquals(ProductName.FILLING, filling.getName()); + } + // TODO: Add test for exception returned when SKU is invalid / Does npt exist } From 187734140959cd0d7fefa8827c40e3458148811e Mon Sep 17 00:00:00 2001 From: shyye Date: Wed, 21 Aug 2024 11:09:46 +0200 Subject: [PATCH 15/93] Add getProduct functions --- src/main/java/com/booleanuk/core/Inventory.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/main/java/com/booleanuk/core/Inventory.java b/src/main/java/com/booleanuk/core/Inventory.java index 1532df4bc..e4e85b566 100644 --- a/src/main/java/com/booleanuk/core/Inventory.java +++ b/src/main/java/com/booleanuk/core/Inventory.java @@ -94,6 +94,22 @@ public void printMenu() { // System.out.printf(leftAlign + leftAlign + newLine, "hello", "world"); } + // TODO: Duplication code, abstraction, but not good otherwise, Factory pattern? + public Coffee getCoffeeProduct(String SKU) { + Product coffeeProduct = inventoryItems.get(SKU); + return (Coffee) coffeeProduct; + } + + public Bagel getBagelProduct(String SKU) { + Product bagelProduct = inventoryItems.get(SKU); + return (Bagel) bagelProduct; + } + + public Filling getFillingProduct(String SKU) { + Product fillingProduct = inventoryItems.get(SKU); + return (Filling) fillingProduct; + } + /** * Return a String that can be used as key for the HashMap inventoryIten From 1367ffc5ae9cdfb1e0357b15fe2b584738b65da4 Mon Sep 17 00:00:00 2001 From: shyye Date: Wed, 21 Aug 2024 12:33:12 +0200 Subject: [PATCH 16/93] Add addCoffee test --- src/test/java/com/booleanuk/core/BasketTest.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/test/java/com/booleanuk/core/BasketTest.java b/src/test/java/com/booleanuk/core/BasketTest.java index 9923fa0ed..508614b9f 100644 --- a/src/test/java/com/booleanuk/core/BasketTest.java +++ b/src/test/java/com/booleanuk/core/BasketTest.java @@ -7,11 +7,18 @@ public class BasketTest { Inventory inventory; Basket basket; + @Test + public void checkPrintBasket() { + this.inventory = new Inventory(); + this.basket = new Basket(new Inventory()); + basket.printBasket(); + } + @Test public void addCoffee() { this.inventory = new Inventory(); - this.basket = new Basket(); - Product coffee = basket.addCoffee(CoffeeVariant.CAPUCCINO); - Assertions.assertTrue(basket.getAll().contains(coffee)); + this.basket = new Basket(new Inventory()); + basket.addCoffee("COFW"); + Assertions.assertEquals("COFW", basket.getAll().get(1).getSKU()); } } From 5c96fcb3fe062c940858a1b245a414f5ad1793f1 Mon Sep 17 00:00:00 2001 From: shyye Date: Wed, 21 Aug 2024 12:33:33 +0200 Subject: [PATCH 17/93] Add addCoffee function --- src/main/java/com/booleanuk/core/Basket.java | 75 ++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 src/main/java/com/booleanuk/core/Basket.java diff --git a/src/main/java/com/booleanuk/core/Basket.java b/src/main/java/com/booleanuk/core/Basket.java new file mode 100644 index 000000000..c8bad3c83 --- /dev/null +++ b/src/main/java/com/booleanuk/core/Basket.java @@ -0,0 +1,75 @@ +package com.booleanuk.core; + +import java.util.HashMap; + +public class Basket { + private Inventory inventory; + private HashMap basketItems; + private int idCount; + + public Basket(Inventory inventory) { + this.inventory = inventory; + this.basketItems = new HashMap(); + this.idCount = 1; + } + + /** + * Create new Id for item in basket. + * Updates idCount afterward. + * @return int itemId + */ + private int createID() { + int itemId = this.idCount; + this.idCount += 1; + return itemId; + } + + public void addCoffee(String SKU) { + Coffee coffee = inventory.getCoffeeProduct(SKU); + basketItems.put(createID(), coffee); + + printBasket(); + } + + public HashMap getAll() { + return basketItems; + } + + public void printBasket() { + // Variables for e.g. "%-15s %-15s %n", keep blank space + String centerSmall = "%27s "; + String center = "%22s "; + String leftAlignSmall = "%-7s "; + String leftAlign = "%-10s "; + String newLine = "%n"; + String divider = "----------------------------------"; + + // TODO: Unnecassary looping + // TODO: Duplicate code + System.out.println(); + System.out.printf(centerSmall + newLine, "=== Bob's Bagels ==="); + System.out.printf(center + newLine, "~ Basket ~"); + System.out.println(divider); + + // Print items in basket + if (basketItems.isEmpty()) { + System.out.println("\tBasket is empty."); + } else { + for (Product item : basketItems.values()) { + if (item.getName() == ProductName.COFFEE) { + System.out.printf( + leftAlignSmall + leftAlignSmall + leftAlign + leftAlign + newLine, + item.getSKU()+" | ", item.getName(), item.getVariant().toString(), "$" + item.getPrice() + ); + } + } + System.out.println(divider); + System.out.printf( + "%s %20s" + newLine, + "Total cost: ", "$?.??" + ); + } + System.out.println(divider); + System.out.println(); + } +} From b3c22573fec7d3398ee82c7d5729b05cb2b6c362 Mon Sep 17 00:00:00 2001 From: shyye Date: Wed, 21 Aug 2024 13:19:13 +0200 Subject: [PATCH 18/93] Add Test --- src/test/java/com/booleanuk/core/BasketTest.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/test/java/com/booleanuk/core/BasketTest.java b/src/test/java/com/booleanuk/core/BasketTest.java index 508614b9f..f4d6931d5 100644 --- a/src/test/java/com/booleanuk/core/BasketTest.java +++ b/src/test/java/com/booleanuk/core/BasketTest.java @@ -19,6 +19,18 @@ public void addCoffee() { this.inventory = new Inventory(); this.basket = new Basket(new Inventory()); basket.addCoffee("COFW"); + basket.printBasket(); Assertions.assertEquals("COFW", basket.getAll().get(1).getSKU()); } + + @Test + public void addBagelAndFilling() { + this.inventory = new Inventory(); + this.basket = new Basket(new Inventory()); + basket.addBagel("BAGE"); + basket.addFilling("FILS"); + basket.printBasket(); + Assertions.assertEquals("BAGE", basket.getAll().get(1).getSKU()); + Assertions.assertEquals("FILS", basket.getAll().get(2).getSKU()); + } } From ee6ee483d654ea099237db7e5410f12fa1a68300 Mon Sep 17 00:00:00 2001 From: shyye Date: Wed, 21 Aug 2024 13:22:15 +0200 Subject: [PATCH 19/93] Add addBagel and addFilling functions --- src/main/java/com/booleanuk/core/Basket.java | 45 +++++++++++++------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/booleanuk/core/Basket.java b/src/main/java/com/booleanuk/core/Basket.java index c8bad3c83..84ac268ce 100644 --- a/src/main/java/com/booleanuk/core/Basket.java +++ b/src/main/java/com/booleanuk/core/Basket.java @@ -1,6 +1,7 @@ package com.booleanuk.core; import java.util.HashMap; +import java.util.Map; public class Basket { private Inventory inventory; @@ -26,46 +27,60 @@ private int createID() { public void addCoffee(String SKU) { Coffee coffee = inventory.getCoffeeProduct(SKU); - basketItems.put(createID(), coffee); - + this.basketItems.put(createID(), coffee); printBasket(); } + public void addBagel(String SKU) { + Bagel bagel = inventory.getBagelProduct(SKU); + this.basketItems.put(createID(), bagel); + } + + public void addFilling(String SKU) { + Filling filling = inventory.getFillingProduct(SKU); + this.basketItems.put(createID(), filling); + } + public HashMap getAll() { return basketItems; } public void printBasket() { // Variables for e.g. "%-15s %-15s %n", keep blank space - String centerSmall = "%27s "; - String center = "%22s "; + String centerSmall = "%34s "; + String center = "%29s "; String leftAlignSmall = "%-7s "; - String leftAlign = "%-10s "; + String leftAlign = "%-15s "; String newLine = "%n"; - String divider = "----------------------------------"; + String divider = "-----------------------------------------------"; // TODO: Unnecassary looping // TODO: Duplicate code System.out.println(); System.out.printf(centerSmall + newLine, "=== Bob's Bagels ==="); System.out.printf(center + newLine, "~ Basket ~"); - System.out.println(divider); + System.out.println(); // Print items in basket if (basketItems.isEmpty()) { System.out.println("\tBasket is empty."); } else { - for (Product item : basketItems.values()) { - if (item.getName() == ProductName.COFFEE) { - System.out.printf( - leftAlignSmall + leftAlignSmall + leftAlign + leftAlign + newLine, - item.getSKU()+" | ", item.getName(), item.getVariant().toString(), "$" + item.getPrice() - ); - } + System.out.printf( + leftAlignSmall + leftAlignSmall + leftAlignSmall + leftAlign + leftAlign + newLine, + "SKU | ", "ID", "Product", "Variant", "Price" + ); + System.out.println(divider); + for (Map.Entry item : basketItems.entrySet()) { + int key = item.getKey(); + Product product = item.getValue(); + System.out.printf( + leftAlignSmall + leftAlignSmall + leftAlignSmall + leftAlign + leftAlign + newLine, + product.getSKU()+" | ", key, product.getName(), product.getVariant().toString(), "$" + product.getPrice() + ); } System.out.println(divider); System.out.printf( - "%s %20s" + newLine, + "%s %33s" + newLine, "Total cost: ", "$?.??" ); } From c89d3178a0d2eb1520470e63f05509586bc56bdf Mon Sep 17 00:00:00 2001 From: shyye Date: Wed, 21 Aug 2024 15:09:16 +0200 Subject: [PATCH 20/93] Add Test --- src/test/java/com/booleanuk/core/BasketTest.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/test/java/com/booleanuk/core/BasketTest.java b/src/test/java/com/booleanuk/core/BasketTest.java index f4d6931d5..d67fc6e4a 100644 --- a/src/test/java/com/booleanuk/core/BasketTest.java +++ b/src/test/java/com/booleanuk/core/BasketTest.java @@ -3,6 +3,8 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import java.util.Arrays; + public class BasketTest { Inventory inventory; Basket basket; @@ -27,10 +29,9 @@ public void addCoffee() { public void addBagelAndFilling() { this.inventory = new Inventory(); this.basket = new Basket(new Inventory()); - basket.addBagel("BAGE"); - basket.addFilling("FILS"); + basket.addBagel("BAGE", Arrays.asList("FILS","FILB")); basket.printBasket(); Assertions.assertEquals("BAGE", basket.getAll().get(1).getSKU()); - Assertions.assertEquals("FILS", basket.getAll().get(2).getSKU()); + Assertions.assertEquals("FILS", basket.getAll().get(101).getSKU()); } } From d734d6725cd8f6a31363c78260c0835191afdc29 Mon Sep 17 00:00:00 2001 From: shyye Date: Wed, 21 Aug 2024 15:10:14 +0200 Subject: [PATCH 21/93] Fix addBagel with filling functions --- src/main/java/com/booleanuk/core/Bagel.java | 10 +++++ src/main/java/com/booleanuk/core/Basket.java | 44 +++++++++++++++----- 2 files changed, 44 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/booleanuk/core/Bagel.java b/src/main/java/com/booleanuk/core/Bagel.java index 1bdf0bac9..51d02fa3e 100644 --- a/src/main/java/com/booleanuk/core/Bagel.java +++ b/src/main/java/com/booleanuk/core/Bagel.java @@ -1,14 +1,24 @@ package com.booleanuk.core; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + public class Bagel extends Product{ + private List fillings; public Bagel(float price, Enum variant) { super(price, variant); + this.fillings = new ArrayList<>(); } @Override public ProductName setName() { return ProductName.BAGEL; } + + public void addFilling(Filling filling) { + this.fillings.add(filling); + } } diff --git a/src/main/java/com/booleanuk/core/Basket.java b/src/main/java/com/booleanuk/core/Basket.java index 84ac268ce..93b16ee5a 100644 --- a/src/main/java/com/booleanuk/core/Basket.java +++ b/src/main/java/com/booleanuk/core/Basket.java @@ -1,47 +1,71 @@ package com.booleanuk.core; -import java.util.HashMap; -import java.util.Map; +import java.util.*; public class Basket { private Inventory inventory; - private HashMap basketItems; + private LinkedHashMap basketItems; private int idCount; public Basket(Inventory inventory) { this.inventory = inventory; - this.basketItems = new HashMap(); + this.basketItems = new LinkedHashMap <>(); this.idCount = 1; } /** * Create new Id for item in basket. * Updates idCount afterward. + * @param String idExtension - Add this for fillings, one unique extension for each filling * @return int itemId */ private int createID() { + // Store variable int itemId = this.idCount; this.idCount += 1; return itemId; } + private int createFillingId(String idExtension) { + //TODO: How to make default variable like in python + + // TODO: Should check if idExtension is valid + + // TODO: Could use int input instead of String + + // Store variable id for previous bagel + int itemId = this.idCount - 1; + + // Add id extension for filling + String tmp = String.valueOf(itemId) + "0" + idExtension; + return Integer.parseInt(tmp); + } + public void addCoffee(String SKU) { Coffee coffee = inventory.getCoffeeProduct(SKU); this.basketItems.put(createID(), coffee); printBasket(); } - public void addBagel(String SKU) { + public void addBagel(String SKU, List SKUfillings) { Bagel bagel = inventory.getBagelProduct(SKU); this.basketItems.put(createID(), bagel); - } - public void addFilling(String SKU) { - Filling filling = inventory.getFillingProduct(SKU); - this.basketItems.put(createID(), filling); + int count = 1; + for (String SKUf : SKUfillings) { + Filling filling = this.inventory.getFillingProduct(SKUf); + bagel.addFilling(filling); + this.basketItems.put(createFillingId(String.valueOf(count)), filling); + count++; + } } - public HashMap getAll() { +// private void addFilling(String SKU) { +// Filling filling = inventory.getFillingProduct(SKU); +// this.basketItems.put(createID(), filling); +// } + + public LinkedHashMap getAll() { return basketItems; } From d1103b74a823de2a41f178482d957fd96b339958 Mon Sep 17 00:00:00 2001 From: shyye Date: Wed, 21 Aug 2024 17:25:29 +0200 Subject: [PATCH 22/93] Add Test --- src/test/java/com/booleanuk/core/BasketTest.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/test/java/com/booleanuk/core/BasketTest.java b/src/test/java/com/booleanuk/core/BasketTest.java index d67fc6e4a..28ab686f5 100644 --- a/src/test/java/com/booleanuk/core/BasketTest.java +++ b/src/test/java/com/booleanuk/core/BasketTest.java @@ -34,4 +34,16 @@ public void addBagelAndFilling() { Assertions.assertEquals("BAGE", basket.getAll().get(1).getSKU()); Assertions.assertEquals("FILS", basket.getAll().get(101).getSKU()); } + + @Test + public void removeBagel() { + this.inventory = new Inventory(); + this.basket = new Basket(new Inventory()); + basket.addBagel("BAGE", Arrays.asList("FILS","FILB")); + basket.addBagel("BAGE", Arrays.asList("FILS","FILB")); + basket.printBasket(); + + basket.remove(1); + basket.printBasket(); + } } From 6c1a85382ac4500cd2aa4f28089ed0e6500f6975 Mon Sep 17 00:00:00 2001 From: shyye Date: Wed, 21 Aug 2024 17:26:04 +0200 Subject: [PATCH 23/93] Add remove function and refactored --- src/main/java/com/booleanuk/core/Bagel.java | 8 ++- src/main/java/com/booleanuk/core/Basket.java | 55 +++++++++++++++---- .../java/com/booleanuk/core/BasketItem.java | 32 +++++++++++ 3 files changed, 81 insertions(+), 14 deletions(-) create mode 100644 src/main/java/com/booleanuk/core/BasketItem.java diff --git a/src/main/java/com/booleanuk/core/Bagel.java b/src/main/java/com/booleanuk/core/Bagel.java index 51d02fa3e..c55dd9e6c 100644 --- a/src/main/java/com/booleanuk/core/Bagel.java +++ b/src/main/java/com/booleanuk/core/Bagel.java @@ -6,7 +6,7 @@ public class Bagel extends Product{ - private List fillings; + private List fillings; public Bagel(float price, Enum variant) { super(price, variant); @@ -18,7 +18,11 @@ public ProductName setName() { return ProductName.BAGEL; } - public void addFilling(Filling filling) { + public void addFilling(int filling) { this.fillings.add(filling); } + + public List getFillings() { + return fillings; + } } diff --git a/src/main/java/com/booleanuk/core/Basket.java b/src/main/java/com/booleanuk/core/Basket.java index 93b16ee5a..3d183b10f 100644 --- a/src/main/java/com/booleanuk/core/Basket.java +++ b/src/main/java/com/booleanuk/core/Basket.java @@ -4,7 +4,7 @@ public class Basket { private Inventory inventory; - private LinkedHashMap basketItems; + private LinkedHashMap basketItems; private int idCount; public Basket(Inventory inventory) { @@ -41,31 +41,61 @@ private int createFillingId(String idExtension) { return Integer.parseInt(tmp); } + // TODO: Refactor and remove this and add generic function nsad public void addCoffee(String SKU) { - Coffee coffee = inventory.getCoffeeProduct(SKU); - this.basketItems.put(createID(), coffee); + BasketItem item = new BasketItem(SKU); + this.basketItems.put(createID(), item); printBasket(); } + + public void addBagel(String SKU) { + BasketItem item = new BasketItem(SKU); + this.basketItems.put(createID(), item); + } + + public void addBagel(String SKU, List SKUfillings) { - Bagel bagel = inventory.getBagelProduct(SKU); - this.basketItems.put(createID(), bagel); + BasketItem item = new BasketItem(SKU); + this.basketItems.put(createID(), item); int count = 1; - for (String SKUf : SKUfillings) { - Filling filling = this.inventory.getFillingProduct(SKUf); - bagel.addFilling(filling); - this.basketItems.put(createFillingId(String.valueOf(count)), filling); + for (String SKU_f : SKUfillings) { + + // Store the created id for the filling + int fillingId = createFillingId(String.valueOf(count)); + + // Add filling to this basket + this.basketItems.put(fillingId, new BasketItem(SKU_f)); + + // Store filling id in bagel basketIem so it is possible to delete later + item.addFillingId(fillingId); + count++; } } + public void remove(int productId) { + BasketItem item = this.basketItems.get(productId); + Product product = this.inventory.getProduct(item.getSKU()); + + if (product.getName() == ProductName.BAGEL && item.getLinkedIds() != null) { + // Get filling for this basketItem + List fillingsIds = item.getLinkedIds(); + // Remove the bagel fillings from the basket + for (Integer fillingId : fillingsIds) { + this.basketItems.remove(fillingId); + } + } + this.basketItems.remove(productId); + } + // private void addFilling(String SKU) { // Filling filling = inventory.getFillingProduct(SKU); // this.basketItems.put(createID(), filling); // } - public LinkedHashMap getAll() { + public LinkedHashMap getAll() { return basketItems; } @@ -94,9 +124,10 @@ public void printBasket() { "SKU | ", "ID", "Product", "Variant", "Price" ); System.out.println(divider); - for (Map.Entry item : basketItems.entrySet()) { + for (Map.Entry item : basketItems.entrySet()) { int key = item.getKey(); - Product product = item.getValue(); + BasketItem basketItem = item.getValue(); + Product product = this.inventory.getProduct(basketItem.getSKU()); System.out.printf( leftAlignSmall + leftAlignSmall + leftAlignSmall + leftAlign + leftAlign + newLine, product.getSKU()+" | ", key, product.getName(), product.getVariant().toString(), "$" + product.getPrice() diff --git a/src/main/java/com/booleanuk/core/BasketItem.java b/src/main/java/com/booleanuk/core/BasketItem.java new file mode 100644 index 000000000..f563bdd36 --- /dev/null +++ b/src/main/java/com/booleanuk/core/BasketItem.java @@ -0,0 +1,32 @@ +package com.booleanuk.core; + +import java.util.ArrayList; +import java.util.List; + +public class BasketItem { + private String SKU; + private List linkedIds; + + public BasketItem(String SKU) { + this.SKU = SKU; + this.linkedIds = new ArrayList<>(); + } + + // TODO: Refactor may not be used + public BasketItem(String SKU, List linkedIds) { + this.SKU = SKU; + this.linkedIds = linkedIds; + } + + public String getSKU() { + return SKU; + } + + public List getLinkedIds() { + return linkedIds; + } + + public void addFillingId(int id) { + this.linkedIds.add(id); + } +} From da4e82577d24feea96efc50523383e003a7e0b32 Mon Sep 17 00:00:00 2001 From: shyye Date: Wed, 21 Aug 2024 17:26:18 +0200 Subject: [PATCH 24/93] Add comment --- src/main/java/com/booleanuk/core/Inventory.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/com/booleanuk/core/Inventory.java b/src/main/java/com/booleanuk/core/Inventory.java index e4e85b566..31ff99c8f 100644 --- a/src/main/java/com/booleanuk/core/Inventory.java +++ b/src/main/java/com/booleanuk/core/Inventory.java @@ -51,6 +51,7 @@ public void printMenu() { // TODO: Unnecassary looping // TODO: Duplicate code + // Simplify, doesn't have to have multiple center System.out.println(); System.out.printf(centerSmall + centerSmall + centerSmall + newLine,"", "=== Bob's Bagels ===", ""); System.out.printf(center + center + center + newLine,"", " ~ Menu ~ ", ""); @@ -110,6 +111,11 @@ public Filling getFillingProduct(String SKU) { return (Filling) fillingProduct; } + // TODO:Refactor or good to have the above methods for the Basket class? + public Product getProduct(String SKU) { + return inventoryItems.get(SKU); + } + /** * Return a String that can be used as key for the HashMap inventoryIten From 6c7d5f4c9924f2c9b4ec6c7dd331808d53f6b051 Mon Sep 17 00:00:00 2001 From: shyye Date: Thu, 22 Aug 2024 06:46:52 +0200 Subject: [PATCH 25/93] Add Test --- .../java/com/booleanuk/core/BasketTest.java | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/test/java/com/booleanuk/core/BasketTest.java b/src/test/java/com/booleanuk/core/BasketTest.java index 28ab686f5..a95062f22 100644 --- a/src/test/java/com/booleanuk/core/BasketTest.java +++ b/src/test/java/com/booleanuk/core/BasketTest.java @@ -25,6 +25,7 @@ public void addCoffee() { Assertions.assertEquals("COFW", basket.getAll().get(1).getSKU()); } + // User story #1 Add a specific type of bagel @Test public void addBagelAndFilling() { this.inventory = new Inventory(); @@ -35,6 +36,7 @@ public void addBagelAndFilling() { Assertions.assertEquals("FILS", basket.getAll().get(101).getSKU()); } + // User story #1 Add a specific type of bagel @Test public void removeBagel() { this.inventory = new Inventory(); @@ -43,7 +45,34 @@ public void removeBagel() { basket.addBagel("BAGE", Arrays.asList("FILS","FILB")); basket.printBasket(); + // TODO: Add test basket.remove(1); basket.printBasket(); } + +// @Test +// public void tryToAddProductThatIsNotInInventory() { +// this.inventory = new Inventory(); +// this.basket = new Basket(new Inventory()); +// basket.addBagel("HELLO", Arrays.asList("FILS","FILB")); +// basket.printBasket(); +// } + + // User story #3 Notify when max capacity of basket is reached + @Test + public void exceedMaxCapacityShouldThrowError() { + this.inventory = new Inventory(); + this.basket = new Basket(new Inventory()); + + basket.changeMaxCapacity(2); + basket.addBagel("BAGE"); + basket.addBagel("BAGE"); + + // TODO: I need to set addToBasket() to protected instead of private and + // test it because I can't test addBgel()/addCoffe() because they includes a try/catch + MaxCapacityException exception = Assertions.assertThrows(MaxCapacityException.class, () -> { + basket.addToBasket(11,new BasketItem("BAGE")); + }); + Assertions.assertEquals("Basket is full, can't add more items", exception.getLocalizedMessage()); + } } From abbd432336edf01f341c8026d7653b3965cbd9b5 Mon Sep 17 00:00:00 2001 From: shyye Date: Thu, 22 Aug 2024 06:47:54 +0200 Subject: [PATCH 26/93] Add addToBasket protected function --- src/main/java/com/booleanuk/core/Basket.java | 74 +++++++++++++++----- 1 file changed, 57 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/booleanuk/core/Basket.java b/src/main/java/com/booleanuk/core/Basket.java index 3d183b10f..c7d2bbfda 100644 --- a/src/main/java/com/booleanuk/core/Basket.java +++ b/src/main/java/com/booleanuk/core/Basket.java @@ -5,11 +5,13 @@ public class Basket { private Inventory inventory; private LinkedHashMap basketItems; + private int maxCapacity; private int idCount; public Basket(Inventory inventory) { this.inventory = inventory; this.basketItems = new LinkedHashMap <>(); + this.maxCapacity = 20; this.idCount = 1; } @@ -41,37 +43,71 @@ private int createFillingId(String idExtension) { return Integer.parseInt(tmp); } - // TODO: Refactor and remove this and add generic function nsad + // TODO: I need to have this because otherwise I can't make a unit test on it, + // but I don't want the inventory or other classes to have aceess to this. + // should I put basket in an own package? + // Oterwise change back to private + // See test exceedMaxCapacityShouldThrowError + protected void addToBasket(int id, BasketItem item) { + if (this.basketItems.size() == maxCapacity) { + throw new MaxCapacityException("Basket is full, can't add more items"); + } + this.basketItems.put(id, item); + } + + // TODO: Refactor and remove this and add generic function nsad?? public void addCoffee(String SKU) { - BasketItem item = new BasketItem(SKU); - this.basketItems.put(createID(), item); - printBasket(); + try { +// BasketItem item = new BasketItem(SKU); +// this.basketItems.put(createID(), item); + + this.addToBasket(createID(), new BasketItem(SKU)); + printBasket(); + } catch (MaxCapacityException e) { + System.out.println(e.getMessage()); + } } public void addBagel(String SKU) { - BasketItem item = new BasketItem(SKU); - this.basketItems.put(createID(), item); + try { +// BasketItem item = new BasketItem(SKU); +// this.basketItems.put(createID(), item); + + this.addToBasket(createID(), new BasketItem(SKU)); + } catch (MaxCapacityException e) { + System.out.println(e.getMessage()); + } +// // TODO: Can't check throw exception in Test if I handle the exception with try/catch +// this.addToBasket(createID(), new BasketItem(SKU)); + + } public void addBagel(String SKU, List SKUfillings) { - BasketItem item = new BasketItem(SKU); - this.basketItems.put(createID(), item); + try { + BasketItem item = new BasketItem(SKU); +// this.basketItems.put(createID(), item); + this.addToBasket(createID(), item); - int count = 1; - for (String SKU_f : SKUfillings) { + int count = 1; + for (String SKU_f : SKUfillings) { - // Store the created id for the filling - int fillingId = createFillingId(String.valueOf(count)); + // Store the created id for the filling + int fillingId = createFillingId(String.valueOf(count)); - // Add filling to this basket - this.basketItems.put(fillingId, new BasketItem(SKU_f)); + // Add filling to this basket +// this.basketItems.put(fillingId, new BasketItem(SKU_f)); + this.addToBasket(fillingId, new BasketItem(SKU_f)); - // Store filling id in bagel basketIem so it is possible to delete later - item.addFillingId(fillingId); + // Store filling id in bagel basketIem so it is possible to delete later + item.addFillingId(fillingId); - count++; + count++; + } + } catch (MaxCapacityException e) { + System.out.println(e.getMessage()); } } @@ -99,6 +135,10 @@ public LinkedHashMap getAll() { return basketItems; } + public void changeMaxCapacity(int newMaxCapacity) { + this.maxCapacity = newMaxCapacity; + } + public void printBasket() { // Variables for e.g. "%-15s %-15s %n", keep blank space String centerSmall = "%34s "; From eeef00efeeb4baaae0058cfcaac93f815f54be60 Mon Sep 17 00:00:00 2001 From: shyye Date: Thu, 22 Aug 2024 06:48:13 +0200 Subject: [PATCH 27/93] Add custom exception --- src/main/java/com/booleanuk/core/MaxCapacityException.java | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 src/main/java/com/booleanuk/core/MaxCapacityException.java diff --git a/src/main/java/com/booleanuk/core/MaxCapacityException.java b/src/main/java/com/booleanuk/core/MaxCapacityException.java new file mode 100644 index 000000000..49bd67b78 --- /dev/null +++ b/src/main/java/com/booleanuk/core/MaxCapacityException.java @@ -0,0 +1,7 @@ +package com.booleanuk.core; + +public class MaxCapacityException extends RuntimeException { + public MaxCapacityException(String message) { + super(message); + } +} From 4ad990da14faaf36e9daec948493d0ba37b08306 Mon Sep 17 00:00:00 2001 From: shyye Date: Thu, 22 Aug 2024 06:54:59 +0200 Subject: [PATCH 28/93] Add comments to Maxcapacity test --- src/test/java/com/booleanuk/core/BasketTest.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/booleanuk/core/BasketTest.java b/src/test/java/com/booleanuk/core/BasketTest.java index a95062f22..003be8427 100644 --- a/src/test/java/com/booleanuk/core/BasketTest.java +++ b/src/test/java/com/booleanuk/core/BasketTest.java @@ -73,6 +73,13 @@ public void exceedMaxCapacityShouldThrowError() { MaxCapacityException exception = Assertions.assertThrows(MaxCapacityException.class, () -> { basket.addToBasket(11,new BasketItem("BAGE")); }); - Assertions.assertEquals("Basket is full, can't add more items", exception.getLocalizedMessage()); +// Assertions.assertEquals("Basket is full, can't add more items.", exception.getLocalizedMessage()); + + // Print out message from exception instead of checking if its assertEqual + System.out.println("\nException message:"); + System.out.println("\t" + exception.getMessage() + "\n"); + + // Public method that should print out the error +// basket.addBagel("BAGE"); } } From 79b4715d48448044d4e4e8885c94cd760e32a6db Mon Sep 17 00:00:00 2001 From: shyye Date: Thu, 22 Aug 2024 07:05:47 +0200 Subject: [PATCH 29/93] Add Test: checkChangeCapacity --- src/test/java/com/booleanuk/core/BasketTest.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/test/java/com/booleanuk/core/BasketTest.java b/src/test/java/com/booleanuk/core/BasketTest.java index 003be8427..d251fc1d5 100644 --- a/src/test/java/com/booleanuk/core/BasketTest.java +++ b/src/test/java/com/booleanuk/core/BasketTest.java @@ -82,4 +82,17 @@ public void exceedMaxCapacityShouldThrowError() { // Public method that should print out the error // basket.addBagel("BAGE"); } + + // User story #4: Change max capacity of basket + @Test + public void checkChangeMaxCapacity() { + this.inventory = new Inventory(); + this.basket = new Basket(new Inventory()); + + basket.changeMaxCapacity(3); + Assertions.assertEquals(3, basket.getMaxCapacity()); + + basket.changeMaxCapacity(12); + Assertions.assertEquals(12, basket.getMaxCapacity()); + } } From e25ba57f12cd87d1ac33d2b9c7d50f6d60e66e05 Mon Sep 17 00:00:00 2001 From: shyye Date: Thu, 22 Aug 2024 07:06:17 +0200 Subject: [PATCH 30/93] Update code --- src/main/java/com/booleanuk/core/Basket.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/booleanuk/core/Basket.java b/src/main/java/com/booleanuk/core/Basket.java index c7d2bbfda..0f4fb1979 100644 --- a/src/main/java/com/booleanuk/core/Basket.java +++ b/src/main/java/com/booleanuk/core/Basket.java @@ -50,7 +50,7 @@ private int createFillingId(String idExtension) { // See test exceedMaxCapacityShouldThrowError protected void addToBasket(int id, BasketItem item) { if (this.basketItems.size() == maxCapacity) { - throw new MaxCapacityException("Basket is full, can't add more items"); + throw new MaxCapacityException("Basket is full, can't add more items."); } this.basketItems.put(id, item); } @@ -139,6 +139,11 @@ public void changeMaxCapacity(int newMaxCapacity) { this.maxCapacity = newMaxCapacity; } + // TODO: I only use this for the test. Should I redo the test? + public int getMaxCapacity() { + return this.maxCapacity; + } + public void printBasket() { // Variables for e.g. "%-15s %-15s %n", keep blank space String centerSmall = "%34s "; From c532786c6e3ac65eb9cdde56c14ac676e50b2e59 Mon Sep 17 00:00:00 2001 From: shyye Date: Thu, 22 Aug 2024 07:06:45 +0200 Subject: [PATCH 31/93] Add comment --- src/test/java/com/booleanuk/core/InventoryTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/java/com/booleanuk/core/InventoryTest.java b/src/test/java/com/booleanuk/core/InventoryTest.java index 6ab8d93eb..e54903243 100644 --- a/src/test/java/com/booleanuk/core/InventoryTest.java +++ b/src/test/java/com/booleanuk/core/InventoryTest.java @@ -29,4 +29,5 @@ public void getProductBasedOnSKU() { Assertions.assertEquals(ProductName.FILLING, filling.getName()); } // TODO: Add test for exception returned when SKU is invalid / Does npt exist + //TODO: Add test for only product no specific version } From b780c9c3a4dce2d87c5ee104c6b5119faac0096b Mon Sep 17 00:00:00 2001 From: shyye Date: Thu, 22 Aug 2024 10:15:37 +0200 Subject: [PATCH 32/93] Update code --- src/main/java/com/booleanuk/core/Bagel.java | 18 +++++----- src/main/java/com/booleanuk/core/Basket.java | 36 +++++++++++++------ .../core/BasketItemExistException.java | 7 ++++ .../java/com/booleanuk/core/BasketTest.java | 21 +++++++++++ 4 files changed, 62 insertions(+), 20 deletions(-) create mode 100644 src/main/java/com/booleanuk/core/BasketItemExistException.java diff --git a/src/main/java/com/booleanuk/core/Bagel.java b/src/main/java/com/booleanuk/core/Bagel.java index c55dd9e6c..7958a6061 100644 --- a/src/main/java/com/booleanuk/core/Bagel.java +++ b/src/main/java/com/booleanuk/core/Bagel.java @@ -6,11 +6,11 @@ public class Bagel extends Product{ - private List fillings; +// private List fillings; public Bagel(float price, Enum variant) { super(price, variant); - this.fillings = new ArrayList<>(); +// this.fillings = new ArrayList<>(); } @Override @@ -18,11 +18,11 @@ public ProductName setName() { return ProductName.BAGEL; } - public void addFilling(int filling) { - this.fillings.add(filling); - } - - public List getFillings() { - return fillings; - } +// public void addFilling(int filling) { +// this.fillings.add(filling); +// } +// +// public List getFillings() { +// return fillings; +// } } diff --git a/src/main/java/com/booleanuk/core/Basket.java b/src/main/java/com/booleanuk/core/Basket.java index 0f4fb1979..3df471c15 100644 --- a/src/main/java/com/booleanuk/core/Basket.java +++ b/src/main/java/com/booleanuk/core/Basket.java @@ -55,6 +55,16 @@ protected void addToBasket(int id, BasketItem item) { this.basketItems.put(id, item); } + // TODO: Same as above, is it good practice to do this? + // it's easier to test Exceptions + protected BasketItem getItemFromBasketOrThrowException(int productId) { + BasketItem item = this.basketItems.get(productId); + if (item == null) { + throw new BasketItemExistException("This item doesn't exist. Can't remove ID #" + productId); + } + return item; + } + // TODO: Refactor and remove this and add generic function nsad?? public void addCoffee(String SKU) { try { @@ -81,7 +91,6 @@ public void addBagel(String SKU) { // // TODO: Can't check throw exception in Test if I handle the exception with try/catch // this.addToBasket(createID(), new BasketItem(SKU)); - } @@ -112,18 +121,23 @@ public void addBagel(String SKU, List SKUfillings) { } public void remove(int productId) { - BasketItem item = this.basketItems.get(productId); - Product product = this.inventory.getProduct(item.getSKU()); - - if (product.getName() == ProductName.BAGEL && item.getLinkedIds() != null) { - // Get filling for this basketItem - List fillingsIds = item.getLinkedIds(); - // Remove the bagel fillings from the basket - for (Integer fillingId : fillingsIds) { - this.basketItems.remove(fillingId); + try { +// BasketItem item = this.basketItems.get(productId); + BasketItem item = this.getItemFromBasketOrThrowException(productId); + Product product = this.inventory.getProduct(item.getSKU()); + + if (product.getName() == ProductName.BAGEL && item.getLinkedIds() != null) { + // Get filling for this basketItem + List fillingsIds = item.getLinkedIds(); + // Remove the bagel fillings from the basket + for (Integer fillingId : fillingsIds) { + this.basketItems.remove(fillingId); + } } + this.basketItems.remove(productId); + } catch (BasketItemExistException e) { + System.out.println(e.getMessage()); } - this.basketItems.remove(productId); } // private void addFilling(String SKU) { diff --git a/src/main/java/com/booleanuk/core/BasketItemExistException.java b/src/main/java/com/booleanuk/core/BasketItemExistException.java new file mode 100644 index 000000000..715a14cad --- /dev/null +++ b/src/main/java/com/booleanuk/core/BasketItemExistException.java @@ -0,0 +1,7 @@ +package com.booleanuk.core; + +public class BasketItemExistException extends RuntimeException { + public BasketItemExistException(String message) { + super(message); + } +} diff --git a/src/test/java/com/booleanuk/core/BasketTest.java b/src/test/java/com/booleanuk/core/BasketTest.java index d251fc1d5..a39b6c87a 100644 --- a/src/test/java/com/booleanuk/core/BasketTest.java +++ b/src/test/java/com/booleanuk/core/BasketTest.java @@ -50,6 +50,27 @@ public void removeBagel() { basket.printBasket(); } + // User story #5 + @Test + public void removeItemFromBasketThatDoNotExist() { + this.inventory = new Inventory(); + this.basket = new Basket(new Inventory()); + int productId = 5; + + // Check that exception function throws error + BasketItemExistException exception = Assertions.assertThrows(BasketItemExistException.class, () -> { + basket.getItemFromBasketOrThrowException(productId); + }); + // Print out message from exception instead of checking if its assertEqual + System.out.println("\nException message:"); + System.out.println("\t" + exception.getMessage() + "\n"); + + // TODO: Split into two tests + + // Check if basket.remove() handles error correct (no exception) + Assertions.assertDoesNotThrow(() -> basket.remove(productId)); + } + // @Test // public void tryToAddProductThatIsNotInInventory() { // this.inventory = new Inventory(); From 34303f0a4edd2ef371cbd247ab5d6c01d185ca14 Mon Sep 17 00:00:00 2001 From: shyye Date: Thu, 22 Aug 2024 12:34:03 +0200 Subject: [PATCH 33/93] Remake of inventory in another package --- .../booleanuk/core/inventory/Inventory.java | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 src/main/java/com/booleanuk/core/inventory/Inventory.java diff --git a/src/main/java/com/booleanuk/core/inventory/Inventory.java b/src/main/java/com/booleanuk/core/inventory/Inventory.java new file mode 100644 index 000000000..563ae0365 --- /dev/null +++ b/src/main/java/com/booleanuk/core/inventory/Inventory.java @@ -0,0 +1,51 @@ +package com.booleanuk.core.inventory; + +import com.booleanuk.core.*; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +public class Inventory { + Map inventoryItems; + + public Inventory() { + this.inventoryItems = new HashMap<>(); + fillInventory(); + } + + /** + * Fill inventory with pre-prepared data. + */ + private void fillInventory() { + + // TODO: Is it okay to initialize the data here? + // For a more general approach -> Use Dependency Injection: + // make product list as input instead of creating it here. + + // Create list with inventory items + ArrayList items = new ArrayList<>(); + + items.add(new BagelItem(0.49f, BagelVariant.ONION)); + items.add(new BagelItem(0.39f, BagelVariant.PLAIN)); + items.add(new BagelItem(0.49f, BagelVariant.EVERYTHING)); + items.add(new BagelItem(0.49f, BagelVariant.SESAME)); + + items.add(new CoffeeItem(0.99f, CoffeeVariant.BLACK)); + items.add(new CoffeeItem(1.19f, CoffeeVariant.WHITE)); + items.add(new CoffeeItem(1.29f, CoffeeVariant.CAPUCCINO)); + items.add(new CoffeeItem(1.29f, CoffeeVariant.LATTE)); + + items.add(new FillingItem(0.12f, FillingVariant.BACON)); + items.add(new FillingItem(0.12f, FillingVariant.EGG)); + items.add(new FillingItem(0.12f, FillingVariant.CHEESE)); + items.add(new FillingItem(0.12f, FillingVariant.CREAM_CHEESE)); + items.add(new FillingItem(0.12f, FillingVariant.SMOKED_SALMON)); + items.add(new FillingItem(0.12f, FillingVariant.HAM)); + + // Add items to inventoryItems and put the SKU value as the key + for (InventoryItem item : items) { + inventoryItems.put(item.getSKU(), item); + } + } +} From 02c05d58d489863fd35452afe931e76d6ffa7364 Mon Sep 17 00:00:00 2001 From: shyye Date: Thu, 22 Aug 2024 12:46:23 +0200 Subject: [PATCH 34/93] Test for new Inventory class --- .../core/inventory/InventoryTest.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 src/test/java/com/booleanuk/core/inventory/InventoryTest.java diff --git a/src/test/java/com/booleanuk/core/inventory/InventoryTest.java b/src/test/java/com/booleanuk/core/inventory/InventoryTest.java new file mode 100644 index 000000000..3149dd2de --- /dev/null +++ b/src/test/java/com/booleanuk/core/inventory/InventoryTest.java @@ -0,0 +1,24 @@ +package com.booleanuk.core.inventory; + +import org.junit.jupiter.api.Test; + +import java.util.Map; + +public class InventoryTest { + Inventory inventory; + + @Test + public void checkInventoryInitialization() { + inventory = new Inventory(); + Map items = inventory.getAllItems(); + + for (InventoryItem i : items.values()) { + System.out.println( + i.getSKU()+", " + + i.getPrice()+", " + + i.getName()+", " + + i.getVariant()+", " + ); + } + } +} From 02c5ded32324edb2c36ae0482ed0cb280065d9ce Mon Sep 17 00:00:00 2001 From: shyye Date: Thu, 22 Aug 2024 12:47:03 +0200 Subject: [PATCH 35/93] Add classes for new inventory --- .../com/booleanuk/core/SKUCalculator.java | 17 ++++++ .../booleanuk/core/inventory/BagelItem.java | 15 +++++ .../booleanuk/core/inventory/CoffeeItem.java | 15 +++++ .../booleanuk/core/inventory/FillingItem.java | 15 +++++ .../booleanuk/core/inventory/Inventory.java | 7 ++- .../core/inventory/InventoryItem.java | 56 +++++++++++++++++++ 6 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/booleanuk/core/SKUCalculator.java create mode 100644 src/main/java/com/booleanuk/core/inventory/BagelItem.java create mode 100644 src/main/java/com/booleanuk/core/inventory/CoffeeItem.java create mode 100644 src/main/java/com/booleanuk/core/inventory/FillingItem.java create mode 100644 src/main/java/com/booleanuk/core/inventory/InventoryItem.java diff --git a/src/main/java/com/booleanuk/core/SKUCalculator.java b/src/main/java/com/booleanuk/core/SKUCalculator.java new file mode 100644 index 000000000..f3fb83300 --- /dev/null +++ b/src/main/java/com/booleanuk/core/SKUCalculator.java @@ -0,0 +1,17 @@ +package com.booleanuk.core; + +public class SKUCalculator { + + /** + * Get SKU value based on name and variant of an item. + * @param name - E.g. ProductName.COFFEE + * @param variant - E.g. BagelVariant.PLAIN + * @return . String with SKU value. + */ + public String getSKU(Enum name, Enum variant) { + String productCode = name.toString().substring(0,3); + String variantCode = variant.toString().substring(0,1); + String skuCode = productCode + variantCode; + return skuCode.toUpperCase(); + } +} diff --git a/src/main/java/com/booleanuk/core/inventory/BagelItem.java b/src/main/java/com/booleanuk/core/inventory/BagelItem.java new file mode 100644 index 000000000..c33bb8424 --- /dev/null +++ b/src/main/java/com/booleanuk/core/inventory/BagelItem.java @@ -0,0 +1,15 @@ +package com.booleanuk.core.inventory; + +import com.booleanuk.core.ProductName; + +public class BagelItem extends InventoryItem { + + public BagelItem(float price, Enum variant) { + super(price, variant); + } + + @Override + public ProductName setName() { + return ProductName.BAGEL; + } +} diff --git a/src/main/java/com/booleanuk/core/inventory/CoffeeItem.java b/src/main/java/com/booleanuk/core/inventory/CoffeeItem.java new file mode 100644 index 000000000..a0bafe96b --- /dev/null +++ b/src/main/java/com/booleanuk/core/inventory/CoffeeItem.java @@ -0,0 +1,15 @@ +package com.booleanuk.core.inventory; + +import com.booleanuk.core.ProductName; + +public class CoffeeItem extends InventoryItem { + + public CoffeeItem(float price, Enum variant) { + super(price, variant); + } + + @Override + public ProductName setName() { + return ProductName.COFFEE; + } +} diff --git a/src/main/java/com/booleanuk/core/inventory/FillingItem.java b/src/main/java/com/booleanuk/core/inventory/FillingItem.java new file mode 100644 index 000000000..5fab5610a --- /dev/null +++ b/src/main/java/com/booleanuk/core/inventory/FillingItem.java @@ -0,0 +1,15 @@ +package com.booleanuk.core.inventory; + +import com.booleanuk.core.ProductName; + +public class FillingItem extends InventoryItem{ + + public FillingItem(float price, Enum variant) { + super(price, variant); + } + + @Override + public ProductName setName() { + return ProductName.FILLING; + } +} diff --git a/src/main/java/com/booleanuk/core/inventory/Inventory.java b/src/main/java/com/booleanuk/core/inventory/Inventory.java index 563ae0365..0fb0a2b55 100644 --- a/src/main/java/com/booleanuk/core/inventory/Inventory.java +++ b/src/main/java/com/booleanuk/core/inventory/Inventory.java @@ -7,7 +7,8 @@ import java.util.Map; public class Inventory { - Map inventoryItems; + + private Map inventoryItems; public Inventory() { this.inventoryItems = new HashMap<>(); @@ -48,4 +49,8 @@ private void fillInventory() { inventoryItems.put(item.getSKU(), item); } } + + public Map getAllItems() { + return inventoryItems; + } } diff --git a/src/main/java/com/booleanuk/core/inventory/InventoryItem.java b/src/main/java/com/booleanuk/core/inventory/InventoryItem.java new file mode 100644 index 000000000..4f99099e6 --- /dev/null +++ b/src/main/java/com/booleanuk/core/inventory/InventoryItem.java @@ -0,0 +1,56 @@ +package com.booleanuk.core.inventory; + +import com.booleanuk.core.ProductName; +import com.booleanuk.core.SKUCalculator; + +public class InventoryItem { + + private String SKU; + private float price; + private ProductName name; + private Enum variant; + + private SKUCalculator skuCalculator; + + public InventoryItem(float price, Enum variant) { + + this.price = price; + this.name = setName(); + this.variant = variant; + + this.skuCalculator = new SKUCalculator(); + this.SKU = setSKU(); + } + + public String getSKU() { + return SKU; + } + + public String setSKU() { + return skuCalculator.getSKU(name, variant); + } + + public float getPrice() { + return price; + } + + public void setPrice(float price) { + this.price = price; + } + + public ProductName getName() { + return name; + } + + public ProductName setName() { + return ProductName.DEFAULT; + } + + public Enum getVariant() { + return variant; + } + + public void setVariant(Enum variant) { + this.variant = variant; + } +} From 7a59496b02a264c93879874ea9b0229c80406ee4 Mon Sep 17 00:00:00 2001 From: shyye Date: Thu, 22 Aug 2024 12:47:30 +0200 Subject: [PATCH 36/93] Comment on test --- src/test/java/com/booleanuk/core/InventoryTest.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/test/java/com/booleanuk/core/InventoryTest.java b/src/test/java/com/booleanuk/core/InventoryTest.java index e54903243..ee5259839 100644 --- a/src/test/java/com/booleanuk/core/InventoryTest.java +++ b/src/test/java/com/booleanuk/core/InventoryTest.java @@ -30,4 +30,9 @@ public void getProductBasedOnSKU() { } // TODO: Add test for exception returned when SKU is invalid / Does npt exist //TODO: Add test for only product no specific version + +// @Test +// public void getProductPrice() { +// this.inventory.getItemPrice(); +// } } From e900dc4339c56dc9c4ad6317de8554b6e8626497 Mon Sep 17 00:00:00 2001 From: shyye Date: Thu, 22 Aug 2024 12:47:50 +0200 Subject: [PATCH 37/93] Comment on code --- .../java/com/booleanuk/core/Inventory.java | 115 ------------------ 1 file changed, 115 deletions(-) diff --git a/src/main/java/com/booleanuk/core/Inventory.java b/src/main/java/com/booleanuk/core/Inventory.java index 31ff99c8f..eaccec8dc 100644 --- a/src/main/java/com/booleanuk/core/Inventory.java +++ b/src/main/java/com/booleanuk/core/Inventory.java @@ -116,7 +116,6 @@ public Product getProduct(String SKU) { return inventoryItems.get(SKU); } - /** * Return a String that can be used as key for the HashMap inventoryIten * @param product @@ -129,118 +128,4 @@ public Product getProduct(String SKU) { // return hashCode.toUpperCase(); // } - - - - - - - - - - - - -// public void printMenu() { -// ArrayList coffee = getAllCoffee(); -// ArrayList bagels = getAllBagels(); -// ArrayList fillings = getAllFillings(); -// -// System.out.println("========== Coffee Menu =========="); -// System.out.println("\t Coffe \t:\t Variant / Price "); -// System.out.println("----------------------------------"); -// for (Coffee c : coffee) { -// System.out.println("\t\t\t\t " + c.getVariant() + "\t $" + c.getPrice()); -// } -// System.out.println(); -// -// System.out.println("========== Bagel Menu =========="); -// System.out.println("\t Bagels \t:\t Variant / Price "); -// System.out.println("----------------------------------"); -// for (Bagel b : bagels) { -// System.out.println("\t\t\t\t " + b.getVariant() + "\t $" + b.getPrice()); -// } -// System.out.println(); -// -// System.out.println("\t Fillings \t:\t Variant / Price "); -// System.out.println("----------------------------------"); -// for (Filling f : fillings) { -// System.out.println("\t\t\t\t " + f.getVariant() + "\t $" + f.getPrice()); -// } -// System.out.println(); -// } -// -// private String calulcateSKU(String name, String variant) { -// // TODO: This can now override SKU if it calculates the same value, fix this. -// // TODO: Not as in example, this takes the whole words -// return name + variant; -// } -// -// private void addProduct(float price, Enum name, Enum variant) { -// String SKU = calulcateSKU(name.toString(), variant.toString()); -// -// // TODO: Change to switch statement -// if (ProductName.COFFEE == name) { -// this.products.add(new Coffee(0, SKU, price, name, variant)); -// } else if (ProductName.BAGEL == name) { -// this.products.add(new Bagel(0, SKU, price, name, variant)); -// } else if (ProductName.FILLING == name) { -// this.products.add(new Filling(0, SKU, price, name, variant)); -// } -// } -// -// private void fillInventory() { -// this.addProduct(0.49f, ProductName.BAGEL, BagelVariant.ONION); -// this.addProduct(0.39f, ProductName.BAGEL, BagelVariant.PLAIN); -// this.addProduct(0.49f, ProductName.BAGEL, BagelVariant.EVERYTHING); -// this.addProduct(0.49f, ProductName.BAGEL, BagelVariant.SESAME); -// -// this.addProduct(0.99f, ProductName.COFFEE, CoffeeVariant.BLACK); -// this.addProduct(1.19f, ProductName.COFFEE, CoffeeVariant.WHITE); -// this.addProduct(1.29f, ProductName.COFFEE, CoffeeVariant.CAPUCCINO); -// this.addProduct(1.29f, ProductName.COFFEE, CoffeeVariant.LATTE); -// -// this.addProduct(0.12f, ProductName.FILLING, FillingVariant.BACON); -// this.addProduct(0.12f, ProductName.FILLING, FillingVariant.EGG); -// this.addProduct(0.12f, ProductName.FILLING, FillingVariant.CHEESE); -// this.addProduct(0.12f, ProductName.FILLING, FillingVariant.CREAM_CHEESE); -// this.addProduct(0.12f, ProductName.FILLING, FillingVariant.SMOKED_SALMON); -// this.addProduct(0.12f, ProductName.FILLING, FillingVariant.HAM); -// } -// -// // TODO: duplication code not good. -// private ArrayList getAllCoffee() { -// ArrayList coffeList = new ArrayList<>(); -// -// for (Product product : products) { -// if (product.getName() == ProductName.COFFEE) { -// coffeList.add((Coffee) product); -// } -// } -// return coffeList; -// } -// -// // TODO: duplication code not good. -// private ArrayList getAllBagels() { -// ArrayList bagelList = new ArrayList<>(); -// -// for (Product product : products) { -// if (product.getName() == ProductName.BAGEL) { -// bagelList.add((Bagel) product); -// } -// } -// return bagelList; -// } -// -// // TODO: duplication code not good. -// private ArrayList getAllFillings() { -// ArrayList fillingsList = new ArrayList<>(); -// -// for (Product product : products) { -// if (product.getName() == ProductName.FILLING) { -// fillingsList.add((Filling) product); -// } -// } -// return fillingsList; -// } } From c78d1bac703056372f82c99f89d7391431c55872 Mon Sep 17 00:00:00 2001 From: shyye Date: Thu, 22 Aug 2024 13:17:49 +0200 Subject: [PATCH 38/93] Add Test: getItemBasedOnSKU --- .../java/com/booleanuk/core/inventory/InventoryTest.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/test/java/com/booleanuk/core/inventory/InventoryTest.java b/src/test/java/com/booleanuk/core/inventory/InventoryTest.java index 3149dd2de..f1be1197d 100644 --- a/src/test/java/com/booleanuk/core/inventory/InventoryTest.java +++ b/src/test/java/com/booleanuk/core/inventory/InventoryTest.java @@ -1,5 +1,7 @@ package com.booleanuk.core.inventory; +import com.booleanuk.core.Coffee; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import java.util.Map; @@ -21,4 +23,10 @@ public void checkInventoryInitialization() { ); } } + + @Test + public void getItemBasedOnSKU() { + inventory = new Inventory(); + Assertions.assertEquals("BAGE", inventory.getItem("BAGE").getSKU()); + } } From 6379d7a48587f8be32dbc1514241b8d18ca5fac6 Mon Sep 17 00:00:00 2001 From: shyye Date: Thu, 22 Aug 2024 13:18:38 +0200 Subject: [PATCH 39/93] Add getItem() and getAllItems() --- src/main/java/com/booleanuk/core/inventory/Inventory.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/booleanuk/core/inventory/Inventory.java b/src/main/java/com/booleanuk/core/inventory/Inventory.java index 0fb0a2b55..711846eff 100644 --- a/src/main/java/com/booleanuk/core/inventory/Inventory.java +++ b/src/main/java/com/booleanuk/core/inventory/Inventory.java @@ -53,4 +53,8 @@ private void fillInventory() { public Map getAllItems() { return inventoryItems; } + + public InventoryItem getItem(String SKU) { + return inventoryItems.get(SKU); + } } From fb31b2876bd84384fd9cd6ffd63692ef85cfb5bd Mon Sep 17 00:00:00 2001 From: shyye Date: Thu, 22 Aug 2024 13:49:47 +0200 Subject: [PATCH 40/93] Add Test: throwExceptionWhenItemIsNotInInventory --- .../core/inventory/InventoryTest.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/test/java/com/booleanuk/core/inventory/InventoryTest.java b/src/test/java/com/booleanuk/core/inventory/InventoryTest.java index f1be1197d..d858404bc 100644 --- a/src/test/java/com/booleanuk/core/inventory/InventoryTest.java +++ b/src/test/java/com/booleanuk/core/inventory/InventoryTest.java @@ -9,6 +9,12 @@ public class InventoryTest { Inventory inventory; + // Print exception method function + public void printExceptionMessageToConsole(Exception e) { + System.out.println("\nException message:"); + System.out.println("\t" + e.getMessage() + "\n"); + } + @Test public void checkInventoryInitialization() { inventory = new Inventory(); @@ -29,4 +35,17 @@ public void getItemBasedOnSKU() { inventory = new Inventory(); Assertions.assertEquals("BAGE", inventory.getItem("BAGE").getSKU()); } + + @Test + public void throwExceptionWhenItemIsNotInInventory() { + inventory = new Inventory(); + + // Try to invoke exception + InventoryItemException e = Assertions.assertThrows( + InventoryItemException.class, + () -> { inventory.getItem("HELLO"); } + ); + Assertions.assertEquals("SKU 'HELLO' does not exist.", e.getMessage()); + printExceptionMessageToConsole(e); + } } From cdffb63e3abad8378442d37f502bdca1ad71ca30 Mon Sep 17 00:00:00 2001 From: shyye Date: Thu, 22 Aug 2024 13:50:24 +0200 Subject: [PATCH 41/93] Add exception case for getItem() --- .../java/com/booleanuk/core/inventory/Inventory.java | 9 ++++++++- .../booleanuk/core/inventory/InventoryItemException.java | 7 +++++++ 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/booleanuk/core/inventory/InventoryItemException.java diff --git a/src/main/java/com/booleanuk/core/inventory/Inventory.java b/src/main/java/com/booleanuk/core/inventory/Inventory.java index 711846eff..f9ca504fb 100644 --- a/src/main/java/com/booleanuk/core/inventory/Inventory.java +++ b/src/main/java/com/booleanuk/core/inventory/Inventory.java @@ -55,6 +55,13 @@ public Map getAllItems() { } public InventoryItem getItem(String SKU) { - return inventoryItems.get(SKU); + + // TODO: Should SKU be converted to uppercase here? + + InventoryItem item = inventoryItems.get(SKU); + if (item == null) { + throw new InventoryItemException("SKU '" + SKU + "' does not exist."); + } + return item; } } diff --git a/src/main/java/com/booleanuk/core/inventory/InventoryItemException.java b/src/main/java/com/booleanuk/core/inventory/InventoryItemException.java new file mode 100644 index 000000000..42a2b44d5 --- /dev/null +++ b/src/main/java/com/booleanuk/core/inventory/InventoryItemException.java @@ -0,0 +1,7 @@ +package com.booleanuk.core.inventory; + +public class InventoryItemException extends RuntimeException { + public InventoryItemException(String message) { + super(message); + } +} From 970b2fec62471f1551e56b2e39b968eace92a904 Mon Sep 17 00:00:00 2001 From: shyye Date: Thu, 22 Aug 2024 15:09:25 +0200 Subject: [PATCH 42/93] Add Test: printInventoryMenu --- .../java/com/booleanuk/core/inventory/InventoryTest.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/test/java/com/booleanuk/core/inventory/InventoryTest.java b/src/test/java/com/booleanuk/core/inventory/InventoryTest.java index d858404bc..ef9ab8d62 100644 --- a/src/test/java/com/booleanuk/core/inventory/InventoryTest.java +++ b/src/test/java/com/booleanuk/core/inventory/InventoryTest.java @@ -48,4 +48,10 @@ public void throwExceptionWhenItemIsNotInInventory() { Assertions.assertEquals("SKU 'HELLO' does not exist.", e.getMessage()); printExceptionMessageToConsole(e); } + + @Test + public void printInventoryMenu() { + inventory = new Inventory(); + inventory.printMenu(); + } } From 4c357b5e470a70b42f174d160429cd57233a569b Mon Sep 17 00:00:00 2001 From: shyye Date: Thu, 22 Aug 2024 15:10:14 +0200 Subject: [PATCH 43/93] Add PrintGenerator and refactor Inventory --- .../booleanuk/core/inventory/Inventory.java | 11 ++++ .../core/printgenerator/PrintGenerator.java | 22 ++++++++ .../printgenerator/PrintInventoryMenu.java | 52 +++++++++++++++++++ 3 files changed, 85 insertions(+) create mode 100644 src/main/java/com/booleanuk/core/printgenerator/PrintGenerator.java create mode 100644 src/main/java/com/booleanuk/core/printgenerator/PrintInventoryMenu.java diff --git a/src/main/java/com/booleanuk/core/inventory/Inventory.java b/src/main/java/com/booleanuk/core/inventory/Inventory.java index f9ca504fb..2947d6ea8 100644 --- a/src/main/java/com/booleanuk/core/inventory/Inventory.java +++ b/src/main/java/com/booleanuk/core/inventory/Inventory.java @@ -1,6 +1,8 @@ package com.booleanuk.core.inventory; import com.booleanuk.core.*; +import com.booleanuk.core.printgenerator.PrintGenerator; +import com.booleanuk.core.printgenerator.PrintInventoryMenu; import java.util.ArrayList; import java.util.HashMap; @@ -64,4 +66,13 @@ public InventoryItem getItem(String SKU) { } return item; } + + public void printMenu() { + + // TODO: Should this be refactored, not initalize it here + // Problem if so is that I need the inventoryItems + + PrintGenerator menu = new PrintInventoryMenu(this.inventoryItems); + menu.print(); + } } diff --git a/src/main/java/com/booleanuk/core/printgenerator/PrintGenerator.java b/src/main/java/com/booleanuk/core/printgenerator/PrintGenerator.java new file mode 100644 index 000000000..456049a51 --- /dev/null +++ b/src/main/java/com/booleanuk/core/printgenerator/PrintGenerator.java @@ -0,0 +1,22 @@ +package com.booleanuk.core.printgenerator; + +public class PrintGenerator { + + /** + * Prints centered text + * @param text - Text + * @param totalWidth - Total width of the output / layout + */ + protected void printCenterTitle(String text, int totalWidth) { + + // Resource: https://www.baeldung.com/java-center-text-output + String padding = "%" + ((totalWidth - text.length()) / 2) + "s"; + String centeredText = String.format(padding + "%s" + padding, "", text, ""); + System.out.println(centeredText); + } + + public void print() { + System.out.println("Hello World!"); + } + +} diff --git a/src/main/java/com/booleanuk/core/printgenerator/PrintInventoryMenu.java b/src/main/java/com/booleanuk/core/printgenerator/PrintInventoryMenu.java new file mode 100644 index 000000000..09803f950 --- /dev/null +++ b/src/main/java/com/booleanuk/core/printgenerator/PrintInventoryMenu.java @@ -0,0 +1,52 @@ +package com.booleanuk.core.printgenerator; + +import com.booleanuk.core.ProductName; +import com.booleanuk.core.inventory.InventoryItem; + +import java.util.Map; + +public class PrintInventoryMenu extends PrintGenerator{ + + private Map inventoryItems; + + public PrintInventoryMenu(Map inventoryItems) { + this.inventoryItems = inventoryItems; + } + + private void printMenuPart(ProductName productName, String title, int outputWidth) { + + // Variables for e.g. "%-15s %-15s %n", keep blank space + String center = "%16s "; + String skuAlign = "%-8s "; + String leftAlign = "%-16s "; + String newLine = "%n"; + String divider = "-------------------------------"; + + printCenterTitle(title, outputWidth); + + for (InventoryItem item : inventoryItems.values()) { + if (item.getName() == productName) { + System.out.printf( + skuAlign + leftAlign + leftAlign + newLine, + item.getSKU()+" | ", item.getVariant().toString(), "$" + item.getPrice() + ); + } + } + System.out.println(); + } + + @Override + public void print() { + + int outputWidth = 32; + + System.out.println(); + printCenterTitle("=== Bob's Bagels Menu ===", outputWidth); + System.out.println(); + + printMenuPart(ProductName.COFFEE, "~ Coffee ~", outputWidth); + printMenuPart(ProductName.BAGEL, "~ Bagels ~", outputWidth); + printMenuPart(ProductName.FILLING, "~ Bagel Fillings ~", outputWidth); + } + +} From 9f49467bf6d9142e59a144d3f77f1bfe789780d9 Mon Sep 17 00:00:00 2001 From: shyye Date: Thu, 22 Aug 2024 15:24:37 +0200 Subject: [PATCH 44/93] Add Test for new Basket class --- .../com/booleanuk/core/basket/BasketTest.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 src/test/java/com/booleanuk/core/basket/BasketTest.java diff --git a/src/test/java/com/booleanuk/core/basket/BasketTest.java b/src/test/java/com/booleanuk/core/basket/BasketTest.java new file mode 100644 index 000000000..e6f33608f --- /dev/null +++ b/src/test/java/com/booleanuk/core/basket/BasketTest.java @@ -0,0 +1,18 @@ +package com.booleanuk.core.basket; + + +import com.booleanuk.core.inventory.Inventory; +import org.junit.jupiter.api.Test; + +public class BasketTest { + + Inventory inventory; + Basket basket; + + @Test + public void printBasket() { + this.inventory = new Inventory(); + this.basket = new Basket(new Inventory()); + basket.printBasket(); + } +} From f34edf02d04d6db4aaafae34efe25c2d7ef13ac3 Mon Sep 17 00:00:00 2001 From: shyye Date: Thu, 22 Aug 2024 16:40:34 +0200 Subject: [PATCH 45/93] Update Test for new Basket class --- .../com/booleanuk/core/basket/BasketTest.java | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/booleanuk/core/basket/BasketTest.java b/src/test/java/com/booleanuk/core/basket/BasketTest.java index e6f33608f..0f3c3af28 100644 --- a/src/test/java/com/booleanuk/core/basket/BasketTest.java +++ b/src/test/java/com/booleanuk/core/basket/BasketTest.java @@ -2,6 +2,7 @@ import com.booleanuk.core.inventory.Inventory; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; public class BasketTest { @@ -11,8 +12,21 @@ public class BasketTest { @Test public void printBasket() { - this.inventory = new Inventory(); - this.basket = new Basket(new Inventory()); + inventory = new Inventory(); + basket = new Basket(new Inventory()); + basket.printBasket(); + } + + @Test + public void addProductsToBasket() { + inventory = new Inventory(); + basket = new Basket(new Inventory()); + + basket.add(new Coffee("COFC")); + basket.add(new Bagel("BAGE")); + basket.add(new Filling("FILB")); + + Assertions.assertEquals(3, basket.getAll().size()); basket.printBasket(); } } From fe1176e368cf57c41c15dcafa447fd797f298853 Mon Sep 17 00:00:00 2001 From: shyye Date: Thu, 22 Aug 2024 16:41:07 +0200 Subject: [PATCH 46/93] Refactor code for Basket functionality --- .../java/com/booleanuk/core/basket/Bagel.java | 32 +++++++++ .../com/booleanuk/core/basket/Basket.java | 58 ++++++++++++++++ .../com/booleanuk/core/basket/BasketItem.java | 14 ++++ .../com/booleanuk/core/basket/Coffee.java | 8 +++ .../com/booleanuk/core/basket/Filling.java | 8 +++ .../core/printgenerator/PrintBasketItems.java | 68 +++++++++++++++++++ 6 files changed, 188 insertions(+) create mode 100644 src/main/java/com/booleanuk/core/basket/Bagel.java create mode 100644 src/main/java/com/booleanuk/core/basket/Basket.java create mode 100644 src/main/java/com/booleanuk/core/basket/BasketItem.java create mode 100644 src/main/java/com/booleanuk/core/basket/Coffee.java create mode 100644 src/main/java/com/booleanuk/core/basket/Filling.java create mode 100644 src/main/java/com/booleanuk/core/printgenerator/PrintBasketItems.java diff --git a/src/main/java/com/booleanuk/core/basket/Bagel.java b/src/main/java/com/booleanuk/core/basket/Bagel.java new file mode 100644 index 000000000..26f112728 --- /dev/null +++ b/src/main/java/com/booleanuk/core/basket/Bagel.java @@ -0,0 +1,32 @@ +package com.booleanuk.core.basket; + +import java.util.ArrayList; +import java.util.List; + +public class Bagel extends BasketItem { + + private List linkedIds; // Id's for the fillings to this Bagel + + public Bagel(String SKU) { + super(SKU); + linkedIds = new ArrayList<>(); + } + + // TODO: Does it work to overlode this? +// public Bagel(String SKU, List linkedIds) { +// super(SKU); +// this.linkedIds = linkedIds; +// } + + public void addFillings(int id) { + linkedIds.add(id); + } + + public void addFillings(List linkedIds) { + +// for (int id : linkedIds) { +// linkedIds.add(id); +// } + linkedIds.addAll(linkedIds); + } +} diff --git a/src/main/java/com/booleanuk/core/basket/Basket.java b/src/main/java/com/booleanuk/core/basket/Basket.java new file mode 100644 index 000000000..a15b40603 --- /dev/null +++ b/src/main/java/com/booleanuk/core/basket/Basket.java @@ -0,0 +1,58 @@ +package com.booleanuk.core.basket; + +import com.booleanuk.core.inventory.Inventory; +import com.booleanuk.core.inventory.InventoryItemException; +import com.booleanuk.core.printgenerator.PrintBasketItems; +import com.booleanuk.core.printgenerator.PrintGenerator; + +import java.util.LinkedHashMap; +import java.util.Map; + +public class Basket { + + private Inventory inventory; + private Map basketItems; + private int maxCapacity; + private int idCount; + + public Basket(Inventory inventory) { + this.inventory = inventory; + this.basketItems = new LinkedHashMap <>(); // LinkedHashMap because I want the items in the order they were added to the basket + this.maxCapacity = 20; + this.idCount = 1; + } + + // Auto create ID + private int createId() { + + int itemId = this.idCount; + this.idCount += 1; + return itemId; + } + + /** + * Add item to basket, auto creates ID. + * @param item id + */ + public void add(BasketItem item) { + try { + this.basketItems.put(createId(), item); + } catch (InventoryItemException e) { + System.out.println(e.getMessage()); + } + } + + public Map getAll() { + return this.basketItems; + } + + + public void printBasket() { + + // TODO: Should I refactor? Feels like it's a poor solution regarding dependencies. + // Check all PrintGenerator cases. + + PrintGenerator basket = new PrintBasketItems(this.inventory, this.basketItems); + basket.print(); + } +} diff --git a/src/main/java/com/booleanuk/core/basket/BasketItem.java b/src/main/java/com/booleanuk/core/basket/BasketItem.java new file mode 100644 index 000000000..14e90d341 --- /dev/null +++ b/src/main/java/com/booleanuk/core/basket/BasketItem.java @@ -0,0 +1,14 @@ +package com.booleanuk.core.basket; + +public class BasketItem { + + private String SKU; + + public BasketItem(String SKU) { + this.SKU = SKU; + } + + public String getSKU() { + return SKU; + } +} diff --git a/src/main/java/com/booleanuk/core/basket/Coffee.java b/src/main/java/com/booleanuk/core/basket/Coffee.java new file mode 100644 index 000000000..67117f8d6 --- /dev/null +++ b/src/main/java/com/booleanuk/core/basket/Coffee.java @@ -0,0 +1,8 @@ +package com.booleanuk.core.basket; + +public class Coffee extends BasketItem { + + public Coffee(String SKU) { + super(SKU); + } +} diff --git a/src/main/java/com/booleanuk/core/basket/Filling.java b/src/main/java/com/booleanuk/core/basket/Filling.java new file mode 100644 index 000000000..737ff6fe1 --- /dev/null +++ b/src/main/java/com/booleanuk/core/basket/Filling.java @@ -0,0 +1,8 @@ +package com.booleanuk.core.basket; + +public class Filling extends BasketItem { + + public Filling(String SKU) { + super(SKU); + } +} diff --git a/src/main/java/com/booleanuk/core/printgenerator/PrintBasketItems.java b/src/main/java/com/booleanuk/core/printgenerator/PrintBasketItems.java new file mode 100644 index 000000000..284858b87 --- /dev/null +++ b/src/main/java/com/booleanuk/core/printgenerator/PrintBasketItems.java @@ -0,0 +1,68 @@ +package com.booleanuk.core.printgenerator; + +import com.booleanuk.core.Product; +import com.booleanuk.core.basket.BasketItem; +import com.booleanuk.core.inventory.Inventory; +import com.booleanuk.core.ProductName; +import com.booleanuk.core.inventory.InventoryItem; + +import java.util.Map; + +public class PrintBasketItems extends PrintGenerator { + + private Inventory inventory; + private Map basketItems; + + public PrintBasketItems(Inventory inventory, Map basketItems) { + this.inventory = inventory; + this.basketItems = basketItems; + } + + @Override + public void print() { + + int outputWidth = 47; + + // Variables for e.g. "%-15s %-15s %n", keep blank space + String centerSmall = "%34s "; + String center = "%29s "; + String leftAlignSmall = "%-7s "; + String leftAlign = "%-15s "; + String newLine = "%n"; + String divider = "-----------------------------------------------"; + + System.out.println(); + printCenterTitle("=== Bob's Bagels Menu ===", outputWidth); + printCenterTitle("~ Basket ~", outputWidth); + System.out.println(); + + // Print items in basket + if (basketItems.isEmpty()) { + System.out.println("\tBasket is empty."); + } else { + System.out.printf( + leftAlignSmall + leftAlignSmall + leftAlignSmall + leftAlign + leftAlign + newLine, + "SKU | ", "ID", "Product", "Variant", "Price" + ); + System.out.println(divider); + for (Map.Entry item : basketItems.entrySet()) { + + int key = item.getKey(); + BasketItem basketItem = item.getValue(); + + InventoryItem product = this.inventory.getItem(basketItem.getSKU()); + System.out.printf( + leftAlignSmall + leftAlignSmall + leftAlignSmall + leftAlign + leftAlign + newLine, + product.getSKU()+" | ", key, product.getName(), product.getVariant().toString(), "$" + product.getPrice() + ); + } + System.out.println(divider); + System.out.printf( + "%s %33s" + newLine, + "Total cost: ", "$?.??" + ); + } + System.out.println(divider); + System.out.println(); + } +} From f751087422171531577f97e528b4788705c1d419 Mon Sep 17 00:00:00 2001 From: shyye Date: Thu, 22 Aug 2024 18:46:36 +0200 Subject: [PATCH 47/93] Refactor code and test --- .../java/com/booleanuk/core/basket/Bagel.java | 37 +++++---- .../com/booleanuk/core/basket/Basket.java | 76 ++++++++++++++++++- .../com/booleanuk/core/basket/BasketItem.java | 10 +++ .../basket/InvalidBasketItemException.java | 7 ++ .../com/booleanuk/core/basket/BasketTest.java | 19 ++++- 5 files changed, 132 insertions(+), 17 deletions(-) create mode 100644 src/main/java/com/booleanuk/core/basket/InvalidBasketItemException.java diff --git a/src/main/java/com/booleanuk/core/basket/Bagel.java b/src/main/java/com/booleanuk/core/basket/Bagel.java index 26f112728..bfa1ebfdd 100644 --- a/src/main/java/com/booleanuk/core/basket/Bagel.java +++ b/src/main/java/com/booleanuk/core/basket/Bagel.java @@ -5,28 +5,39 @@ public class Bagel extends BasketItem { - private List linkedIds; // Id's for the fillings to this Bagel + private List linkedFillingSKUs; + private List linkedFillingIds; // Id's for the fillings to this Bagel public Bagel(String SKU) { super(SKU); - linkedIds = new ArrayList<>(); + linkedFillingSKUs = new ArrayList<>(); + linkedFillingIds = new ArrayList<>(); } // TODO: Does it work to overlode this? -// public Bagel(String SKU, List linkedIds) { -// super(SKU); -// this.linkedIds = linkedIds; + public Bagel(String SKU, List linkedFillingsSKUs) { + super(SKU); + this.linkedFillingSKUs = linkedFillingsSKUs; + linkedFillingIds = new ArrayList<>(); + } + +// public void addFilling(String SKU) { +// linkedFillingSKUs.add(SKU); +// } +// +// public void addFillings(List linkedIds) { +// +//// for (int id : linkedIds) { +//// linkedIds.add(id); +//// } +// linkedFillingSKUs.addAll(linkedIds); // } - public void addFillings(int id) { - linkedIds.add(id); + public List getLinkedFillingSKUs() { + return linkedFillingSKUs; } - public void addFillings(List linkedIds) { - -// for (int id : linkedIds) { -// linkedIds.add(id); -// } - linkedIds.addAll(linkedIds); + public List getLinkedFillingIds() { + return linkedFillingIds; } } diff --git a/src/main/java/com/booleanuk/core/basket/Basket.java b/src/main/java/com/booleanuk/core/basket/Basket.java index a15b40603..893cbf1e4 100644 --- a/src/main/java/com/booleanuk/core/basket/Basket.java +++ b/src/main/java/com/booleanuk/core/basket/Basket.java @@ -1,11 +1,13 @@ package com.booleanuk.core.basket; +import com.booleanuk.core.MaxCapacityException; import com.booleanuk.core.inventory.Inventory; import com.booleanuk.core.inventory.InventoryItemException; import com.booleanuk.core.printgenerator.PrintBasketItems; import com.booleanuk.core.printgenerator.PrintGenerator; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; public class Basket { @@ -13,12 +15,14 @@ public class Basket { private Inventory inventory; private Map basketItems; private int maxCapacity; + private int size; private int idCount; public Basket(Inventory inventory) { this.inventory = inventory; this.basketItems = new LinkedHashMap <>(); // LinkedHashMap because I want the items in the order they were added to the basket this.maxCapacity = 20; + this.size = 0; this.idCount = 1; } @@ -30,15 +34,78 @@ private int createId() { return itemId; } + private int createFillingId(String idExtension) { + //TODO: How to make default variable like in python + + // TODO: Should check if idExtension is valid + + // TODO: Could use int input instead of String + + // Store variable id for previous bagel + int itemId = this.idCount - 1; + + // Add id extension for filling + String tmp = String.valueOf(itemId) + "0" + idExtension; + return Integer.parseInt(tmp); + } + + + + protected void addToBasket(int itemId, BasketItem item) { + + // Validate input + if (this.getSize() == maxCapacity) { + throw new MaxCapacityException("Basket is full, can't add more items."); + } + + // TODO: Add exception for when id already exist + + // Fillings can not be added as an item itself + // Fillings that belongs to a bagel have id's over 100 + if (item.getClass().getName() == Filling.class.getName() && item.getId() < 100) { + throw new InvalidBasketItemException("Fillings can't be added alone. Must belong to a bagel."); + } + + // Set id if no exception has been thrown + item.setId(itemId); + // Update size of basket + this.size++; + // Add item to basket + this.basketItems.put(item.getId(), item); + } + /** * Add item to basket, auto creates ID. * @param item id */ public void add(BasketItem item) { + + // Try catch maxCapacity + // If item is bagel, check if we can add more basket items + // OR doesn't filling counts as items maybe hmmm + try { - this.basketItems.put(createId(), item); - } catch (InventoryItemException e) { - System.out.println(e.getMessage()); + // If item is a Bagel, add all it's fillings to basket if they exist + if (item.getClass().getName() == Bagel.class.getName()) { + Bagel bagel = (Bagel) item; + List fillingSKUs = bagel.getLinkedFillingSKUs(); + + if (!fillingSKUs.isEmpty()) { + List fillingIds = bagel.getLinkedFillingIds(); + + int count = 1; + for (String f_SKU : fillingSKUs) { + int fillingId = createFillingId(String.valueOf(count)); + this.addToBasket(fillingId, new BasketItem(f_SKU)); + fillingIds.add(fillingId); + count++; + } + } + } + this.addToBasket(createId(), item); + + } catch (Exception e) { + System.out.println(e.getClass().getName() + ": " + e.getMessage()); } } @@ -46,6 +113,9 @@ public Map getAll() { return this.basketItems; } + public int getSize() { + return size; + } public void printBasket() { diff --git a/src/main/java/com/booleanuk/core/basket/BasketItem.java b/src/main/java/com/booleanuk/core/basket/BasketItem.java index 14e90d341..7bed8bd5e 100644 --- a/src/main/java/com/booleanuk/core/basket/BasketItem.java +++ b/src/main/java/com/booleanuk/core/basket/BasketItem.java @@ -3,11 +3,21 @@ public class BasketItem { private String SKU; + private int Id; public BasketItem(String SKU) { + this.Id = -1; this.SKU = SKU; } + protected void setId(int itemId){ + this.Id = itemId; + } + + public int getId() { + return Id; + } + public String getSKU() { return SKU; } diff --git a/src/main/java/com/booleanuk/core/basket/InvalidBasketItemException.java b/src/main/java/com/booleanuk/core/basket/InvalidBasketItemException.java new file mode 100644 index 000000000..4544d196b --- /dev/null +++ b/src/main/java/com/booleanuk/core/basket/InvalidBasketItemException.java @@ -0,0 +1,7 @@ +package com.booleanuk.core.basket; + +public class InvalidBasketItemException extends RuntimeException { + public InvalidBasketItemException(String message) { + super(message); + } +} diff --git a/src/test/java/com/booleanuk/core/basket/BasketTest.java b/src/test/java/com/booleanuk/core/basket/BasketTest.java index 0f3c3af28..58d116d47 100644 --- a/src/test/java/com/booleanuk/core/basket/BasketTest.java +++ b/src/test/java/com/booleanuk/core/basket/BasketTest.java @@ -5,6 +5,8 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import java.util.Arrays; + public class BasketTest { Inventory inventory; @@ -26,7 +28,22 @@ public void addProductsToBasket() { basket.add(new Bagel("BAGE")); basket.add(new Filling("FILB")); - Assertions.assertEquals(3, basket.getAll().size()); + // Fillings should not be able to be added without a bagel + Assertions.assertEquals(2, basket.getAll().size()); + Assertions.assertEquals(2, basket.getSize()); + basket.printBasket(); } + +// @Test +// public void addBagelAndFilling() { +// inventory = new Inventory(); +// basket = new Basket(new Inventory()); +// +// basket.add(new Bagel("BAGE", Arrays.asList("FILS","FILB"))); +// basket.printBasket(); +// +// Assertions.assertEquals("BAGE", basket.getAll().get(1).getSKU()); +// Assertions.assertEquals("FILS", basket.getAll().get(101).getSKU()); +// } } From 67e83d9810f5542a27c99058ec8266135131ff78 Mon Sep 17 00:00:00 2001 From: shyye Date: Fri, 23 Aug 2024 06:25:19 +0200 Subject: [PATCH 48/93] Refactor code and test for adding bagel with fillings --- .../com/booleanuk/core/basket/Basket.java | 6 ++++- .../com/booleanuk/core/basket/BasketTest.java | 22 +++++++++---------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/booleanuk/core/basket/Basket.java b/src/main/java/com/booleanuk/core/basket/Basket.java index 893cbf1e4..ac36d7f9f 100644 --- a/src/main/java/com/booleanuk/core/basket/Basket.java +++ b/src/main/java/com/booleanuk/core/basket/Basket.java @@ -90,6 +90,8 @@ public void add(BasketItem item) { Bagel bagel = (Bagel) item; List fillingSKUs = bagel.getLinkedFillingSKUs(); + this.addToBasket(createId(), item); + if (!fillingSKUs.isEmpty()) { List fillingIds = bagel.getLinkedFillingIds(); @@ -101,8 +103,10 @@ public void add(BasketItem item) { count++; } } + } else { + this.addToBasket(createId(), item); } - this.addToBasket(createId(), item); + } catch (Exception e) { System.out.println(e.getClass().getName() + ": " + e.getMessage()); diff --git a/src/test/java/com/booleanuk/core/basket/BasketTest.java b/src/test/java/com/booleanuk/core/basket/BasketTest.java index 58d116d47..dcadf4818 100644 --- a/src/test/java/com/booleanuk/core/basket/BasketTest.java +++ b/src/test/java/com/booleanuk/core/basket/BasketTest.java @@ -35,15 +35,15 @@ public void addProductsToBasket() { basket.printBasket(); } -// @Test -// public void addBagelAndFilling() { -// inventory = new Inventory(); -// basket = new Basket(new Inventory()); -// -// basket.add(new Bagel("BAGE", Arrays.asList("FILS","FILB"))); -// basket.printBasket(); -// -// Assertions.assertEquals("BAGE", basket.getAll().get(1).getSKU()); -// Assertions.assertEquals("FILS", basket.getAll().get(101).getSKU()); -// } + @Test + public void addBagelAndFilling() { + inventory = new Inventory(); + basket = new Basket(new Inventory()); + + basket.add(new Bagel("BAGE", Arrays.asList("FILS","FILB"))); + basket.printBasket(); + + Assertions.assertEquals("BAGE", basket.getAll().get(1).getSKU()); + Assertions.assertEquals("FILS", basket.getAll().get(101).getSKU()); + } } From 764dd91f2dd22f0ec6fb3c194661dda6f83ae4c4 Mon Sep 17 00:00:00 2001 From: shyye Date: Fri, 23 Aug 2024 06:55:18 +0200 Subject: [PATCH 49/93] Refactor code and test for rmeoving bagel with its fillings --- .../com/booleanuk/core/basket/Basket.java | 24 ++++++++++++++++++- .../com/booleanuk/core/basket/BasketTest.java | 22 +++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/booleanuk/core/basket/Basket.java b/src/main/java/com/booleanuk/core/basket/Basket.java index ac36d7f9f..c1ac0e6e2 100644 --- a/src/main/java/com/booleanuk/core/basket/Basket.java +++ b/src/main/java/com/booleanuk/core/basket/Basket.java @@ -74,6 +74,13 @@ protected void addToBasket(int itemId, BasketItem item) { this.basketItems.put(item.getId(), item); } + protected void removeFromBasket(int itemId) { + if (basketItems.get(1) == null) { + throw new InvalidBasketItemException("Basket item with ID #" + itemId + ", doesn't exist.\nCan't remove from basket."); + } + this.basketItems.remove(itemId); + } + /** * Add item to basket, auto creates ID. * @param item id @@ -107,12 +114,27 @@ public void add(BasketItem item) { this.addToBasket(createId(), item); } - } catch (Exception e) { System.out.println(e.getClass().getName() + ": " + e.getMessage()); } } + public void remove(int itemId) { + + // TODO: Could this be simplified? + // TODO: should throw exception if not exist, seperate intro function, just like with add + BasketItem item = this.basketItems.get(itemId); + if (item.getClass().getName() == Bagel.class.getName()) { + Bagel bagel = (Bagel) item; + List fillingIds = bagel.getLinkedFillingIds(); + + for (int f_id : fillingIds) { + this.removeFromBasket(f_id); + } + } + this.removeFromBasket(1); + } + public Map getAll() { return this.basketItems; } diff --git a/src/test/java/com/booleanuk/core/basket/BasketTest.java b/src/test/java/com/booleanuk/core/basket/BasketTest.java index dcadf4818..928cde85a 100644 --- a/src/test/java/com/booleanuk/core/basket/BasketTest.java +++ b/src/test/java/com/booleanuk/core/basket/BasketTest.java @@ -19,6 +19,8 @@ public void printBasket() { basket.printBasket(); } + // User story #1: Add specific bagel + // Specific type is here to select SKU for specific bagel variant @Test public void addProductsToBasket() { inventory = new Inventory(); @@ -35,6 +37,10 @@ public void addProductsToBasket() { basket.printBasket(); } + // TODO: Add test for adding something that do not exist + + // TODO: Add test for maxcapacity error + @Test public void addBagelAndFilling() { inventory = new Inventory(); @@ -46,4 +52,20 @@ public void addBagelAndFilling() { Assertions.assertEquals("BAGE", basket.getAll().get(1).getSKU()); Assertions.assertEquals("FILS", basket.getAll().get(101).getSKU()); } + + // User story #2: Remove a bagel + @Test + public void removeBagelShouldAlsoRemoveFillings() { + inventory = new Inventory(); + basket = new Basket(new Inventory()); + basket.add(new Bagel("BAGE", Arrays.asList("FILS","FILB"))); + basket.add(new Bagel("BAGE", Arrays.asList("FILS","FILB"))); + basket.printBasket(); + + // TODO: Add test + basket.remove(1); + Assertions.assertEquals(null, basket.getAll().get(1)); + Assertions.assertEquals(null, basket.getAll().get(101)); + basket.printBasket(); + } } From 0d9dfe5fd33506544477500b5ebaa5ef79a7a93b Mon Sep 17 00:00:00 2001 From: shyye Date: Fri, 23 Aug 2024 06:56:43 +0200 Subject: [PATCH 50/93] Simplify asserion to Asserions.assertNull --- src/test/java/com/booleanuk/core/basket/BasketTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/booleanuk/core/basket/BasketTest.java b/src/test/java/com/booleanuk/core/basket/BasketTest.java index 928cde85a..08b88a51c 100644 --- a/src/test/java/com/booleanuk/core/basket/BasketTest.java +++ b/src/test/java/com/booleanuk/core/basket/BasketTest.java @@ -64,8 +64,8 @@ public void removeBagelShouldAlsoRemoveFillings() { // TODO: Add test basket.remove(1); - Assertions.assertEquals(null, basket.getAll().get(1)); - Assertions.assertEquals(null, basket.getAll().get(101)); + Assertions.assertNull(basket.getAll().get(1)); + Assertions.assertNull(basket.getAll().get(101)); basket.printBasket(); } } From f5bdbf0db8e7c1f5bc2f39b530a5a2a37e28c460 Mon Sep 17 00:00:00 2001 From: shyye Date: Fri, 23 Aug 2024 07:33:32 +0200 Subject: [PATCH 51/93] Refactor code and test for exceeding max capacity --- src/main/java/com/booleanuk/core/Basket.java | 2 + .../com/booleanuk/core/basket/Basket.java | 8 +- .../{ => basket}/MaxCapacityException.java | 2 +- .../java/com/booleanuk/core/BasketTest.java | 1 + .../com/booleanuk/core/basket/BasketTest.java | 73 +++++++++++++++++++ 5 files changed, 83 insertions(+), 3 deletions(-) rename src/main/java/com/booleanuk/core/{ => basket}/MaxCapacityException.java (80%) diff --git a/src/main/java/com/booleanuk/core/Basket.java b/src/main/java/com/booleanuk/core/Basket.java index 3df471c15..a2f1e0721 100644 --- a/src/main/java/com/booleanuk/core/Basket.java +++ b/src/main/java/com/booleanuk/core/Basket.java @@ -1,5 +1,7 @@ package com.booleanuk.core; +import com.booleanuk.core.basket.MaxCapacityException; + import java.util.*; public class Basket { diff --git a/src/main/java/com/booleanuk/core/basket/Basket.java b/src/main/java/com/booleanuk/core/basket/Basket.java index c1ac0e6e2..58179dd25 100644 --- a/src/main/java/com/booleanuk/core/basket/Basket.java +++ b/src/main/java/com/booleanuk/core/basket/Basket.java @@ -1,8 +1,6 @@ package com.booleanuk.core.basket; -import com.booleanuk.core.MaxCapacityException; import com.booleanuk.core.inventory.Inventory; -import com.booleanuk.core.inventory.InventoryItemException; import com.booleanuk.core.printgenerator.PrintBasketItems; import com.booleanuk.core.printgenerator.PrintGenerator; @@ -92,6 +90,7 @@ public void add(BasketItem item) { // OR doesn't filling counts as items maybe hmmm try { + // If item is a Bagel, add all it's fillings to basket if they exist if (item.getClass().getName() == Bagel.class.getName()) { Bagel bagel = (Bagel) item; @@ -151,4 +150,9 @@ public void printBasket() { PrintGenerator basket = new PrintBasketItems(this.inventory, this.basketItems); basket.print(); } + + // TODO: Should I do a get/setfunctions on maxCapacity or is this ok? + public void changeMaxCapacity(int newMaxCapacity) { + this.maxCapacity = newMaxCapacity; + } } diff --git a/src/main/java/com/booleanuk/core/MaxCapacityException.java b/src/main/java/com/booleanuk/core/basket/MaxCapacityException.java similarity index 80% rename from src/main/java/com/booleanuk/core/MaxCapacityException.java rename to src/main/java/com/booleanuk/core/basket/MaxCapacityException.java index 49bd67b78..4bfe8810d 100644 --- a/src/main/java/com/booleanuk/core/MaxCapacityException.java +++ b/src/main/java/com/booleanuk/core/basket/MaxCapacityException.java @@ -1,4 +1,4 @@ -package com.booleanuk.core; +package com.booleanuk.core.basket; public class MaxCapacityException extends RuntimeException { public MaxCapacityException(String message) { diff --git a/src/test/java/com/booleanuk/core/BasketTest.java b/src/test/java/com/booleanuk/core/BasketTest.java index a39b6c87a..8facb99e8 100644 --- a/src/test/java/com/booleanuk/core/BasketTest.java +++ b/src/test/java/com/booleanuk/core/BasketTest.java @@ -1,5 +1,6 @@ package com.booleanuk.core; +import com.booleanuk.core.basket.MaxCapacityException; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; diff --git a/src/test/java/com/booleanuk/core/basket/BasketTest.java b/src/test/java/com/booleanuk/core/basket/BasketTest.java index 08b88a51c..6493f992e 100644 --- a/src/test/java/com/booleanuk/core/basket/BasketTest.java +++ b/src/test/java/com/booleanuk/core/basket/BasketTest.java @@ -12,6 +12,13 @@ public class BasketTest { Inventory inventory; Basket basket; + // Print exception method function + // TODO: Duplication from InventoryTest + public void printExceptionMessageToConsole(Exception e) { + System.out.println("\nException message:"); + System.out.println("\t" + e.getMessage() + "\n"); + } + @Test public void printBasket() { inventory = new Inventory(); @@ -40,6 +47,64 @@ public void addProductsToBasket() { // TODO: Add test for adding something that do not exist // TODO: Add test for maxcapacity error + // User story #3: Throw exception when trying to add items and maxCapacity of basket is reached + @Test + public void exceedMaxCapacityShouldThrowError() { + inventory = new Inventory(); + basket = new Basket(new Inventory()); + + basket.changeMaxCapacity(2); + basket.add(new Coffee("COFC")); + basket.add(new Bagel("BAGE")); + + // TODO: I need to set addToBasket() to 'protected' instead of 'private', is it ok? + // It's because I can't test private methods. + // And I want to test this exception + // If I just test the "parent method" add() it will not throw an exception + // because I handle the exception with try/catch in add() + // add() then calls addToBasket() which is the function that can throw exceptions + MaxCapacityException e = Assertions.assertThrows( + MaxCapacityException.class, + () -> { basket.addToBasket(11, new Bagel("BAGE")); } + ); + Assertions.assertEquals("Basket is full, can't add more items.", e.getMessage()); + printExceptionMessageToConsole(e); + } + + @Test + public void exceedMaxCapacityShouldNotThrowError() { + + // TODO: Check format on this exception + + inventory = new Inventory(); + basket = new Basket(new Inventory()); + + basket.changeMaxCapacity(2); + basket.add(new Coffee("COFC")); + basket.add(new Bagel("BAGE")); + + // Check if basket.add() handles error correct (no exception) + Assertions.assertDoesNotThrow(() -> basket.add(new Bagel("BAGE"))); + } + + + + // User story #4: Change max capacity for basket +// @Test +// public void checkChangeMaxCapacity() { +// this.inventory = new com.booleanuk.core.Inventory(); +// this.basket = new com.booleanuk.core.Basket(new com.booleanuk.core.Inventory()); +// +// basket.changeMaxCapacity(3); +// Assertions.assertEquals(3, basket.getMaxCapacity()); +// +// basket.changeMaxCapacity(12); +// Assertions.assertEquals(12, basket.getMaxCapacity()); +// } +// + + + @Test public void addBagelAndFilling() { @@ -68,4 +133,12 @@ public void removeBagelShouldAlsoRemoveFillings() { Assertions.assertNull(basket.getAll().get(101)); basket.printBasket(); } + + // TODO: add method for remove and chekc exception + // TODO: I need to set removeFromBasket() to 'protected' instead of 'private', is it ok? + // It's because I can't test private methods. + // And I want to test this exception + // If I just test the "parent method" remove() it will not throw an exception + // because I handle the exception with try/catch in remove() + // remove() then calls removeFromBasket() which is the function that can throw exceptions } From 4c3c5723636538f28e96f0530e7f434114546f1f Mon Sep 17 00:00:00 2001 From: shyye Date: Fri, 23 Aug 2024 07:37:16 +0200 Subject: [PATCH 52/93] Refactor code and test for exceeding max capacity --- src/test/java/com/booleanuk/core/basket/BasketTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/booleanuk/core/basket/BasketTest.java b/src/test/java/com/booleanuk/core/basket/BasketTest.java index 6493f992e..c1a48fbdb 100644 --- a/src/test/java/com/booleanuk/core/basket/BasketTest.java +++ b/src/test/java/com/booleanuk/core/basket/BasketTest.java @@ -49,7 +49,7 @@ public void addProductsToBasket() { // TODO: Add test for maxcapacity error // User story #3: Throw exception when trying to add items and maxCapacity of basket is reached @Test - public void exceedMaxCapacityShouldThrowError() { + public void exceedMaxCapacityShouldThrowException() { inventory = new Inventory(); basket = new Basket(new Inventory()); @@ -72,7 +72,7 @@ public void exceedMaxCapacityShouldThrowError() { } @Test - public void exceedMaxCapacityShouldNotThrowError() { + public void exceedMaxCapacityShouldHandleException() { // TODO: Check format on this exception From 8d13b41c700a8b1fed05e9872a028f81546c24c9 Mon Sep 17 00:00:00 2001 From: shyye Date: Fri, 23 Aug 2024 07:41:25 +0200 Subject: [PATCH 53/93] Refactor code and test for change max capacity --- .../com/booleanuk/core/basket/Basket.java | 5 ++++ .../com/booleanuk/core/basket/BasketTest.java | 24 +++++++------------ 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/booleanuk/core/basket/Basket.java b/src/main/java/com/booleanuk/core/basket/Basket.java index 58179dd25..eb3fcb54c 100644 --- a/src/main/java/com/booleanuk/core/basket/Basket.java +++ b/src/main/java/com/booleanuk/core/basket/Basket.java @@ -151,6 +151,11 @@ public void printBasket() { basket.print(); } + // TODO: I only use this for the test. Should I keep it or change the test? + public int getMaxCapacity() { + return this.maxCapacity; + } + // TODO: Should I do a get/setfunctions on maxCapacity or is this ok? public void changeMaxCapacity(int newMaxCapacity) { this.maxCapacity = newMaxCapacity; diff --git a/src/test/java/com/booleanuk/core/basket/BasketTest.java b/src/test/java/com/booleanuk/core/basket/BasketTest.java index c1a48fbdb..946022127 100644 --- a/src/test/java/com/booleanuk/core/basket/BasketTest.java +++ b/src/test/java/com/booleanuk/core/basket/BasketTest.java @@ -87,24 +87,18 @@ public void exceedMaxCapacityShouldHandleException() { Assertions.assertDoesNotThrow(() -> basket.add(new Bagel("BAGE"))); } - - // User story #4: Change max capacity for basket -// @Test -// public void checkChangeMaxCapacity() { -// this.inventory = new com.booleanuk.core.Inventory(); -// this.basket = new com.booleanuk.core.Basket(new com.booleanuk.core.Inventory()); -// -// basket.changeMaxCapacity(3); -// Assertions.assertEquals(3, basket.getMaxCapacity()); -// -// basket.changeMaxCapacity(12); -// Assertions.assertEquals(12, basket.getMaxCapacity()); -// } -// - + @Test + public void changeMaxCapacity() { + inventory = new Inventory(); + basket = new Basket(new Inventory()); + basket.changeMaxCapacity(3); + Assertions.assertEquals(3, basket.getMaxCapacity()); + basket.changeMaxCapacity(12); + Assertions.assertEquals(12, basket.getMaxCapacity()); + } @Test public void addBagelAndFilling() { From 58b16931bcd6f09068bb9297e2ef9e457a8dcbc8 Mon Sep 17 00:00:00 2001 From: shyye Date: Fri, 23 Aug 2024 11:25:48 +0200 Subject: [PATCH 54/93] Refactor code and test for exception when removing item that doesn't exist --- .../com/booleanuk/core/basket/Basket.java | 38 +++++++++----- .../core/inventory/InventoryItem.java | 3 ++ .../com/booleanuk/core/basket/BasketTest.java | 51 +++++++++++++------ 3 files changed, 65 insertions(+), 27 deletions(-) diff --git a/src/main/java/com/booleanuk/core/basket/Basket.java b/src/main/java/com/booleanuk/core/basket/Basket.java index eb3fcb54c..7afbc3698 100644 --- a/src/main/java/com/booleanuk/core/basket/Basket.java +++ b/src/main/java/com/booleanuk/core/basket/Basket.java @@ -1,5 +1,6 @@ package com.booleanuk.core.basket; +import com.booleanuk.core.BasketItemExistException; import com.booleanuk.core.inventory.Inventory; import com.booleanuk.core.printgenerator.PrintBasketItems; import com.booleanuk.core.printgenerator.PrintGenerator; @@ -50,7 +51,6 @@ private int createFillingId(String idExtension) { protected void addToBasket(int itemId, BasketItem item) { - // Validate input if (this.getSize() == maxCapacity) { throw new MaxCapacityException("Basket is full, can't add more items."); @@ -73,12 +73,22 @@ protected void addToBasket(int itemId, BasketItem item) { } protected void removeFromBasket(int itemId) { - if (basketItems.get(1) == null) { - throw new InvalidBasketItemException("Basket item with ID #" + itemId + ", doesn't exist.\nCan't remove from basket."); + if (basketItems.get(itemId) == null) { + throw new InvalidBasketItemException("Basket item with ID #" + itemId + ", doesn't exist. Can't remove from basket."); } this.basketItems.remove(itemId); } + // TODO: Check where get item functionality is used and replace with this function + // This exception is trown both here and in the above method, how to reduce duplication in best way? + protected BasketItem getBasketItem(int itemId) { + BasketItem item = this.basketItems.get(itemId); + if (item == null) { + throw new InvalidBasketItemException("Basket item with ID #" + itemId + ", doesn't exist. Can't remove from basket."); + } + return item; + } + /** * Add item to basket, auto creates ID. * @param item id @@ -120,18 +130,22 @@ public void add(BasketItem item) { public void remove(int itemId) { - // TODO: Could this be simplified? - // TODO: should throw exception if not exist, seperate intro function, just like with add - BasketItem item = this.basketItems.get(itemId); - if (item.getClass().getName() == Bagel.class.getName()) { - Bagel bagel = (Bagel) item; - List fillingIds = bagel.getLinkedFillingIds(); + try { + // TODO: Could this be simplified? + // TODO: should throw exception if not exist, seperate intro function, just like with add + BasketItem item = this.getBasketItem(itemId); + if (item.getClass().getName() == Bagel.class.getName()) { + Bagel bagel = (Bagel) item; + List fillingIds = bagel.getLinkedFillingIds(); - for (int f_id : fillingIds) { - this.removeFromBasket(f_id); + for (int f_id : fillingIds) { + this.removeFromBasket(f_id); + } } + this.removeFromBasket(1); + } catch (Exception e) { + System.out.println(e.getMessage()); } - this.removeFromBasket(1); } public Map getAll() { diff --git a/src/main/java/com/booleanuk/core/inventory/InventoryItem.java b/src/main/java/com/booleanuk/core/inventory/InventoryItem.java index 4f99099e6..29848ab00 100644 --- a/src/main/java/com/booleanuk/core/inventory/InventoryItem.java +++ b/src/main/java/com/booleanuk/core/inventory/InventoryItem.java @@ -5,6 +5,9 @@ public class InventoryItem { + // TODO: should I change this to protected? + // TODO should I change this to abstract? Check if possible. + private String SKU; private float price; private ProductName name; diff --git a/src/test/java/com/booleanuk/core/basket/BasketTest.java b/src/test/java/com/booleanuk/core/basket/BasketTest.java index 946022127..32ba8e770 100644 --- a/src/test/java/com/booleanuk/core/basket/BasketTest.java +++ b/src/test/java/com/booleanuk/core/basket/BasketTest.java @@ -1,6 +1,7 @@ package com.booleanuk.core.basket; +import com.booleanuk.core.BasketItemExistException; import com.booleanuk.core.inventory.Inventory; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -14,6 +15,7 @@ public class BasketTest { // Print exception method function // TODO: Duplication from InventoryTest + // TODO: Make this code to own class and use for output in exceptions, maybe color it red, or maybe make an interface to the Exception class public void printExceptionMessageToConsole(Exception e) { System.out.println("\nException message:"); System.out.println("\t" + e.getMessage() + "\n"); @@ -29,7 +31,7 @@ public void printBasket() { // User story #1: Add specific bagel // Specific type is here to select SKU for specific bagel variant @Test - public void addProductsToBasket() { + public void addItemaToBasket() { inventory = new Inventory(); basket = new Basket(new Inventory()); @@ -44,9 +46,10 @@ public void addProductsToBasket() { basket.printBasket(); } + // TODO: Add test for adding something that do not exist - // TODO: Add test for maxcapacity error + // User story #3: Throw exception when trying to add items and maxCapacity of basket is reached @Test public void exceedMaxCapacityShouldThrowException() { @@ -57,12 +60,6 @@ public void exceedMaxCapacityShouldThrowException() { basket.add(new Coffee("COFC")); basket.add(new Bagel("BAGE")); - // TODO: I need to set addToBasket() to 'protected' instead of 'private', is it ok? - // It's because I can't test private methods. - // And I want to test this exception - // If I just test the "parent method" add() it will not throw an exception - // because I handle the exception with try/catch in add() - // add() then calls addToBasket() which is the function that can throw exceptions MaxCapacityException e = Assertions.assertThrows( MaxCapacityException.class, () -> { basket.addToBasket(11, new Bagel("BAGE")); } @@ -128,11 +125,35 @@ public void removeBagelShouldAlsoRemoveFillings() { basket.printBasket(); } - // TODO: add method for remove and chekc exception - // TODO: I need to set removeFromBasket() to 'protected' instead of 'private', is it ok? - // It's because I can't test private methods. - // And I want to test this exception - // If I just test the "parent method" remove() it will not throw an exception - // because I handle the exception with try/catch in remove() - // remove() then calls removeFromBasket() which is the function that can throw exceptions + // User story #5: Throw exception when trying to remove item that doesn't exist. + @Test + public void removeItemThatDoesNotExistShouldThrowException() { + inventory = new Inventory(); + basket = new Basket(new Inventory()); + + // TODO: I need to set removeFromBasket() to 'protected' instead of 'private', is it ok? + // It's because I can't test private methods. + // And I want to test this exception + // If I just test the "parent method" remove() it will not throw an exception + // because I handle the exception with try/catch in remove() + // remove() then calls removeFromBasket() which is the function that can throw exceptions + InvalidBasketItemException e = Assertions.assertThrows( + InvalidBasketItemException.class, + () -> { basket.removeFromBasket(11); } + ); + Assertions.assertEquals("Basket item with ID #11, doesn't exist. Can't remove from basket.", e.getMessage()); + printExceptionMessageToConsole(e); + } + + @Test + public void removeItemThatDoesNotExistShouldHandleException() { + + // TODO: Check format on this exception + + inventory = new Inventory(); + basket = new Basket(new Inventory()); + + // Check if basket.add() handles error correct (no exception) + Assertions.assertDoesNotThrow(() -> basket.remove(12)); + } } From 0b0a069c380710f846efbddd373d82111404a33a Mon Sep 17 00:00:00 2001 From: shyye Date: Fri, 23 Aug 2024 12:33:07 +0200 Subject: [PATCH 55/93] Add Test: getTotalCostOfBasket --- .../com/booleanuk/core/basket/BasketTest.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/test/java/com/booleanuk/core/basket/BasketTest.java b/src/test/java/com/booleanuk/core/basket/BasketTest.java index 32ba8e770..ae21ccde9 100644 --- a/src/test/java/com/booleanuk/core/basket/BasketTest.java +++ b/src/test/java/com/booleanuk/core/basket/BasketTest.java @@ -1,6 +1,7 @@ package com.booleanuk.core.basket; +import com.booleanuk.core.BasketItem; import com.booleanuk.core.BasketItemExistException; import com.booleanuk.core.inventory.Inventory; import org.junit.jupiter.api.Assertions; @@ -156,4 +157,22 @@ public void removeItemThatDoesNotExistShouldHandleException() { // Check if basket.add() handles error correct (no exception) Assertions.assertDoesNotThrow(() -> basket.remove(12)); } + + // User story #6: Get total cost of basket + @Test + public void getTotalCostOfBasket() { + inventory = new Inventory(); + basket = new Basket(new Inventory()); + Assertions.assertEquals(0, basket.getTotalCost()); + + basket.add(new Coffee("COFW")); + basket.add(new Bagel("BAGE", Arrays.asList("FILS","FILB"))); + + // COFW, 1.19 + // BAGE, 0.49 + // FILS, 0.12 + // FILB, 0.12 + // = 1.92 + Assertions.assertEquals(1.92, basket.getTotalCost()); + } } From 4a40572c03305b90091bc932c3f5a75bdeb3ac71 Mon Sep 17 00:00:00 2001 From: shyye Date: Fri, 23 Aug 2024 12:33:40 +0200 Subject: [PATCH 56/93] Add getTotalCost() and updateTotalCost() --- .../com/booleanuk/core/basket/Basket.java | 52 +++++++++++++++++-- 1 file changed, 48 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/booleanuk/core/basket/Basket.java b/src/main/java/com/booleanuk/core/basket/Basket.java index 7afbc3698..848883af8 100644 --- a/src/main/java/com/booleanuk/core/basket/Basket.java +++ b/src/main/java/com/booleanuk/core/basket/Basket.java @@ -16,6 +16,7 @@ public class Basket { private int maxCapacity; private int size; private int idCount; + private double totalCost; public Basket(Inventory inventory) { this.inventory = inventory; @@ -23,6 +24,7 @@ public Basket(Inventory inventory) { this.maxCapacity = 20; this.size = 0; this.idCount = 1; + this.totalCost = 0.0d; } // Auto create ID @@ -60,7 +62,7 @@ protected void addToBasket(int itemId, BasketItem item) { // Fillings can not be added as an item itself // Fillings that belongs to a bagel have id's over 100 - if (item.getClass().getName() == Filling.class.getName() && item.getId() < 100) { + if (item.getClass().getName().equals(Filling.class.getName()) && item.getId() < 100) { throw new InvalidBasketItemException("Fillings can't be added alone. Must belong to a bagel."); } @@ -99,14 +101,23 @@ public void add(BasketItem item) { // If item is bagel, check if we can add more basket items // OR doesn't filling counts as items maybe hmmm + // TODO: Duplication code for updating id and totalCost + try { + // TODO: Change to switch statement and create Coffe, Bagel, Filling Objects instead of BasketItems + // If item is a Bagel, add all it's fillings to basket if they exist if (item.getClass().getName() == Bagel.class.getName()) { Bagel bagel = (Bagel) item; List fillingSKUs = bagel.getLinkedFillingSKUs(); - this.addToBasket(createId(), item); + int bagelId = createId(); + this.addToBasket(bagelId, item); + item.setId(bagelId); + + // Update totalCost for thi Basket + this.updateTotalCost(item); if (!fillingSKUs.isEmpty()) { List fillingIds = bagel.getLinkedFillingIds(); @@ -114,13 +125,25 @@ public void add(BasketItem item) { int count = 1; for (String f_SKU : fillingSKUs) { int fillingId = createFillingId(String.valueOf(count)); - this.addToBasket(fillingId, new BasketItem(f_SKU)); + + BasketItem filling = new Filling(f_SKU); // TODO: Will not work if I change to filling + filling.setId(fillingId); + + this.addToBasket(fillingId, filling); fillingIds.add(fillingId); + count++; + + // Update totalCost for thi Basket + this.updateTotalCost(filling); } } } else { - this.addToBasket(createId(), item); + int generalId = createId(); + this.addToBasket(generalId, item); + + // Update totalCost for thi Basket + this.updateTotalCost(item); } } catch (Exception e) { @@ -174,4 +197,25 @@ public int getMaxCapacity() { public void changeMaxCapacity(int newMaxCapacity) { this.maxCapacity = newMaxCapacity; } + + private void updateTotalCost(BasketItem item) { + + // TODO: Should I use float or double? + // change here or change on objects + // Now the object has float on price, and totalCost has double + + float itemPrice = inventory.getItem(item.getSKU()).getPrice(); + double newTotalCost = this.totalCost + itemPrice; + + // Resource: https://www.baeldung.com/java-round-decimal-number + int numOfDecimals = 2; + double scale = Math.pow(10, numOfDecimals); + double rounded = Math.round(newTotalCost * scale) / scale; + + this.totalCost = rounded; + } + + public double getTotalCost() { + return this.totalCost; + } } From 6fddda04920adfdfc2db709aa317af6eb719fa0a Mon Sep 17 00:00:00 2001 From: shyye Date: Fri, 23 Aug 2024 14:18:34 +0200 Subject: [PATCH 57/93] Add Test: getPriceOfBagel --- .../java/com/booleanuk/core/inventory/InventoryTest.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/test/java/com/booleanuk/core/inventory/InventoryTest.java b/src/test/java/com/booleanuk/core/inventory/InventoryTest.java index ef9ab8d62..4ac60dd78 100644 --- a/src/test/java/com/booleanuk/core/inventory/InventoryTest.java +++ b/src/test/java/com/booleanuk/core/inventory/InventoryTest.java @@ -1,5 +1,6 @@ package com.booleanuk.core.inventory; +import com.booleanuk.core.BasketItem; import com.booleanuk.core.Coffee; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -49,6 +50,14 @@ public void throwExceptionWhenItemIsNotInInventory() { printExceptionMessageToConsole(e); } + // User story #7: Get price of bagel + @Test + public void getPriceOfBagel() { + inventory = new Inventory(); + BagelItem bagel = (BagelItem) inventory.getItem("BAGE"); + Assertions.assertEquals(0.49, bagel.getPrice()); + } + @Test public void printInventoryMenu() { inventory = new Inventory(); From a3801e3fe2a43623bf4d12cb77cfc5c3f235d252 Mon Sep 17 00:00:00 2001 From: shyye Date: Fri, 23 Aug 2024 14:19:04 +0200 Subject: [PATCH 58/93] Add PriceCalculator with rounding function --- .../com/booleanuk/core/PriceCalculator.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 src/main/java/com/booleanuk/core/PriceCalculator.java diff --git a/src/main/java/com/booleanuk/core/PriceCalculator.java b/src/main/java/com/booleanuk/core/PriceCalculator.java new file mode 100644 index 000000000..4417bc085 --- /dev/null +++ b/src/main/java/com/booleanuk/core/PriceCalculator.java @@ -0,0 +1,24 @@ +package com.booleanuk.core; + +public class PriceCalculator { + + // TODO: How to write a class comment? + // This class should calculate price. + // The aim is to fix so InventoryItem and basket have a common approach on rounding numbers + + // Use double or float, float saves memory, double is easier to work with + + public double round(float total, int numOfDecimals) { + + // TODO: Should I use float or double? + // change here or change on objects + // Now the object has float on price, and totalCost has double + + // Resource: https://www.baeldung.com/java-round-decimal-number + + double scale = Math.pow(10, numOfDecimals); + double rounded = Math.round(total * scale) / scale; + + return rounded; + } +} From 687a345a13f099a8fc6133aa0c4b439fe0e764ba Mon Sep 17 00:00:00 2001 From: shyye Date: Fri, 23 Aug 2024 14:19:23 +0200 Subject: [PATCH 59/93] Update calculate price --- .../com/booleanuk/core/basket/Basket.java | 26 +++++++------------ .../core/inventory/InventoryItem.java | 9 +++++-- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/main/java/com/booleanuk/core/basket/Basket.java b/src/main/java/com/booleanuk/core/basket/Basket.java index 848883af8..abc00ae3f 100644 --- a/src/main/java/com/booleanuk/core/basket/Basket.java +++ b/src/main/java/com/booleanuk/core/basket/Basket.java @@ -1,6 +1,7 @@ package com.booleanuk.core.basket; import com.booleanuk.core.BasketItemExistException; +import com.booleanuk.core.PriceCalculator; import com.booleanuk.core.inventory.Inventory; import com.booleanuk.core.printgenerator.PrintBasketItems; import com.booleanuk.core.printgenerator.PrintGenerator; @@ -16,7 +17,8 @@ public class Basket { private int maxCapacity; private int size; private int idCount; - private double totalCost; + private float totalCost; + private PriceCalculator priceCalculator; public Basket(Inventory inventory) { this.inventory = inventory; @@ -24,7 +26,8 @@ public Basket(Inventory inventory) { this.maxCapacity = 20; this.size = 0; this.idCount = 1; - this.totalCost = 0.0d; + this.totalCost = 0.0f; + this.priceCalculator = new PriceCalculator(); // Should maybe have dependency injection instead. } // Auto create ID @@ -200,22 +203,13 @@ public void changeMaxCapacity(int newMaxCapacity) { private void updateTotalCost(BasketItem item) { - // TODO: Should I use float or double? - // change here or change on objects - // Now the object has float on price, and totalCost has double - - float itemPrice = inventory.getItem(item.getSKU()).getPrice(); - double newTotalCost = this.totalCost + itemPrice; - - // Resource: https://www.baeldung.com/java-round-decimal-number - int numOfDecimals = 2; - double scale = Math.pow(10, numOfDecimals); - double rounded = Math.round(newTotalCost * scale) / scale; - - this.totalCost = rounded; +// float itemPrice = inventory.getItem(item.getSKU()).getPrice(); + double itemPrice = inventory.getItem(item.getSKU()).getPrice(); + this.totalCost+= itemPrice; } public double getTotalCost() { - return this.totalCost; + // TODO Changed to double, this may be unnecessary now + return priceCalculator.round(this.totalCost, 2); } } diff --git a/src/main/java/com/booleanuk/core/inventory/InventoryItem.java b/src/main/java/com/booleanuk/core/inventory/InventoryItem.java index 29848ab00..7daec73b9 100644 --- a/src/main/java/com/booleanuk/core/inventory/InventoryItem.java +++ b/src/main/java/com/booleanuk/core/inventory/InventoryItem.java @@ -1,5 +1,6 @@ package com.booleanuk.core.inventory; +import com.booleanuk.core.PriceCalculator; import com.booleanuk.core.ProductName; import com.booleanuk.core.SKUCalculator; @@ -14,6 +15,7 @@ public class InventoryItem { private Enum variant; private SKUCalculator skuCalculator; + private PriceCalculator priceCalculator; public InventoryItem(float price, Enum variant) { @@ -23,6 +25,9 @@ public InventoryItem(float price, Enum variant) { this.skuCalculator = new SKUCalculator(); this.SKU = setSKU(); + + this.priceCalculator = new PriceCalculator(); + } public String getSKU() { @@ -33,8 +38,8 @@ public String setSKU() { return skuCalculator.getSKU(name, variant); } - public float getPrice() { - return price; + public double getPrice() { + return priceCalculator.round(price, 2); } public void setPrice(float price) { From e0b2b666444179799b4a84b191d90ba18e6553af Mon Sep 17 00:00:00 2001 From: shyye Date: Fri, 23 Aug 2024 14:27:54 +0200 Subject: [PATCH 60/93] Update test --- .../java/com/booleanuk/core/basket/BasketTest.java | 2 ++ .../com/booleanuk/core/inventory/InventoryTest.java | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/src/test/java/com/booleanuk/core/basket/BasketTest.java b/src/test/java/com/booleanuk/core/basket/BasketTest.java index ae21ccde9..b6c42bd50 100644 --- a/src/test/java/com/booleanuk/core/basket/BasketTest.java +++ b/src/test/java/com/booleanuk/core/basket/BasketTest.java @@ -49,6 +49,7 @@ public void addItemaToBasket() { // TODO: Add test for adding something that do not exist + // This is an inventory error, maybe add the test there. // User story #3: Throw exception when trying to add items and maxCapacity of basket is reached @@ -98,6 +99,7 @@ public void changeMaxCapacity() { Assertions.assertEquals(12, basket.getMaxCapacity()); } + // User story #8: Add bagel with filling @Test public void addBagelAndFilling() { inventory = new Inventory(); diff --git a/src/test/java/com/booleanuk/core/inventory/InventoryTest.java b/src/test/java/com/booleanuk/core/inventory/InventoryTest.java index 4ac60dd78..e17edebdf 100644 --- a/src/test/java/com/booleanuk/core/inventory/InventoryTest.java +++ b/src/test/java/com/booleanuk/core/inventory/InventoryTest.java @@ -37,6 +37,8 @@ public void getItemBasedOnSKU() { Assertions.assertEquals("BAGE", inventory.getItem("BAGE").getSKU()); } + // User story #10: Can't add something that are not in the inventory / in stock + // TODO: This inventory don't keep track on number of items in stock, so it is infinite @Test public void throwExceptionWhenItemIsNotInInventory() { inventory = new Inventory(); @@ -58,6 +60,14 @@ public void getPriceOfBagel() { Assertions.assertEquals(0.49, bagel.getPrice()); } + // User story #9: Get price of filling + @Test + public void getPriceOfFilling() { + inventory = new Inventory(); + FillingItem filling = (FillingItem) inventory.getItem("FILB"); + Assertions.assertEquals(0.12, filling.getPrice()); + } + @Test public void printInventoryMenu() { inventory = new Inventory(); From 101604a80e124df5ca212b5b00d99f968d1c6b5e Mon Sep 17 00:00:00 2001 From: shyye Date: Fri, 23 Aug 2024 14:58:04 +0200 Subject: [PATCH 61/93] Refactor, delete old files --- src/main/java/com/booleanuk/core/Bagel.java | 28 --- src/main/java/com/booleanuk/core/Basket.java | 206 ------------------ .../java/com/booleanuk/core/BasketItem.java | 32 --- .../core/BasketItemExistException.java | 7 - src/main/java/com/booleanuk/core/Coffee.java | 14 -- src/main/java/com/booleanuk/core/Filling.java | 13 -- .../java/com/booleanuk/core/Inventory.java | 131 ----------- src/main/java/com/booleanuk/core/Product.java | 52 ----- .../com/booleanuk/core/basket/Basket.java | 1 - .../core/printgenerator/PrintBasketItems.java | 2 - .../java/com/booleanuk/core/BasketTest.java | 120 ---------- .../com/booleanuk/core/InventoryTest.java | 38 ---- .../com/booleanuk/core/basket/BasketTest.java | 2 - .../core/inventory/InventoryTest.java | 2 - 14 files changed, 648 deletions(-) delete mode 100644 src/main/java/com/booleanuk/core/Bagel.java delete mode 100644 src/main/java/com/booleanuk/core/Basket.java delete mode 100644 src/main/java/com/booleanuk/core/BasketItem.java delete mode 100644 src/main/java/com/booleanuk/core/BasketItemExistException.java delete mode 100644 src/main/java/com/booleanuk/core/Coffee.java delete mode 100644 src/main/java/com/booleanuk/core/Filling.java delete mode 100644 src/main/java/com/booleanuk/core/Inventory.java delete mode 100644 src/main/java/com/booleanuk/core/Product.java delete mode 100644 src/test/java/com/booleanuk/core/BasketTest.java delete mode 100644 src/test/java/com/booleanuk/core/InventoryTest.java diff --git a/src/main/java/com/booleanuk/core/Bagel.java b/src/main/java/com/booleanuk/core/Bagel.java deleted file mode 100644 index 7958a6061..000000000 --- a/src/main/java/com/booleanuk/core/Bagel.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.booleanuk.core; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -public class Bagel extends Product{ - -// private List fillings; - - public Bagel(float price, Enum variant) { - super(price, variant); -// this.fillings = new ArrayList<>(); - } - - @Override - public ProductName setName() { - return ProductName.BAGEL; - } - -// public void addFilling(int filling) { -// this.fillings.add(filling); -// } -// -// public List getFillings() { -// return fillings; -// } -} diff --git a/src/main/java/com/booleanuk/core/Basket.java b/src/main/java/com/booleanuk/core/Basket.java deleted file mode 100644 index a2f1e0721..000000000 --- a/src/main/java/com/booleanuk/core/Basket.java +++ /dev/null @@ -1,206 +0,0 @@ -package com.booleanuk.core; - -import com.booleanuk.core.basket.MaxCapacityException; - -import java.util.*; - -public class Basket { - private Inventory inventory; - private LinkedHashMap basketItems; - private int maxCapacity; - private int idCount; - - public Basket(Inventory inventory) { - this.inventory = inventory; - this.basketItems = new LinkedHashMap <>(); - this.maxCapacity = 20; - this.idCount = 1; - } - - /** - * Create new Id for item in basket. - * Updates idCount afterward. - * @param String idExtension - Add this for fillings, one unique extension for each filling - * @return int itemId - */ - private int createID() { - // Store variable - int itemId = this.idCount; - this.idCount += 1; - return itemId; - } - - private int createFillingId(String idExtension) { - //TODO: How to make default variable like in python - - // TODO: Should check if idExtension is valid - - // TODO: Could use int input instead of String - - // Store variable id for previous bagel - int itemId = this.idCount - 1; - - // Add id extension for filling - String tmp = String.valueOf(itemId) + "0" + idExtension; - return Integer.parseInt(tmp); - } - - // TODO: I need to have this because otherwise I can't make a unit test on it, - // but I don't want the inventory or other classes to have aceess to this. - // should I put basket in an own package? - // Oterwise change back to private - // See test exceedMaxCapacityShouldThrowError - protected void addToBasket(int id, BasketItem item) { - if (this.basketItems.size() == maxCapacity) { - throw new MaxCapacityException("Basket is full, can't add more items."); - } - this.basketItems.put(id, item); - } - - // TODO: Same as above, is it good practice to do this? - // it's easier to test Exceptions - protected BasketItem getItemFromBasketOrThrowException(int productId) { - BasketItem item = this.basketItems.get(productId); - if (item == null) { - throw new BasketItemExistException("This item doesn't exist. Can't remove ID #" + productId); - } - return item; - } - - // TODO: Refactor and remove this and add generic function nsad?? - public void addCoffee(String SKU) { - try { -// BasketItem item = new BasketItem(SKU); -// this.basketItems.put(createID(), item); - - this.addToBasket(createID(), new BasketItem(SKU)); - printBasket(); - } catch (MaxCapacityException e) { - System.out.println(e.getMessage()); - } - } - - - public void addBagel(String SKU) { - try { -// BasketItem item = new BasketItem(SKU); -// this.basketItems.put(createID(), item); - - this.addToBasket(createID(), new BasketItem(SKU)); - } catch (MaxCapacityException e) { - System.out.println(e.getMessage()); - } -// // TODO: Can't check throw exception in Test if I handle the exception with try/catch -// this.addToBasket(createID(), new BasketItem(SKU)); - - } - - - public void addBagel(String SKU, List SKUfillings) { - try { - BasketItem item = new BasketItem(SKU); -// this.basketItems.put(createID(), item); - this.addToBasket(createID(), item); - - int count = 1; - for (String SKU_f : SKUfillings) { - - // Store the created id for the filling - int fillingId = createFillingId(String.valueOf(count)); - - // Add filling to this basket -// this.basketItems.put(fillingId, new BasketItem(SKU_f)); - this.addToBasket(fillingId, new BasketItem(SKU_f)); - - // Store filling id in bagel basketIem so it is possible to delete later - item.addFillingId(fillingId); - - count++; - } - } catch (MaxCapacityException e) { - System.out.println(e.getMessage()); - } - } - - public void remove(int productId) { - try { -// BasketItem item = this.basketItems.get(productId); - BasketItem item = this.getItemFromBasketOrThrowException(productId); - Product product = this.inventory.getProduct(item.getSKU()); - - if (product.getName() == ProductName.BAGEL && item.getLinkedIds() != null) { - // Get filling for this basketItem - List fillingsIds = item.getLinkedIds(); - // Remove the bagel fillings from the basket - for (Integer fillingId : fillingsIds) { - this.basketItems.remove(fillingId); - } - } - this.basketItems.remove(productId); - } catch (BasketItemExistException e) { - System.out.println(e.getMessage()); - } - } - -// private void addFilling(String SKU) { -// Filling filling = inventory.getFillingProduct(SKU); -// this.basketItems.put(createID(), filling); -// } - - public LinkedHashMap getAll() { - return basketItems; - } - - public void changeMaxCapacity(int newMaxCapacity) { - this.maxCapacity = newMaxCapacity; - } - - // TODO: I only use this for the test. Should I redo the test? - public int getMaxCapacity() { - return this.maxCapacity; - } - - public void printBasket() { - // Variables for e.g. "%-15s %-15s %n", keep blank space - String centerSmall = "%34s "; - String center = "%29s "; - String leftAlignSmall = "%-7s "; - String leftAlign = "%-15s "; - String newLine = "%n"; - String divider = "-----------------------------------------------"; - - // TODO: Unnecassary looping - // TODO: Duplicate code - System.out.println(); - System.out.printf(centerSmall + newLine, "=== Bob's Bagels ==="); - System.out.printf(center + newLine, "~ Basket ~"); - System.out.println(); - - // Print items in basket - if (basketItems.isEmpty()) { - System.out.println("\tBasket is empty."); - } else { - System.out.printf( - leftAlignSmall + leftAlignSmall + leftAlignSmall + leftAlign + leftAlign + newLine, - "SKU | ", "ID", "Product", "Variant", "Price" - ); - System.out.println(divider); - for (Map.Entry item : basketItems.entrySet()) { - int key = item.getKey(); - BasketItem basketItem = item.getValue(); - Product product = this.inventory.getProduct(basketItem.getSKU()); - System.out.printf( - leftAlignSmall + leftAlignSmall + leftAlignSmall + leftAlign + leftAlign + newLine, - product.getSKU()+" | ", key, product.getName(), product.getVariant().toString(), "$" + product.getPrice() - ); - } - System.out.println(divider); - System.out.printf( - "%s %33s" + newLine, - "Total cost: ", "$?.??" - ); - } - System.out.println(divider); - System.out.println(); - } -} diff --git a/src/main/java/com/booleanuk/core/BasketItem.java b/src/main/java/com/booleanuk/core/BasketItem.java deleted file mode 100644 index f563bdd36..000000000 --- a/src/main/java/com/booleanuk/core/BasketItem.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.booleanuk.core; - -import java.util.ArrayList; -import java.util.List; - -public class BasketItem { - private String SKU; - private List linkedIds; - - public BasketItem(String SKU) { - this.SKU = SKU; - this.linkedIds = new ArrayList<>(); - } - - // TODO: Refactor may not be used - public BasketItem(String SKU, List linkedIds) { - this.SKU = SKU; - this.linkedIds = linkedIds; - } - - public String getSKU() { - return SKU; - } - - public List getLinkedIds() { - return linkedIds; - } - - public void addFillingId(int id) { - this.linkedIds.add(id); - } -} diff --git a/src/main/java/com/booleanuk/core/BasketItemExistException.java b/src/main/java/com/booleanuk/core/BasketItemExistException.java deleted file mode 100644 index 715a14cad..000000000 --- a/src/main/java/com/booleanuk/core/BasketItemExistException.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.booleanuk.core; - -public class BasketItemExistException extends RuntimeException { - public BasketItemExistException(String message) { - super(message); - } -} diff --git a/src/main/java/com/booleanuk/core/Coffee.java b/src/main/java/com/booleanuk/core/Coffee.java deleted file mode 100644 index d529bd178..000000000 --- a/src/main/java/com/booleanuk/core/Coffee.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.booleanuk.core; - -public class Coffee extends Product{ - - - public Coffee(float price, Enum variant) { - super(price, variant); - } - - @Override - public ProductName setName() { - return ProductName.COFFEE; - } -} \ No newline at end of file diff --git a/src/main/java/com/booleanuk/core/Filling.java b/src/main/java/com/booleanuk/core/Filling.java deleted file mode 100644 index 63a0d7761..000000000 --- a/src/main/java/com/booleanuk/core/Filling.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.booleanuk.core; - -public class Filling extends Product { - - public Filling(float price, Enum variant) { - super(price, variant); - } - - @Override - public ProductName setName() { - return ProductName.FILLING; - } -} diff --git a/src/main/java/com/booleanuk/core/Inventory.java b/src/main/java/com/booleanuk/core/Inventory.java deleted file mode 100644 index eaccec8dc..000000000 --- a/src/main/java/com/booleanuk/core/Inventory.java +++ /dev/null @@ -1,131 +0,0 @@ -package com.booleanuk.core; - -import java.util.ArrayList; -import java.util.HashMap; - -public class Inventory { - private HashMap inventoryItems; - - public Inventory() { - this.inventoryItems = new HashMap<>(); - fillInventory(); - } - - private void fillInventory() { - - // TODO: Weird to have them here, should move - // Initialize list with inventory products - ArrayList products = new ArrayList<>(); - - products.add(new Bagel(0.49f, BagelVariant.ONION)); - products.add(new Bagel(0.39f, BagelVariant.PLAIN)); - products.add(new Bagel(0.49f, BagelVariant.EVERYTHING)); - products.add(new Bagel(0.49f, BagelVariant.SESAME)); - - products.add(new Coffee(0.99f, CoffeeVariant.BLACK)); - products.add(new Coffee(1.19f, CoffeeVariant.WHITE)); - products.add(new Coffee(1.29f, CoffeeVariant.CAPUCCINO)); - products.add(new Coffee(1.29f, CoffeeVariant.LATTE)); - - products.add(new Filling(0.12f, FillingVariant.BACON)); - products.add(new Filling(0.12f, FillingVariant.EGG)); - products.add(new Filling(0.12f, FillingVariant.CHEESE)); - products.add(new Filling(0.12f, FillingVariant.CREAM_CHEESE)); - products.add(new Filling(0.12f, FillingVariant.SMOKED_SALMON)); - products.add(new Filling(0.12f, FillingVariant.HAM)); - - // Add products to HashMap - for (Product p : products) { - inventoryItems.put(p.getSKU(), p); - } - } - - public void printMenu() { - // Variables for e.g. "%-15s %-15s %n", keep blank space - String centerSmall = "%4s "; - String center = "%7s "; - String skuAlign = "%-8s "; - String leftAlign = "%-16s "; - String newLine = "%n"; - String divider = "-------------------------------"; - - // TODO: Unnecassary looping - // TODO: Duplicate code - // Simplify, doesn't have to have multiple center - System.out.println(); - System.out.printf(centerSmall + centerSmall + centerSmall + newLine,"", "=== Bob's Bagels ===", ""); - System.out.printf(center + center + center + newLine,"", " ~ Menu ~ ", ""); - System.out.println(divider); - - // Coffee menu - System.out.printf(center + center + center + newLine,"", " COFFEE ", ""); - for (Product item : inventoryItems.values()) { - if (item.getName() == ProductName.COFFEE) { - System.out.printf( - skuAlign + leftAlign + leftAlign + newLine, - item.getSKU()+" | ", item.getVariant().toString(), "$" + item.getPrice() - ); - } - } - System.out.println(); - - // Bagel Menu Bagels - System.out.printf(center + center + center + newLine,"", " Bagels ", ""); - for (Product item : inventoryItems.values()) { - if (item.getName() == ProductName.BAGEL) { - System.out.printf( - skuAlign + leftAlign + leftAlign + newLine, - item.getSKU()+" | ", item.getVariant().toString(), "$" + item.getPrice() - ); - } - } - System.out.println(); - - // Bagel Menu Bagels - System.out.printf(center + center + center + newLine,"", "Bagel Fillings", ""); - for (Product item : inventoryItems.values()) { - if (item.getName() == ProductName.FILLING) { - System.out.printf( - skuAlign + leftAlign + leftAlign + newLine, - item.getSKU()+" | ", item.getVariant().toString(), "$" + item.getPrice() - ); - } - } - System.out.println(); -// System.out.printf(leftAlign + leftAlign + newLine, "hello", "world"); - } - - // TODO: Duplication code, abstraction, but not good otherwise, Factory pattern? - public Coffee getCoffeeProduct(String SKU) { - Product coffeeProduct = inventoryItems.get(SKU); - return (Coffee) coffeeProduct; - } - - public Bagel getBagelProduct(String SKU) { - Product bagelProduct = inventoryItems.get(SKU); - return (Bagel) bagelProduct; - } - - public Filling getFillingProduct(String SKU) { - Product fillingProduct = inventoryItems.get(SKU); - return (Filling) fillingProduct; - } - - // TODO:Refactor or good to have the above methods for the Basket class? - public Product getProduct(String SKU) { - return inventoryItems.get(SKU); - } - - /** - * Return a String that can be used as key for the HashMap inventoryIten - * @param product - * @return - */ -// private String hash(Product product) { -// String productCode = product.getName().toString().substring(0,2); -// String variantCode = product.getVariant().toString().substring(0,2); -// String hashCode = productCode + variantCode; -// return hashCode.toUpperCase(); -// } - -} diff --git a/src/main/java/com/booleanuk/core/Product.java b/src/main/java/com/booleanuk/core/Product.java deleted file mode 100644 index 882da9ad5..000000000 --- a/src/main/java/com/booleanuk/core/Product.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.booleanuk.core; - -public class Product { - private String SKU; - private float price; - private ProductName name; - private Enum variant; - - public Product(float price, Enum variant) { - this.price = price; - this.name = setName(); - this.variant = variant; - this.SKU = setSKU(name, variant); - } - - - public String getSKU() { - return this.SKU; - } - - public String setSKU(ProductName name, Enum variant) { - String productCode = name.toString().substring(0,3); - String variantCode = variant.toString().substring(0,1); - String hashCode = productCode + variantCode; - - return hashCode.toUpperCase(); - } - - public float getPrice() { - return this.price; - } - - public void setPrice(float price) { - this.price = price; - } - - public Enum getName() { - return this.name; - } - - public ProductName setName() { - return ProductName.DEFAULT; - } - - public Enum getVariant() { - return variant; - } - - public void setVariant(Enum variant) { - this.variant = variant; - } -} diff --git a/src/main/java/com/booleanuk/core/basket/Basket.java b/src/main/java/com/booleanuk/core/basket/Basket.java index abc00ae3f..1e2ae4fa5 100644 --- a/src/main/java/com/booleanuk/core/basket/Basket.java +++ b/src/main/java/com/booleanuk/core/basket/Basket.java @@ -1,6 +1,5 @@ package com.booleanuk.core.basket; -import com.booleanuk.core.BasketItemExistException; import com.booleanuk.core.PriceCalculator; import com.booleanuk.core.inventory.Inventory; import com.booleanuk.core.printgenerator.PrintBasketItems; diff --git a/src/main/java/com/booleanuk/core/printgenerator/PrintBasketItems.java b/src/main/java/com/booleanuk/core/printgenerator/PrintBasketItems.java index 284858b87..ae0be5cbb 100644 --- a/src/main/java/com/booleanuk/core/printgenerator/PrintBasketItems.java +++ b/src/main/java/com/booleanuk/core/printgenerator/PrintBasketItems.java @@ -1,9 +1,7 @@ package com.booleanuk.core.printgenerator; -import com.booleanuk.core.Product; import com.booleanuk.core.basket.BasketItem; import com.booleanuk.core.inventory.Inventory; -import com.booleanuk.core.ProductName; import com.booleanuk.core.inventory.InventoryItem; import java.util.Map; diff --git a/src/test/java/com/booleanuk/core/BasketTest.java b/src/test/java/com/booleanuk/core/BasketTest.java deleted file mode 100644 index 8facb99e8..000000000 --- a/src/test/java/com/booleanuk/core/BasketTest.java +++ /dev/null @@ -1,120 +0,0 @@ -package com.booleanuk.core; - -import com.booleanuk.core.basket.MaxCapacityException; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -import java.util.Arrays; - -public class BasketTest { - Inventory inventory; - Basket basket; - - @Test - public void checkPrintBasket() { - this.inventory = new Inventory(); - this.basket = new Basket(new Inventory()); - basket.printBasket(); - } - - @Test - public void addCoffee() { - this.inventory = new Inventory(); - this.basket = new Basket(new Inventory()); - basket.addCoffee("COFW"); - basket.printBasket(); - Assertions.assertEquals("COFW", basket.getAll().get(1).getSKU()); - } - - // User story #1 Add a specific type of bagel - @Test - public void addBagelAndFilling() { - this.inventory = new Inventory(); - this.basket = new Basket(new Inventory()); - basket.addBagel("BAGE", Arrays.asList("FILS","FILB")); - basket.printBasket(); - Assertions.assertEquals("BAGE", basket.getAll().get(1).getSKU()); - Assertions.assertEquals("FILS", basket.getAll().get(101).getSKU()); - } - - // User story #1 Add a specific type of bagel - @Test - public void removeBagel() { - this.inventory = new Inventory(); - this.basket = new Basket(new Inventory()); - basket.addBagel("BAGE", Arrays.asList("FILS","FILB")); - basket.addBagel("BAGE", Arrays.asList("FILS","FILB")); - basket.printBasket(); - - // TODO: Add test - basket.remove(1); - basket.printBasket(); - } - - // User story #5 - @Test - public void removeItemFromBasketThatDoNotExist() { - this.inventory = new Inventory(); - this.basket = new Basket(new Inventory()); - int productId = 5; - - // Check that exception function throws error - BasketItemExistException exception = Assertions.assertThrows(BasketItemExistException.class, () -> { - basket.getItemFromBasketOrThrowException(productId); - }); - // Print out message from exception instead of checking if its assertEqual - System.out.println("\nException message:"); - System.out.println("\t" + exception.getMessage() + "\n"); - - // TODO: Split into two tests - - // Check if basket.remove() handles error correct (no exception) - Assertions.assertDoesNotThrow(() -> basket.remove(productId)); - } - -// @Test -// public void tryToAddProductThatIsNotInInventory() { -// this.inventory = new Inventory(); -// this.basket = new Basket(new Inventory()); -// basket.addBagel("HELLO", Arrays.asList("FILS","FILB")); -// basket.printBasket(); -// } - - // User story #3 Notify when max capacity of basket is reached - @Test - public void exceedMaxCapacityShouldThrowError() { - this.inventory = new Inventory(); - this.basket = new Basket(new Inventory()); - - basket.changeMaxCapacity(2); - basket.addBagel("BAGE"); - basket.addBagel("BAGE"); - - // TODO: I need to set addToBasket() to protected instead of private and - // test it because I can't test addBgel()/addCoffe() because they includes a try/catch - MaxCapacityException exception = Assertions.assertThrows(MaxCapacityException.class, () -> { - basket.addToBasket(11,new BasketItem("BAGE")); - }); -// Assertions.assertEquals("Basket is full, can't add more items.", exception.getLocalizedMessage()); - - // Print out message from exception instead of checking if its assertEqual - System.out.println("\nException message:"); - System.out.println("\t" + exception.getMessage() + "\n"); - - // Public method that should print out the error -// basket.addBagel("BAGE"); - } - - // User story #4: Change max capacity of basket - @Test - public void checkChangeMaxCapacity() { - this.inventory = new Inventory(); - this.basket = new Basket(new Inventory()); - - basket.changeMaxCapacity(3); - Assertions.assertEquals(3, basket.getMaxCapacity()); - - basket.changeMaxCapacity(12); - Assertions.assertEquals(12, basket.getMaxCapacity()); - } -} diff --git a/src/test/java/com/booleanuk/core/InventoryTest.java b/src/test/java/com/booleanuk/core/InventoryTest.java deleted file mode 100644 index ee5259839..000000000 --- a/src/test/java/com/booleanuk/core/InventoryTest.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.booleanuk.core; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -public class InventoryTest { - Inventory inventory; - - - @Test - public void checkInventoryInitialization() { - - // TODO: How to test print statements - this.inventory = new Inventory(); - inventory.printMenu(); - } - - @Test - public void getProductBasedOnSKU() { - this.inventory = new Inventory(); - - Coffee coffee = inventory.getCoffeeProduct("COFC"); - Assertions.assertEquals(ProductName.COFFEE, coffee.getName()); - - Bagel bagel = inventory.getBagelProduct("BAGE"); - Assertions.assertEquals(ProductName.BAGEL, bagel.getName()); - - Filling filling = inventory.getFillingProduct("FILB"); - Assertions.assertEquals(ProductName.FILLING, filling.getName()); - } - // TODO: Add test for exception returned when SKU is invalid / Does npt exist - //TODO: Add test for only product no specific version - -// @Test -// public void getProductPrice() { -// this.inventory.getItemPrice(); -// } -} diff --git a/src/test/java/com/booleanuk/core/basket/BasketTest.java b/src/test/java/com/booleanuk/core/basket/BasketTest.java index b6c42bd50..c751809d0 100644 --- a/src/test/java/com/booleanuk/core/basket/BasketTest.java +++ b/src/test/java/com/booleanuk/core/basket/BasketTest.java @@ -1,8 +1,6 @@ package com.booleanuk.core.basket; -import com.booleanuk.core.BasketItem; -import com.booleanuk.core.BasketItemExistException; import com.booleanuk.core.inventory.Inventory; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; diff --git a/src/test/java/com/booleanuk/core/inventory/InventoryTest.java b/src/test/java/com/booleanuk/core/inventory/InventoryTest.java index e17edebdf..f1a9ff88f 100644 --- a/src/test/java/com/booleanuk/core/inventory/InventoryTest.java +++ b/src/test/java/com/booleanuk/core/inventory/InventoryTest.java @@ -1,7 +1,5 @@ package com.booleanuk.core.inventory; -import com.booleanuk.core.BasketItem; -import com.booleanuk.core.Coffee; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; From 8d6530d2e9b44f92c018dcb7a6695fcf5a4e9524 Mon Sep 17 00:00:00 2001 From: shyye Date: Fri, 23 Aug 2024 15:08:39 +0200 Subject: [PATCH 62/93] Clean up code --- src/main/java/com/booleanuk/core/basket/Bagel.java | 13 ------------- src/main/java/com/booleanuk/core/basket/Basket.java | 4 ++-- .../core/printgenerator/PrintBasketItems.java | 2 -- 3 files changed, 2 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/booleanuk/core/basket/Bagel.java b/src/main/java/com/booleanuk/core/basket/Bagel.java index bfa1ebfdd..263051574 100644 --- a/src/main/java/com/booleanuk/core/basket/Bagel.java +++ b/src/main/java/com/booleanuk/core/basket/Bagel.java @@ -14,25 +14,12 @@ public Bagel(String SKU) { linkedFillingIds = new ArrayList<>(); } - // TODO: Does it work to overlode this? public Bagel(String SKU, List linkedFillingsSKUs) { super(SKU); this.linkedFillingSKUs = linkedFillingsSKUs; linkedFillingIds = new ArrayList<>(); } -// public void addFilling(String SKU) { -// linkedFillingSKUs.add(SKU); -// } -// -// public void addFillings(List linkedIds) { -// -//// for (int id : linkedIds) { -//// linkedIds.add(id); -//// } -// linkedFillingSKUs.addAll(linkedIds); -// } - public List getLinkedFillingSKUs() { return linkedFillingSKUs; } diff --git a/src/main/java/com/booleanuk/core/basket/Basket.java b/src/main/java/com/booleanuk/core/basket/Basket.java index 1e2ae4fa5..3e5ddb894 100644 --- a/src/main/java/com/booleanuk/core/basket/Basket.java +++ b/src/main/java/com/booleanuk/core/basket/Basket.java @@ -48,7 +48,7 @@ private int createFillingId(String idExtension) { int itemId = this.idCount - 1; // Add id extension for filling - String tmp = String.valueOf(itemId) + "0" + idExtension; + String tmp = itemId + "0" + idExtension; return Integer.parseInt(tmp); } @@ -110,7 +110,7 @@ public void add(BasketItem item) { // TODO: Change to switch statement and create Coffe, Bagel, Filling Objects instead of BasketItems // If item is a Bagel, add all it's fillings to basket if they exist - if (item.getClass().getName() == Bagel.class.getName()) { + if (item.getClass().getName().equals(Bagel.class.getName())) { Bagel bagel = (Bagel) item; List fillingSKUs = bagel.getLinkedFillingSKUs(); diff --git a/src/main/java/com/booleanuk/core/printgenerator/PrintBasketItems.java b/src/main/java/com/booleanuk/core/printgenerator/PrintBasketItems.java index ae0be5cbb..040eff7c7 100644 --- a/src/main/java/com/booleanuk/core/printgenerator/PrintBasketItems.java +++ b/src/main/java/com/booleanuk/core/printgenerator/PrintBasketItems.java @@ -22,8 +22,6 @@ public void print() { int outputWidth = 47; // Variables for e.g. "%-15s %-15s %n", keep blank space - String centerSmall = "%34s "; - String center = "%29s "; String leftAlignSmall = "%-7s "; String leftAlign = "%-15s "; String newLine = "%n"; From 769e01cede75dedf6c547dd03907f253e2ab7dbc Mon Sep 17 00:00:00 2001 From: shyye Date: Fri, 23 Aug 2024 16:26:22 +0200 Subject: [PATCH 63/93] Simplify remove() --- .../com/booleanuk/core/basket/Basket.java | 47 ++++++++++++++----- 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/booleanuk/core/basket/Basket.java b/src/main/java/com/booleanuk/core/basket/Basket.java index 3e5ddb894..d50b1a4b7 100644 --- a/src/main/java/com/booleanuk/core/basket/Basket.java +++ b/src/main/java/com/booleanuk/core/basket/Basket.java @@ -1,7 +1,10 @@ package com.booleanuk.core.basket; +import com.booleanuk.core.PriceCalculationVariant; import com.booleanuk.core.PriceCalculator; +import com.booleanuk.core.inventory.FillingItem; import com.booleanuk.core.inventory.Inventory; +import com.booleanuk.core.inventory.InventoryItem; import com.booleanuk.core.printgenerator.PrintBasketItems; import com.booleanuk.core.printgenerator.PrintGenerator; @@ -119,7 +122,7 @@ public void add(BasketItem item) { item.setId(bagelId); // Update totalCost for thi Basket - this.updateTotalCost(item); + this.updateTotalCost(item, PriceCalculationVariant.ADDITION); if (!fillingSKUs.isEmpty()) { List fillingIds = bagel.getLinkedFillingIds(); @@ -137,7 +140,7 @@ public void add(BasketItem item) { count++; // Update totalCost for thi Basket - this.updateTotalCost(filling); + this.updateTotalCost(filling, PriceCalculationVariant.ADDITION); } } } else { @@ -145,7 +148,7 @@ public void add(BasketItem item) { this.addToBasket(generalId, item); // Update totalCost for thi Basket - this.updateTotalCost(item); + this.updateTotalCost(item, PriceCalculationVariant.ADDITION); } } catch (Exception e) { @@ -156,18 +159,25 @@ public void add(BasketItem item) { public void remove(int itemId) { try { - // TODO: Could this be simplified? - // TODO: should throw exception if not exist, seperate intro function, just like with add BasketItem item = this.getBasketItem(itemId); - if (item.getClass().getName() == Bagel.class.getName()) { + + // Class names + String thisItemClass = item.getClass().getName(); + String BagelClass = Bagel.class.getName(); + + // Remove fillings if it is a Bagel + if (thisItemClass.equals(BagelClass)) { + Bagel bagel = (Bagel) item; List fillingIds = bagel.getLinkedFillingIds(); + // Remove all fillings for (int f_id : fillingIds) { this.removeFromBasket(f_id); } } - this.removeFromBasket(1); + this.removeFromBasket(itemId); + } catch (Exception e) { System.out.println(e.getMessage()); } @@ -186,7 +196,7 @@ public void printBasket() { // TODO: Should I refactor? Feels like it's a poor solution regarding dependencies. // Check all PrintGenerator cases. - PrintGenerator basket = new PrintBasketItems(this.inventory, this.basketItems); + PrintGenerator basket = new PrintBasketItems(this.inventory, this.basketItems, this.getTotalCost()); basket.print(); } @@ -200,15 +210,28 @@ public void changeMaxCapacity(int newMaxCapacity) { this.maxCapacity = newMaxCapacity; } - private void updateTotalCost(BasketItem item) { + private void updateTotalCost(BasketItem item, PriceCalculationVariant option) { -// float itemPrice = inventory.getItem(item.getSKU()).getPrice(); double itemPrice = inventory.getItem(item.getSKU()).getPrice(); - this.totalCost+= itemPrice; + + if (option == PriceCalculationVariant.ADDITION) { + this.totalCost += itemPrice; + } else if (option == PriceCalculationVariant.SUBTRACTION){ + this.totalCost -= itemPrice; + } } public double getTotalCost() { // TODO Changed to double, this may be unnecessary now - return priceCalculator.round(this.totalCost, 2); + + // TODO: Is it bad performance to loop like this? + // Should I instead keep track on the price everytime an item is added or removed? + + float total = 0; + for (BasketItem item : this.basketItems.values()) { + InventoryItem inventoryItem = inventory.getItem(item.getSKU()); + total += inventoryItem.getPrice(); + } + return priceCalculator.round(total, 2); } } From 908f728816feadd29afafba9938f9296bc17bf2e Mon Sep 17 00:00:00 2001 From: shyye Date: Fri, 23 Aug 2024 16:39:40 +0200 Subject: [PATCH 64/93] Simplify add() --- .../com/booleanuk/core/basket/Basket.java | 29 +++++++------------ 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/booleanuk/core/basket/Basket.java b/src/main/java/com/booleanuk/core/basket/Basket.java index d50b1a4b7..ceaf8b3f0 100644 --- a/src/main/java/com/booleanuk/core/basket/Basket.java +++ b/src/main/java/com/booleanuk/core/basket/Basket.java @@ -102,18 +102,17 @@ protected BasketItem getBasketItem(int itemId) { */ public void add(BasketItem item) { - // Try catch maxCapacity - // If item is bagel, check if we can add more basket items - // OR doesn't filling counts as items maybe hmmm - - // TODO: Duplication code for updating id and totalCost - try { - // TODO: Change to switch statement and create Coffe, Bagel, Filling Objects instead of BasketItems + // TODO: Duplication of id with different variables? Simplify? + // Could I use some inheritance/polymorphism? + + // Class names + String thisItemClass = item.getClass().getName(); + String BagelClass = Bagel.class.getName(); - // If item is a Bagel, add all it's fillings to basket if they exist - if (item.getClass().getName().equals(Bagel.class.getName())) { + // Add fillings if it is a Bagel + if (thisItemClass.equals(BagelClass)) { Bagel bagel = (Bagel) item; List fillingSKUs = bagel.getLinkedFillingSKUs(); @@ -121,9 +120,7 @@ public void add(BasketItem item) { this.addToBasket(bagelId, item); item.setId(bagelId); - // Update totalCost for thi Basket - this.updateTotalCost(item, PriceCalculationVariant.ADDITION); - + // Add fillings and save the filling ids' to the bagel if (!fillingSKUs.isEmpty()) { List fillingIds = bagel.getLinkedFillingIds(); @@ -131,24 +128,18 @@ public void add(BasketItem item) { for (String f_SKU : fillingSKUs) { int fillingId = createFillingId(String.valueOf(count)); - BasketItem filling = new Filling(f_SKU); // TODO: Will not work if I change to filling + BasketItem filling = new Filling(f_SKU); filling.setId(fillingId); this.addToBasket(fillingId, filling); fillingIds.add(fillingId); count++; - - // Update totalCost for thi Basket - this.updateTotalCost(filling, PriceCalculationVariant.ADDITION); } } } else { int generalId = createId(); this.addToBasket(generalId, item); - - // Update totalCost for thi Basket - this.updateTotalCost(item, PriceCalculationVariant.ADDITION); } } catch (Exception e) { From 93bee082768ebda6c553aa46631f96ec08042058 Mon Sep 17 00:00:00 2001 From: shyye Date: Fri, 23 Aug 2024 16:41:13 +0200 Subject: [PATCH 65/93] remove updateTotalCost(), only use getTotalCost() --- src/main/java/com/booleanuk/core/basket/Basket.java | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/main/java/com/booleanuk/core/basket/Basket.java b/src/main/java/com/booleanuk/core/basket/Basket.java index ceaf8b3f0..7803501d0 100644 --- a/src/main/java/com/booleanuk/core/basket/Basket.java +++ b/src/main/java/com/booleanuk/core/basket/Basket.java @@ -201,17 +201,6 @@ public void changeMaxCapacity(int newMaxCapacity) { this.maxCapacity = newMaxCapacity; } - private void updateTotalCost(BasketItem item, PriceCalculationVariant option) { - - double itemPrice = inventory.getItem(item.getSKU()).getPrice(); - - if (option == PriceCalculationVariant.ADDITION) { - this.totalCost += itemPrice; - } else if (option == PriceCalculationVariant.SUBTRACTION){ - this.totalCost -= itemPrice; - } - } - public double getTotalCost() { // TODO Changed to double, this may be unnecessary now From b3f044ad328da6a2cbde7177167d78cd63f339ac Mon Sep 17 00:00:00 2001 From: shyye Date: Fri, 23 Aug 2024 16:44:46 +0200 Subject: [PATCH 66/93] Add total cost variable for basket --- .../com/booleanuk/core/printgenerator/PrintBasketItems.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/booleanuk/core/printgenerator/PrintBasketItems.java b/src/main/java/com/booleanuk/core/printgenerator/PrintBasketItems.java index 040eff7c7..c82a5eb05 100644 --- a/src/main/java/com/booleanuk/core/printgenerator/PrintBasketItems.java +++ b/src/main/java/com/booleanuk/core/printgenerator/PrintBasketItems.java @@ -10,10 +10,12 @@ public class PrintBasketItems extends PrintGenerator { private Inventory inventory; private Map basketItems; + private double basketTotalCost; - public PrintBasketItems(Inventory inventory, Map basketItems) { + public PrintBasketItems(Inventory inventory, Map basketItems, double basketTotalCost) { this.inventory = inventory; this.basketItems = basketItems; + this.basketTotalCost = basketTotalCost; } @Override @@ -55,7 +57,7 @@ public void print() { System.out.println(divider); System.out.printf( "%s %33s" + newLine, - "Total cost: ", "$?.??" + "Total cost: ", "$"+basketTotalCost ); } System.out.println(divider); From 3c1b7d6fa95f78ebcdba8ebbc143ba76370233a1 Mon Sep 17 00:00:00 2001 From: shyye Date: Fri, 23 Aug 2024 17:16:34 +0200 Subject: [PATCH 67/93] Update imports --- src/main/java/com/booleanuk/core/basket/Basket.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/com/booleanuk/core/basket/Basket.java b/src/main/java/com/booleanuk/core/basket/Basket.java index 7803501d0..3acb0c6a9 100644 --- a/src/main/java/com/booleanuk/core/basket/Basket.java +++ b/src/main/java/com/booleanuk/core/basket/Basket.java @@ -1,8 +1,6 @@ package com.booleanuk.core.basket; -import com.booleanuk.core.PriceCalculationVariant; import com.booleanuk.core.PriceCalculator; -import com.booleanuk.core.inventory.FillingItem; import com.booleanuk.core.inventory.Inventory; import com.booleanuk.core.inventory.InventoryItem; import com.booleanuk.core.printgenerator.PrintBasketItems; From d291f20e50b11aea663aa5715ae4a343ebb3a64e Mon Sep 17 00:00:00 2001 From: shyye Date: Sat, 24 Aug 2024 09:30:02 +0200 Subject: [PATCH 68/93] Clean up --- .../booleanuk/core/inventory/Inventory.java | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/booleanuk/core/inventory/Inventory.java b/src/main/java/com/booleanuk/core/inventory/Inventory.java index 2947d6ea8..655f75efd 100644 --- a/src/main/java/com/booleanuk/core/inventory/Inventory.java +++ b/src/main/java/com/booleanuk/core/inventory/Inventory.java @@ -1,6 +1,8 @@ package com.booleanuk.core.inventory; -import com.booleanuk.core.*; +import com.booleanuk.core.enums.BagelVariant; +import com.booleanuk.core.enums.CoffeeVariant; +import com.booleanuk.core.enums.FillingVariant; import com.booleanuk.core.printgenerator.PrintGenerator; import com.booleanuk.core.printgenerator.PrintInventoryMenu; @@ -11,6 +13,8 @@ public class Inventory { private Map inventoryItems; + // Initialized locally + private PrintGenerator menu; public Inventory() { this.inventoryItems = new HashMap<>(); @@ -26,6 +30,14 @@ private void fillInventory() { // For a more general approach -> Use Dependency Injection: // make product list as input instead of creating it here. + // TODO: A bit weird approach to put it in a list first and then loop. Is it a better way? + // I do this because I auto-generate the SKU value in the superclass 'InventoryItem'. + // So I create all objects (BagelItem, CoffeItem, FillingItem) first, and store in a temporary list + // Then I loop through all items to get the SKU value for each + // I put the SKU value as the key in the HashMap 'inventoryItems'. + // (The SKU value is then both in the objects and as a key) + + // Create list with inventory items ArrayList items = new ArrayList<>(); @@ -69,10 +81,10 @@ public InventoryItem getItem(String SKU) { public void printMenu() { - // TODO: Should this be refactored, not initalize it here - // Problem if so is that I need the inventoryItems + // TODO: Should this be refactored, not initialize it here + // Problem if so is that I need to pass in the inventoryItems - PrintGenerator menu = new PrintInventoryMenu(this.inventoryItems); + menu = new PrintInventoryMenu(this.inventoryItems); menu.print(); } } From e5ad8198d5fc572d60abef733040caed753b46c9 Mon Sep 17 00:00:00 2001 From: shyye Date: Sat, 24 Aug 2024 09:31:05 +0200 Subject: [PATCH 69/93] Moved files, automatic refactor on imports --- src/main/java/com/booleanuk/core/basket/Basket.java | 4 ++-- .../booleanuk/core/{ => calculators}/PriceCalculator.java | 6 +++++- .../com/booleanuk/core/{ => calculators}/SKUCalculator.java | 2 +- .../java/com/booleanuk/core/{ => enums}/BagelVariant.java | 2 +- .../java/com/booleanuk/core/{ => enums}/CoffeeVariant.java | 2 +- .../java/com/booleanuk/core/{ => enums}/FillingVariant.java | 2 +- .../java/com/booleanuk/core/{ => enums}/ProductName.java | 2 +- src/main/java/com/booleanuk/core/inventory/BagelItem.java | 2 +- src/main/java/com/booleanuk/core/inventory/CoffeeItem.java | 2 +- src/main/java/com/booleanuk/core/inventory/FillingItem.java | 2 +- .../java/com/booleanuk/core/inventory/InventoryItem.java | 6 +++--- .../booleanuk/core/printgenerator/PrintInventoryMenu.java | 2 +- 12 files changed, 19 insertions(+), 15 deletions(-) rename src/main/java/com/booleanuk/core/{ => calculators}/PriceCalculator.java (88%) rename src/main/java/com/booleanuk/core/{ => calculators}/SKUCalculator.java (92%) rename src/main/java/com/booleanuk/core/{ => enums}/BagelVariant.java (70%) rename src/main/java/com/booleanuk/core/{ => enums}/CoffeeVariant.java (69%) rename src/main/java/com/booleanuk/core/{ => enums}/FillingVariant.java (76%) rename src/main/java/com/booleanuk/core/{ => enums}/ProductName.java (69%) diff --git a/src/main/java/com/booleanuk/core/basket/Basket.java b/src/main/java/com/booleanuk/core/basket/Basket.java index 3acb0c6a9..b344722cf 100644 --- a/src/main/java/com/booleanuk/core/basket/Basket.java +++ b/src/main/java/com/booleanuk/core/basket/Basket.java @@ -1,6 +1,6 @@ package com.booleanuk.core.basket; -import com.booleanuk.core.PriceCalculator; +import com.booleanuk.core.calculators.PriceCalculator; import com.booleanuk.core.inventory.Inventory; import com.booleanuk.core.inventory.InventoryItem; import com.booleanuk.core.printgenerator.PrintBasketItems; @@ -26,7 +26,7 @@ public Basket(Inventory inventory) { this.maxCapacity = 20; this.size = 0; this.idCount = 1; - this.totalCost = 0.0f; + this.totalCost = 0.0f; //TODO: remove this.priceCalculator = new PriceCalculator(); // Should maybe have dependency injection instead. } diff --git a/src/main/java/com/booleanuk/core/PriceCalculator.java b/src/main/java/com/booleanuk/core/calculators/PriceCalculator.java similarity index 88% rename from src/main/java/com/booleanuk/core/PriceCalculator.java rename to src/main/java/com/booleanuk/core/calculators/PriceCalculator.java index 4417bc085..c841ff5e4 100644 --- a/src/main/java/com/booleanuk/core/PriceCalculator.java +++ b/src/main/java/com/booleanuk/core/calculators/PriceCalculator.java @@ -1,4 +1,4 @@ -package com.booleanuk.core; +package com.booleanuk.core.calculators; public class PriceCalculator { @@ -21,4 +21,8 @@ public double round(float total, int numOfDecimals) { return rounded; } + +// public double combinationDiscount() { +// +// } } diff --git a/src/main/java/com/booleanuk/core/SKUCalculator.java b/src/main/java/com/booleanuk/core/calculators/SKUCalculator.java similarity index 92% rename from src/main/java/com/booleanuk/core/SKUCalculator.java rename to src/main/java/com/booleanuk/core/calculators/SKUCalculator.java index f3fb83300..a1136a7ab 100644 --- a/src/main/java/com/booleanuk/core/SKUCalculator.java +++ b/src/main/java/com/booleanuk/core/calculators/SKUCalculator.java @@ -1,4 +1,4 @@ -package com.booleanuk.core; +package com.booleanuk.core.calculators; public class SKUCalculator { diff --git a/src/main/java/com/booleanuk/core/BagelVariant.java b/src/main/java/com/booleanuk/core/enums/BagelVariant.java similarity index 70% rename from src/main/java/com/booleanuk/core/BagelVariant.java rename to src/main/java/com/booleanuk/core/enums/BagelVariant.java index 87cf5cb80..3db8a8357 100644 --- a/src/main/java/com/booleanuk/core/BagelVariant.java +++ b/src/main/java/com/booleanuk/core/enums/BagelVariant.java @@ -1,4 +1,4 @@ -package com.booleanuk.core; +package com.booleanuk.core.enums; public enum BagelVariant { ONION, diff --git a/src/main/java/com/booleanuk/core/CoffeeVariant.java b/src/main/java/com/booleanuk/core/enums/CoffeeVariant.java similarity index 69% rename from src/main/java/com/booleanuk/core/CoffeeVariant.java rename to src/main/java/com/booleanuk/core/enums/CoffeeVariant.java index 17304f424..8cdb816a6 100644 --- a/src/main/java/com/booleanuk/core/CoffeeVariant.java +++ b/src/main/java/com/booleanuk/core/enums/CoffeeVariant.java @@ -1,4 +1,4 @@ -package com.booleanuk.core; +package com.booleanuk.core.enums; public enum CoffeeVariant { BLACK, diff --git a/src/main/java/com/booleanuk/core/FillingVariant.java b/src/main/java/com/booleanuk/core/enums/FillingVariant.java similarity index 76% rename from src/main/java/com/booleanuk/core/FillingVariant.java rename to src/main/java/com/booleanuk/core/enums/FillingVariant.java index 24d26a706..0770e32d6 100644 --- a/src/main/java/com/booleanuk/core/FillingVariant.java +++ b/src/main/java/com/booleanuk/core/enums/FillingVariant.java @@ -1,4 +1,4 @@ -package com.booleanuk.core; +package com.booleanuk.core.enums; public enum FillingVariant { BACON, diff --git a/src/main/java/com/booleanuk/core/ProductName.java b/src/main/java/com/booleanuk/core/enums/ProductName.java similarity index 69% rename from src/main/java/com/booleanuk/core/ProductName.java rename to src/main/java/com/booleanuk/core/enums/ProductName.java index 700b833b9..533f3b3ae 100644 --- a/src/main/java/com/booleanuk/core/ProductName.java +++ b/src/main/java/com/booleanuk/core/enums/ProductName.java @@ -1,4 +1,4 @@ -package com.booleanuk.core; +package com.booleanuk.core.enums; public enum ProductName { DEFAULT, diff --git a/src/main/java/com/booleanuk/core/inventory/BagelItem.java b/src/main/java/com/booleanuk/core/inventory/BagelItem.java index c33bb8424..2ec89706a 100644 --- a/src/main/java/com/booleanuk/core/inventory/BagelItem.java +++ b/src/main/java/com/booleanuk/core/inventory/BagelItem.java @@ -1,6 +1,6 @@ package com.booleanuk.core.inventory; -import com.booleanuk.core.ProductName; +import com.booleanuk.core.enums.ProductName; public class BagelItem extends InventoryItem { diff --git a/src/main/java/com/booleanuk/core/inventory/CoffeeItem.java b/src/main/java/com/booleanuk/core/inventory/CoffeeItem.java index a0bafe96b..52c641507 100644 --- a/src/main/java/com/booleanuk/core/inventory/CoffeeItem.java +++ b/src/main/java/com/booleanuk/core/inventory/CoffeeItem.java @@ -1,6 +1,6 @@ package com.booleanuk.core.inventory; -import com.booleanuk.core.ProductName; +import com.booleanuk.core.enums.ProductName; public class CoffeeItem extends InventoryItem { diff --git a/src/main/java/com/booleanuk/core/inventory/FillingItem.java b/src/main/java/com/booleanuk/core/inventory/FillingItem.java index 5fab5610a..6174016d4 100644 --- a/src/main/java/com/booleanuk/core/inventory/FillingItem.java +++ b/src/main/java/com/booleanuk/core/inventory/FillingItem.java @@ -1,6 +1,6 @@ package com.booleanuk.core.inventory; -import com.booleanuk.core.ProductName; +import com.booleanuk.core.enums.ProductName; public class FillingItem extends InventoryItem{ diff --git a/src/main/java/com/booleanuk/core/inventory/InventoryItem.java b/src/main/java/com/booleanuk/core/inventory/InventoryItem.java index 7daec73b9..09e272fe6 100644 --- a/src/main/java/com/booleanuk/core/inventory/InventoryItem.java +++ b/src/main/java/com/booleanuk/core/inventory/InventoryItem.java @@ -1,8 +1,8 @@ package com.booleanuk.core.inventory; -import com.booleanuk.core.PriceCalculator; -import com.booleanuk.core.ProductName; -import com.booleanuk.core.SKUCalculator; +import com.booleanuk.core.calculators.PriceCalculator; +import com.booleanuk.core.enums.ProductName; +import com.booleanuk.core.calculators.SKUCalculator; public class InventoryItem { diff --git a/src/main/java/com/booleanuk/core/printgenerator/PrintInventoryMenu.java b/src/main/java/com/booleanuk/core/printgenerator/PrintInventoryMenu.java index 09803f950..59ab73272 100644 --- a/src/main/java/com/booleanuk/core/printgenerator/PrintInventoryMenu.java +++ b/src/main/java/com/booleanuk/core/printgenerator/PrintInventoryMenu.java @@ -1,6 +1,6 @@ package com.booleanuk.core.printgenerator; -import com.booleanuk.core.ProductName; +import com.booleanuk.core.enums.ProductName; import com.booleanuk.core.inventory.InventoryItem; import java.util.Map; From 354d97cfa2d92af0d8b036041df6619b72150ae1 Mon Sep 17 00:00:00 2001 From: shyye Date: Sat, 24 Aug 2024 09:32:08 +0200 Subject: [PATCH 70/93] Update enums, calculators, inventory --- .../java/com/booleanuk/core/domain-model.md | 34 +++++++++++-------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/booleanuk/core/domain-model.md b/src/main/java/com/booleanuk/core/domain-model.md index 3ff72a1d3..27b8e32dd 100644 --- a/src/main/java/com/booleanuk/core/domain-model.md +++ b/src/main/java/com/booleanuk/core/domain-model.md @@ -1,25 +1,29 @@ # Domain Model -## Enums +## Package: enums | Classes | Variables | Methods | Scenario | Output | |------------------|-----------|---------|----------|--------| -| `ProductSKU` | | | | | -| `CoffeeVariant` | | | | | | `BagelVariant` | | | | | +| `CoffeeVariant` | | | | | | `FillingVariant` | | | | | +| `ProductName` | | | | | + +## Package: calculators +| Classes | Variables | Methods | Scenario | Output | +|-------------------|-----------|---------|----------|--------| +| `PriceCalculator` | | | | | +| `SKUCalculator` | | | | | -## Inventory -| Classes | Variables | Methods | Scenario | Output | -|-------------|---------------------------------|-----------------------------------------------------------------|--------------------------------------------------------|------------| -| `Inventory` | `- ArrayList products` | | | | -| | | `-addProduct(String SKU, float price, Enum name, Enum variant)` | Add product to inventory. | - | -| | | `-fillInventory()` | Initialize inventory with specified items. | | -| | | `-getAllCoffee()` | Get a list of all coffee products. | List | -| | | `-getAllBagels()` | Get a list of all bagel products. | List | -| | | `-getAllFillings()` | Get a list of all filling products. | List | -| | | `-calculateSKU(String productName, String productVariant)` | Calculate SKU based on productName and productVariant. | String | -| | | `+getPrice(Enum productName, Enum productVariant)` | Get price by providing SKU | float | -| | | `+printMenu()` | Print meny of all items in inventory. | Print text | +## Package: inventory +| Classes | Variables | Methods | Scenario | Output | +|-------------|-----------------------------------------------|-----------------------------------------------------------------|-----------------------------------------------|------------------------------| +| `Inventory` | `-Map inventoryItems ` | | | | +| | `-PrintGenerator menu` | | | | +| | | `-fillInventory()` | Initialize inventory with specified items. | | +| | | `+getAllItems()` | Get all inventory items. | Map | +| | | `+getItem(String SKU)` | If item is in inventory (valid SKU). | InventoryItem | +| | | | If item does not exist. | throw InventoryItemException | +| | | `+printMenu()` | Print menu with all items from the inventory. | Print to console/terminal | ## Basket | Classes | Variables | Methods | Scenario | Output | From cad76e6ba62e8421ea5579d1002c4f2990857e77 Mon Sep 17 00:00:00 2001 From: shyye Date: Sat, 24 Aug 2024 14:09:44 +0200 Subject: [PATCH 71/93] Update inventory --- .../java/com/booleanuk/core/domain-model.md | 35 ++++++++++++++----- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/booleanuk/core/domain-model.md b/src/main/java/com/booleanuk/core/domain-model.md index 27b8e32dd..275426f2a 100644 --- a/src/main/java/com/booleanuk/core/domain-model.md +++ b/src/main/java/com/booleanuk/core/domain-model.md @@ -15,15 +15,32 @@ | `SKUCalculator` | | | | | ## Package: inventory -| Classes | Variables | Methods | Scenario | Output | -|-------------|-----------------------------------------------|-----------------------------------------------------------------|-----------------------------------------------|------------------------------| -| `Inventory` | `-Map inventoryItems ` | | | | -| | `-PrintGenerator menu` | | | | -| | | `-fillInventory()` | Initialize inventory with specified items. | | -| | | `+getAllItems()` | Get all inventory items. | Map | -| | | `+getItem(String SKU)` | If item is in inventory (valid SKU). | InventoryItem | -| | | | If item does not exist. | throw InventoryItemException | -| | | `+printMenu()` | Print menu with all items from the inventory. | Print to console/terminal | +| Classes | Variables | Methods | Scenario | Output | +|-----------------------------------------------------|-----------------------------------------------|-----------------------------------------|-------------------------------------------------------|------------------------------| +| `Inventory` | `-Map inventoryItems ` | | | | +| | `-PrintGenerator menu` | | | | +| | | `-fillInventory()` | Initialize inventory with specified items. | | +| | | `+getAllItems()` | Get all inventory items. | Map | +| | | `+getItem(String SKU)` | If item is in inventory (valid SKU). | InventoryItem | +| | | | If item does not exist. | throw InventoryItemException | +| | | `+printMenu()` | Print menu with all items from the inventory. | Print to console/terminal | +| | | | | | +| `InventoryItem` | `-String SKU` | `+getSKU()` | | String | +| | | `#setSKU()` | Set SKU based on name and variant. | String | +| | `-float price` | `+getPrice()` | Get price calculated with PriceCalculator.round(). | double | +| | | `#setPrice(float price)` | Set price. | - | +| | `-ProductName name` | `+getName()` | Get product name. | ProductName | +| | | `#setName()` | Set product name. | ProductName | +| | `-Enum variant` | `+getVariant(Enum variant)` | Get product variant (DEFAULT, COFFE, BAGEL, FILLING). | Enum | +| | | `#setVariant()` | Set product variant. | - | +| | `-SKUCalculator skuCalculator` | | | | +| | `-PriceCalculator priceCalculator` | | | | +| | | | | | +| `CoffeeItem` extends `InventoryItem` | @Ovverride `+setName()` | | | ProductName | +| `BagelItem` extends `InventoryItem` | @Ovverride `+setName()` | | | ProductName | +| `FillingItem` extends `InventoryItem` | @Ovverride `+setName()` | | | ProductName | +| | | | | | +| `InventoryItemException` extends `RuntimeException` | | | | | ## Basket | Classes | Variables | Methods | Scenario | Output | From 14ed5db40f51df8dfbf8242a8d64ecc762bffefe Mon Sep 17 00:00:00 2001 From: shyye Date: Sat, 24 Aug 2024 14:11:10 +0200 Subject: [PATCH 72/93] Update inventory --- .../booleanuk/core/inventory/InventoryItem.java | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/booleanuk/core/inventory/InventoryItem.java b/src/main/java/com/booleanuk/core/inventory/InventoryItem.java index 09e272fe6..ebb48364d 100644 --- a/src/main/java/com/booleanuk/core/inventory/InventoryItem.java +++ b/src/main/java/com/booleanuk/core/inventory/InventoryItem.java @@ -8,14 +8,15 @@ public class InventoryItem { // TODO: should I change this to protected? // TODO should I change this to abstract? Check if possible. + // TODO: Change 'float price' to double? Or keep float as it takes up less memory? - private String SKU; + private final String SKU; private float price; - private ProductName name; + private final ProductName name; private Enum variant; - private SKUCalculator skuCalculator; - private PriceCalculator priceCalculator; + private final SKUCalculator skuCalculator; + private final PriceCalculator priceCalculator; public InventoryItem(float price, Enum variant) { @@ -34,7 +35,7 @@ public String getSKU() { return SKU; } - public String setSKU() { + protected String setSKU() { return skuCalculator.getSKU(name, variant); } @@ -42,7 +43,7 @@ public double getPrice() { return priceCalculator.round(price, 2); } - public void setPrice(float price) { + protected void setPrice(float price) { this.price = price; } @@ -50,7 +51,7 @@ public ProductName getName() { return name; } - public ProductName setName() { + protected ProductName setName() { return ProductName.DEFAULT; } @@ -58,7 +59,7 @@ public Enum getVariant() { return variant; } - public void setVariant(Enum variant) { + protected void setVariant(Enum variant) { this.variant = variant; } } From f34d364df4579360b52ba4cadd574f9c08225425 Mon Sep 17 00:00:00 2001 From: shyye Date: Sat, 24 Aug 2024 16:10:46 +0200 Subject: [PATCH 73/93] Re-order methods and members --- .../com/booleanuk/core/basket/Basket.java | 126 ++++++++++-------- 1 file changed, 69 insertions(+), 57 deletions(-) diff --git a/src/main/java/com/booleanuk/core/basket/Basket.java b/src/main/java/com/booleanuk/core/basket/Basket.java index b344722cf..8da4f8067 100644 --- a/src/main/java/com/booleanuk/core/basket/Basket.java +++ b/src/main/java/com/booleanuk/core/basket/Basket.java @@ -14,19 +14,19 @@ public class Basket { private Inventory inventory; private Map basketItems; - private int maxCapacity; - private int size; private int idCount; - private float totalCost; + private int size; + private int maxCapacity; + private PriceCalculator priceCalculator; + private PrintGenerator basket; public Basket(Inventory inventory) { this.inventory = inventory; this.basketItems = new LinkedHashMap <>(); // LinkedHashMap because I want the items in the order they were added to the basket - this.maxCapacity = 20; - this.size = 0; this.idCount = 1; - this.totalCost = 0.0f; //TODO: remove + this.size = 0; + this.maxCapacity = 20; this.priceCalculator = new PriceCalculator(); // Should maybe have dependency injection instead. } @@ -38,8 +38,10 @@ private int createId() { return itemId; } + // Auto create ID for fillings private int createFillingId(String idExtension) { - //TODO: How to make default variable like in python + + // TODO: How to make default variable like in python // TODO: Should check if idExtension is valid @@ -53,8 +55,39 @@ private int createFillingId(String idExtension) { return Integer.parseInt(tmp); } + // Get Basket size + public int getSize() { + return size; + } + + // Get max capacity, max amount of products allowed in basket. + // Fillings doesn't count as an item, and fillings can only be added together with a Bagel. + public int getMaxCapacity() { + return this.maxCapacity; + } + + // Change max capacity + // TODO: Should make sure that newMaxCapacity is not a negative value + public void changeMaxCapacity(int newMaxCapacity) { + this.maxCapacity = newMaxCapacity; + } + + // Get all basket items + public Map getAll() { + return this.basketItems; + } + // Get basket item based on id. + protected BasketItem getBasketItem(int itemId) { + BasketItem item = this.basketItems.get(itemId); + if (item == null) { + throw new InvalidBasketItemException("Basket item with ID #" + itemId + ", doesn't exist. Can't remove from basket."); + } + return item; + } + // Inner function for add() + // Validates input protected void addToBasket(int itemId, BasketItem item) { // Validate input if (this.getSize() == maxCapacity) { @@ -62,6 +95,7 @@ protected void addToBasket(int itemId, BasketItem item) { } // TODO: Add exception for when id already exist + // TODO: Can use 'instanceof' instead of checking class name? // Fillings can not be added as an item itself // Fillings that belongs to a bagel have id's over 100 @@ -71,33 +105,14 @@ protected void addToBasket(int itemId, BasketItem item) { // Set id if no exception has been thrown item.setId(itemId); - // Update size of basket - this.size++; - // Add item to basket - this.basketItems.put(item.getId(), item); - } - protected void removeFromBasket(int itemId) { - if (basketItems.get(itemId) == null) { - throw new InvalidBasketItemException("Basket item with ID #" + itemId + ", doesn't exist. Can't remove from basket."); - } - this.basketItems.remove(itemId); - } + this.basketItems.put(item.getId(), item); - // TODO: Check where get item functionality is used and replace with this function - // This exception is trown both here and in the above method, how to reduce duplication in best way? - protected BasketItem getBasketItem(int itemId) { - BasketItem item = this.basketItems.get(itemId); - if (item == null) { - throw new InvalidBasketItemException("Basket item with ID #" + itemId + ", doesn't exist. Can't remove from basket."); - } - return item; + // Update size of basket + this.size++; } - /** - * Add item to basket, auto creates ID. - * @param item id - */ + // Add BasketItem (Coffee Bagel or Filling) to basket public void add(BasketItem item) { try { @@ -145,6 +160,19 @@ public void add(BasketItem item) { } } + // Inner function for remove() + // Validates input + protected void removeFromBasket(int itemId) { + if (basketItems.get(itemId) == null) { + throw new InvalidBasketItemException("Basket item with ID #" + itemId + ", doesn't exist. Can't remove from basket."); + } + this.basketItems.remove(itemId); + + // Update size of basket + this.size--; + } + + // Remove item from basket based on id. public void remove(int itemId) { try { @@ -172,33 +200,7 @@ public void remove(int itemId) { } } - public Map getAll() { - return this.basketItems; - } - - public int getSize() { - return size; - } - - public void printBasket() { - - // TODO: Should I refactor? Feels like it's a poor solution regarding dependencies. - // Check all PrintGenerator cases. - - PrintGenerator basket = new PrintBasketItems(this.inventory, this.basketItems, this.getTotalCost()); - basket.print(); - } - - // TODO: I only use this for the test. Should I keep it or change the test? - public int getMaxCapacity() { - return this.maxCapacity; - } - - // TODO: Should I do a get/setfunctions on maxCapacity or is this ok? - public void changeMaxCapacity(int newMaxCapacity) { - this.maxCapacity = newMaxCapacity; - } - + // Get total cost of all items in basket public double getTotalCost() { // TODO Changed to double, this may be unnecessary now @@ -212,4 +214,14 @@ public double getTotalCost() { } return priceCalculator.round(total, 2); } + + // Print basket with items and total cost. + public void printBasket() { + + // TODO: Should I refactor? Feels like it's a poor solution regarding dependencies. + // Check all PrintGenerator cases. + + basket = new PrintBasketItems(this.inventory, this.basketItems, this.getTotalCost()); + basket.print(); + } } From 4bed7c6319f63a38cc7b7f1c0e8c004243615716 Mon Sep 17 00:00:00 2001 From: shyye Date: Sat, 24 Aug 2024 16:27:02 +0200 Subject: [PATCH 74/93] Re-order class members --- src/main/java/com/booleanuk/core/basket/BasketItem.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/booleanuk/core/basket/BasketItem.java b/src/main/java/com/booleanuk/core/basket/BasketItem.java index 7bed8bd5e..51bbdf50b 100644 --- a/src/main/java/com/booleanuk/core/basket/BasketItem.java +++ b/src/main/java/com/booleanuk/core/basket/BasketItem.java @@ -2,8 +2,8 @@ public class BasketItem { - private String SKU; private int Id; + private String SKU; public BasketItem(String SKU) { this.Id = -1; From 2649fdea9f928eb872e814dbe6184fe088219778 Mon Sep 17 00:00:00 2001 From: shyye Date: Sat, 24 Aug 2024 16:36:00 +0200 Subject: [PATCH 75/93] Small fix --- src/main/java/com/booleanuk/core/basket/Bagel.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/booleanuk/core/basket/Bagel.java b/src/main/java/com/booleanuk/core/basket/Bagel.java index 263051574..739a73a73 100644 --- a/src/main/java/com/booleanuk/core/basket/Bagel.java +++ b/src/main/java/com/booleanuk/core/basket/Bagel.java @@ -17,7 +17,7 @@ public Bagel(String SKU) { public Bagel(String SKU, List linkedFillingsSKUs) { super(SKU); this.linkedFillingSKUs = linkedFillingsSKUs; - linkedFillingIds = new ArrayList<>(); + this.linkedFillingIds = new ArrayList<>(); } public List getLinkedFillingSKUs() { From daa8c030d01bbef4113fda8329ac557cf9bc2df6 Mon Sep 17 00:00:00 2001 From: shyye Date: Sat, 24 Aug 2024 16:39:25 +0200 Subject: [PATCH 76/93] Update domain model --- .../java/com/booleanuk/core/domain-model.md | 77 +++++++++---------- 1 file changed, 36 insertions(+), 41 deletions(-) diff --git a/src/main/java/com/booleanuk/core/domain-model.md b/src/main/java/com/booleanuk/core/domain-model.md index 275426f2a..7daf4463c 100644 --- a/src/main/java/com/booleanuk/core/domain-model.md +++ b/src/main/java/com/booleanuk/core/domain-model.md @@ -42,48 +42,43 @@ | | | | | | | `InventoryItemException` extends `RuntimeException` | | | | | -## Basket -| Classes | Variables | Methods | Scenario | Output | -|----------|---------------------------------|----------------------------------------|---------------------------------------------------------------------------------------------------------------|-----------------| -| `Basket` | `- static int idCount` | | "Fake autoincrement id". Counter which will be increased everytime a new product is added to the basket. | | -| | `- ArrayList products` | `addCoffee(enum variant)` | Add coffee with specified variant. Then run printBasket(). | | -| | | | Can't add coffee. | throw exception | -| | | `addBagel(enum variant, enum filling)` | Add bagel with specified variant and filling. At the moment just one filling can be added. run printBasket(). | | -| | | | Can't add bagel. | throw exception | -| | | `remove(int ProduktId)` | Product is in basket and can be removed. | Show message | -| | | | Product is not in basket and can not be removed. | throw exception | -| | `int maxCapacity` | `changeCapacity(int newCapacity)` | If newCapacity is more than 0. | true | -| | | | If newCapacity is less than 1. | false | -| | `float totalCost` | `setTotalCost(float newTotalCost)` | | | -| | | `getTotalCost()` | Get total cost of all products. | float | -| | | `printBasket()` | Prints the content of the basket. | Print text | -| | | `getAll()` | Get all products in basket. | List | +## Package: basket +| Classes | Variables | Methods | Scenario | Output | +|--------------------------------|-----------------------------------------|---------------------------------------------|--------------------------------------------------------------------------------------------------------------------|--------------------------------------------------| +| `Basket(Inventory inventory)` | `-Inventory inventory` | | | | +| | `-Map basketItems` | `+getAll()` | Get all basket items. | Map | +| | | `#getBasketItem(int itemId)` | If item exist. | BasketItem | +| | | | If items doesn't exist. | throw InvalidBasketItemException | +| | | `#addToBasket(int itemId, BasketItem item)` | Inner function for add(), validates input. Add item to basket if possible. | | +| | | | If item can't be added, notify with error. | MaxCapacityException, InvalidBasketItemException | +| | | `+add(BasketItem item)` | Make a request to `#addToBasket(int itemId, BasketItem item)`. | - | +| | | | If exception is thrown, handle exception. | Print exception to console/terminal | +| | | `#removeFromBasket(int itemId)` | Inner function for remove(). If valid item id, remove item from basket. | | +| | | | if not valid item id, notify with error. | InvalidBasketItemException | +| | | `+remove(int itemId)` | Make a request to `#removeFromBasket(int itemId)`. Remove item if possible. | | +| | | | If exception is thrown, handle exception. | Print exception to console/terminal | +| | | `+getTotalCost()` | Get total cost of all items in basket. | double | +| | | `+printBasket()` | Print content of basket and total price. | Print to console/terminal | +| | `-int idCount` | `-createId()` | "Auto" creates Id for basket items except filling Ids. E.g. returns id 1. | int | +| | | `-createFillingId(String idExtension)` | "Auto" creates id for filling based on the bagels id. E.g. Bagel id: 1, filling id: 101. | int | +| | `-int size` | `+getSize()` | Get the counted size of basket
(fillings doesn't count as an item and can only be added together with a Bagel). | int | +| | `-int maxCapacity` | `+getMaxCapacity()` | Get max capacity of basket. | int | +| | | `+changeMaxCapacity(int newMaxCapacity)` | Change max capacity. | - | +| | `-PriceCalculator priceCalculator` | | | | +| | `-PrintGenerator basket` | | | | +| | | | | | +| `BasketItem(String SKU)` | `-int Id` | `+setId(int itemId)` | | | +| | | `+getId(int itemId)` | | int | +| | `-String SKU` | `+getSKU()` | | String | +| | | | | | +| `Coffee` extends `BasketItem` | | | | | +| `Bagel` extends `BasketItem` | `-List linkedFillingSKUs` | `+getLinkedFillingSKUs` | Get a list of inventory item SKU's that was added together with this bagel. | List | +| | `-List linkedFillingIds` | `getLinkedFillingIds` | Get a list of basket item ids' (the ids' of the fillings that belongs to this bagel). | List | +| `Filling` extends `BasketItem` | | | | | +| | | | | | +| `InvalidBasketItemException` | | | | | +| `MaxCapacityException` | | | | | -## Product -| Classes | Variables | Methods | Scenario | Output | -|-----------|----------------|--------------|------------------------------------|--------| -| `Product` | `int id` | | | | -| | `enum SKU` | | | | -| | `float price` | | | | -| | `enum name` | | | | -| | `enum variant` | | | | -| | | `setSKU()` | Set SKU based on name and variant. | - | -| | | `getPrice()` | Get price for this product. | float | - -## Coffee extends Product (Inherit) -| Classes | Variables | Methods | Scenario | Output | -|---------|-----------|----------------------|-------------------------------------|--------| -| `Coffe` | | `@override setSKU()` | | | - -## Bagel extends Product (Inherit) -| Classes | Variables | Methods | Scenario | Output | -|---------|-----------|-----------------------|-------------------------------------|--------| -| `Bagel` | | `@override setSKU()` | | | - -## Filling extends Product (Inherit) -| Classes | Variables | Methods | Scenario | Output | -|-----------|-----------|-----------------------|-------------------------------------|--------| -| `Filling` | | `@override setSKU()` | | | # Class Diagram ## Diagram From a93bd75d9fe538406d039492c598901c679949c0 Mon Sep 17 00:00:00 2001 From: shyye Date: Sat, 24 Aug 2024 19:37:12 +0200 Subject: [PATCH 77/93] Update domain model with printgenerator classes --- src/main/java/com/booleanuk/core/domain-model.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/main/java/com/booleanuk/core/domain-model.md b/src/main/java/com/booleanuk/core/domain-model.md index 7daf4463c..3075dcc99 100644 --- a/src/main/java/com/booleanuk/core/domain-model.md +++ b/src/main/java/com/booleanuk/core/domain-model.md @@ -79,6 +79,19 @@ | `InvalidBasketItemException` | | | | | | `MaxCapacityException` | | | | | +## Package: printgenerator +| Classes | Variables | Methods | Scenario | Output | +|-----------------------------------------------|---------------------------------------------|-------------------------------------------------------------------------|-----------------------------------------|--------| +| `PrintGenerator` | | `printCenterTitle(String text, int totalWidth)` | Center test in console/terminal output. | | +| | ` | `print()` | | | +| | | | | | +| `PrintInventoryMenu` extends `PrintGenerator` | `Map inventoryItems` | `printMenuPart(ProductName productName, String title, int outputWidth)` | | | +| | | @Override `print()` | | | +| | | | | | +| `PrintBasketItems` extends `PrintGenerator` | `Inventory inventory` | | | | +| | `Map basketItems` | | | | +| | `double basketTotalCost` | | | | +| | | @Override `print()` | | | # Class Diagram ## Diagram From 63611aee2b2708fce58a1ca308f9cafe3d4ccd15 Mon Sep 17 00:00:00 2001 From: shyye Date: Sun, 25 Aug 2024 11:05:57 +0200 Subject: [PATCH 78/93] Add Text: calcualte discount --- .../core/calculators/PriceCalculatorTest.java | 131 ++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 src/test/java/com/booleanuk/core/calculators/PriceCalculatorTest.java diff --git a/src/test/java/com/booleanuk/core/calculators/PriceCalculatorTest.java b/src/test/java/com/booleanuk/core/calculators/PriceCalculatorTest.java new file mode 100644 index 000000000..9caa625ee --- /dev/null +++ b/src/test/java/com/booleanuk/core/calculators/PriceCalculatorTest.java @@ -0,0 +1,131 @@ +package com.booleanuk.core.calculators; + +import com.booleanuk.core.basket.Bagel; +import com.booleanuk.core.basket.Basket; +import com.booleanuk.core.basket.BasketItem; +import com.booleanuk.core.basket.Coffee; +import com.booleanuk.core.inventory.Inventory; +import com.booleanuk.core.inventory.SpecialOffer; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Map; + +public class PriceCalculatorTest { + PriceCalculator priceCalculator; + Inventory inventory; + Basket basket; + + @Test + public void calculateBagelOnionDicountShouldGetDiscount() { + inventory = new Inventory(); + ArrayList specialOffers = inventory.getSpecialOffers(); + + basket = new Basket(new Inventory()); + for (int i = 0; i < 6; i++) { + basket.add(new Bagel("BAGO")); + } + + Map basketItems = basket.getAll(); + + priceCalculator = new PriceCalculator(); + double discount = priceCalculator.calculateDiscount(inventory, basketItems, specialOffers); + + // Standard price 6 * 0.49 = 2.94 + // Discount 2.94 - 2.49 = 0.45 + Assertions.assertEquals(0.45, discount); + } + + @Test + public void calculateBagelOnionDicountShouldNotGetDiscountForFiveBagels() { + inventory = new Inventory(); + ArrayList specialOffers = inventory.getSpecialOffers(); + + basket = new Basket(new Inventory()); + for (int i = 0; i < 5; i++) { + basket.add(new Bagel("BAGO")); + } + + Map basketItems = basket.getAll(); + + priceCalculator = new PriceCalculator(); + double discount = priceCalculator.calculateDiscount(inventory, basketItems, specialOffers); + Assertions.assertEquals(0.0, discount); + } + + @Test + public void calculateBagelOnionDicountShouldGetDiscountOnlyForSixBagels() { + inventory = new Inventory(); + ArrayList specialOffers = inventory.getSpecialOffers(); + + basket = new Basket(new Inventory()); + for (int i = 0; i < 7; i++) { + basket.add(new Bagel("BAGO")); + } + + Map basketItems = basket.getAll(); + + priceCalculator = new PriceCalculator(); + double discount = priceCalculator.calculateDiscount(inventory, basketItems, specialOffers); + + // Standard price 6 * 0.49 = 2.94 + // Discount 2.94 - 2.49 = 0.45 + Assertions.assertEquals(0.45, discount); + } + + @Test + public void calculateBagelPlainDicountShouldGetDiscountForTwelveBagels() { + inventory = new Inventory(); + ArrayList specialOffers = inventory.getSpecialOffers(); + + basket = new Basket(new Inventory()); + for (int i = 0; i < 12; i++) { + basket.add(new Bagel("BAGP")); + } + + Map basketItems = basket.getAll(); + + priceCalculator = new PriceCalculator(); + double discount = priceCalculator.calculateDiscount(inventory, basketItems, specialOffers); + + // Standard price 12 * 0.39 = 4.68 + // Discount 4.68 - 3.99 = 0.69 + Assertions.assertEquals(0.69, discount); + } + + @Test + public void calculateCombinationDiscountShouldReturnDiscount() { + inventory = new Inventory(); + ArrayList specialOffers = inventory.getSpecialOffers(); + + basket = new Basket(new Inventory()); + basket.add(new Coffee("COFB")); + basket.add(new Bagel("BAGE", Arrays.asList("FILS","FILB"))); + basket.add(new Bagel("BAGP")); + + Map basketItems = basket.getAll(); + + priceCalculator = new PriceCalculator(); + double discount = priceCalculator.calculateDiscount(inventory, basketItems, specialOffers); + + // Special offer for COFB: Coffee + Bagel for 1.25 + + + // TODO: If special offers are added to other coffee types, this test will not work + // Coffee + Cheapest Bagel = 0.99 + 0.39 = 1.38 + // Coffee + other Bagel = 0.99 + 0.49 = 1,48 + + // Should use discount on cheapest Bagel first + Assertions.assertEquals(1.38, discount); + } + + + + + + // TODO: + // Check why BGLO doesn't exist - WRITE IN README THAT I HAVE DIFFERENT SKU's + // Work with calculateDiscount() +} From aed5832b74247be182c392248eb0a16cbec18241 Mon Sep 17 00:00:00 2001 From: shyye Date: Sun, 25 Aug 2024 11:06:36 +0200 Subject: [PATCH 79/93] Add special offers to Inventory --- .../booleanuk/core/inventory/Inventory.java | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/main/java/com/booleanuk/core/inventory/Inventory.java b/src/main/java/com/booleanuk/core/inventory/Inventory.java index 655f75efd..29c9c429a 100644 --- a/src/main/java/com/booleanuk/core/inventory/Inventory.java +++ b/src/main/java/com/booleanuk/core/inventory/Inventory.java @@ -3,6 +3,7 @@ import com.booleanuk.core.enums.BagelVariant; import com.booleanuk.core.enums.CoffeeVariant; import com.booleanuk.core.enums.FillingVariant; +import com.booleanuk.core.enums.ProductName; import com.booleanuk.core.printgenerator.PrintGenerator; import com.booleanuk.core.printgenerator.PrintInventoryMenu; @@ -13,12 +14,14 @@ public class Inventory { private Map inventoryItems; + private ArrayList specialOffers; // Initialized locally private PrintGenerator menu; public Inventory() { this.inventoryItems = new HashMap<>(); fillInventory(); + createSpecialOffers(); } /** @@ -64,10 +67,37 @@ private void fillInventory() { } } + // Create special offers + private void createSpecialOffers() { + + specialOffers = new ArrayList<>(); + + // Special offers + SpecialOffer BAGOsixMultiPriceOffer = new SpecialOfferMultiPrice("BAGO", 6,2.49); + SpecialOffer BAGEsixMultiPriceOffer = new SpecialOfferMultiPrice("BAGE",6,2.49); + SpecialOffer BAGPtwelveMultiPriceOffer = new SpecialOfferMultiPrice("BAGP", 12,3.99); + + ArrayList offerItems = new ArrayList<>() {{ + add(ProductName.COFFEE); + add(ProductName.BAGEL); + }}; + SpecialOffer coffeAndBagelOffer = new SpecialOfferCombination("COFB", offerItems, 1.25); + + this.specialOffers.add(BAGOsixMultiPriceOffer); + this.specialOffers.add(BAGEsixMultiPriceOffer); + this.specialOffers.add(BAGPtwelveMultiPriceOffer); + this.specialOffers.add(coffeAndBagelOffer); + } + public Map getAllItems() { return inventoryItems; } + // Get all special offers + public ArrayList getSpecialOffers() { + return specialOffers; + } + public InventoryItem getItem(String SKU) { // TODO: Should SKU be converted to uppercase here? From 2eedc4bf5196e74ed60702cfeda5928586e237c7 Mon Sep 17 00:00:00 2001 From: shyye Date: Sun, 25 Aug 2024 11:06:56 +0200 Subject: [PATCH 80/93] Add special offer classes --- .../core/inventory/SpecialOffer.java | 28 +++++++++++++++++++ .../inventory/SpecialOfferCombination.java | 27 ++++++++++++++++++ .../inventory/SpecialOfferMultiPrice.java | 23 +++++++++++++++ 3 files changed, 78 insertions(+) create mode 100644 src/main/java/com/booleanuk/core/inventory/SpecialOffer.java create mode 100644 src/main/java/com/booleanuk/core/inventory/SpecialOfferCombination.java create mode 100644 src/main/java/com/booleanuk/core/inventory/SpecialOfferMultiPrice.java diff --git a/src/main/java/com/booleanuk/core/inventory/SpecialOffer.java b/src/main/java/com/booleanuk/core/inventory/SpecialOffer.java new file mode 100644 index 000000000..737d3d879 --- /dev/null +++ b/src/main/java/com/booleanuk/core/inventory/SpecialOffer.java @@ -0,0 +1,28 @@ +package com.booleanuk.core.inventory; + +public abstract class SpecialOffer { + + private String SKU; + private double offerPrice; + + public SpecialOffer(String SKU, double offerPrice) { + this.offerPrice = offerPrice; + this.SKU = SKU; + } + + public String getSKU() { + return SKU; + } + + public void setSKU(String SKU) { + this.SKU = SKU; + } + + public double getOfferPrice() { + return offerPrice; + } + + public void setOfferPrice(double offerPrice) { + this.offerPrice = offerPrice; + } +} diff --git a/src/main/java/com/booleanuk/core/inventory/SpecialOfferCombination.java b/src/main/java/com/booleanuk/core/inventory/SpecialOfferCombination.java new file mode 100644 index 000000000..8750cf587 --- /dev/null +++ b/src/main/java/com/booleanuk/core/inventory/SpecialOfferCombination.java @@ -0,0 +1,27 @@ +package com.booleanuk.core.inventory; + +import com.booleanuk.core.enums.ProductName; + +import java.util.ArrayList; + +public class SpecialOfferCombination extends SpecialOffer{ + + private ArrayList offerItems; // List of items that in combination generates an offer + + public SpecialOfferCombination(String SKU, double offerPrice) { + super(SKU, offerPrice); + } + + public SpecialOfferCombination(String SKU, ArrayList offerItems, double offerPrice) { + super(SKU, offerPrice); + this.offerItems = offerItems; + } + + public ArrayList getOfferItems() { + return offerItems; + } + + public void setOfferItems(ArrayList offerItems) { + this.offerItems = offerItems; + } +} diff --git a/src/main/java/com/booleanuk/core/inventory/SpecialOfferMultiPrice.java b/src/main/java/com/booleanuk/core/inventory/SpecialOfferMultiPrice.java new file mode 100644 index 000000000..aeef664fe --- /dev/null +++ b/src/main/java/com/booleanuk/core/inventory/SpecialOfferMultiPrice.java @@ -0,0 +1,23 @@ +package com.booleanuk.core.inventory; + +public class SpecialOfferMultiPrice extends SpecialOffer{ + + private int numOfItems; + + public SpecialOfferMultiPrice(String SKU, double offerPrice) { + super(SKU, offerPrice); + } + + public SpecialOfferMultiPrice(String SKU, int numOfItems, double offerPrice) { + super(SKU, offerPrice); + this.numOfItems = numOfItems; + } + + public int getNumOfItems() { + return numOfItems; + } + + public void setNumOfItems(int numOfItems) { + this.numOfItems = numOfItems; + } +} From a85822c6d5567c001d663a8f2db543101ce58404 Mon Sep 17 00:00:00 2001 From: shyye Date: Sun, 25 Aug 2024 11:08:28 +0200 Subject: [PATCH 81/93] Add calculateDiscount to PriceCalcualtor --- .../core/calculators/PriceCalculator.java | 112 +++++++++++++++++- 1 file changed, 109 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/booleanuk/core/calculators/PriceCalculator.java b/src/main/java/com/booleanuk/core/calculators/PriceCalculator.java index c841ff5e4..7803511fd 100644 --- a/src/main/java/com/booleanuk/core/calculators/PriceCalculator.java +++ b/src/main/java/com/booleanuk/core/calculators/PriceCalculator.java @@ -1,5 +1,13 @@ package com.booleanuk.core.calculators; +import com.booleanuk.core.basket.BasketItem; +import com.booleanuk.core.enums.ProductName; +import com.booleanuk.core.inventory.*; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + public class PriceCalculator { // TODO: How to write a class comment? @@ -22,7 +30,105 @@ public double round(float total, int numOfDecimals) { return rounded; } -// public double combinationDiscount() { -// -// } + public double calculateDiscount(Inventory inventory, Map basketItems, ArrayList specialOffers) { + + double discount = 0; + + // Convert special offers to Hashmap + HashMap specialOfferMap = new HashMap<>(); + for (SpecialOffer s : specialOffers) { + specialOfferMap.put(s.getSKU(), s); + } + + // Count occurrences of discount items + HashMap discountItems = new HashMap<>(); + for (BasketItem item : basketItems.values()) { + + String key_sku = item.getSKU(); + + // Store the SKU as key, and count how many times it occurs for SKU's that have special offers + SpecialOffer offer = specialOfferMap.get(key_sku); + if (offer != null) { + + if (discountItems.get(key_sku) == null) { + discountItems.put(key_sku, 1); + } else { + int numOfItems = discountItems.get(key_sku); + discountItems.put(key_sku, numOfItems + 1); + } + } + } + + for (Map.Entry item : discountItems.entrySet()) { + + SpecialOffer offer = specialOfferMap.get(item.getKey()); + + // The special price for the offer, and number of items in this basket that has that offer + double specialPrice = offer.getOfferPrice(); + int numOfBasketItems = item.getValue(); + + + // + // Multi-Price Offer + // + if (offer instanceof SpecialOfferMultiPrice) { + + SpecialOfferMultiPrice multiPriceOffer = (SpecialOfferMultiPrice) offer; + + // Get number of items required to get the offer + int minimumNumOfItems = multiPriceOffer.getNumOfItems(); + + if (numOfBasketItems < minimumNumOfItems) { + // Too few items, no offer + break; + } + + // Count how many discounts + int numOfDiscounts = Math.floorDiv(numOfBasketItems, minimumNumOfItems); + + // Get ordinary price for the item, from the inventory + double itemPrice = inventory.getItem(item.getKey()).getPrice(); + double ordinaryPrice = minimumNumOfItems * itemPrice; + double diffPrice = ordinaryPrice - specialPrice; + + // Calculate total discount for this offer + // add to discount + discount += numOfDiscounts * diffPrice; + + + // + // Combination Offer + // + } else if (offer instanceof SpecialOfferCombination) { + + // TODO: I will assume that the offer Coffee + Bagel for 1.25, includes all coffee types and all bagel types. + + SpecialOfferCombination combinationOffer = (SpecialOfferCombination) offer; + + // Get combination of items required to get the offer + ArrayList offerItems = combinationOffer.getOfferItems(); + + // Store the number of occurrences for each offerItem (ProductName type) + HashMap> offerItemOccurrences = new HashMap<>(); + + for (ProductName productName : offerItems) { + for (BasketItem b : basketItems.values()) { + + String b_SKU = b.getSKU(); + InventoryItem inventoryItem = inventory.getItem(b_SKU); + + if (productName == inventoryItem.getName()){ + + } + } + } + + + } + } + + // TODO: instead of casting to float, change float to double in rest of the program + + return this.round((float) discount, 2); + } } From 4956c84947a821992e7c2110906584f43afa9016 Mon Sep 17 00:00:00 2001 From: shyye Date: Sun, 25 Aug 2024 17:12:47 +0200 Subject: [PATCH 82/93] Update test --- .../core/calculators/PriceCalculatorTest.java | 143 +++++++++++------- 1 file changed, 87 insertions(+), 56 deletions(-) diff --git a/src/test/java/com/booleanuk/core/calculators/PriceCalculatorTest.java b/src/test/java/com/booleanuk/core/calculators/PriceCalculatorTest.java index 9caa625ee..7200b9f48 100644 --- a/src/test/java/com/booleanuk/core/calculators/PriceCalculatorTest.java +++ b/src/test/java/com/booleanuk/core/calculators/PriceCalculatorTest.java @@ -6,6 +6,7 @@ import com.booleanuk.core.basket.Coffee; import com.booleanuk.core.inventory.Inventory; import com.booleanuk.core.inventory.SpecialOffer; +import com.booleanuk.core.inventory.SpecialOfferMultiPrice; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -21,105 +22,135 @@ public class PriceCalculatorTest { @Test public void calculateBagelOnionDicountShouldGetDiscount() { inventory = new Inventory(); - ArrayList specialOffers = inventory.getSpecialOffers(); + ArrayList specialOffers = inventory.getSpecialOffersMultiPrice(); basket = new Basket(new Inventory()); for (int i = 0; i < 6; i++) { basket.add(new Bagel("BAGO")); } - + for (int i = 0; i < 12; i++) { + basket.add(new Bagel("BAGP")); + } Map basketItems = basket.getAll(); + // TODO : Looks confusing with dependecies and names priceCalculator = new PriceCalculator(); - double discount = priceCalculator.calculateDiscount(inventory, basketItems, specialOffers); + ArrayList discountList = priceCalculator.calculateSpecialOfferMultiPrice( + inventory, basketItems, specialOffers); + + // Print values + for (DiscountObjectMultiPrice d : discountList) { + System.out.println("SKU: "+d.getSKU() + + ", x"+d.getNumOfDiscountItems()+" items gives" + + " x"+d.getNumberOfDiscounts()+" discounts" + + ", ordinary items x"+d.getNumOfOrdinaryItems() + + ", discount: "+d.getDiscount()); + } // Standard price 6 * 0.49 = 2.94 // Discount 2.94 - 2.49 = 0.45 - Assertions.assertEquals(0.45, discount); + Assertions.assertEquals(1, discountList.get(1).getNumberOfDiscounts()); + Assertions.assertEquals(6, discountList.get(1).getNumOfDiscountItems()); + Assertions.assertEquals(0, discountList.get(1).getNumOfOrdinaryItems()); + Assertions.assertEquals(0.45, discountList.get(1).getDiscount()); + + // Standard price 12 * 0.39 = 4.68 + // Discount 4.68 - 3.99 = 0.69 + Assertions.assertEquals(1, discountList.get(0).getNumberOfDiscounts()); + Assertions.assertEquals(12, discountList.get(0).getNumOfDiscountItems()); + Assertions.assertEquals(0, discountList.get(0).getNumOfOrdinaryItems()); + Assertions.assertEquals(0.69, discountList.get(0).getDiscount()); } @Test public void calculateBagelOnionDicountShouldNotGetDiscountForFiveBagels() { inventory = new Inventory(); - ArrayList specialOffers = inventory.getSpecialOffers(); + ArrayList specialOffers = inventory.getSpecialOffersMultiPrice(); basket = new Basket(new Inventory()); for (int i = 0; i < 5; i++) { basket.add(new Bagel("BAGO")); } - Map basketItems = basket.getAll(); + // Setup calculation and print result priceCalculator = new PriceCalculator(); - double discount = priceCalculator.calculateDiscount(inventory, basketItems, specialOffers); - Assertions.assertEquals(0.0, discount); + ArrayList discountList = priceCalculator.calculateSpecialOfferMultiPrice( + inventory, basketItems, specialOffers); + + for (DiscountObjectMultiPrice d : discountList) { + System.out.println("SKU: "+d.getSKU() + + ", x"+d.getNumOfDiscountItems()+" items gives" + + " x"+d.getNumberOfDiscounts()+" discounts" + + ", ordinary items x"+d.getNumOfOrdinaryItems() + + ", discount: "+d.getDiscount()); + } + + Assertions.assertEquals(0, discountList.get(0).getNumberOfDiscounts()); + Assertions.assertEquals(0, discountList.get(0).getNumOfDiscountItems()); + Assertions.assertEquals(5, discountList.get(0).getNumOfOrdinaryItems()); + Assertions.assertEquals(0.0, discountList.get(0).getDiscount()); } @Test public void calculateBagelOnionDicountShouldGetDiscountOnlyForSixBagels() { inventory = new Inventory(); - ArrayList specialOffers = inventory.getSpecialOffers(); + ArrayList specialOffers = inventory.getSpecialOffersMultiPrice(); basket = new Basket(new Inventory()); for (int i = 0; i < 7; i++) { basket.add(new Bagel("BAGO")); } - Map basketItems = basket.getAll(); + // Setup calculation and print result priceCalculator = new PriceCalculator(); - double discount = priceCalculator.calculateDiscount(inventory, basketItems, specialOffers); + ArrayList discountList = priceCalculator.calculateSpecialOfferMultiPrice( + inventory, basketItems, specialOffers); + + for (DiscountObjectMultiPrice d : discountList) { + System.out.println("SKU: "+d.getSKU() + + ", x"+d.getNumOfDiscountItems()+" items gives" + + " x"+d.getNumberOfDiscounts()+" discounts" + + ", ordinary items x"+d.getNumOfOrdinaryItems() + + ", discount: "+d.getDiscount()); + } // Standard price 6 * 0.49 = 2.94 // Discount 2.94 - 2.49 = 0.45 - Assertions.assertEquals(0.45, discount); + Assertions.assertEquals(1, discountList.get(0).getNumberOfDiscounts()); + Assertions.assertEquals(6, discountList.get(0).getNumOfDiscountItems()); + Assertions.assertEquals(1, discountList.get(0).getNumOfOrdinaryItems()); + Assertions.assertEquals(0.45, discountList.get(0).getDiscount()); } - @Test - public void calculateBagelPlainDicountShouldGetDiscountForTwelveBagels() { - inventory = new Inventory(); - ArrayList specialOffers = inventory.getSpecialOffers(); - - basket = new Basket(new Inventory()); - for (int i = 0; i < 12; i++) { - basket.add(new Bagel("BAGP")); - } - Map basketItems = basket.getAll(); - - priceCalculator = new PriceCalculator(); - double discount = priceCalculator.calculateDiscount(inventory, basketItems, specialOffers); - - // Standard price 12 * 0.39 = 4.68 - // Discount 4.68 - 3.99 = 0.69 - Assertions.assertEquals(0.69, discount); - } - - @Test - public void calculateCombinationDiscountShouldReturnDiscount() { - inventory = new Inventory(); - ArrayList specialOffers = inventory.getSpecialOffers(); - - basket = new Basket(new Inventory()); - basket.add(new Coffee("COFB")); - basket.add(new Bagel("BAGE", Arrays.asList("FILS","FILB"))); - basket.add(new Bagel("BAGP")); - - Map basketItems = basket.getAll(); - - priceCalculator = new PriceCalculator(); - double discount = priceCalculator.calculateDiscount(inventory, basketItems, specialOffers); - - // Special offer for COFB: Coffee + Bagel for 1.25 - - - // TODO: If special offers are added to other coffee types, this test will not work - // Coffee + Cheapest Bagel = 0.99 + 0.39 = 1.38 - // Coffee + other Bagel = 0.99 + 0.49 = 1,48 - - // Should use discount on cheapest Bagel first - Assertions.assertEquals(1.38, discount); - } +// +// @Test +// public void calculateCombinationDiscountShouldReturnDiscount() { +// inventory = new Inventory(); +// ArrayList specialOffers = inventory.getSpecialOffers(); +// +// basket = new Basket(new Inventory()); +// basket.add(new Coffee("COFB")); +// basket.add(new Bagel("BAGE", Arrays.asList("FILS","FILB"))); +// basket.add(new Bagel("BAGP")); +// +// Map basketItems = basket.getAll(); +// +// priceCalculator = new PriceCalculator(); +// double discount = priceCalculator.calculateDiscount(inventory, basketItems, specialOffers); +// +// // Special offer for COFB: Coffee + Bagel for 1.25 +// +// +// // TODO: If special offers are added to other coffee types, this test will not work +// // Coffee + Cheapest Bagel = 0.99 + 0.39 = 1.38 +// // Coffee + other Bagel = 0.99 + 0.49 = 1,48 +// +// // Should use discount on cheapest Bagel first +// Assertions.assertEquals(1.38, discount); +// } From 18529cfbeeb75e80321ff02cc4ff02066dd807a5 Mon Sep 17 00:00:00 2001 From: shyye Date: Sun, 25 Aug 2024 17:13:40 +0200 Subject: [PATCH 83/93] Restruct code --- .../DiscountObjectCombination.java | 36 +++++ .../calculators/DiscountObjectMultiPrice.java | 58 ++++++++ .../core/calculators/PriceCalculator.java | 133 +++++++++++++++++- .../booleanuk/core/inventory/Inventory.java | 42 ++++-- .../core/inventory/SpecialOffer.java | 12 +- .../inventory/SpecialOfferCombination.java | 8 +- .../inventory/SpecialOfferMultiPrice.java | 15 +- 7 files changed, 270 insertions(+), 34 deletions(-) create mode 100644 src/main/java/com/booleanuk/core/calculators/DiscountObjectCombination.java create mode 100644 src/main/java/com/booleanuk/core/calculators/DiscountObjectMultiPrice.java diff --git a/src/main/java/com/booleanuk/core/calculators/DiscountObjectCombination.java b/src/main/java/com/booleanuk/core/calculators/DiscountObjectCombination.java new file mode 100644 index 000000000..0adb5a820 --- /dev/null +++ b/src/main/java/com/booleanuk/core/calculators/DiscountObjectCombination.java @@ -0,0 +1,36 @@ +package com.booleanuk.core.calculators; + +import com.booleanuk.core.enums.ProductName; + +import java.util.ArrayList; + +public class DiscountObjectCombination { + + private ArrayList offerItems; + private int numOfDiscounts; + private double discountSum; + + public ArrayList getOfferItems() { + return offerItems; + } + + public void setOfferItems(ArrayList offerItems) { + this.offerItems = offerItems; + } + + public int getNumOfDiscounts() { + return numOfDiscounts; + } + + public void setNumOfDiscounts(int numOfDiscounts) { + this.numOfDiscounts = numOfDiscounts; + } + + public double getDiscountSum() { + return discountSum; + } + + public void setDiscountSum(double discountSum) { + this.discountSum = discountSum; + } +} diff --git a/src/main/java/com/booleanuk/core/calculators/DiscountObjectMultiPrice.java b/src/main/java/com/booleanuk/core/calculators/DiscountObjectMultiPrice.java new file mode 100644 index 000000000..2434893f3 --- /dev/null +++ b/src/main/java/com/booleanuk/core/calculators/DiscountObjectMultiPrice.java @@ -0,0 +1,58 @@ +package com.booleanuk.core.calculators; + +public class DiscountObjectMultiPrice { + + private String SKU; + private int numberOfDiscounts; + private int numOfDiscountItems; // Number of items that is counted into the discount. E.g. 6 for 2.49 + private double discountSum; + private int numOfOrdinaryItems; // Items without discountSum + + public DiscountObjectMultiPrice(String SKU, int numberOfDiscounts, int numOfDiscountItems, double discountSum, int numOfOrdinaryItems) { + this.SKU = SKU; + this.numberOfDiscounts = numberOfDiscounts; + this.numOfDiscountItems = numOfDiscountItems; + this.discountSum = discountSum; + this.numOfOrdinaryItems = numOfOrdinaryItems; + } + + public String getSKU() { + return SKU; + } + + public void setSKU(String SKU) { + this.SKU = SKU; + } + + public int getNumberOfDiscounts() { + return numberOfDiscounts; + } + + public void setNumberOfDiscounts(int numberOfDiscounts) { + this.numberOfDiscounts = numberOfDiscounts; + } + + public int getNumOfDiscountItems() { + return numOfDiscountItems; + } + + public void setNumOfDiscountItems(int numOfDiscountItems) { + this.numOfDiscountItems = numOfDiscountItems; + } + + public double getDiscount() { + return discountSum; + } + + public void setDiscount(double discountSum) { + this.discountSum = discountSum; + } + + public int getNumOfOrdinaryItems() { + return numOfOrdinaryItems; + } + + public void setNumOfOrdinaryItems(int numOfOrdinaryItems) { + this.numOfOrdinaryItems = numOfOrdinaryItems; + } +} diff --git a/src/main/java/com/booleanuk/core/calculators/PriceCalculator.java b/src/main/java/com/booleanuk/core/calculators/PriceCalculator.java index 7803511fd..86cb0fd40 100644 --- a/src/main/java/com/booleanuk/core/calculators/PriceCalculator.java +++ b/src/main/java/com/booleanuk/core/calculators/PriceCalculator.java @@ -16,6 +16,8 @@ public class PriceCalculator { // Use double or float, float saves memory, double is easier to work with + private DiscountObjectMultiPrice discountObjectMultiPrice; + public double round(float total, int numOfDecimals) { // TODO: Should I use float or double? @@ -30,15 +32,74 @@ public double round(float total, int numOfDecimals) { return rounded; } + public ArrayList calculateSpecialOfferMultiPrice(Inventory inventory, Map basketItems, ArrayList specialOffers) { + + ArrayList discountList = new ArrayList<>(); + + // Store list of SKU with number of occurrences. + HashMap skuOccurrences = new HashMap<>(); + for (BasketItem item : basketItems.values()) { + + String sku = item.getSKU(); + if (skuOccurrences.get(sku) == null) { + skuOccurrences.put(sku, 1); + } else { + int numOfItems = skuOccurrences.get(sku); + skuOccurrences.put(sku, numOfItems + 1); + } + } + + // Store Special Offers with the corresponding SKU as key in HashMap + HashMap skuSpecialOfferPairs = new HashMap<>(); + for (SpecialOfferMultiPrice offer : specialOffers) { + skuSpecialOfferPairs.put(offer.getSKU(), offer); + } + + // Calculate discounts + for (Map.Entry skuEntry : skuOccurrences.entrySet()) { + + String sku = skuEntry.getKey(); + int numOfBasketItems = skuEntry.getValue(); + int minimumNumOfItems = skuSpecialOfferPairs.get(sku).getNumOfItems(); // Minimun number of items required to get an offer + + // Count how many discounts + int numOfDiscounts = Math.floorDiv(numOfBasketItems, minimumNumOfItems); + int numOfDiscountItems = (numOfDiscounts * minimumNumOfItems); + int numOfOrdinaryItems = numOfBasketItems - numOfDiscountItems; + + // Get ordinary price for the item, from the inventory + double itemPrice = inventory.getItem(sku).getPrice(); + double ordinaryPrice = minimumNumOfItems * itemPrice; + double specialOfferPrice = skuSpecialOfferPairs.get(sku).getOfferPrice(); + double diffPrice = ordinaryPrice - specialOfferPrice; + + // Calculate total discount for this offer + // add to discount + double discountSum = numOfDiscounts * diffPrice; + discountSum = this.round((float) discountSum, 2); // TODO: Change fromm float to double + discountList.add( + new DiscountObjectMultiPrice( + sku, + numOfDiscounts, + numOfDiscountItems, + discountSum, + numOfOrdinaryItems + )); + } + + return discountList; + } + public double calculateDiscount(Inventory inventory, Map basketItems, ArrayList specialOffers) { double discount = 0; + ArrayList discountObjectMultiPriceList = new ArrayList<>(); // Convert special offers to Hashmap HashMap specialOfferMap = new HashMap<>(); - for (SpecialOffer s : specialOffers) { - specialOfferMap.put(s.getSKU(), s); - } +// for (SpecialOffer s : specialOffers) { +// specialOfferMap.put(s.getSKU(), s); +// } // Count occurrences of discount items HashMap discountItems = new HashMap<>(); @@ -119,10 +180,76 @@ public double calculateDiscount(Inventory inventory, Map ba if (productName == inventoryItem.getName()){ + if (offerItemOccurrences.get(productName) == null) { + ArrayList list = new ArrayList<>(); + list.add(b_SKU); + + offerItemOccurrences.put(productName, list); + } else { + ArrayList list = offerItemOccurrences.get(productName); + list.add(b_SKU); + + offerItemOccurrences.put(productName, list); + } } } } + // Find the list of least items, and save the size + int minItemSize = 0; + boolean isValidSpecialOffer = true; + for (ArrayList skuList : offerItemOccurrences.values()) { + + // If one or more list of SKU's doesn't contain anything, no special offers available + if (skuList.size() == 0) { + isValidSpecialOffer = false; + break; + } else if (skuList.size() < minItemSize) { + minItemSize = skuList.size(); + } + } + + + // Store the price for each offerItem into categories split by ProductName type + HashMap> offerItemPrices = new HashMap<>(); + +// if (isValidSpecialOffer) { +// +// // Sort into ProductName, and store Price +// for (ProductName productName : offerItems) { +// +// for (ArrayList skuList : offerItemOccurrences.values()) { +// +// for (String sku : skuList) { +// double price = inventory.getItem(sku).getPrice(); +// +// if (offerItemPrices.get(sku) == null) { +// ArrayList list = new ArrayList<>(); +// list.add(price); +// +// offerItemPrices.put(sku, list); +// } else { +// ArrayList list = offerItemPrices.get(sku); +// list.add(price); +// +// offerItemPrices.put(sku, list); +// } +// } +// } +// } +// +// // Sort with the cheapest first +// +// // Loop minItemSize times +// +// // get ordinary price +// +// // Calculate difference +// +// //return discount +// } + + } } diff --git a/src/main/java/com/booleanuk/core/inventory/Inventory.java b/src/main/java/com/booleanuk/core/inventory/Inventory.java index 29c9c429a..17b8b55fc 100644 --- a/src/main/java/com/booleanuk/core/inventory/Inventory.java +++ b/src/main/java/com/booleanuk/core/inventory/Inventory.java @@ -14,7 +14,8 @@ public class Inventory { private Map inventoryItems; - private ArrayList specialOffers; + private ArrayList specialOffersMultiPrice; + private ArrayList specialOffersCombination; // Initialized locally private PrintGenerator menu; @@ -70,23 +71,24 @@ private void fillInventory() { // Create special offers private void createSpecialOffers() { - specialOffers = new ArrayList<>(); + specialOffersMultiPrice = new ArrayList<>(); + specialOffersCombination = new ArrayList<>(); - // Special offers - SpecialOffer BAGOsixMultiPriceOffer = new SpecialOfferMultiPrice("BAGO", 6,2.49); - SpecialOffer BAGEsixMultiPriceOffer = new SpecialOfferMultiPrice("BAGE",6,2.49); - SpecialOffer BAGPtwelveMultiPriceOffer = new SpecialOfferMultiPrice("BAGP", 12,3.99); + // Special offers Multi-Price + SpecialOfferMultiPrice BAGOsixMultiPriceOffer = new SpecialOfferMultiPrice("BAGO", 6,2.49); + SpecialOfferMultiPrice BAGEsixMultiPriceOffer = new SpecialOfferMultiPrice("BAGE",6,2.49); + SpecialOfferMultiPrice BAGPtwelveMultiPriceOffer = new SpecialOfferMultiPrice("BAGP", 12,3.99); + this.specialOffersMultiPrice.add(BAGOsixMultiPriceOffer); + this.specialOffersMultiPrice.add(BAGEsixMultiPriceOffer); + this.specialOffersMultiPrice.add(BAGPtwelveMultiPriceOffer); + // Special offers Combination ArrayList offerItems = new ArrayList<>() {{ add(ProductName.COFFEE); add(ProductName.BAGEL); }}; - SpecialOffer coffeAndBagelOffer = new SpecialOfferCombination("COFB", offerItems, 1.25); - - this.specialOffers.add(BAGOsixMultiPriceOffer); - this.specialOffers.add(BAGEsixMultiPriceOffer); - this.specialOffers.add(BAGPtwelveMultiPriceOffer); - this.specialOffers.add(coffeAndBagelOffer); + SpecialOfferCombination coffeAndBagelOffer = new SpecialOfferCombination(offerItems, 1.25); + this.specialOffersCombination.add(coffeAndBagelOffer); } public Map getAllItems() { @@ -94,8 +96,20 @@ public Map getAllItems() { } // Get all special offers - public ArrayList getSpecialOffers() { - return specialOffers; + // TODO: Check this structure, dublication code +// public ArrayList getSpecialOffers(SpecialOffer type) { +// if (type instanceof SpecialOfferMultiPrice) { +// return specialOffersMultiPrice; +// } +// return specialOffersCombination; +// } + + public ArrayList getSpecialOffersMultiPrice() { + return specialOffersMultiPrice; + } + + public ArrayList getSpecialOffersCombination() { + return specialOffersCombination; } public InventoryItem getItem(String SKU) { diff --git a/src/main/java/com/booleanuk/core/inventory/SpecialOffer.java b/src/main/java/com/booleanuk/core/inventory/SpecialOffer.java index 737d3d879..cad04c249 100644 --- a/src/main/java/com/booleanuk/core/inventory/SpecialOffer.java +++ b/src/main/java/com/booleanuk/core/inventory/SpecialOffer.java @@ -2,20 +2,10 @@ public abstract class SpecialOffer { - private String SKU; private double offerPrice; - public SpecialOffer(String SKU, double offerPrice) { + public SpecialOffer(double offerPrice) { this.offerPrice = offerPrice; - this.SKU = SKU; - } - - public String getSKU() { - return SKU; - } - - public void setSKU(String SKU) { - this.SKU = SKU; } public double getOfferPrice() { diff --git a/src/main/java/com/booleanuk/core/inventory/SpecialOfferCombination.java b/src/main/java/com/booleanuk/core/inventory/SpecialOfferCombination.java index 8750cf587..3917b457e 100644 --- a/src/main/java/com/booleanuk/core/inventory/SpecialOfferCombination.java +++ b/src/main/java/com/booleanuk/core/inventory/SpecialOfferCombination.java @@ -8,12 +8,12 @@ public class SpecialOfferCombination extends SpecialOffer{ private ArrayList offerItems; // List of items that in combination generates an offer - public SpecialOfferCombination(String SKU, double offerPrice) { - super(SKU, offerPrice); + public SpecialOfferCombination(double offerPrice) { + super(offerPrice); } - public SpecialOfferCombination(String SKU, ArrayList offerItems, double offerPrice) { - super(SKU, offerPrice); + public SpecialOfferCombination(ArrayList offerItems, double offerPrice) { + super(offerPrice); this.offerItems = offerItems; } diff --git a/src/main/java/com/booleanuk/core/inventory/SpecialOfferMultiPrice.java b/src/main/java/com/booleanuk/core/inventory/SpecialOfferMultiPrice.java index aeef664fe..2ddbacf87 100644 --- a/src/main/java/com/booleanuk/core/inventory/SpecialOfferMultiPrice.java +++ b/src/main/java/com/booleanuk/core/inventory/SpecialOfferMultiPrice.java @@ -2,17 +2,28 @@ public class SpecialOfferMultiPrice extends SpecialOffer{ + private String SKU; private int numOfItems; public SpecialOfferMultiPrice(String SKU, double offerPrice) { - super(SKU, offerPrice); + super(offerPrice); + this.SKU = SKU; } public SpecialOfferMultiPrice(String SKU, int numOfItems, double offerPrice) { - super(SKU, offerPrice); + super(offerPrice); + this.SKU = SKU; this.numOfItems = numOfItems; } + public String getSKU() { + return SKU; + } + + public void setSKU(String SKU) { + this.SKU = SKU; + } + public int getNumOfItems() { return numOfItems; } From f2db79b39e873a4560ac3815774f083412f73b8f Mon Sep 17 00:00:00 2001 From: shyye Date: Mon, 26 Aug 2024 10:41:16 +0200 Subject: [PATCH 84/93] Add Test for discount --- .../core/calculators/PriceCalculatorTest.java | 105 +++++++++++++----- 1 file changed, 79 insertions(+), 26 deletions(-) diff --git a/src/test/java/com/booleanuk/core/calculators/PriceCalculatorTest.java b/src/test/java/com/booleanuk/core/calculators/PriceCalculatorTest.java index 7200b9f48..036beca17 100644 --- a/src/test/java/com/booleanuk/core/calculators/PriceCalculatorTest.java +++ b/src/test/java/com/booleanuk/core/calculators/PriceCalculatorTest.java @@ -6,6 +6,7 @@ import com.booleanuk.core.basket.Coffee; import com.booleanuk.core.inventory.Inventory; import com.booleanuk.core.inventory.SpecialOffer; +import com.booleanuk.core.inventory.SpecialOfferCombination; import com.booleanuk.core.inventory.SpecialOfferMultiPrice; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -125,32 +126,84 @@ public void calculateBagelOnionDicountShouldGetDiscountOnlyForSixBagels() { } -// -// @Test -// public void calculateCombinationDiscountShouldReturnDiscount() { -// inventory = new Inventory(); -// ArrayList specialOffers = inventory.getSpecialOffers(); -// -// basket = new Basket(new Inventory()); -// basket.add(new Coffee("COFB")); -// basket.add(new Bagel("BAGE", Arrays.asList("FILS","FILB"))); -// basket.add(new Bagel("BAGP")); -// -// Map basketItems = basket.getAll(); -// -// priceCalculator = new PriceCalculator(); -// double discount = priceCalculator.calculateDiscount(inventory, basketItems, specialOffers); -// -// // Special offer for COFB: Coffee + Bagel for 1.25 -// -// -// // TODO: If special offers are added to other coffee types, this test will not work -// // Coffee + Cheapest Bagel = 0.99 + 0.39 = 1.38 -// // Coffee + other Bagel = 0.99 + 0.49 = 1,48 -// -// // Should use discount on cheapest Bagel first -// Assertions.assertEquals(1.38, discount); -// } + // TODO: Test fillings + + @Test + public void calculateCombinationDiscountShouldReturnDiscount() { + inventory = new Inventory(); + ArrayList specialOffers = inventory.getSpecialOffersCombination(); + + basket = new Basket(new Inventory()); + basket.add(new Coffee("COFB")); + basket.add(new Bagel("BAGE", Arrays.asList("FILS","FILB"))); + basket.add(new Bagel("BAGP")); + basket.add(new Bagel("BAGE")); + basket.add(new Bagel("BAGO")); + Map basketItems = basket.getAll(); + + // Setup calculation and print result + priceCalculator = new PriceCalculator(); + ArrayList discountList = priceCalculator.calculateSpecialOfferCombination( + inventory, basketItems, specialOffers); + + for (DiscountObjectCombination d : discountList) { + System.out.println("Offer items: "+d.getOfferItems() + + " x"+d.getNumOfDiscounts()+" discounts" + + ", discount: "+d.getDiscountSum()); + } + + // Special offer for COFB: Coffee + Bagel for 1.25 + // BAGE 0.49 + // BAGP 0.39 + // COFB 0.99 + // (cheapest combo) Ordinary price 0.99 + 0.39 = 1.38 + // Ordinary - specialPrice 1.38 - 1.25 = 0.13 + Assertions.assertEquals(1, discountList.get(0).getNumOfDiscounts()); + Assertions.assertEquals(0.13, discountList.get(0).getDiscountSum()); + } + + @Test + public void calculateCombinationDiscountShouldReturnDiscounts() { + inventory = new Inventory(); + ArrayList specialOffers = inventory.getSpecialOffersCombination(); + + basket = new Basket(new Inventory()); + basket.add(new Coffee("COFB")); + basket.add(new Bagel("BAGE", Arrays.asList("FILS","FILB"))); + basket.add(new Bagel("BAGP")); + basket.add(new Bagel("BAGE")); + basket.add(new Bagel("BAGO")); + basket.add(new Coffee("COFW")); + Map basketItems = basket.getAll(); + + // Setup calculation and print result + priceCalculator = new PriceCalculator(); + ArrayList discountList = priceCalculator.calculateSpecialOfferCombination( + inventory, basketItems, specialOffers); + + for (DiscountObjectCombination d : discountList) { + System.out.println("Offer items: "+d.getOfferItems() + + " x"+d.getNumOfDiscounts()+" discounts" + + ", discount: "+d.getDiscountSum()); + } + + // Special offer for COFB: Coffee + Bagel for 1.25 + // BAGE 0.49 + // BAGP 0.39 + // COFB 0.99 + // COFW 1.19 + + // (combo 1) Ordinary price 0.99 + 0.39 = 1.38 + // Ordinary - specialPrice 1.38 - 1.25 = 0.13 + + // (combo 2) Ordinary price 1.19 + 0.49 = 1.68 + // Ordinary - specialPrice 1.68 - 1.25 = 0.43 + + // 0.13 + 0.43 = 0.56 + + Assertions.assertEquals(2, discountList.get(0).getNumOfDiscounts()); + Assertions.assertEquals(0.56, discountList.get(0).getDiscountSum()); + } From 4b5704b77e2cc830ac2cd0ce7516f9f4c2a87cef Mon Sep 17 00:00:00 2001 From: shyye Date: Mon, 26 Aug 2024 10:41:39 +0200 Subject: [PATCH 85/93] Update code for discount --- .../DiscountObjectCombination.java | 6 + .../core/calculators/PriceCalculator.java | 262 ++++++++---------- 2 files changed, 116 insertions(+), 152 deletions(-) diff --git a/src/main/java/com/booleanuk/core/calculators/DiscountObjectCombination.java b/src/main/java/com/booleanuk/core/calculators/DiscountObjectCombination.java index 0adb5a820..ef234c45a 100644 --- a/src/main/java/com/booleanuk/core/calculators/DiscountObjectCombination.java +++ b/src/main/java/com/booleanuk/core/calculators/DiscountObjectCombination.java @@ -10,6 +10,12 @@ public class DiscountObjectCombination { private int numOfDiscounts; private double discountSum; + public DiscountObjectCombination(ArrayList offerItems, int numOfDiscounts, double discountSum) { + this.offerItems = offerItems; + this.numOfDiscounts = numOfDiscounts; + this.discountSum = discountSum; + } + public ArrayList getOfferItems() { return offerItems; } diff --git a/src/main/java/com/booleanuk/core/calculators/PriceCalculator.java b/src/main/java/com/booleanuk/core/calculators/PriceCalculator.java index 86cb0fd40..858eadb43 100644 --- a/src/main/java/com/booleanuk/core/calculators/PriceCalculator.java +++ b/src/main/java/com/booleanuk/core/calculators/PriceCalculator.java @@ -32,11 +32,22 @@ public double round(float total, int numOfDecimals) { return rounded; } - public ArrayList calculateSpecialOfferMultiPrice(Inventory inventory, Map basketItems, ArrayList specialOffers) { - + /** + * Calculate Multi-Price discounts and returns an ArrayList with + * all the items from the basket together with eventual discounts. + * @param inventory + * @param basketItems + * @param specialOffers + * @return + */ + public ArrayList calculateSpecialOfferMultiPrice( + Inventory inventory, Map basketItems, + ArrayList specialOffers) + { ArrayList discountList = new ArrayList<>(); - // Store list of SKU with number of occurrences. + // Store list of SKU with number of occurrences (basket items). HashMap skuOccurrences = new HashMap<>(); for (BasketItem item : basketItems.values()) { @@ -90,172 +101,119 @@ public ArrayList calculateSpecialOfferMultiPrice(Inven return discountList; } - public double calculateDiscount(Inventory inventory, Map basketItems, ArrayList specialOffers) { - - double discount = 0; - ArrayList discountObjectMultiPriceList = new ArrayList<>(); - - // Convert special offers to Hashmap - HashMap specialOfferMap = new HashMap<>(); -// for (SpecialOffer s : specialOffers) { -// specialOfferMap.put(s.getSKU(), s); -// } - - // Count occurrences of discount items - HashMap discountItems = new HashMap<>(); - for (BasketItem item : basketItems.values()) { - - String key_sku = item.getSKU(); - - // Store the SKU as key, and count how many times it occurs for SKU's that have special offers - SpecialOffer offer = specialOfferMap.get(key_sku); - if (offer != null) { - - if (discountItems.get(key_sku) == null) { - discountItems.put(key_sku, 1); - } else { - int numOfItems = discountItems.get(key_sku); - discountItems.put(key_sku, numOfItems + 1); + /** + * Calculates Combination discounts, and returns an ArrayList of discount objects with: + * A list of included product names of the items in the combination offer. E.g. 'COFFEE, BAGEL' + * the total discount price + * the number of discounts + * @param inventory + * @param basketItems + * @param specialOffers + * @return + */ + public ArrayList calculateSpecialOfferCombination( + Inventory inventory, Map basketItems, + ArrayList specialOffers) + { + ArrayList discountList = new ArrayList<>(); + + // TODO: Could this be simplified? + + // Calculate special offers for each offer. + // E.g. if there exist more than one offer like 'Coffee + Bagel for 1.25', 'Juice + cookie for 0.5' + for (SpecialOfferCombination offer : specialOffers) { + + ArrayList offerItems = offer.getOfferItems(); + + // Store an copy of an InventoryITem for each basket item, sorted into ProductNames (e.g. COFFEE, BAGEL), + // The ProductNames represents the combination of items that offer includes, e.g. 'Coffee + Bagel' offer. + HashMap> itemsSortedByProductName = new HashMap<>(); + for (ProductName productName : offerItems) { + for (BasketItem b : basketItems.values()) { + + InventoryItem inventoryItem = inventory.getItem(b.getSKU()); + + if (productName == inventoryItem.getName()){ + + if (itemsSortedByProductName.get(productName) == null) { + ArrayList list = new ArrayList<>(); + list.add(inventoryItem); + + itemsSortedByProductName.put(productName, list); + } else { + ArrayList list = itemsSortedByProductName.get(productName); + list.add(inventoryItem); + + itemsSortedByProductName.put(productName, list); + } + } } } - } - for (Map.Entry item : discountItems.entrySet()) { - - SpecialOffer offer = specialOfferMap.get(item.getKey()); - - // The special price for the offer, and number of items in this basket that has that offer - double specialPrice = offer.getOfferPrice(); - int numOfBasketItems = item.getValue(); - - - // - // Multi-Price Offer - // - if (offer instanceof SpecialOfferMultiPrice) { - - SpecialOfferMultiPrice multiPriceOffer = (SpecialOfferMultiPrice) offer; - - // Get number of items required to get the offer - int minimumNumOfItems = multiPriceOffer.getNumOfItems(); - - if (numOfBasketItems < minimumNumOfItems) { - // Too few items, no offer + // Find the list of least items, and save the size + // This is to find how many offers the user will get based on the amount of + // combinations that exists in the basket + int minItemSize = -1; + boolean isValidSpecialOffer = true; + for (ArrayList itemList : itemsSortedByProductName.values()) { + + // If one or more list of basket items (inventory objects) doesn't contain anything, + // no special offers available + if (itemList.isEmpty()) { + isValidSpecialOffer = false; break; - } - - // Count how many discounts - int numOfDiscounts = Math.floorDiv(numOfBasketItems, minimumNumOfItems); - - // Get ordinary price for the item, from the inventory - double itemPrice = inventory.getItem(item.getKey()).getPrice(); - double ordinaryPrice = minimumNumOfItems * itemPrice; - double diffPrice = ordinaryPrice - specialPrice; - // Calculate total discount for this offer - // add to discount - discount += numOfDiscounts * diffPrice; - - - // - // Combination Offer - // - } else if (offer instanceof SpecialOfferCombination) { - - // TODO: I will assume that the offer Coffee + Bagel for 1.25, includes all coffee types and all bagel types. - - SpecialOfferCombination combinationOffer = (SpecialOfferCombination) offer; - - // Get combination of items required to get the offer - ArrayList offerItems = combinationOffer.getOfferItems(); - - // Store the number of occurrences for each offerItem (ProductName type) - HashMap> offerItemOccurrences = new HashMap<>(); - - for (ProductName productName : offerItems) { - for (BasketItem b : basketItems.values()) { + } else if (minItemSize == -1) { + minItemSize = itemList.size(); + } else if (itemList.size() < minItemSize) { + minItemSize = itemList.size(); + } + } - String b_SKU = b.getSKU(); - InventoryItem inventoryItem = inventory.getItem(b_SKU); + // Sort lists by price + // I assume that the offer will be valid on the cheapest products first + // Therefore I sort the lists by price + // Resource: https://www.geeksforgeeks.org/how-to-sort-an-arraylist-of-objects-by-property-in-java/ + for (ArrayList itemList : itemsSortedByProductName.values()) { + itemList.sort((a, b) -> Double.compare(a.getPrice(), b.getPrice())); + } - if (productName == inventoryItem.getName()){ + // Caclucate discount + if (isValidSpecialOffer) { - if (offerItemOccurrences.get(productName) == null) { - ArrayList list = new ArrayList<>(); - list.add(b_SKU); + int numOfDiscounts = 0; + double discount = 0.0; + double discountRounded = 0; + // Calculate number of discounts, and amount of discount + for (int i = 0; i < minItemSize; i++) { - offerItemOccurrences.put(productName, list); - } else { - ArrayList list = offerItemOccurrences.get(productName); - list.add(b_SKU); + // Store the combination of items included in the offer + // Starting with the cheapest ones. + ArrayList combinationItems = new ArrayList<>(); + for (ArrayList itemList : itemsSortedByProductName.values()) { - offerItemOccurrences.put(productName, list); - } - } + combinationItems.add(itemList.get(i)); } - } - // Find the list of least items, and save the size - int minItemSize = 0; - boolean isValidSpecialOffer = true; - for (ArrayList skuList : offerItemOccurrences.values()) { - - // If one or more list of SKU's doesn't contain anything, no special offers available - if (skuList.size() == 0) { - isValidSpecialOffer = false; - break; - } else if (skuList.size() < minItemSize) { - minItemSize = skuList.size(); + double ordinaryPrice = 0; + for (InventoryItem item : combinationItems) { + ordinaryPrice += item.getPrice(); } - } - - - // Store the price for each offerItem into categories split by ProductName type - HashMap> offerItemPrices = new HashMap<>(); - -// if (isValidSpecialOffer) { -// -// // Sort into ProductName, and store Price -// for (ProductName productName : offerItems) { -// -// for (ArrayList skuList : offerItemOccurrences.values()) { -// -// for (String sku : skuList) { -// double price = inventory.getItem(sku).getPrice(); -// -// if (offerItemPrices.get(sku) == null) { -// ArrayList list = new ArrayList<>(); -// list.add(price); -// -// offerItemPrices.put(sku, list); -// } else { -// ArrayList list = offerItemPrices.get(sku); -// list.add(price); -// -// offerItemPrices.put(sku, list); -// } -// } -// } -// } -// -// // Sort with the cheapest first -// -// // Loop minItemSize times -// -// // get ordinary price -// -// // Calculate difference -// -// //return discount -// } - + double specialPrice = offer.getOfferPrice(); + double diffPrice = ordinaryPrice - specialPrice; + // Update + numOfDiscounts++; + discount += diffPrice; + discountRounded = this.round((float) discount, 2); + } + discountList.add(new DiscountObjectCombination(offerItems, numOfDiscounts, discountRounded)); } - } - // TODO: instead of casting to float, change float to double in rest of the program + } - return this.round((float) discount, 2); + return discountList; } } From 48b2a77adff8d3174722dd15239a43e3e3937813 Mon Sep 17 00:00:00 2001 From: shyye Date: Mon, 26 Aug 2024 10:43:01 +0200 Subject: [PATCH 86/93] Update comments --- .../booleanuk/core/calculators/PriceCalculatorTest.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/test/java/com/booleanuk/core/calculators/PriceCalculatorTest.java b/src/test/java/com/booleanuk/core/calculators/PriceCalculatorTest.java index 036beca17..76c53af9f 100644 --- a/src/test/java/com/booleanuk/core/calculators/PriceCalculatorTest.java +++ b/src/test/java/com/booleanuk/core/calculators/PriceCalculatorTest.java @@ -20,6 +20,9 @@ public class PriceCalculatorTest { Inventory inventory; Basket basket; + /** + * EXTENSION 1 + */ @Test public void calculateBagelOnionDicountShouldGetDiscount() { inventory = new Inventory(); @@ -205,11 +208,6 @@ public void calculateCombinationDiscountShouldReturnDiscounts() { Assertions.assertEquals(0.56, discountList.get(0).getDiscountSum()); } - - - - // TODO: // Check why BGLO doesn't exist - WRITE IN README THAT I HAVE DIFFERENT SKU's - // Work with calculateDiscount() } From 30ac94d18cc67800538bc0df6480f645c8cb1367 Mon Sep 17 00:00:00 2001 From: shyye Date: Mon, 26 Aug 2024 11:19:20 +0200 Subject: [PATCH 87/93] Update comments --- .../calculators/DiscountObjectMultiPrice.java | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/booleanuk/core/calculators/DiscountObjectMultiPrice.java b/src/main/java/com/booleanuk/core/calculators/DiscountObjectMultiPrice.java index 2434893f3..951eb38b9 100644 --- a/src/main/java/com/booleanuk/core/calculators/DiscountObjectMultiPrice.java +++ b/src/main/java/com/booleanuk/core/calculators/DiscountObjectMultiPrice.java @@ -20,39 +20,39 @@ public String getSKU() { return SKU; } - public void setSKU(String SKU) { - this.SKU = SKU; - } +// public void setSKU(String SKU) { +// this.SKU = SKU; +// } public int getNumberOfDiscounts() { return numberOfDiscounts; } - public void setNumberOfDiscounts(int numberOfDiscounts) { - this.numberOfDiscounts = numberOfDiscounts; - } +// public void setNumberOfDiscounts(int numberOfDiscounts) { +// this.numberOfDiscounts = numberOfDiscounts; +// } public int getNumOfDiscountItems() { return numOfDiscountItems; } - public void setNumOfDiscountItems(int numOfDiscountItems) { - this.numOfDiscountItems = numOfDiscountItems; - } +// public void setNumOfDiscountItems(int numOfDiscountItems) { +// this.numOfDiscountItems = numOfDiscountItems; +// } public double getDiscount() { return discountSum; } - public void setDiscount(double discountSum) { - this.discountSum = discountSum; - } +// public void setDiscount(double discountSum) { +// this.discountSum = discountSum; +// } public int getNumOfOrdinaryItems() { return numOfOrdinaryItems; } - public void setNumOfOrdinaryItems(int numOfOrdinaryItems) { - this.numOfOrdinaryItems = numOfOrdinaryItems; - } +// public void setNumOfOrdinaryItems(int numOfOrdinaryItems) { +// this.numOfOrdinaryItems = numOfOrdinaryItems; +// } } From b5416b2cb5eb3bf75804b1f8c61a91250efb232d Mon Sep 17 00:00:00 2001 From: shyye Date: Mon, 26 Aug 2024 11:20:07 +0200 Subject: [PATCH 88/93] Update domain model for Extension 1 --- .../java/com/booleanuk/core/domain-model.md | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/booleanuk/core/domain-model.md b/src/main/java/com/booleanuk/core/domain-model.md index 3075dcc99..1bbd3fdd9 100644 --- a/src/main/java/com/booleanuk/core/domain-model.md +++ b/src/main/java/com/booleanuk/core/domain-model.md @@ -9,10 +9,23 @@ | `ProductName` | | | | | ## Package: calculators -| Classes | Variables | Methods | Scenario | Output | -|-------------------|-----------|---------|----------|--------| -| `PriceCalculator` | | | | | -| `SKUCalculator` | | | | | +| Classes | Variables | Methods | Scenario | Output | +|-----------------------------|-------------------------------------|--------------------------------------|-------------------------------------------------------------------------------------------------------------------|--------| +| `DiscountObjectCombination` | `ArrayList offerItems` | `get/setOfferItems()` | (Extension 1) | | +| | `int numOfDiscounts` | `get/setNumOfDiscounts()` | (Extension 1) | | +| | `double discountSum` | `getDiscountSum()` | (Extension 1) | | +| | | | | | +| `DiscountObjectMultiPrice` | `String SKU` | `getSKU()` | (Extension 1) | | +| | `int numberOfDiscounts` | `getNumberOfDiscounts()` | (Extension 1) | | +| | `int numOfDiscountItems` | `getNumOfDiscountItems()` | (Extension 1)
Number of items for this SKU that is counted into the discount.
E.g. 6 items for '6 for 2.49' | | +| | `double discountSum` | `getDiscount()` | (Extension 1) | | +| | `int numOfOrdinaryItems` | `getNumOfOrdinaryItems` | (Extension 1)
Number of items for this SKU that doesn't have any discounts. | | +| | | | | | +| `PriceCalculator` | | `calculateSpecialOfferMultiPrice()` | (Extension 1) | | +| | | `calculateSpecialOfferCombination()` | (Extension 1) | | +| | | | | | +| `SKUCalculator` | | | | | + ## Package: inventory | Classes | Variables | Methods | Scenario | Output | @@ -41,6 +54,11 @@ | `FillingItem` extends `InventoryItem` | @Ovverride `+setName()` | | | ProductName | | | | | | | | `InventoryItemException` extends `RuntimeException` | | | | | +| | | | | | +| `SpecialOffer` | `double offerPrice` | | (Extension 1) | | +| `SpecialOfferCombination` extends `SpecialOffer` | `ArrayList offerItems` | | (Extension 1) | | +| `SpecialOfferMultiPrice` extends `SpecialOffer` | `String SKU` | | (Extension 1) | | +| | `int numOfItems` | | (Extension 1) | | ## Package: basket | Classes | Variables | Methods | Scenario | Output | From 3692ace6e8c981a3dcb43014a17bcad34c4fb5c1 Mon Sep 17 00:00:00 2001 From: shyye Date: Mon, 26 Aug 2024 11:32:38 +0200 Subject: [PATCH 89/93] Add readme for core and extensions comments --- src/main/java/com/booleanuk/core/README.md | 62 ++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 src/main/java/com/booleanuk/core/README.md diff --git a/src/main/java/com/booleanuk/core/README.md b/src/main/java/com/booleanuk/core/README.md new file mode 100644 index 000000000..264cfc3b1 --- /dev/null +++ b/src/main/java/com/booleanuk/core/README.md @@ -0,0 +1,62 @@ +# Bob's Bagels OOP + +## Core requirements +- [x] #1 I'd like to add a specific type of bagel to my basket. +- [x] #2 I'd like to remove a bagel from my basket. +- [x] #3 I'd like to know when my basket is full when I try adding an item beyond my basket capacity. +- [x] #4 I’d like to change the capacity of baskets. +- [x] #5 I'd like to know if I try to remove an item that doesn't exist in my basket. +- [x] #6 I'd like to know the total cost of items in my basket. +- [x] #7 I'd like to know the cost of a bagel before I add it to my basket.* +- [x] #8 I'd like to be able to choose fillings for my bagel. +- [x] #9 I'd like to know the cost of each filling before I add it to my bagel order.* +- [x] #10 I want customers to only be able to order things that we stock in our inventory.** + +\* The inventory have functionality to print out the menu, but there are no functions that follows abstraction like +'getAllBagels()' etc. There is only functionality to get the inventory Map/List that contains objects with getPrice() functions. + +** The inventory doesn't count how many of each item in stock, but customers can only choose things that are in the inventory. + +## Extension 1 + +### User Stories + +``` +1. +As a manager, +So the customers can benefit from our discounts, +I want the discounts for all items in basket to be calculated autoamtically. +``` + +### Comments +- Added the classes SpecailOffer, SpecialOfferCombination, SpecialOfferMultiPrice to 'package: inventory' +- Added the classes DiscountObjectCombination and DiscountObjectMultiPrice to 'package: calculators'. Because the discount is calculated in the PriceCalculator class. + +### Method/Calculation notes +``` +# Discounts + +if discount 6 for 2.55 + get normalPrice + normalPrice - discountPrice = discount + + get all items with SKU X + 6 // numOfItems = number of discounts + number of discounts * discount. + + result for this SKU = totalCost - totalDiscount + +if discount is Coffe + Bagel = 1.33 + get normalPrice + normalPrice - discountPrice = discount + + get all occurencies of product A + get all occurencies of product B + + if one or both is 0 -> no discount + if A = B -> discounts on all pairs + if A < B -> discount * the same number as A + and vice versa +``` + +## Extension 2 \ No newline at end of file From 0115f305557caf71b91963040d7b55df338d05c5 Mon Sep 17 00:00:00 2001 From: shyye Date: Mon, 26 Aug 2024 15:59:39 +0200 Subject: [PATCH 90/93] Add printCheck in Test --- .../com/booleanuk/core/basket/BasketTest.java | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/test/java/com/booleanuk/core/basket/BasketTest.java b/src/test/java/com/booleanuk/core/basket/BasketTest.java index c751809d0..521ce69ee 100644 --- a/src/test/java/com/booleanuk/core/basket/BasketTest.java +++ b/src/test/java/com/booleanuk/core/basket/BasketTest.java @@ -175,4 +175,43 @@ public void getTotalCostOfBasket() { // = 1.92 Assertions.assertEquals(1.92, basket.getTotalCost()); } + + // Extension 2 + @Test + public void printReceipt() { + inventory = new Inventory(); + basket = new Basket(new Inventory()); + basket.changeMaxCapacity(40); + + for (int i = 0; i < 2; i++) { + basket.add(new Bagel("BAGO")); + } + + for (int i = 0; i < 12; i++) { + basket.add(new Bagel("BAGP")); + } + + for (int i = 0; i < 6; i++) { + basket.add(new Bagel("BAGE")); + } + + for (int i = 0; i < 3; i++) { + basket.add(new Bagel("COFB")); + } + + basket.printReceipt(); + + // Everything Bagel, 6, 2.49 + // TODO: How to add test here? Have test in priceCalculator + } + + // Extension 3 +// @Test +// public void printDiscountReceipt() { +// inventory = new Inventory(); +// basket = new Basket(new Inventory()); +// +// basket.printReceipt() +// +// } } From 47ca7c50c23c14a1ebd59cb68a2b1551cdb8b433 Mon Sep 17 00:00:00 2001 From: shyye Date: Mon, 26 Aug 2024 16:00:19 +0200 Subject: [PATCH 91/93] Update code, change structure, a bit overcomplicated --- .../com/booleanuk/core/basket/Basket.java | 90 ++++++++++++++++++- .../core/basket/BasketItemFormatted.java | 48 ++++++++++ .../calculators/DiscountObjectMultiPrice.java | 69 ++++++++++---- .../core/calculators/PriceCalculator.java | 85 +++++++++++++----- .../com/booleanuk/core/enums/ProductName.java | 22 ++++- .../core/printgenerator/PrintReceipt.java | 62 +++++++++++++ 6 files changed, 327 insertions(+), 49 deletions(-) create mode 100644 src/main/java/com/booleanuk/core/basket/BasketItemFormatted.java create mode 100644 src/main/java/com/booleanuk/core/printgenerator/PrintReceipt.java diff --git a/src/main/java/com/booleanuk/core/basket/Basket.java b/src/main/java/com/booleanuk/core/basket/Basket.java index 8da4f8067..880259a8c 100644 --- a/src/main/java/com/booleanuk/core/basket/Basket.java +++ b/src/main/java/com/booleanuk/core/basket/Basket.java @@ -1,11 +1,15 @@ package com.booleanuk.core.basket; +import com.booleanuk.core.calculators.DiscountObjectCombination; +import com.booleanuk.core.calculators.DiscountObjectMultiPrice; import com.booleanuk.core.calculators.PriceCalculator; import com.booleanuk.core.inventory.Inventory; import com.booleanuk.core.inventory.InventoryItem; import com.booleanuk.core.printgenerator.PrintBasketItems; import com.booleanuk.core.printgenerator.PrintGenerator; +import com.booleanuk.core.printgenerator.PrintReceipt; +import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -19,7 +23,7 @@ public class Basket { private int maxCapacity; private PriceCalculator priceCalculator; - private PrintGenerator basket; + private PrintGenerator printGenerator; public Basket(Inventory inventory) { this.inventory = inventory; @@ -221,7 +225,87 @@ public void printBasket() { // TODO: Should I refactor? Feels like it's a poor solution regarding dependencies. // Check all PrintGenerator cases. - basket = new PrintBasketItems(this.inventory, this.basketItems, this.getTotalCost()); - basket.print(); + printGenerator = new PrintBasketItems(this.inventory, this.basketItems, this.getTotalCost()); + printGenerator.print(); + } + + public void printReceipt() { + + ArrayList itemsAndDiscounts = priceCalculator.calculateSpecialOfferMultiPrice( + this.inventory, + this.basketItems, + this.inventory.getSpecialOffersMultiPrice() + ); + ArrayList additionalDiscounts = priceCalculator.calculateSpecialOfferCombination( + this.inventory, + this.basketItems, + this.inventory.getSpecialOffersCombination() + ); + + + // Create a list of printable objects + // Calculates MultiPrice discounts + double totalCost = 0; + ArrayList printableListItems = new ArrayList<>(); + for (DiscountObjectMultiPrice item : itemsAndDiscounts) { + + // TODO: Refactor, unnecessary calculation + boolean hasDiscountItems = item.getNumOfDiscountItems() != 0; + boolean hasOrdinaryItems = item.getNumOfOrdinaryItems() != 0; + + InventoryItem inventoryItem = this.inventory.getItem(item.getSKU()); + String variant = inventoryItem.getVariant().toString(); + String name = inventoryItem.getName().getString(); + + String combinedName = variant + " " + name; + int amount; + double price; + double discount = item.getDiscount(); + + if (hasDiscountItems) { + amount = item.getNumOfDiscountItems(); + price = item.getPriceForDiscountItems(); + + BasketItemFormatted formattedItem = new BasketItemFormatted( + combinedName, + amount, + price, + discount + ); + printableListItems.add(formattedItem); + totalCost += price; + } + + if (hasOrdinaryItems) { + amount = item.getNumOfOrdinaryItems(); + price = item.getPriceForOrdinaryItems(); + + BasketItemFormatted formattedItem = new BasketItemFormatted( + combinedName, + amount, + price, + discount + ); + printableListItems.add(formattedItem); + totalCost += price; + } + + } + + totalCost = priceCalculator.round((float) totalCost, 2); + + // Calculate combination discounts +// int additionalDiscount = 0; +// for (DiscountObjectCombination item : additionalDiscounts) { +// additionalDiscount += item.getDiscountSum(); +// } +// totalCost = totalCost - additionalDiscount; + + printGenerator = new PrintReceipt( + printableListItems, + totalCost + ); + + printGenerator.print(); } } diff --git a/src/main/java/com/booleanuk/core/basket/BasketItemFormatted.java b/src/main/java/com/booleanuk/core/basket/BasketItemFormatted.java new file mode 100644 index 000000000..1b258ffdb --- /dev/null +++ b/src/main/java/com/booleanuk/core/basket/BasketItemFormatted.java @@ -0,0 +1,48 @@ +package com.booleanuk.core.basket; + +public class BasketItemFormatted { + + private String name; + private int amount; + private double price; + private double discount; + + public BasketItemFormatted(String name, int amount, double price, double discount) { + this.name = name; + this.amount = amount; + this.price = price; + this.discount = discount; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getAmount() { + return amount; + } + + public void setAmount(int amount) { + this.amount = amount; + } + + public double getPrice() { + return price; + } + + public void setPrice(double price) { + this.price = price; + } + + public double getDiscount() { + return discount; + } + + public void setDiscount(double discount) { + this.discount = discount; + } +} diff --git a/src/main/java/com/booleanuk/core/calculators/DiscountObjectMultiPrice.java b/src/main/java/com/booleanuk/core/calculators/DiscountObjectMultiPrice.java index 951eb38b9..369367c4d 100644 --- a/src/main/java/com/booleanuk/core/calculators/DiscountObjectMultiPrice.java +++ b/src/main/java/com/booleanuk/core/calculators/DiscountObjectMultiPrice.java @@ -2,57 +2,88 @@ public class DiscountObjectMultiPrice { + // TODO: Confusing to use this object for both items with discounts and items without discounts for a specific SKU + private String SKU; + private int numberOfDiscounts; private int numOfDiscountItems; // Number of items that is counted into the discount. E.g. 6 for 2.49 - private double discountSum; + private double priceForDiscountItems; + private double discount; + private int numOfOrdinaryItems; // Items without discountSum + private double priceForOrdinaryItems; - public DiscountObjectMultiPrice(String SKU, int numberOfDiscounts, int numOfDiscountItems, double discountSum, int numOfOrdinaryItems) { + public DiscountObjectMultiPrice( + String SKU, int numberOfDiscounts, + int numOfDiscountItems, + double priceForDiscountItems, + double discount, + int numOfOrdinaryItems, + double priceForOrdinaryItems) + { this.SKU = SKU; this.numberOfDiscounts = numberOfDiscounts; this.numOfDiscountItems = numOfDiscountItems; - this.discountSum = discountSum; + this.priceForDiscountItems = priceForDiscountItems; + this.discount = discount; this.numOfOrdinaryItems = numOfOrdinaryItems; + this.priceForOrdinaryItems = priceForOrdinaryItems; } public String getSKU() { return SKU; } -// public void setSKU(String SKU) { -// this.SKU = SKU; -// } + public void setSKU(String SKU) { + this.SKU = SKU; + } public int getNumberOfDiscounts() { return numberOfDiscounts; } -// public void setNumberOfDiscounts(int numberOfDiscounts) { -// this.numberOfDiscounts = numberOfDiscounts; -// } + public void setNumberOfDiscounts(int numberOfDiscounts) { + this.numberOfDiscounts = numberOfDiscounts; + } public int getNumOfDiscountItems() { return numOfDiscountItems; } -// public void setNumOfDiscountItems(int numOfDiscountItems) { -// this.numOfDiscountItems = numOfDiscountItems; -// } + public void setNumOfDiscountItems(int numOfDiscountItems) { + this.numOfDiscountItems = numOfDiscountItems; + } + + public double getPriceForDiscountItems() { + return priceForDiscountItems; + } + + public void setPriceForDiscountItems(double priceForDiscountItems) { + this.priceForDiscountItems = priceForDiscountItems; + } public double getDiscount() { - return discountSum; + return discount; } -// public void setDiscount(double discountSum) { -// this.discountSum = discountSum; -// } + public void setDiscount(double discount) { + this.discount = discount; + } public int getNumOfOrdinaryItems() { return numOfOrdinaryItems; } -// public void setNumOfOrdinaryItems(int numOfOrdinaryItems) { -// this.numOfOrdinaryItems = numOfOrdinaryItems; -// } + public void setNumOfOrdinaryItems(int numOfOrdinaryItems) { + this.numOfOrdinaryItems = numOfOrdinaryItems; + } + + public double getPriceForOrdinaryItems() { + return priceForOrdinaryItems; + } + + public void setPriceForOrdinaryItems(double priceForOrdinaryItems) { + this.priceForOrdinaryItems = priceForOrdinaryItems; + } } diff --git a/src/main/java/com/booleanuk/core/calculators/PriceCalculator.java b/src/main/java/com/booleanuk/core/calculators/PriceCalculator.java index 858eadb43..19b816749 100644 --- a/src/main/java/com/booleanuk/core/calculators/PriceCalculator.java +++ b/src/main/java/com/booleanuk/core/calculators/PriceCalculator.java @@ -67,35 +67,74 @@ public ArrayList calculateSpecialOfferMultiPrice( } // Calculate discounts + int numOfDiscounts; + int numOfDiscountItems; + int numOfOrdinaryItems; + double priceForDiscountItems; + double priceForOrdinaryItems; + double discountSum; for (Map.Entry skuEntry : skuOccurrences.entrySet()) { String sku = skuEntry.getKey(); - int numOfBasketItems = skuEntry.getValue(); - int minimumNumOfItems = skuSpecialOfferPairs.get(sku).getNumOfItems(); // Minimun number of items required to get an offer - // Count how many discounts - int numOfDiscounts = Math.floorDiv(numOfBasketItems, minimumNumOfItems); - int numOfDiscountItems = (numOfDiscounts * minimumNumOfItems); - int numOfOrdinaryItems = numOfBasketItems - numOfDiscountItems; + int numOfBasketItems = skuEntry.getValue(); + numOfOrdinaryItems = numOfBasketItems; // If there is no discount items, all basket items with this SKU are ordinary items - // Get ordinary price for the item, from the inventory + // Get standard price for item with this SKU double itemPrice = inventory.getItem(sku).getPrice(); - double ordinaryPrice = minimumNumOfItems * itemPrice; - double specialOfferPrice = skuSpecialOfferPairs.get(sku).getOfferPrice(); - double diffPrice = ordinaryPrice - specialOfferPrice; - - // Calculate total discount for this offer - // add to discount - double discountSum = numOfDiscounts * diffPrice; - discountSum = this.round((float) discountSum, 2); // TODO: Change fromm float to double - discountList.add( - new DiscountObjectMultiPrice( - sku, - numOfDiscounts, - numOfDiscountItems, - discountSum, - numOfOrdinaryItems - )); + priceForOrdinaryItems = numOfOrdinaryItems * itemPrice; // If there is no discounts, this is the price for all items. + priceForOrdinaryItems = this.round((float) priceForOrdinaryItems, 2); + + if (skuSpecialOfferPairs.get(sku) != null) { + + int minimumNumOfItems = skuSpecialOfferPairs.get(sku).getNumOfItems(); // Minimun number of items required to get an offer + + // Count how many discounts + numOfDiscounts = Math.floorDiv(numOfBasketItems, minimumNumOfItems); + numOfDiscountItems = (numOfDiscounts * minimumNumOfItems); + numOfOrdinaryItems = numOfBasketItems - numOfDiscountItems; + + // Calculate the discount price by subtraction ordinary price by special offer price + double ordinaryPrice = minimumNumOfItems * itemPrice; + double specialOfferPrice = skuSpecialOfferPairs.get(sku).getOfferPrice(); + double diffPrice = ordinaryPrice - specialOfferPrice; + + // Calculate total discount for this offer + // add to discount + discountSum = numOfDiscounts * diffPrice; + discountSum = this.round((float) discountSum, 2); // TODO: Change fromm float to double + + priceForDiscountItems = numOfDiscounts * specialOfferPrice; + priceForOrdinaryItems = numOfOrdinaryItems * itemPrice; + + priceForDiscountItems = this.round((float) priceForDiscountItems, 2); + priceForOrdinaryItems = this.round((float) priceForOrdinaryItems, 2); + + discountList.add( + new DiscountObjectMultiPrice( + sku, + numOfDiscounts, + numOfDiscountItems, + priceForDiscountItems, + discountSum, + numOfOrdinaryItems, + priceForOrdinaryItems + )); + + } else { + discountList.add( + new DiscountObjectMultiPrice( + sku, + 0, + 0, + 0.0, + 0.0, + numOfOrdinaryItems, + priceForOrdinaryItems + )); + } + + } return discountList; diff --git a/src/main/java/com/booleanuk/core/enums/ProductName.java b/src/main/java/com/booleanuk/core/enums/ProductName.java index 533f3b3ae..fcba49d31 100644 --- a/src/main/java/com/booleanuk/core/enums/ProductName.java +++ b/src/main/java/com/booleanuk/core/enums/ProductName.java @@ -1,8 +1,22 @@ package com.booleanuk.core.enums; public enum ProductName { - DEFAULT, - COFFEE, - BAGEL, - FILLING, + + // Resource: https://www.youtube.com/watch?v=wq9SJb8VeyM + + DEFAULT("DEFAULT"), + COFFEE("Coffee"), + BAGEL("Bagel"), + FILLING("Filling"); + + private final String string; + + ProductName(String string) { + this.string = string; + } + + public String getString() { + return string; + } + } \ No newline at end of file diff --git a/src/main/java/com/booleanuk/core/printgenerator/PrintReceipt.java b/src/main/java/com/booleanuk/core/printgenerator/PrintReceipt.java new file mode 100644 index 000000000..970300204 --- /dev/null +++ b/src/main/java/com/booleanuk/core/printgenerator/PrintReceipt.java @@ -0,0 +1,62 @@ +package com.booleanuk.core.printgenerator; + +import com.booleanuk.core.basket.BasketItemFormatted; +import com.booleanuk.core.calculators.DiscountObjectCombination; +import com.booleanuk.core.calculators.DiscountObjectMultiPrice; +import com.booleanuk.core.inventory.Inventory; +import com.booleanuk.core.inventory.InventoryItem; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; + +public class PrintReceipt extends PrintGenerator{ + + private String dateCreated; + private ArrayList pritableItemsList; + private double totalCost; + + public PrintReceipt(ArrayList pritableItemsList, double totalCost) { + this.dateCreated = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")); + this.pritableItemsList = pritableItemsList; + this.totalCost = totalCost; + } + + @Override + public void print() { + + // TODO: not good to let a print function calculate, should be refactored + double totalDiscount = 0; + + // Variables for e.g. "%-15s %-15s %n", keep blank space + String leftAlignSmall = "%7s "; + String leftAlign = "%-17s "; + String newLine = "%n"; + String divider = "---------------------------------"; + int totalwidth = 33; + + System.out.println(); + printCenterTitle("~~~Bob's Bagels ~~~", totalwidth); + System.out.println(); + printCenterTitle(dateCreated.toString(), totalwidth); + System.out.println(); + System.out.println(divider); + System.out.println(); + + for (BasketItemFormatted item : pritableItemsList) { + + System.out.printf( + leftAlign + leftAlignSmall + leftAlignSmall + newLine, + item.getName(), item.getAmount(), "£"+item.getPrice() + ); + } + + System.out.println("\n"+divider); + System.out.printf( + "%s %20s" + newLine, + "Total cost: ", "£"+totalCost + ); + System.out.println(); + + } +} From eb1fd820b006e60310a3b88021224dfddf0cbac7 Mon Sep 17 00:00:00 2001 From: shyye Date: Mon, 26 Aug 2024 19:02:32 +0200 Subject: [PATCH 92/93] Update code, change structure, a bit overcomplicated --- assets/images/class_diagram_basket.png | Bin 0 -> 112300 bytes assets/images/class_diagram_inventory.png | Bin 0 -> 105580 bytes .../images/class_diagram_printGenerator.png | Bin 0 -> 27682 bytes ...iagram.png => gleek_class-diagram_old.png} | Bin src/main/java/com/booleanuk/core/README.md | 39 +++++- .../com/booleanuk/core/basket/Basket.java | 130 +++++++++++++++++- .../java/com/booleanuk/core/domain-model.md | 41 +++--- .../printgenerator/PrintDiscountReceipt.java | 76 ++++++++++ .../core/printgenerator/PrintReceipt.java | 9 +- .../com/booleanuk/core/basket/BasketTest.java | 38 +++-- .../core/calculators/PriceCalculatorTest.java | 2 +- 11 files changed, 301 insertions(+), 34 deletions(-) create mode 100644 assets/images/class_diagram_basket.png create mode 100644 assets/images/class_diagram_inventory.png create mode 100644 assets/images/class_diagram_printGenerator.png rename assets/images/{gleek_class-diagram.png => gleek_class-diagram_old.png} (100%) create mode 100644 src/main/java/com/booleanuk/core/printgenerator/PrintDiscountReceipt.java diff --git a/assets/images/class_diagram_basket.png b/assets/images/class_diagram_basket.png new file mode 100644 index 0000000000000000000000000000000000000000..b966d68cde4f2f30eafb6c510728ebb235cc2205 GIT binary patch literal 112300 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 literal 0 HcmV?d00001 diff --git a/assets/images/class_diagram_inventory.png b/assets/images/class_diagram_inventory.png new file mode 100644 index 0000000000000000000000000000000000000000..3ad443eec80ff369e152a8acee808f5468623fdd GIT binary patch literal 105580 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 f|L39Ox itemsAndDiscounts = priceCalculator.calculateSpecialOfferMultiPrice( @@ -255,9 +259,10 @@ public void printReceipt() { InventoryItem inventoryItem = this.inventory.getItem(item.getSKU()); String variant = inventoryItem.getVariant().toString(); + String name = inventoryItem.getName().getString(); + String combinedName = name + " ("+variant.toLowerCase()+")"; - String combinedName = variant + " " + name; int amount; double price; double discount = item.getDiscount(); @@ -289,11 +294,132 @@ public void printReceipt() { printableListItems.add(formattedItem); totalCost += price; } + } + + // Add fillings as separate list, half hardcoded + ArrayList fillingsList = new ArrayList<>(); + for (BasketItem item : this.basketItems.values()) { + + InventoryItem inventoryItem = this.inventory.getItem(item.getSKU()); + String variant = inventoryItem.getVariant().toString(); + String name = inventoryItem.getName().getString(); + double price = inventoryItem.getPrice(); + + if (inventoryItem.getName() == ProductName.FILLING) { + + String combinedName = name + " ("+variant.toLowerCase()+")"; + + BasketItemFormatted formattedItem = new BasketItemFormatted( + combinedName, + 1, + price, + 0 + ); + } + totalCost += price; + } + + totalCost = priceCalculator.round((float) totalCost, 2); + + printGenerator = new PrintReceipt( + printableListItems, + totalCost + ); + + printGenerator.print(); + } + + public void printDiscountReceipt() { + + ArrayList itemsAndDiscounts = priceCalculator.calculateSpecialOfferMultiPrice( + this.inventory, + this.basketItems, + this.inventory.getSpecialOffersMultiPrice() + ); + ArrayList additionalDiscounts = priceCalculator.calculateSpecialOfferCombination( + this.inventory, + this.basketItems, + this.inventory.getSpecialOffersCombination() + ); + + + // Create a list of printable objects + // Calculates MultiPrice discounts + double totalCost = 0; + ArrayList printableListItems = new ArrayList<>(); + for (DiscountObjectMultiPrice item : itemsAndDiscounts) { + + // TODO: Refactor, unnecessary calculation + boolean hasDiscountItems = item.getNumOfDiscountItems() != 0; + boolean hasOrdinaryItems = item.getNumOfOrdinaryItems() != 0; + + InventoryItem inventoryItem = this.inventory.getItem(item.getSKU()); + String variant = inventoryItem.getVariant().toString(); + + String name = inventoryItem.getName().getString(); + String combinedName = name + " ("+variant.toLowerCase()+")"; + + int amount; + double price; + double discount; + + if (hasDiscountItems) { + amount = item.getNumOfDiscountItems(); + price = item.getPriceForDiscountItems(); + discount = item.getDiscount(); + + BasketItemFormatted formattedItem = new BasketItemFormatted( + combinedName, + amount, + price, + discount + ); + printableListItems.add(formattedItem); + totalCost += price; + } + + if (hasOrdinaryItems) { + amount = item.getNumOfOrdinaryItems(); + price = item.getPriceForOrdinaryItems(); + discount = 0.0; + + BasketItemFormatted formattedItem = new BasketItemFormatted( + combinedName, + amount, + price, + discount + ); + printableListItems.add(formattedItem); + totalCost += price; + } + } + + // Add fillings as separate list, half hardcoded + ArrayList fillingsList = new ArrayList<>(); + for (BasketItem item : this.basketItems.values()) { + InventoryItem inventoryItem = this.inventory.getItem(item.getSKU()); + String variant = inventoryItem.getVariant().toString(); + String name = inventoryItem.getName().getString(); + double price = inventoryItem.getPrice(); + + if (inventoryItem.getName() == ProductName.FILLING) { + + String combinedName = name + " ("+variant.toLowerCase()+")"; + + BasketItemFormatted formattedItem = new BasketItemFormatted( + combinedName, + 1, + price, + 0 + ); + } + totalCost += price; } totalCost = priceCalculator.round((float) totalCost, 2); + // TODO: Add combination offer // Calculate combination discounts // int additionalDiscount = 0; // for (DiscountObjectCombination item : additionalDiscounts) { @@ -301,7 +427,7 @@ public void printReceipt() { // } // totalCost = totalCost - additionalDiscount; - printGenerator = new PrintReceipt( + printGenerator = new PrintDiscountReceipt( printableListItems, totalCost ); diff --git a/src/main/java/com/booleanuk/core/domain-model.md b/src/main/java/com/booleanuk/core/domain-model.md index 1bbd3fdd9..e4a402fd0 100644 --- a/src/main/java/com/booleanuk/core/domain-model.md +++ b/src/main/java/com/booleanuk/core/domain-model.md @@ -94,28 +94,35 @@ | | `-List linkedFillingIds` | `getLinkedFillingIds` | Get a list of basket item ids' (the ids' of the fillings that belongs to this bagel). | List | | `Filling` extends `BasketItem` | | | | | | | | | | | +| `BasketItemFormatted` | | | (Extension 2 and 3) | | +| | | | | | | `InvalidBasketItemException` | | | | | | `MaxCapacityException` | | | | | ## Package: printgenerator -| Classes | Variables | Methods | Scenario | Output | -|-----------------------------------------------|---------------------------------------------|-------------------------------------------------------------------------|-----------------------------------------|--------| -| `PrintGenerator` | | `printCenterTitle(String text, int totalWidth)` | Center test in console/terminal output. | | -| | ` | `print()` | | | -| | | | | | -| `PrintInventoryMenu` extends `PrintGenerator` | `Map inventoryItems` | `printMenuPart(ProductName productName, String title, int outputWidth)` | | | -| | | @Override `print()` | | | -| | | | | | -| `PrintBasketItems` extends `PrintGenerator` | `Inventory inventory` | | | | -| | `Map basketItems` | | | | -| | `double basketTotalCost` | | | | -| | | @Override `print()` | | | +| Classes | Variables | Methods | Scenario | Output | +|-------------------------------------------------|---------------------------------------------|-------------------------------------------------------------------------|-----------------------------------------|--------| +| `PrintGenerator` | | `printCenterTitle(String text, int totalWidth)` | Center test in console/terminal output. | | +| | ` | `print()` | | | +| | | | | | +| `PrintInventoryMenu` extends `PrintGenerator` | `Map inventoryItems` | `printMenuPart(ProductName productName, String title, int outputWidth)` | | | +| | | @Override `print()` | | | +| | | | | | +| `PrintBasketItems` extends `PrintGenerator` | `Inventory inventory` | | | | +| | `Map basketItems` | | | | +| | `double basketTotalCost` | | | | +| | | @Override `print()` | | | +| | | | | | +| `PrintReceipt` extends `PrintGenerator` | | | (Extension 2) | | +| `PrintDiscountReceipt` extends `PrintGenerator` | | | (Extension 3) | | # Class Diagram -## Diagram -TODO: UPDATE.... -![Class Diagram](/assets/images/gleek_class-diagram.png) -## Code -TODO: ..... + + + ![Class Diagram](/assets/images/class_diagram_inventory.png) + ![Class Diagram](/assets/images/class_diagram_basket.png) + ![Class Diagram](/assets/images/class_diagram_printGenerator.png) diff --git a/src/main/java/com/booleanuk/core/printgenerator/PrintDiscountReceipt.java b/src/main/java/com/booleanuk/core/printgenerator/PrintDiscountReceipt.java new file mode 100644 index 000000000..314b29daf --- /dev/null +++ b/src/main/java/com/booleanuk/core/printgenerator/PrintDiscountReceipt.java @@ -0,0 +1,76 @@ +package com.booleanuk.core.printgenerator; + +import com.booleanuk.core.basket.BasketItemFormatted; +import com.booleanuk.core.calculators.DiscountObjectMultiPrice; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; + +public class PrintDiscountReceipt extends PrintGenerator{ + + private String dateCreated; + private ArrayList pritableItemsList; + private double totalCost; + + public PrintDiscountReceipt(ArrayList pritableItemsList, double totalCost) { + this.dateCreated = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")); + this.pritableItemsList = pritableItemsList; + this.totalCost = totalCost; + } + + @Override + public void print() { + + // TODO: not good to let a print function calculate, should be refactored + double totalDiscount = 0; + + // Variables for e.g. "%-15s %-15s %n", keep blank space + String leftAlignSmall = "%7s "; + String leftAlign = "%-23s "; + String newLine = "%n"; + String divider = "----------------------------------------"; + int totalwidth = 40; + + System.out.println(); + printCenterTitle("~~~Bob's Bagels ~~~", totalwidth); + System.out.println(); + printCenterTitle(dateCreated.toString(), totalwidth); + System.out.println(); + System.out.println(divider); + System.out.println(); + + double total = 0.0; + for (BasketItemFormatted item : pritableItemsList) { + total += item.getDiscount(); // TODO: Should not calculate here, should refactor + + System.out.printf( + leftAlign + leftAlignSmall + leftAlignSmall + newLine, + item.getName(), item.getAmount(), "£"+item.getPrice() + ); + + if (item.getDiscount() != 0.0) { + System.out.printf( + leftAlign + leftAlignSmall + leftAlignSmall + newLine, + "", "", "(-£"+item.getDiscount()+")" + ); + } + } + + System.out.println("\n"+divider); + System.out.printf( + "%s %26s" + newLine, + "Total cost: ", "£"+totalCost + ); + + System.out.println(); + printCenterTitle("You saved a total of £"+total, totalwidth); + printCenterTitle("on this shop!", totalwidth); + System.out.println(); + + System.out.println(); + printCenterTitle("Thank you", totalwidth); + printCenterTitle("for your order!", totalwidth); + System.out.println(); + } +} diff --git a/src/main/java/com/booleanuk/core/printgenerator/PrintReceipt.java b/src/main/java/com/booleanuk/core/printgenerator/PrintReceipt.java index 970300204..1fd8ca73e 100644 --- a/src/main/java/com/booleanuk/core/printgenerator/PrintReceipt.java +++ b/src/main/java/com/booleanuk/core/printgenerator/PrintReceipt.java @@ -30,10 +30,10 @@ public void print() { // Variables for e.g. "%-15s %-15s %n", keep blank space String leftAlignSmall = "%7s "; - String leftAlign = "%-17s "; + String leftAlign = "%-23s "; String newLine = "%n"; - String divider = "---------------------------------"; - int totalwidth = 33; + String divider = "----------------------------------------"; + int totalwidth = 40; System.out.println(); printCenterTitle("~~~Bob's Bagels ~~~", totalwidth); @@ -57,6 +57,9 @@ public void print() { "Total cost: ", "£"+totalCost ); System.out.println(); + printCenterTitle("Thank you", totalwidth); + printCenterTitle("for your order!", totalwidth); + System.out.println(); } } diff --git a/src/test/java/com/booleanuk/core/basket/BasketTest.java b/src/test/java/com/booleanuk/core/basket/BasketTest.java index 521ce69ee..5b3b12b4a 100644 --- a/src/test/java/com/booleanuk/core/basket/BasketTest.java +++ b/src/test/java/com/booleanuk/core/basket/BasketTest.java @@ -198,20 +198,38 @@ public void printReceipt() { for (int i = 0; i < 3; i++) { basket.add(new Bagel("COFB")); } + basket.add(new Bagel("BAGE", Arrays.asList("FILS","FILB"))); basket.printReceipt(); - // Everything Bagel, 6, 2.49 - // TODO: How to add test here? Have test in priceCalculator + // NOTE Tests are in priceCalculator } // Extension 3 -// @Test -// public void printDiscountReceipt() { -// inventory = new Inventory(); -// basket = new Basket(new Inventory()); -// -// basket.printReceipt() -// -// } + @Test + public void printDiscountReceipt() { + inventory = new Inventory(); + basket = new Basket(new Inventory()); + basket.changeMaxCapacity(40); + + for (int i = 0; i < 2; i++) { + basket.add(new Bagel("BAGO")); + } + + for (int i = 0; i < 12; i++) { + basket.add(new Bagel("BAGP")); + } + + for (int i = 0; i < 6; i++) { + basket.add(new Bagel("BAGE")); + } + + for (int i = 0; i < 3; i++) { + basket.add(new Bagel("COFB")); + } + basket.add(new Bagel("BAGE", Arrays.asList("FILS","FILB"))); + basket.printDiscountReceipt(); + + // NOTE Tests are in priceCalculator + } } diff --git a/src/test/java/com/booleanuk/core/calculators/PriceCalculatorTest.java b/src/test/java/com/booleanuk/core/calculators/PriceCalculatorTest.java index 76c53af9f..0d7251ba3 100644 --- a/src/test/java/com/booleanuk/core/calculators/PriceCalculatorTest.java +++ b/src/test/java/com/booleanuk/core/calculators/PriceCalculatorTest.java @@ -209,5 +209,5 @@ public void calculateCombinationDiscountShouldReturnDiscounts() { } // TODO: - // Check why BGLO doesn't exist - WRITE IN README THAT I HAVE DIFFERENT SKU's + // NOTE: I have different SKU's than in the examples because I create SKU differently } From 87e5fc7b543245a1dc0a1ef46a6bbdc6557ced18 Mon Sep 17 00:00:00 2001 From: shyye Date: Mon, 26 Aug 2024 19:06:08 +0200 Subject: [PATCH 93/93] Update domain and readme --- src/main/java/com/booleanuk/core/README.md | 1 + src/main/java/com/booleanuk/core/domain-model.md | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/main/java/com/booleanuk/core/README.md b/src/main/java/com/booleanuk/core/README.md index c2e56e192..97c039226 100644 --- a/src/main/java/com/booleanuk/core/README.md +++ b/src/main/java/com/booleanuk/core/README.md @@ -2,6 +2,7 @@ NOTES! - I have done Core and Extension 1-3 +- The domain model and class diagram are in [domain-model.md](domain-model.md) - The classes printInventoryMenu and printInventoryBasket were created during the core part and are not a part of the requirements - I did overthink a lot in this exercise, I'm not happy with all parts at the end, I think it could be much more simplified. - There are some code duplications and I have commented "TODO:" on things I'm unsure about or things I think could be designed better. diff --git a/src/main/java/com/booleanuk/core/domain-model.md b/src/main/java/com/booleanuk/core/domain-model.md index e4a402fd0..9e8b0a458 100644 --- a/src/main/java/com/booleanuk/core/domain-model.md +++ b/src/main/java/com/booleanuk/core/domain-model.md @@ -122,6 +122,8 @@ --> +NOTE! Some classes are excluded from the class diagram, and just included in the domain model. + ![Class Diagram](/assets/images/class_diagram_inventory.png) ![Class Diagram](/assets/images/class_diagram_basket.png) ![Class Diagram](/assets/images/class_diagram_printGenerator.png)