From 1466f131a1093bc2a486fb5d426a4c1a52bdda11 Mon Sep 17 00:00:00 2001 From: Tuva Aarseth Date: Mon, 19 Aug 2024 14:12:48 +0200 Subject: [PATCH 01/16] Created class diagram and domain model. --- class_diagram.jpg | Bin 0 -> 39050 bytes domain-model.md | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 class_diagram.jpg create mode 100644 domain-model.md diff --git a/class_diagram.jpg b/class_diagram.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7cf057185cc7090bd2efe485b608d7d397704fa6 GIT binary patch literal 39050 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 TqLj?*Z_9&xryxAW->3fv(EyIW literal 0 HcmV?d00001 diff --git a/domain-model.md b/domain-model.md new file mode 100644 index 000000000..943951870 --- /dev/null +++ b/domain-model.md @@ -0,0 +1,32 @@ +## Class diagram +![](./class_diagram.jpg) + + + +### Item class +| Method | Scenario | Output | +|----------|-------------------|--------| +| `Item()` | Class constructor | - | + +### Menu class +| Method | Scenario | Output | +|--------------------------------|-----------------------------------------------------|-------------------------------| +| `getMenu()` | - | List of menu | +| `getItemPrice(itemId: String)` | Item exists in menu
Item does not exist in menu | Item price
-1 (try catch) | + + +### Basket class + +| Method | Scenario | Outcome | Output | +|---------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `addItem(itemId: String)` | Item exists in menu but not in basketItems
Item exists in menu and in basketItems
Item does not exist in menu | Item is added to basketItems with the correct quantity
The quantity of the item in basketItems is changed
No changes | "'itemVariant' 'itemName' added to basket, quantity: 'quantity'."
"'itemVariant' 'itemName' added to basket, quantity: 'quantity'."
"This item is not on the menu." | +| `removeItem(itemId: String, removeDuplicates: Boolean)` | Item exists in basketItems and removeDuplicates=true
Item exists in basketItems and removeDuplicates=false
Item does not exist in basket | | "'itemVariant' 'itemName' removed from basket, quantity: 'quantity'."
"'itemVariant' 'itemName' removed from basket, quantity: 1."
"This item does not exist in your basket." | +| `sumOrder()` | basketItems is not empty
basketItems is empty | | "The sum of your order is: 'sum'"
"Your basket is empty." | +| `setBasketSize(int)` | Basket capacity is changed to a positive integer by a "manager"
Basket capacity value is not positive | |Return true
Return false | + + +### Assumptions: + +- Fillings can be added regardless of the presence of a bagel in the basket. +- Fillings, coffee, and bagels count toward the maximum basket size. +- The "manager" role is purely fictional and not actually implemented \ No newline at end of file From dc5324e1c6bbb6a32d34573f942c0f15abcea1a0 Mon Sep 17 00:00:00 2001 From: Tuva Aarseth Date: Mon, 19 Aug 2024 15:12:07 +0200 Subject: [PATCH 02/16] Created tests for all methods --- domain-model.md | 12 ++-- src/main/java/com/booleanuk/core/Basket.java | 4 ++ src/main/java/com/booleanuk/core/Item.java | 4 ++ src/main/java/com/booleanuk/core/Menu.java | 4 ++ .../java/com/booleanuk/core/BasketTest.java | 58 +++++++++++++++++++ .../java/com/booleanuk/core/ItemTest.java | 4 ++ .../java/com/booleanuk/core/MenuTest.java | 25 ++++++++ 7 files changed, 105 insertions(+), 6 deletions(-) create mode 100644 src/main/java/com/booleanuk/core/Basket.java create mode 100644 src/main/java/com/booleanuk/core/Item.java create mode 100644 src/main/java/com/booleanuk/core/Menu.java create mode 100644 src/test/java/com/booleanuk/core/BasketTest.java create mode 100644 src/test/java/com/booleanuk/core/ItemTest.java create mode 100644 src/test/java/com/booleanuk/core/MenuTest.java diff --git a/domain-model.md b/domain-model.md index 943951870..c9a9e03c1 100644 --- a/domain-model.md +++ b/domain-model.md @@ -17,12 +17,12 @@ ### Basket class -| Method | Scenario | Outcome | Output | -|---------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `addItem(itemId: String)` | Item exists in menu but not in basketItems
Item exists in menu and in basketItems
Item does not exist in menu | Item is added to basketItems with the correct quantity
The quantity of the item in basketItems is changed
No changes | "'itemVariant' 'itemName' added to basket, quantity: 'quantity'."
"'itemVariant' 'itemName' added to basket, quantity: 'quantity'."
"This item is not on the menu." | -| `removeItem(itemId: String, removeDuplicates: Boolean)` | Item exists in basketItems and removeDuplicates=true
Item exists in basketItems and removeDuplicates=false
Item does not exist in basket | | "'itemVariant' 'itemName' removed from basket, quantity: 'quantity'."
"'itemVariant' 'itemName' removed from basket, quantity: 1."
"This item does not exist in your basket." | -| `sumOrder()` | basketItems is not empty
basketItems is empty | | "The sum of your order is: 'sum'"
"Your basket is empty." | -| `setBasketSize(int)` | Basket capacity is changed to a positive integer by a "manager"
Basket capacity value is not positive | |Return true
Return false | +| Method | Scenario | Outcome | Output | +|---------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `addItem(itemId: String, quantity: int)` | Item exists in menu but not in basketItems
Item exists in menu and in basketItems
Item does not exist in menu | Item is added to basketItems with the correct quantity
The quantity of the item in basketItems is changed
- | "'quantity' 'itemVariant' 'itemName' added to basket."
"'quantity' 'itemVariant' 'itemName' added to basket."
"This item is not on the menu." | +| `removeItem(itemId: String, removeDuplicates: Boolean)` | Item exists in basketItems and removeDuplicates=true
Item exists in basketItems and removeDuplicates=false
Item does not exist in basket | Entry is removed from basketItems
The quantity of the item in basketItems is subtracted 1.
- | "'quantity' 'itemVariant' 'itemName's removed from basket."
"'itemVariant' 'itemName' removed from basket."
"This item does not exist in your basket." | +| `sumOrder()` | basketItems is not empty
basketItems is empty | | "The sum of your order is: 'sum'"
"Your basket is empty." | +| `setBasketSize(int)` | Basket capacity is changed to a positive integer by a "manager"
Basket capacity value is not positive | | Return true
Return false | ### Assumptions: 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..4aab45ed7 --- /dev/null +++ b/src/main/java/com/booleanuk/core/Basket.java @@ -0,0 +1,4 @@ +package com.booleanuk.core; + +public class Basket { +} diff --git a/src/main/java/com/booleanuk/core/Item.java b/src/main/java/com/booleanuk/core/Item.java new file mode 100644 index 000000000..b85344c21 --- /dev/null +++ b/src/main/java/com/booleanuk/core/Item.java @@ -0,0 +1,4 @@ +package com.booleanuk.core; + +public class Item { +} diff --git a/src/main/java/com/booleanuk/core/Menu.java b/src/main/java/com/booleanuk/core/Menu.java new file mode 100644 index 000000000..6bbbf156e --- /dev/null +++ b/src/main/java/com/booleanuk/core/Menu.java @@ -0,0 +1,4 @@ +package com.booleanuk.core; + +public class Menu { +} 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..53e38dc94 --- /dev/null +++ b/src/test/java/com/booleanuk/core/BasketTest.java @@ -0,0 +1,58 @@ +package com.booleanuk.core; +/* + @Test + public void testAddBagel(){ + Basket basket = new Basket(); + // Test if valid bagel is added to basket + Assertions.assertEquals("Bagel added to basket.", basket.addBagel("Sesame")); + Assertions.assertEquals("Bagel added to basket.", basket.addBagel("Oat")); + // Test if invalid bagel is not added to basket + Assertions.assertEquals("This bagel is not on the menu.", basket.addBagel("Totally not a bagel.")); + } +*/ + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class BasketTest { + @Test + public void testAddItem(){ + Basket basket = new Basket(); + + Assertions.assertEquals("2 Onion Bagel added to basket.", basket.addItem("BGLO", 2)); + Assertions.assertEquals("1 Plain Bagel added to basket.", basket.addItem("BGLP", 1)); + Assertions.assertEquals("This item is not on the menu.", basket.addItem("WRONG", 1)); + Assertions.assertEquals(3, basket.basketItems.size()); + } + + @Test + public void testRemoveItem(){ + Basket basket = new Basket(); + + basket.addItem("BGLO", 2); + basket.addItem("BGLP", 1); + Assertions.assertEquals("Plain Bagel removed from basket.", basket.removeItem("BGLP", false)); + Assertions.assertEquals(2, basket.basketItems.size()); + Assertions.assertEquals("2 Onion Bagels removed from basket.", basket.removeItem("BGLO", true)); + Assertions.assertEquals(0, basket.basketItems.size()); + } + + @Test + public void testSumOrder(){ + Basket basket = new Basket(); + + Assertions.assertEquals("Your basket is empty.", basket.sumOrder()); + basket.addItem("BGLO", 2); + basket.addItem("BGLP", 1); + + Assertions.assertEquals("The sum of your order is: 1.37", basket.sumOrder()); + } + + @Test + public void testSetBasketSize(){ + Basket basket = new Basket(); + + Assertions.assertTrue(basket.setBasketSize(10)); + Assertions.assertFalse(basket.setBasketSize(-2)); + } +} diff --git a/src/test/java/com/booleanuk/core/ItemTest.java b/src/test/java/com/booleanuk/core/ItemTest.java new file mode 100644 index 000000000..be04480f7 --- /dev/null +++ b/src/test/java/com/booleanuk/core/ItemTest.java @@ -0,0 +1,4 @@ +package com.booleanuk.core; + +public class ItemTest { +} diff --git a/src/test/java/com/booleanuk/core/MenuTest.java b/src/test/java/com/booleanuk/core/MenuTest.java new file mode 100644 index 000000000..c6056abd9 --- /dev/null +++ b/src/test/java/com/booleanuk/core/MenuTest.java @@ -0,0 +1,25 @@ +package com.booleanuk.core; +/* + @Test + public void testAddBagel(){ + Basket basket = new Basket(); + // Test if valid bagel is added to basket + Assertions.assertEquals("Bagel added to basket.", basket.addBagel("Sesame")); + Assertions.assertEquals("Bagel added to basket.", basket.addBagel("Oat")); + // Test if invalid bagel is not added to basket + Assertions.assertEquals("This bagel is not on the menu.", basket.addBagel("Totally not a bagel.")); + } +*/ + + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class MenuTest { + @Test + public void testGetItemPrice(){ + Menu menu = new Menu(); + + Assertions.assertEquals(0.49f, getItemPrice("BGLO")); + } +} From 11f0b63666b7f1b047075ae008c215914c705f8a Mon Sep 17 00:00:00 2001 From: Tuva Aarseth Date: Wed, 21 Aug 2024 12:24:12 +0200 Subject: [PATCH 03/16] Core implemented --- domain-model.md | 21 ++--- src/main/java/com/booleanuk/core/Basket.java | 83 +++++++++++++++++++ src/main/java/com/booleanuk/core/Item.java | 29 +++++++ src/main/java/com/booleanuk/core/Menu.java | 57 +++++++++++++ .../java/com/booleanuk/core/BasketTest.java | 66 +++++++++------ .../java/com/booleanuk/core/MenuTest.java | 26 ++---- 6 files changed, 231 insertions(+), 51 deletions(-) diff --git a/domain-model.md b/domain-model.md index c9a9e03c1..ef91e7b2a 100644 --- a/domain-model.md +++ b/domain-model.md @@ -9,20 +9,21 @@ | `Item()` | Class constructor | - | ### Menu class -| Method | Scenario | Output | -|--------------------------------|-----------------------------------------------------|-------------------------------| -| `getMenu()` | - | List of menu | -| `getItemPrice(itemId: String)` | Item exists in menu
Item does not exist in menu | Item price
-1 (try catch) | +| Method | Scenario | Output | +|-------------------------------|-----------------------------------------------------|----------------| +| `getMenu()` | - | List of menu | +| `itemExists(itemId: String)` | Item exists in menu
Item does not exist in menu | true
false | +| `getItemMenu(itemId: String)` | Item exists in menu
Item does not exist in menu | Item
null | ### Basket class -| Method | Scenario | Outcome | Output | -|---------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `addItem(itemId: String, quantity: int)` | Item exists in menu but not in basketItems
Item exists in menu and in basketItems
Item does not exist in menu | Item is added to basketItems with the correct quantity
The quantity of the item in basketItems is changed
- | "'quantity' 'itemVariant' 'itemName' added to basket."
"'quantity' 'itemVariant' 'itemName' added to basket."
"This item is not on the menu." | -| `removeItem(itemId: String, removeDuplicates: Boolean)` | Item exists in basketItems and removeDuplicates=true
Item exists in basketItems and removeDuplicates=false
Item does not exist in basket | Entry is removed from basketItems
The quantity of the item in basketItems is subtracted 1.
- | "'quantity' 'itemVariant' 'itemName's removed from basket."
"'itemVariant' 'itemName' removed from basket."
"This item does not exist in your basket." | -| `sumOrder()` | basketItems is not empty
basketItems is empty | | "The sum of your order is: 'sum'"
"Your basket is empty." | -| `setBasketSize(int)` | Basket capacity is changed to a positive integer by a "manager"
Basket capacity value is not positive | | Return true
Return false | +| Method | Scenario | Outcome | Output | +|---------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `addItem(itemId: String, quantity: int)` | Item exists in menu but not in basketItems
Item exists in menu and in basketItems
Item does not exist in menu
Basket is full | Item is added to basketItems with the correct quantity
The quantity of the item in basketItems is changed
-
- | "'quantity' 'itemVariant' 'itemName' added to basket."
"'quantity' 'itemVariant' 'itemName' added to basket."
"This item is not on the menu."
"Basket is full." | +| `removeItem(itemId: String, removeDuplicates: Boolean)` | Item exists in basketItems and removeDuplicates=true
Item exists in basketItems and removeDuplicates=false
Item does not exist in basket | Entry is removed from basketItems
The quantity of the item in basketItems is subtracted 1.
- | "'quantity' 'itemVariant' 'itemName's removed from basket."
"'itemVariant' 'itemName' removed from basket."
"This item does not exist in your basket." | +| `sumOrder()` | basketItems is not empty
basketItems is empty | | "The sum of your order is: 'sum'"
"Your basket is empty." | +| `setBasketSize(int)` | Basket capacity is changed to a positive integer by a "manager"
Basket capacity value is not positive | | Return true
Return false | ### Assumptions: diff --git a/src/main/java/com/booleanuk/core/Basket.java b/src/main/java/com/booleanuk/core/Basket.java index 4aab45ed7..0a240cc36 100644 --- a/src/main/java/com/booleanuk/core/Basket.java +++ b/src/main/java/com/booleanuk/core/Basket.java @@ -1,4 +1,87 @@ package com.booleanuk.core; +import java.util.HashMap; + public class Basket { + private int maxBasketSize; + private int basketSize; + private HashMap basketItems; + Menu menu = new Menu(); + + + public Basket(){ + this.maxBasketSize = 15; + this.basketItems = new HashMap<>(); + this.basketSize = 0; + } + + public Boolean setMaxBasketSize(int size){ + if (size>-1){ + this.maxBasketSize = size; + return true; + } + return false; + } + + public int getMaxBasketSize(){ + return maxBasketSize; + } + + public int getBasketSize(){ + return this.basketSize; + } + + public HashMap getBasketItems(){ + return this.basketItems; + } + + public String addItem(String itemId, int quantity){ + if (menu.itemExistsMenu(itemId)){ + if (basketSize < maxBasketSize){ + basketItems.put(menu.getMenuItem(itemId), quantity); + basketSize+=quantity; + return quantity + " " + menu.getMenuItem(itemId).getItemVariant() + " " + menu.getMenuItem(itemId).getItemName() + " added to basket."; + } + return "Basket is full."; + } + return "This item is not on the menu."; + } + + public String removeItem(String itemId, Boolean removeDuplicates){ + Item item = menu.getMenuItem(itemId); + if (basketItems.containsKey(item)){ + if (removeDuplicates){ + int quantity = basketItems.get(item); + basketItems.remove(item); + basketSize -= quantity; + return quantity + " " + item.getItemVariant() + " " + item.getItemName() + "s removed from basket."; + }else { + basketItems.put(item, basketItems.get(item)-1); + basketSize -= 1; + if (basketItems.get(item) == 0){ + basketItems.remove(item); + } + return item.getItemVariant() + " " + item.getItemName() + " removed from basket."; + } + + } + return "This item does not exist in your basket."; + } + + public String sumOrder(){ + if (basketSize == 0){ + return "Your basket is empty."; + } + + float totalSum = 0; + for (HashMap.Entry entry : basketItems.entrySet()){ + int quantity = entry.getValue(); + float price = entry.getKey().getItemPrice(); + + float sum = price * quantity; + totalSum += sum; + } + return "The sum of your order is: " + String.format("%.2f", totalSum); + } + } diff --git a/src/main/java/com/booleanuk/core/Item.java b/src/main/java/com/booleanuk/core/Item.java index b85344c21..135c5a424 100644 --- a/src/main/java/com/booleanuk/core/Item.java +++ b/src/main/java/com/booleanuk/core/Item.java @@ -1,4 +1,33 @@ package com.booleanuk.core; public class Item { + + private String itemSKU; + private float itemPrice; + private String itemName; + private String itemVariant; + + public Item(String itemSKU, float itemPrice, String itemName, String itemVariant){ + this.itemSKU = itemSKU; + this.itemPrice=itemPrice; + this.itemName=itemName; + this.itemVariant=itemVariant; + } + + public String getItemSKU(){ + return itemSKU; + } + + public float getItemPrice(){ + return itemPrice; + } + + public String getItemName(){ + return itemName; + } + + public String getItemVariant(){ + return itemVariant; + } + } diff --git a/src/main/java/com/booleanuk/core/Menu.java b/src/main/java/com/booleanuk/core/Menu.java index 6bbbf156e..7eceb8677 100644 --- a/src/main/java/com/booleanuk/core/Menu.java +++ b/src/main/java/com/booleanuk/core/Menu.java @@ -1,4 +1,61 @@ package com.booleanuk.core; +import java.util.ArrayList; + public class Menu { + + private final ArrayList menu= new ArrayList<>(){ + { + add(new Item("BGLO", 0.49f, "Bagel", "Onion")); + add(new Item("BGLP", 0.39f, "Bagel", "Plain")); + add(new Item("BGLE", 0.49f, "Bagel", "Everything")); + add(new Item("BGLS", 0.49f, "Bagel", "Sesame")); + add(new Item("COFB", 0.99f, "Bagel", "Black")); + add(new Item("COFW", 1.19f, "Bagel", "White")); + add(new Item("COFC", 1.29f, "Bagel", "Cappuccino")); + add(new Item("COFL", 1.29f, "Bagel", "Latte")); + add(new Item("FILB", 0.12f, "Bagel", "Bacon")); + add(new Item("FILE", 0.12f, "Bagel", "Egg")); + add(new Item("FILC", 0.12f, "Bagel", "Cheese")); + add(new Item("FILX", 0.12f, "Bagel", "Cream cheese")); + add(new Item("FILS", 0.12f, "Bagel", "Smoked salmon")); + add(new Item("FILH", 0.12f, "Bagel", "Ham")); + } + }; + + public ArrayList getMenu(){ + return this.menu; + } + + public boolean itemExistsMenu(String itemSKU){ + for (Item item : menu){ + if (item.getItemSKU().equals(itemSKU)){ + return true; + } + } + return false; + } + + public Item getMenuItem(String itemSKU){ + if (itemExistsMenu(itemSKU)){ + for (Item item : menu){ + if (item.getItemSKU().equals(itemSKU)){ + return item; + } + } + } + return null; + } + + public String getItemCost(String itemSKU){ + if (itemExistsMenu(itemSKU)){ + for (Item item : menu){ + if (item.getItemSKU().equals(itemSKU)){ + return String.format("%.2f", item.getItemPrice()); + } + } + } + return null; + } + } diff --git a/src/test/java/com/booleanuk/core/BasketTest.java b/src/test/java/com/booleanuk/core/BasketTest.java index 53e38dc94..75db5feed 100644 --- a/src/test/java/com/booleanuk/core/BasketTest.java +++ b/src/test/java/com/booleanuk/core/BasketTest.java @@ -1,58 +1,76 @@ package com.booleanuk.core; -/* - @Test - public void testAddBagel(){ - Basket basket = new Basket(); - // Test if valid bagel is added to basket - Assertions.assertEquals("Bagel added to basket.", basket.addBagel("Sesame")); - Assertions.assertEquals("Bagel added to basket.", basket.addBagel("Oat")); - // Test if invalid bagel is not added to basket - Assertions.assertEquals("This bagel is not on the menu.", basket.addBagel("Totally not a bagel.")); - } -*/ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; public class BasketTest { @Test - public void testAddItem(){ + public void addBagelToBasket(){ Basket basket = new Basket(); Assertions.assertEquals("2 Onion Bagel added to basket.", basket.addItem("BGLO", 2)); Assertions.assertEquals("1 Plain Bagel added to basket.", basket.addItem("BGLP", 1)); - Assertions.assertEquals("This item is not on the menu.", basket.addItem("WRONG", 1)); - Assertions.assertEquals(3, basket.basketItems.size()); + + Assertions.assertEquals(2, basket.getBasketItems().get(basket.menu.getMenuItem("BGLO"))); + Assertions.assertEquals(1, basket.getBasketItems().get(basket.menu.getMenuItem("BGLP"))); + Assertions.assertEquals(3, basket.getBasketSize()); } @Test - public void testRemoveItem(){ + public void removeBagelFromBasket(){ Basket basket = new Basket(); basket.addItem("BGLO", 2); basket.addItem("BGLP", 1); Assertions.assertEquals("Plain Bagel removed from basket.", basket.removeItem("BGLP", false)); - Assertions.assertEquals(2, basket.basketItems.size()); + Assertions.assertEquals(2, basket.getBasketSize()); Assertions.assertEquals("2 Onion Bagels removed from basket.", basket.removeItem("BGLO", true)); - Assertions.assertEquals(0, basket.basketItems.size()); + Assertions.assertEquals(0, basket.getBasketSize()); + } + + @Test + public void addBagelFullBasket(){ + Basket basket = new Basket(); + basket.addItem("BGLO", 15); + Assertions.assertEquals("Basket is full.", basket.addItem("BGLP", 1)); + + } + + @Test + public void changeBasketCapacity(){ + Basket basket = new Basket(); + + Assertions.assertTrue(basket.setMaxBasketSize(10)); + Assertions.assertEquals(10, basket.getMaxBasketSize()); + Assertions.assertFalse(basket.setMaxBasketSize(-2)); + } + + @Test + public void removeItemNotInBasket(){ + Basket basket = new Basket(); + + Assertions.assertEquals("This item does not exist in your basket.", basket.removeItem("COFB", false)); } @Test - public void testSumOrder(){ + public void totalCostItemsInBasket(){ Basket basket = new Basket(); Assertions.assertEquals("Your basket is empty.", basket.sumOrder()); + basket.addItem("BGLO", 2); basket.addItem("BGLP", 1); + basket.addItem("FILE", 1); + basket.addItem("COFC", 1); + - Assertions.assertEquals("The sum of your order is: 1.37", basket.sumOrder()); + Assertions.assertEquals("The sum of your order is: 2.78", basket.sumOrder()); } @Test - public void testSetBasketSize(){ - Basket basket = new Basket(); - - Assertions.assertTrue(basket.setBasketSize(10)); - Assertions.assertFalse(basket.setBasketSize(-2)); + public void getItemCost(){ + Menu menu = new Menu(); + Assertions.assertEquals("0.49", menu.getItemCost("BGLS")); } + } diff --git a/src/test/java/com/booleanuk/core/MenuTest.java b/src/test/java/com/booleanuk/core/MenuTest.java index c6056abd9..6c6647b0b 100644 --- a/src/test/java/com/booleanuk/core/MenuTest.java +++ b/src/test/java/com/booleanuk/core/MenuTest.java @@ -1,25 +1,17 @@ package com.booleanuk.core; -/* - @Test - public void testAddBagel(){ - Basket basket = new Basket(); - // Test if valid bagel is added to basket - Assertions.assertEquals("Bagel added to basket.", basket.addBagel("Sesame")); - Assertions.assertEquals("Bagel added to basket.", basket.addBagel("Oat")); - // Test if invalid bagel is not added to basket - Assertions.assertEquals("This bagel is not on the menu.", basket.addBagel("Totally not a bagel.")); - } -*/ - import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -public class MenuTest { - @Test - public void testGetItemPrice(){ - Menu menu = new Menu(); +class MenuTest { + Menu menu; - Assertions.assertEquals(0.49f, getItemPrice("BGLO")); + public MenuTest(){ + this.menu = new Menu(); } + + /*@Test + public void testGetItemPrice(){ + Assertions.assertEquals(0.49f, menu.getItemPrice("BGLO")); + }*/ } From 78d12916191c8a89712e7a47be764f617fdfb063 Mon Sep 17 00:00:00 2001 From: Tuva Aarseth Date: Wed, 21 Aug 2024 14:54:14 +0200 Subject: [PATCH 04/16] Extension 1: Updated domain model and created tests. --- domain-model.md | 11 ++-- src/main/java/com/booleanuk/core/Basket.java | 31 +++++---- .../java/com/booleanuk/core/BasketTest.java | 63 ++++++++++++++++++- 3 files changed, 87 insertions(+), 18 deletions(-) diff --git a/domain-model.md b/domain-model.md index ef91e7b2a..c8e966c95 100644 --- a/domain-model.md +++ b/domain-model.md @@ -18,12 +18,13 @@ ### Basket class -| Method | Scenario | Outcome | Output | -|---------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `addItem(itemId: String, quantity: int)` | Item exists in menu but not in basketItems
Item exists in menu and in basketItems
Item does not exist in menu
Basket is full | Item is added to basketItems with the correct quantity
The quantity of the item in basketItems is changed
-
- | "'quantity' 'itemVariant' 'itemName' added to basket."
"'quantity' 'itemVariant' 'itemName' added to basket."
"This item is not on the menu."
"Basket is full." | +| Method | Scenario | Outcome | Output | +|---------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `addItem(itemId: String, quantity: int)` | Item exists in menu but not in basketItems
Item exists in menu and in basketItems
Item does not exist in menu
Basket is full | Item is added to basketItems with the correct quantity
The quantity of the item in basketItems is changed
-
- | "'quantity' 'itemVariant' 'itemName' added to basket."
"'quantity' 'itemVariant' 'itemName' added to basket."
"This item is not on the menu."
"Basket is full." | | `removeItem(itemId: String, removeDuplicates: Boolean)` | Item exists in basketItems and removeDuplicates=true
Item exists in basketItems and removeDuplicates=false
Item does not exist in basket | Entry is removed from basketItems
The quantity of the item in basketItems is subtracted 1.
- | "'quantity' 'itemVariant' 'itemName's removed from basket."
"'itemVariant' 'itemName' removed from basket."
"This item does not exist in your basket." | -| `sumOrder()` | basketItems is not empty
basketItems is empty | | "The sum of your order is: 'sum'"
"Your basket is empty." | -| `setBasketSize(int)` | Basket capacity is changed to a positive integer by a "manager"
Basket capacity value is not positive | | Return true
Return false | +| `sumOrder()` | basketItems is not empty
basketItems is empty | | "The sum of your order is: 'sum'"
"Your basket is empty." | +| `sumOrderDiscount()` | 6 bagels of any kind
12 bagels of any kind
1 bagel and 1 coffee | Sum = 2.49
Sum = 3.99
Sum = 1.25 | "The sum of your order is: 'sum'" | +| `setBasketSize(int)` | Basket capacity is changed to a positive integer by a "manager"
Basket capacity value is not positive | | Return true
Return false | ### Assumptions: diff --git a/src/main/java/com/booleanuk/core/Basket.java b/src/main/java/com/booleanuk/core/Basket.java index 0a240cc36..65bfa8f61 100644 --- a/src/main/java/com/booleanuk/core/Basket.java +++ b/src/main/java/com/booleanuk/core/Basket.java @@ -5,7 +5,7 @@ public class Basket { private int maxBasketSize; private int basketSize; - private HashMap basketItems; + private HashMap basketItems; Menu menu = new Menu(); @@ -31,14 +31,19 @@ public int getBasketSize(){ return this.basketSize; } - public HashMap getBasketItems(){ + public HashMap getBasketItems(){ return this.basketItems; } public String addItem(String itemId, int quantity){ if (menu.itemExistsMenu(itemId)){ if (basketSize < maxBasketSize){ - basketItems.put(menu.getMenuItem(itemId), quantity); + if (basketItems.containsKey(itemId)){ + basketItems.put(itemId, quantity += basketItems.get(itemId)); + basketSize+=quantity; + return quantity + " " + menu.getMenuItem(itemId).getItemVariant() + " " + menu.getMenuItem(itemId).getItemName() + " added to basket."; + } + basketItems.put(itemId, quantity); basketSize+=quantity; return quantity + " " + menu.getMenuItem(itemId).getItemVariant() + " " + menu.getMenuItem(itemId).getItemName() + " added to basket."; } @@ -49,17 +54,17 @@ public String addItem(String itemId, int quantity){ public String removeItem(String itemId, Boolean removeDuplicates){ Item item = menu.getMenuItem(itemId); - if (basketItems.containsKey(item)){ + if (basketItems.containsKey(itemId)){ if (removeDuplicates){ - int quantity = basketItems.get(item); - basketItems.remove(item); + int quantity = basketItems.get(itemId); + basketItems.remove(itemId); basketSize -= quantity; return quantity + " " + item.getItemVariant() + " " + item.getItemName() + "s removed from basket."; }else { - basketItems.put(item, basketItems.get(item)-1); + basketItems.put(itemId, basketItems.get(itemId)-1); basketSize -= 1; - if (basketItems.get(item) == 0){ - basketItems.remove(item); + if (basketItems.get(itemId) == 0){ + basketItems.remove(itemId); } return item.getItemVariant() + " " + item.getItemName() + " removed from basket."; } @@ -74,9 +79,9 @@ public String sumOrder(){ } float totalSum = 0; - for (HashMap.Entry entry : basketItems.entrySet()){ + for (HashMap.Entry entry : basketItems.entrySet()){ int quantity = entry.getValue(); - float price = entry.getKey().getItemPrice(); + float price = menu.getMenuItem(entry.getKey()).getItemPrice(); float sum = price * quantity; totalSum += sum; @@ -84,4 +89,8 @@ public String sumOrder(){ return "The sum of your order is: " + String.format("%.2f", totalSum); } + public String sumOrderDiscount(){ + return "SUM"; + } + } diff --git a/src/test/java/com/booleanuk/core/BasketTest.java b/src/test/java/com/booleanuk/core/BasketTest.java index 75db5feed..ee82c4790 100644 --- a/src/test/java/com/booleanuk/core/BasketTest.java +++ b/src/test/java/com/booleanuk/core/BasketTest.java @@ -4,6 +4,7 @@ import org.junit.jupiter.api.Test; public class BasketTest { + // Core requirements tests @Test public void addBagelToBasket(){ Basket basket = new Basket(); @@ -11,8 +12,8 @@ public void addBagelToBasket(){ Assertions.assertEquals("2 Onion Bagel added to basket.", basket.addItem("BGLO", 2)); Assertions.assertEquals("1 Plain Bagel added to basket.", basket.addItem("BGLP", 1)); - Assertions.assertEquals(2, basket.getBasketItems().get(basket.menu.getMenuItem("BGLO"))); - Assertions.assertEquals(1, basket.getBasketItems().get(basket.menu.getMenuItem("BGLP"))); + Assertions.assertEquals(2, basket.getBasketItems().get("BGLO")); + Assertions.assertEquals(1, basket.getBasketItems().get("BGLP")); Assertions.assertEquals(3, basket.getBasketSize()); } @@ -65,6 +66,9 @@ public void totalCostItemsInBasket(){ Assertions.assertEquals("The sum of your order is: 2.78", basket.sumOrder()); + basket.addItem("COFC", 1); + Assertions.assertEquals("The sum of your order is: 4.07", basket.sumOrder()); + } @Test @@ -73,4 +77,59 @@ public void getItemCost(){ Assertions.assertEquals("0.49", menu.getItemCost("BGLS")); } + // Extension 1 requirements tests + + @Test + public void bagelDiscount(){ + Basket basket = new Basket(); + basket.setMaxBasketSize(25); + + basket.addItem("BGLO", 5); + basket.addItem("FILB", 1); + Assertions.assertEquals("The sum of your order is: 2.57", basket.sumOrderDiscount()); + + basket.addItem("BGLO", 1); + Assertions.assertEquals("The sum of your order is: 2.61", basket.sumOrderDiscount()); + + basket.addItem("BGLP", 3); + Assertions.assertEquals("The sum of your order is: 3.78", basket.sumOrderDiscount()); + + basket.addItem("BGLS", 3); + Assertions.assertEquals("The sum of your order is: 4.11", basket.sumOrderDiscount()); + + basket.addItem("BGLE", 1); + Assertions.assertEquals("The sum of your order is: 4.60", basket.sumOrderDiscount()); + + basket.addItem("BGLE", 11); + Assertions.assertEquals("The sum of your order is: 8.10", basket.sumOrderDiscount()); + + } + + @Test + public void bagelCoffeeDiscount(){ + Basket basket = new Basket(); + + basket.addItem("BGLO", 2); + basket.addItem("COFW", 1); + + Assertions.assertEquals("The sum of your order is: 1.74", basket.sumOrderDiscount()); + basket.removeItem("BGLO", false); + + Assertions.assertEquals("The sum of your order is: 1.25", basket.sumOrderDiscount()); + + + } + + @Test + public void allDiscounts(){ + Basket basket = new Basket(); + basket.setMaxBasketSize(25); + + basket.addItem("BGLS", 6); + basket.addItem("BGLO", 13); + basket.addItem("FILC", 1); + basket.addItem("COFL", 1); + + Assertions.assertEquals("The sum of your order is: 7.85", basket.sumOrderDiscount()); + } } From 1e5cf4cb1bd469802c8762ac5e87f32ff54d443c Mon Sep 17 00:00:00 2001 From: Tuva Aarseth Date: Thu, 22 Aug 2024 14:45:34 +0200 Subject: [PATCH 05/16] Extension 1: Implementation to pass tests complete --- src/main/java/com/booleanuk/core/Basket.java | 96 ++++++------- .../java/com/booleanuk/core/CashRegister.java | 126 ++++++++++++++++++ src/main/java/com/booleanuk/core/Menu.java | 46 ++++--- .../java/com/booleanuk/core/BasketTest.java | 34 ++--- 4 files changed, 210 insertions(+), 92 deletions(-) create mode 100644 src/main/java/com/booleanuk/core/CashRegister.java diff --git a/src/main/java/com/booleanuk/core/Basket.java b/src/main/java/com/booleanuk/core/Basket.java index 65bfa8f61..dcc2cfeba 100644 --- a/src/main/java/com/booleanuk/core/Basket.java +++ b/src/main/java/com/booleanuk/core/Basket.java @@ -2,95 +2,83 @@ import java.util.HashMap; +import static com.booleanuk.core.Menu.*; + public class Basket { private int maxBasketSize; - private int basketSize; private HashMap basketItems; - Menu menu = new Menu(); public Basket(){ this.maxBasketSize = 15; this.basketItems = new HashMap<>(); - this.basketSize = 0; } public Boolean setMaxBasketSize(int size){ - if (size>-1){ - this.maxBasketSize = size; - return true; + if (size<0){ + return false; } - return false; + this.maxBasketSize = size; + return true; } public int getMaxBasketSize(){ - return maxBasketSize; + return this.maxBasketSize; } public int getBasketSize(){ - return this.basketSize; + if (isEmpty()){ + return 0; + } + + int basketSize = 0; + for (HashMap.Entry entry : basketItems.entrySet()){ + basketSize += entry.getValue(); + } + return basketSize; + } + + public boolean isEmpty(){ + return this.basketItems.isEmpty(); } public HashMap getBasketItems(){ return this.basketItems; } - public String addItem(String itemId, int quantity){ - if (menu.itemExistsMenu(itemId)){ - if (basketSize < maxBasketSize){ - if (basketItems.containsKey(itemId)){ - basketItems.put(itemId, quantity += basketItems.get(itemId)); - basketSize+=quantity; - return quantity + " " + menu.getMenuItem(itemId).getItemVariant() + " " + menu.getMenuItem(itemId).getItemName() + " added to basket."; - } - basketItems.put(itemId, quantity); - basketSize+=quantity; - return quantity + " " + menu.getMenuItem(itemId).getItemVariant() + " " + menu.getMenuItem(itemId).getItemName() + " added to basket."; - } + public String addItem(String itemId, int quantity) { + if (getBasketSize() == maxBasketSize){ return "Basket is full."; } - return "This item is not on the menu."; - } - - public String removeItem(String itemId, Boolean removeDuplicates){ - Item item = menu.getMenuItem(itemId); - if (basketItems.containsKey(itemId)){ - if (removeDuplicates){ - int quantity = basketItems.get(itemId); - basketItems.remove(itemId); - basketSize -= quantity; - return quantity + " " + item.getItemVariant() + " " + item.getItemName() + "s removed from basket."; - }else { - basketItems.put(itemId, basketItems.get(itemId)-1); - basketSize -= 1; - if (basketItems.get(itemId) == 0){ - basketItems.remove(itemId); - } - return item.getItemVariant() + " " + item.getItemName() + " removed from basket."; - } + if (!itemExistsMenu(itemId)){ + return "This item is not on the menu."; } - return "This item does not exist in your basket."; + + basketItems.merge(itemId, quantity, Integer::sum); + Item item = getMenuItem(itemId); + + return quantity + " " + item.getItemVariant() + + " " + item.getItemName() + " added to basket."; } - public String sumOrder(){ - if (basketSize == 0){ - return "Your basket is empty."; + + public String removeItem(String itemId, Boolean removeDuplicates){ + + if (!basketItems.containsKey(itemId)){ + return "This item does not exist in your basket."; } - float totalSum = 0; - for (HashMap.Entry entry : basketItems.entrySet()){ - int quantity = entry.getValue(); - float price = menu.getMenuItem(entry.getKey()).getItemPrice(); + Item item = getMenuItem(itemId); + int quantity = basketItems.get(itemId); - float sum = price * quantity; - totalSum += sum; + if (removeDuplicates | quantity == 1 ){ + basketItems.remove(itemId); + return quantity + " " + item.getItemVariant() + " " + item.getItemName() + " removed from basket."; } - return "The sum of your order is: " + String.format("%.2f", totalSum); - } - public String sumOrderDiscount(){ - return "SUM"; + basketItems.merge(itemId, -1, Integer::sum); + return "1 " + item.getItemVariant() + " " + item.getItemName() + " removed from basket."; } } diff --git a/src/main/java/com/booleanuk/core/CashRegister.java b/src/main/java/com/booleanuk/core/CashRegister.java new file mode 100644 index 000000000..c01ddefdf --- /dev/null +++ b/src/main/java/com/booleanuk/core/CashRegister.java @@ -0,0 +1,126 @@ +package com.booleanuk.core; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; + +import static com.booleanuk.core.Menu.*; + + +public class CashRegister { + Basket basket; + + public CashRegister(Basket basket){ + this.basket = basket; + } + + public String sumOrder(){ + + if (basket.isEmpty()){ + return "Your basket is empty."; + } + + float totalSum = 0; + for (HashMap.Entry entry : basket.getBasketItems().entrySet()){ + int quantity = entry.getValue(); + float price = getMenuItem(entry.getKey()).getItemPrice(); + + totalSum += price * quantity; + } + return "The sum of your order is: " + String.format("%.2f", totalSum); + } + + + /*while (bagelCount !=0 && quantity != 0){ + float price = getMenuItem(entry.getKey()).getItemPrice(); + totalSum += price; + bagelCount--; + quantity--; + } + return "The sum of your order is: " + String.format("%.2f", totalSum);*/ + + + public String sumOrderDiscount(){ + if (basket.isEmpty()){ + return "Your basket is empty."; + } + + float totalSum = 0; + int bagelCount = 0; + int coffeeCount = 0; + + for (HashMap.Entry entry : basket.getBasketItems().entrySet()){ + if (getMenuItem(entry.getKey()).getItemName().equals("Filling")){ + int quantity = entry.getValue(); + float price = getMenuItem(entry.getKey()).getItemPrice(); + + float sum = price * quantity; + totalSum += sum; + } + if (getMenuItem(entry.getKey()).getItemName().equals("Bagel")){ + int quantity = entry.getValue(); + bagelCount += quantity; + } + if (getMenuItem(entry.getKey()).getItemName().equals("Coffee")){ + int quantity = entry.getValue(); + coffeeCount += quantity; + } + } + + while (bagelCount >= 12){ + totalSum += 3.99f; + bagelCount -= 12; + } + + while (bagelCount>=6){ + totalSum += 2.49f; + bagelCount -= 6; + } + + while (bagelCount>0 && coffeeCount > 0){ + totalSum += 1.25f; + bagelCount -= 1; + coffeeCount -= 1; + } + + + if (bagelCount!= 0){ + ArrayList basketBagelsPrices = new ArrayList<>(); + + for (HashMap.Entry entry : basket.getBasketItems().entrySet()){ + Item item = getMenuItem(entry.getKey()); + int quantity = entry.getValue(); + + if ("Bagel".equals(item.getItemName())){ + for (int i = 0; i < quantity; i++ ){ + basketBagelsPrices.add(item.getItemPrice()); + } + } + } + + Collections.sort(basketBagelsPrices); + for (int i = 0; i < bagelCount; i++){ + totalSum += basketBagelsPrices.get(i); + + } + + return "The sum of your order is: " + String.format("%.2f", totalSum); + } + if (coffeeCount!= 0){ + for (HashMap.Entry entry : basket.getBasketItems().entrySet()){ + if ("Coffee".equals(getMenuItem(entry.getKey()).getItemName())){ + int quantity = entry.getValue(); + while (coffeeCount != 0 && quantity != 0){ + float price = getMenuItem(entry.getKey()).getItemPrice(); + totalSum += price; + coffeeCount--; + quantity--; + } + return "The sum of your order is: " + String.format("%.2f", totalSum); + } + } + } + + return "The sum of your order is: " + String.format("%.2f", totalSum); + } +} diff --git a/src/main/java/com/booleanuk/core/Menu.java b/src/main/java/com/booleanuk/core/Menu.java index 7eceb8677..3efc25c33 100644 --- a/src/main/java/com/booleanuk/core/Menu.java +++ b/src/main/java/com/booleanuk/core/Menu.java @@ -4,30 +4,32 @@ public class Menu { - private final ArrayList menu= new ArrayList<>(){ + public final static ArrayList menu = new ArrayList<>(); + + static { + populateMenu(); + } + + private static void populateMenu() { { - add(new Item("BGLO", 0.49f, "Bagel", "Onion")); - add(new Item("BGLP", 0.39f, "Bagel", "Plain")); - add(new Item("BGLE", 0.49f, "Bagel", "Everything")); - add(new Item("BGLS", 0.49f, "Bagel", "Sesame")); - add(new Item("COFB", 0.99f, "Bagel", "Black")); - add(new Item("COFW", 1.19f, "Bagel", "White")); - add(new Item("COFC", 1.29f, "Bagel", "Cappuccino")); - add(new Item("COFL", 1.29f, "Bagel", "Latte")); - add(new Item("FILB", 0.12f, "Bagel", "Bacon")); - add(new Item("FILE", 0.12f, "Bagel", "Egg")); - add(new Item("FILC", 0.12f, "Bagel", "Cheese")); - add(new Item("FILX", 0.12f, "Bagel", "Cream cheese")); - add(new Item("FILS", 0.12f, "Bagel", "Smoked salmon")); - add(new Item("FILH", 0.12f, "Bagel", "Ham")); + menu.add(new Item("BGLO", 0.49f, "Bagel", "Onion")); + menu.add(new Item("BGLP", 0.39f, "Bagel", "Plain")); + menu.add(new Item("BGLE", 0.49f, "Bagel", "Everything")); + menu.add(new Item("BGLS", 0.49f, "Bagel", "Sesame")); + menu.add(new Item("COFB", 0.99f, "Coffee", "Black")); + menu.add(new Item("COFW", 1.19f, "Coffee", "White")); + menu.add(new Item("COFC", 1.29f, "Coffee", "Cappuccino")); + menu.add(new Item("COFL", 1.29f, "Coffee", "Latte")); + menu.add(new Item("FILB", 0.12f, "Filling", "Bacon")); + menu.add(new Item("FILE", 0.12f, "Filling", "Egg")); + menu.add(new Item("FILC", 0.12f, "Filling", "Cheese")); + menu.add(new Item("FILX", 0.12f, "Filling", "Cream cheese")); + menu.add(new Item("FILS", 0.12f, "Filling", "Smoked salmon")); + menu.add(new Item("FILH", 0.12f, "Filling", "Ham")); } }; - public ArrayList getMenu(){ - return this.menu; - } - - public boolean itemExistsMenu(String itemSKU){ + public static boolean itemExistsMenu(String itemSKU){ for (Item item : menu){ if (item.getItemSKU().equals(itemSKU)){ return true; @@ -36,7 +38,7 @@ public boolean itemExistsMenu(String itemSKU){ return false; } - public Item getMenuItem(String itemSKU){ + public static Item getMenuItem(String itemSKU){ if (itemExistsMenu(itemSKU)){ for (Item item : menu){ if (item.getItemSKU().equals(itemSKU)){ @@ -47,7 +49,7 @@ public Item getMenuItem(String itemSKU){ return null; } - public String getItemCost(String itemSKU){ + public static String getItemCost(String itemSKU){ if (itemExistsMenu(itemSKU)){ for (Item item : menu){ if (item.getItemSKU().equals(itemSKU)){ diff --git a/src/test/java/com/booleanuk/core/BasketTest.java b/src/test/java/com/booleanuk/core/BasketTest.java index ee82c4790..b66a53027 100644 --- a/src/test/java/com/booleanuk/core/BasketTest.java +++ b/src/test/java/com/booleanuk/core/BasketTest.java @@ -23,9 +23,9 @@ public void removeBagelFromBasket(){ basket.addItem("BGLO", 2); basket.addItem("BGLP", 1); - Assertions.assertEquals("Plain Bagel removed from basket.", basket.removeItem("BGLP", false)); + Assertions.assertEquals("1 Plain Bagel removed from basket.", basket.removeItem("BGLP", false)); Assertions.assertEquals(2, basket.getBasketSize()); - Assertions.assertEquals("2 Onion Bagels removed from basket.", basket.removeItem("BGLO", true)); + Assertions.assertEquals("2 Onion Bagel removed from basket.", basket.removeItem("BGLO", true)); Assertions.assertEquals(0, basket.getBasketSize()); } @@ -56,8 +56,9 @@ public void removeItemNotInBasket(){ @Test public void totalCostItemsInBasket(){ Basket basket = new Basket(); + CashRegister register = new CashRegister(basket); - Assertions.assertEquals("Your basket is empty.", basket.sumOrder()); + Assertions.assertEquals("Your basket is empty.", register.sumOrder()); basket.addItem("BGLO", 2); basket.addItem("BGLP", 1); @@ -65,9 +66,9 @@ public void totalCostItemsInBasket(){ basket.addItem("COFC", 1); - Assertions.assertEquals("The sum of your order is: 2.78", basket.sumOrder()); + Assertions.assertEquals("The sum of your order is: 2.78", register.sumOrder()); basket.addItem("COFC", 1); - Assertions.assertEquals("The sum of your order is: 4.07", basket.sumOrder()); + Assertions.assertEquals("The sum of your order is: 4.07", register.sumOrder()); } @@ -82,47 +83,48 @@ public void getItemCost(){ @Test public void bagelDiscount(){ Basket basket = new Basket(); + CashRegister register = new CashRegister(basket); basket.setMaxBasketSize(25); basket.addItem("BGLO", 5); basket.addItem("FILB", 1); - Assertions.assertEquals("The sum of your order is: 2.57", basket.sumOrderDiscount()); + Assertions.assertEquals("The sum of your order is: 2.57", register.sumOrderDiscount()); basket.addItem("BGLO", 1); - Assertions.assertEquals("The sum of your order is: 2.61", basket.sumOrderDiscount()); + Assertions.assertEquals("The sum of your order is: 2.61", register.sumOrderDiscount()); basket.addItem("BGLP", 3); - Assertions.assertEquals("The sum of your order is: 3.78", basket.sumOrderDiscount()); + Assertions.assertEquals("The sum of your order is: 3.78", register.sumOrderDiscount()); basket.addItem("BGLS", 3); - Assertions.assertEquals("The sum of your order is: 4.11", basket.sumOrderDiscount()); + Assertions.assertEquals("The sum of your order is: 4.11", register.sumOrderDiscount()); basket.addItem("BGLE", 1); - Assertions.assertEquals("The sum of your order is: 4.60", basket.sumOrderDiscount()); + Assertions.assertEquals("The sum of your order is: 4.50", register.sumOrderDiscount()); basket.addItem("BGLE", 11); - Assertions.assertEquals("The sum of your order is: 8.10", basket.sumOrderDiscount()); + Assertions.assertEquals("The sum of your order is: 8.10", register.sumOrderDiscount()); } @Test public void bagelCoffeeDiscount(){ Basket basket = new Basket(); + CashRegister register = new CashRegister(basket); basket.addItem("BGLO", 2); basket.addItem("COFW", 1); - Assertions.assertEquals("The sum of your order is: 1.74", basket.sumOrderDiscount()); + Assertions.assertEquals("The sum of your order is: 1.74", register.sumOrderDiscount()); basket.removeItem("BGLO", false); - Assertions.assertEquals("The sum of your order is: 1.25", basket.sumOrderDiscount()); - - + Assertions.assertEquals("The sum of your order is: 1.25", register.sumOrderDiscount()); } @Test public void allDiscounts(){ Basket basket = new Basket(); + CashRegister register = new CashRegister(basket); basket.setMaxBasketSize(25); basket.addItem("BGLS", 6); @@ -130,6 +132,6 @@ public void allDiscounts(){ basket.addItem("FILC", 1); basket.addItem("COFL", 1); - Assertions.assertEquals("The sum of your order is: 7.85", basket.sumOrderDiscount()); + Assertions.assertEquals("The sum of your order is: 7.85", register.sumOrderDiscount()); } } From d27a4ca0a82e309db4db2ffb405a4354e71cfe05 Mon Sep 17 00:00:00 2001 From: Tuva Aarseth Date: Thu, 22 Aug 2024 18:37:44 +0200 Subject: [PATCH 06/16] Extension 1: Refactoring of discount and sum methods --- src/main/java/com/booleanuk/core/Basket.java | 2 +- .../java/com/booleanuk/core/CashRegister.java | 122 ++++++++++++++++-- .../java/com/booleanuk/core/BasketTest.java | 32 ++--- 3 files changed, 123 insertions(+), 33 deletions(-) diff --git a/src/main/java/com/booleanuk/core/Basket.java b/src/main/java/com/booleanuk/core/Basket.java index dcc2cfeba..bfeaa3096 100644 --- a/src/main/java/com/booleanuk/core/Basket.java +++ b/src/main/java/com/booleanuk/core/Basket.java @@ -72,7 +72,7 @@ public String removeItem(String itemId, Boolean removeDuplicates){ Item item = getMenuItem(itemId); int quantity = basketItems.get(itemId); - if (removeDuplicates | quantity == 1 ){ + if (removeDuplicates){ basketItems.remove(itemId); return quantity + " " + item.getItemVariant() + " " + item.getItemName() + " removed from basket."; } diff --git a/src/main/java/com/booleanuk/core/CashRegister.java b/src/main/java/com/booleanuk/core/CashRegister.java index c01ddefdf..972decd8a 100644 --- a/src/main/java/com/booleanuk/core/CashRegister.java +++ b/src/main/java/com/booleanuk/core/CashRegister.java @@ -9,25 +9,129 @@ public class CashRegister { Basket basket; + private float sum = 0; + private float discountedSum = 0; + private float totalDiscount = 0; public CashRegister(Basket basket){ this.basket = basket; } - public String sumOrder(){ + public String sumOrder() { - if (basket.isEmpty()){ + if (basket.isEmpty()) { return "Your basket is empty."; } + getDiscountBagel(); + int bagelCount = 0; + int coffeeCount = 0; - float totalSum = 0; + for (HashMap.Entry entry : basket.getBasketItems().entrySet()) { + Item item = getMenuItem(entry.getKey()); + if (item.getItemName().equals("Bagel")){ + bagelCount += entry.getValue(); + } + + if (item.getItemName().equals("Coffee")){ + coffeeCount += entry.getValue(); + } + } + if (basket.isEmpty()){ + return "The sum of your order is: " + String.format("%.2f", discountedSum); + } + + while (bagelCount!=0 && coffeeCount!=0){ + for (HashMap.Entry entry : basket.getBasketItems().entrySet()){ + Item item1 = getMenuItem(entry.getKey()); + if (item1.getItemName().equals("Bagel")){ + sum += (item1.getItemPrice()); + basket.removeItem(item1.getItemSKU(), false); + break; + } + } + for (HashMap.Entry entry2 : basket.getBasketItems().entrySet()){ + Item item2 = getMenuItem(entry2.getKey()); + if (item2.getItemName().equals("Coffee")){ + sum += (item2.getItemPrice()); + discountedSum += 1.25f; + basket.removeItem(item2.getItemSKU(), false); + break; + } + } + bagelCount--; + coffeeCount--; + } + + if (basket.isEmpty()){ + return "The sum of your order is: " + String.format("%.2f", discountedSum); + } for (HashMap.Entry entry : basket.getBasketItems().entrySet()){ + Item item = getMenuItem(entry.getKey()); int quantity = entry.getValue(); - float price = getMenuItem(entry.getKey()).getItemPrice(); + float price = item.getItemPrice(); - totalSum += price * quantity; + sum += quantity*price; + discountedSum += quantity*price; } - return "The sum of your order is: " + String.format("%.2f", totalSum); + + return "The sum of your order is: " + String.format("%.2f", discountedSum); + } + + /*float sum = 0; + float discountedSum = 0; + int bagelCount = 0; + int coffeeCount = 0; + + for (HashMap.Entry entry : basket.getBasketItems().entrySet()){ + int quantity = entry.getValue(); + float discount = 0; + + + /*if (getMenuItem(entry.getKey()).getItemName().equals("Bagel")){ + discount = getDiscountBagelAndRemainingQuantity(item, quantity)[0]; + + bagelCount += (int) getDiscountBagelAndRemainingQuantity(item, quantity)[1]; + } + + if (getMenuItem(entry.getKey()).getItemName().equals("Coffee")){ + coffeeCount += quantity; + }*/ + + /*float price = getMenuItem(entry.getKey()).getItemPrice(); + + sum += price * quantity; + discountedSum += (price * quantity) - discount; + } + + return "The sum of your order is: " + String.format("%.2f", discountedSum); + }*/ + + public void getDiscountBagel(){ + for (HashMap.Entry entry : basket.getBasketItems().entrySet()){ + Item item = getMenuItem(entry.getKey()); + if (item.getItemName().equals("Bagel")){ + while (entry.getValue() >= 12){ + sum += (item.getItemPrice() * 12); + discountedSum += 3.99f; + for (int i = 0; i<12; i++){ + basket.removeItem(item.getItemSKU(), false); + } + } + while (entry.getValue() >= 6){ + sum += (item.getItemPrice() * 6); + discountedSum += 2.49f; + for (int i = 0; i<6; i++){ + basket.removeItem(item.getItemSKU(), false); + } + } + } + + } + + } + + public float getDiscountBagelCoffee(int bagelCount, int coffeeCount){ + return 0; } @@ -40,7 +144,7 @@ public String sumOrder(){ return "The sum of your order is: " + String.format("%.2f", totalSum);*/ - public String sumOrderDiscount(){ + /*public String sumOrderDiscount(){ if (basket.isEmpty()){ return "Your basket is empty."; } @@ -120,7 +224,7 @@ public String sumOrderDiscount(){ } } } - return "The sum of your order is: " + String.format("%.2f", totalSum); - } + }*/ + } diff --git a/src/test/java/com/booleanuk/core/BasketTest.java b/src/test/java/com/booleanuk/core/BasketTest.java index b66a53027..164f17a24 100644 --- a/src/test/java/com/booleanuk/core/BasketTest.java +++ b/src/test/java/com/booleanuk/core/BasketTest.java @@ -53,7 +53,7 @@ public void removeItemNotInBasket(){ Assertions.assertEquals("This item does not exist in your basket.", basket.removeItem("COFB", false)); } - @Test + /*@Test public void totalCostItemsInBasket(){ Basket basket = new Basket(); CashRegister register = new CashRegister(basket); @@ -70,7 +70,7 @@ public void totalCostItemsInBasket(){ basket.addItem("COFC", 1); Assertions.assertEquals("The sum of your order is: 4.07", register.sumOrder()); - } + }*/ @Test public void getItemCost(){ @@ -78,6 +78,7 @@ public void getItemCost(){ Assertions.assertEquals("0.49", menu.getItemCost("BGLS")); } + // Extension 1 requirements tests @Test @@ -85,25 +86,13 @@ public void bagelDiscount(){ Basket basket = new Basket(); CashRegister register = new CashRegister(basket); basket.setMaxBasketSize(25); + basket.addItem("BGLO", 18); + basket.addItem("BGLP", 1); + basket.addItem("COFB",1); - basket.addItem("BGLO", 5); - basket.addItem("FILB", 1); - Assertions.assertEquals("The sum of your order is: 2.57", register.sumOrderDiscount()); - - basket.addItem("BGLO", 1); - Assertions.assertEquals("The sum of your order is: 2.61", register.sumOrderDiscount()); - - basket.addItem("BGLP", 3); - Assertions.assertEquals("The sum of your order is: 3.78", register.sumOrderDiscount()); - - basket.addItem("BGLS", 3); - Assertions.assertEquals("The sum of your order is: 4.11", register.sumOrderDiscount()); + Assertions.assertEquals("The sum of your order is: 7.73", register.sumOrder()); - basket.addItem("BGLE", 1); - Assertions.assertEquals("The sum of your order is: 4.50", register.sumOrderDiscount()); - basket.addItem("BGLE", 11); - Assertions.assertEquals("The sum of your order is: 8.10", register.sumOrderDiscount()); } @@ -115,10 +104,7 @@ public void bagelCoffeeDiscount(){ basket.addItem("BGLO", 2); basket.addItem("COFW", 1); - Assertions.assertEquals("The sum of your order is: 1.74", register.sumOrderDiscount()); - basket.removeItem("BGLO", false); - - Assertions.assertEquals("The sum of your order is: 1.25", register.sumOrderDiscount()); + Assertions.assertEquals("The sum of your order is: 1.74", register.sumOrder()); } @Test @@ -132,6 +118,6 @@ public void allDiscounts(){ basket.addItem("FILC", 1); basket.addItem("COFL", 1); - Assertions.assertEquals("The sum of your order is: 7.85", register.sumOrderDiscount()); + Assertions.assertEquals("The sum of your order is: 7.85", register.sumOrder()); } } From c51173b1d003dbf75d07d320b82dab7f132d11a7 Mon Sep 17 00:00:00 2001 From: Tuva Aarseth Date: Fri, 23 Aug 2024 09:31:19 +0200 Subject: [PATCH 07/16] Extension 1: refactoring of sum, discount and tests --- src/main/java/com/booleanuk/core/Basket.java | 12 +- .../java/com/booleanuk/core/CashRegister.java | 216 +++++------------- .../java/com/booleanuk/core/BasketTest.java | 19 -- 3 files changed, 61 insertions(+), 186 deletions(-) diff --git a/src/main/java/com/booleanuk/core/Basket.java b/src/main/java/com/booleanuk/core/Basket.java index bfeaa3096..26b3a08b5 100644 --- a/src/main/java/com/booleanuk/core/Basket.java +++ b/src/main/java/com/booleanuk/core/Basket.java @@ -27,7 +27,7 @@ public int getMaxBasketSize(){ } public int getBasketSize(){ - if (isEmpty()){ + if (basketItems.isEmpty()){ return 0; } @@ -39,7 +39,10 @@ public int getBasketSize(){ } public boolean isEmpty(){ - return this.basketItems.isEmpty(); + if (this.basketItems.isEmpty()){ + return true; + } + return getBasketSize() == 0; } public HashMap getBasketItems(){ @@ -72,6 +75,11 @@ public String removeItem(String itemId, Boolean removeDuplicates){ Item item = getMenuItem(itemId); int quantity = basketItems.get(itemId); + if (quantity==0){ + basketItems.remove(itemId); + return "This item does not exist in your basket."; + } + if (removeDuplicates){ basketItems.remove(itemId); return quantity + " " + item.getItemVariant() + " " + item.getItemName() + " removed from basket."; diff --git a/src/main/java/com/booleanuk/core/CashRegister.java b/src/main/java/com/booleanuk/core/CashRegister.java index 972decd8a..c42cddfa0 100644 --- a/src/main/java/com/booleanuk/core/CashRegister.java +++ b/src/main/java/com/booleanuk/core/CashRegister.java @@ -1,7 +1,5 @@ package com.booleanuk.core; -import java.util.ArrayList; -import java.util.Collections; import java.util.HashMap; import static com.booleanuk.core.Menu.*; @@ -22,209 +20,97 @@ public String sumOrder() { if (basket.isEmpty()) { return "Your basket is empty."; } - getDiscountBagel(); - int bagelCount = 0; - int coffeeCount = 0; - - for (HashMap.Entry entry : basket.getBasketItems().entrySet()) { - Item item = getMenuItem(entry.getKey()); - if (item.getItemName().equals("Bagel")){ - bagelCount += entry.getValue(); - } - if (item.getItemName().equals("Coffee")){ - coffeeCount += entry.getValue(); - } + if (!basket.isEmpty()){ + getDiscountBagel(); } - if (basket.isEmpty()){ - return "The sum of your order is: " + String.format("%.2f", discountedSum); - } - - while (bagelCount!=0 && coffeeCount!=0){ - for (HashMap.Entry entry : basket.getBasketItems().entrySet()){ - Item item1 = getMenuItem(entry.getKey()); - if (item1.getItemName().equals("Bagel")){ - sum += (item1.getItemPrice()); - basket.removeItem(item1.getItemSKU(), false); - break; - } - } - for (HashMap.Entry entry2 : basket.getBasketItems().entrySet()){ - Item item2 = getMenuItem(entry2.getKey()); - if (item2.getItemName().equals("Coffee")){ - sum += (item2.getItemPrice()); - discountedSum += 1.25f; - basket.removeItem(item2.getItemSKU(), false); - break; - } - } - bagelCount--; - coffeeCount--; - } - - if (basket.isEmpty()){ - return "The sum of your order is: " + String.format("%.2f", discountedSum); + if (!basket.isEmpty()) { + getDiscountCoffeeBagel(); } - for (HashMap.Entry entry : basket.getBasketItems().entrySet()){ - Item item = getMenuItem(entry.getKey()); - int quantity = entry.getValue(); - float price = item.getItemPrice(); - - sum += quantity*price; - discountedSum += quantity*price; + if (!basket.isEmpty()) { + getRemainingSum(); } return "The sum of your order is: " + String.format("%.2f", discountedSum); } - /*float sum = 0; - float discountedSum = 0; - int bagelCount = 0; - int coffeeCount = 0; - - for (HashMap.Entry entry : basket.getBasketItems().entrySet()){ - int quantity = entry.getValue(); - float discount = 0; - - - /*if (getMenuItem(entry.getKey()).getItemName().equals("Bagel")){ - discount = getDiscountBagelAndRemainingQuantity(item, quantity)[0]; - - bagelCount += (int) getDiscountBagelAndRemainingQuantity(item, quantity)[1]; - } - - if (getMenuItem(entry.getKey()).getItemName().equals("Coffee")){ - coffeeCount += quantity; - }*/ - - /*float price = getMenuItem(entry.getKey()).getItemPrice(); - - sum += price * quantity; - discountedSum += (price * quantity) - discount; - } - - return "The sum of your order is: " + String.format("%.2f", discountedSum); - }*/ - public void getDiscountBagel(){ for (HashMap.Entry entry : basket.getBasketItems().entrySet()){ - Item item = getMenuItem(entry.getKey()); - if (item.getItemName().equals("Bagel")){ + Item bagel = getMenuItem(entry.getKey()); + + if (bagel.getItemName().equals("Bagel")){ while (entry.getValue() >= 12){ - sum += (item.getItemPrice() * 12); + sum += (bagel.getItemPrice() * 12); discountedSum += 3.99f; + for (int i = 0; i<12; i++){ - basket.removeItem(item.getItemSKU(), false); + basket.removeItem(bagel.getItemSKU(), false); } } + while (entry.getValue() >= 6){ - sum += (item.getItemPrice() * 6); + sum += (bagel.getItemPrice() * 6); discountedSum += 2.49f; + for (int i = 0; i<6; i++){ - basket.removeItem(item.getItemSKU(), false); + basket.removeItem(bagel.getItemSKU(), false); } } } - } - } - public float getDiscountBagelCoffee(int bagelCount, int coffeeCount){ - return 0; - } - - - /*while (bagelCount !=0 && quantity != 0){ - float price = getMenuItem(entry.getKey()).getItemPrice(); - totalSum += price; - bagelCount--; - quantity--; - } - return "The sum of your order is: " + String.format("%.2f", totalSum);*/ - - - /*public String sumOrderDiscount(){ - if (basket.isEmpty()){ - return "Your basket is empty."; - } - - float totalSum = 0; + public void getDiscountCoffeeBagel(){ int bagelCount = 0; int coffeeCount = 0; - for (HashMap.Entry entry : basket.getBasketItems().entrySet()){ - if (getMenuItem(entry.getKey()).getItemName().equals("Filling")){ - int quantity = entry.getValue(); - float price = getMenuItem(entry.getKey()).getItemPrice(); + for (HashMap.Entry entry : basket.getBasketItems().entrySet()) { + Item item = getMenuItem(entry.getKey()); - float sum = price * quantity; - totalSum += sum; - } - if (getMenuItem(entry.getKey()).getItemName().equals("Bagel")){ - int quantity = entry.getValue(); - bagelCount += quantity; - } - if (getMenuItem(entry.getKey()).getItemName().equals("Coffee")){ - int quantity = entry.getValue(); - coffeeCount += quantity; + if (item.getItemName().equals("Bagel")){ + bagelCount += entry.getValue(); } - } - while (bagelCount >= 12){ - totalSum += 3.99f; - bagelCount -= 12; - } - - while (bagelCount>=6){ - totalSum += 2.49f; - bagelCount -= 6; - } - - while (bagelCount>0 && coffeeCount > 0){ - totalSum += 1.25f; - bagelCount -= 1; - coffeeCount -= 1; + if (item.getItemName().equals("Coffee")){ + coffeeCount += entry.getValue(); + } } - - if (bagelCount!= 0){ - ArrayList basketBagelsPrices = new ArrayList<>(); - + while (bagelCount!=0 && coffeeCount!=0){ for (HashMap.Entry entry : basket.getBasketItems().entrySet()){ - Item item = getMenuItem(entry.getKey()); - int quantity = entry.getValue(); + Item bagel = getMenuItem(entry.getKey()); - if ("Bagel".equals(item.getItemName())){ - for (int i = 0; i < quantity; i++ ){ - basketBagelsPrices.add(item.getItemPrice()); - } + if (bagel.getItemName().equals("Bagel") && entry.getValue()!= 0){ + sum += (bagel.getItemPrice()); + basket.removeItem(bagel.getItemSKU(), false); + break; } } - Collections.sort(basketBagelsPrices); - for (int i = 0; i < bagelCount; i++){ - totalSum += basketBagelsPrices.get(i); - - } + for (HashMap.Entry entry2 : basket.getBasketItems().entrySet()){ + Item coffee = getMenuItem(entry2.getKey()); - return "The sum of your order is: " + String.format("%.2f", totalSum); - } - if (coffeeCount!= 0){ - for (HashMap.Entry entry : basket.getBasketItems().entrySet()){ - if ("Coffee".equals(getMenuItem(entry.getKey()).getItemName())){ - int quantity = entry.getValue(); - while (coffeeCount != 0 && quantity != 0){ - float price = getMenuItem(entry.getKey()).getItemPrice(); - totalSum += price; - coffeeCount--; - quantity--; - } - return "The sum of your order is: " + String.format("%.2f", totalSum); + if (coffee.getItemName().equals("Coffee") && entry2.getValue()!= 0){ + sum += (coffee.getItemPrice()); + discountedSum += 1.25f; + basket.removeItem(coffee.getItemSKU(), false); + break; } } + bagelCount--; + coffeeCount--; } - return "The sum of your order is: " + String.format("%.2f", totalSum); - }*/ + } + + public void getRemainingSum(){ + for (HashMap.Entry entry : basket.getBasketItems().entrySet()){ + Item item = getMenuItem(entry.getKey()); + int quantity = entry.getValue(); + float price = item.getItemPrice(); + + sum += quantity*price; + discountedSum += quantity*price; + } + } } diff --git a/src/test/java/com/booleanuk/core/BasketTest.java b/src/test/java/com/booleanuk/core/BasketTest.java index 164f17a24..88be6ffe5 100644 --- a/src/test/java/com/booleanuk/core/BasketTest.java +++ b/src/test/java/com/booleanuk/core/BasketTest.java @@ -53,25 +53,6 @@ public void removeItemNotInBasket(){ Assertions.assertEquals("This item does not exist in your basket.", basket.removeItem("COFB", false)); } - /*@Test - public void totalCostItemsInBasket(){ - Basket basket = new Basket(); - CashRegister register = new CashRegister(basket); - - Assertions.assertEquals("Your basket is empty.", register.sumOrder()); - - basket.addItem("BGLO", 2); - basket.addItem("BGLP", 1); - basket.addItem("FILE", 1); - basket.addItem("COFC", 1); - - - Assertions.assertEquals("The sum of your order is: 2.78", register.sumOrder()); - basket.addItem("COFC", 1); - Assertions.assertEquals("The sum of your order is: 4.07", register.sumOrder()); - - }*/ - @Test public void getItemCost(){ Menu menu = new Menu(); From e8db009658285b90757b7fac2447196812e996d4 Mon Sep 17 00:00:00 2001 From: Tuva Aarseth Date: Fri, 23 Aug 2024 12:00:05 +0200 Subject: [PATCH 08/16] Extension 2: Created domain model --- domain-model.md | 23 ++++++++++++++-- src/main/java/com/booleanuk/core/Basket.java | 11 +++++--- .../java/com/booleanuk/core/CashRegister.java | 26 +++++++++++++++---- .../java/com/booleanuk/core/BasketTest.java | 20 +++++++++++--- 4 files changed, 67 insertions(+), 13 deletions(-) diff --git a/domain-model.md b/domain-model.md index c8e966c95..64923d5c0 100644 --- a/domain-model.md +++ b/domain-model.md @@ -22,10 +22,29 @@ |---------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `addItem(itemId: String, quantity: int)` | Item exists in menu but not in basketItems
Item exists in menu and in basketItems
Item does not exist in menu
Basket is full | Item is added to basketItems with the correct quantity
The quantity of the item in basketItems is changed
-
- | "'quantity' 'itemVariant' 'itemName' added to basket."
"'quantity' 'itemVariant' 'itemName' added to basket."
"This item is not on the menu."
"Basket is full." | | `removeItem(itemId: String, removeDuplicates: Boolean)` | Item exists in basketItems and removeDuplicates=true
Item exists in basketItems and removeDuplicates=false
Item does not exist in basket | Entry is removed from basketItems
The quantity of the item in basketItems is subtracted 1.
- | "'quantity' 'itemVariant' 'itemName's removed from basket."
"'itemVariant' 'itemName' removed from basket."
"This item does not exist in your basket." | -| `sumOrder()` | basketItems is not empty
basketItems is empty | | "The sum of your order is: 'sum'"
"Your basket is empty." | -| `sumOrderDiscount()` | 6 bagels of any kind
12 bagels of any kind
1 bagel and 1 coffee | Sum = 2.49
Sum = 3.99
Sum = 1.25 | "The sum of your order is: 'sum'" | | `setBasketSize(int)` | Basket capacity is changed to a positive integer by a "manager"
Basket capacity value is not positive | | Return true
Return false | +### CashRegister class + +| Method | Scenario | Output | +|----------------------------|------------------------------------------------------------------|---------------------------------------------------------------| +| `sumOrder()` | basketItems is not empty
basketItems is empty | "The sum of your order is: 'sum'"
"Your basket is empty." | +| `getDiscountBagel()` | 12 or more bagels of same type
6 or more bagels of same type | Discounted price is 3.99
Discounted price is 2.49 | +| `getDiscountCoffeeBagel()` | Minimum one coffee and one bagel remaining in basket | Discounted price is 1.25 | +| `getRemainingSum()` | Remaining items in basket | Calculate price | + + +### Receipt interface + + +| Method | Scenario | Output | +|-----------------------------------------------------------------|------------------------------------------------------------------|---------------------------------------------------------------| +| `getReceiptLine(itemName: String, quantity: int, price: float)` | Minimum one coffee and one bagel remaining in basket | Discounted price is 1.25 | +| `getDiscountedSum()` | Remaining items in basket | Calculate price | +| `createFinalReceipt()` | | | + + + ### Assumptions: diff --git a/src/main/java/com/booleanuk/core/Basket.java b/src/main/java/com/booleanuk/core/Basket.java index 26b3a08b5..5e610742a 100644 --- a/src/main/java/com/booleanuk/core/Basket.java +++ b/src/main/java/com/booleanuk/core/Basket.java @@ -14,6 +14,14 @@ public Basket(){ this.basketItems = new HashMap<>(); } + public HashMap getBasketItems(){ + return this.basketItems; + } + + public void setBasketItems(HashMap basketItems) { + this.basketItems = basketItems; + } + public Boolean setMaxBasketSize(int size){ if (size<0){ return false; @@ -45,9 +53,6 @@ public boolean isEmpty(){ return getBasketSize() == 0; } - public HashMap getBasketItems(){ - return this.basketItems; - } public String addItem(String itemId, int quantity) { if (getBasketSize() == maxBasketSize){ diff --git a/src/main/java/com/booleanuk/core/CashRegister.java b/src/main/java/com/booleanuk/core/CashRegister.java index c42cddfa0..4ffc62635 100644 --- a/src/main/java/com/booleanuk/core/CashRegister.java +++ b/src/main/java/com/booleanuk/core/CashRegister.java @@ -1,6 +1,7 @@ package com.booleanuk.core; import java.util.HashMap; +import java.util.Map; import static com.booleanuk.core.Menu.*; @@ -16,6 +17,13 @@ public CashRegister(Basket basket){ } public String sumOrder() { + //HashMap basketCopy = basket.getBasketItems(); + HashMap basketCopy; + basketCopy = basket.getBasketItems(); + + sum = 0; + discountedSum = 0; + totalDiscount = 0; if (basket.isEmpty()) { return "Your basket is empty."; @@ -31,6 +39,8 @@ public String sumOrder() { getRemainingSum(); } + basket.setBasketItems(basketCopy); + return "The sum of your order is: " + String.format("%.2f", discountedSum); } @@ -104,12 +114,18 @@ public void getDiscountCoffeeBagel(){ public void getRemainingSum(){ for (HashMap.Entry entry : basket.getBasketItems().entrySet()){ - Item item = getMenuItem(entry.getKey()); - int quantity = entry.getValue(); - float price = item.getItemPrice(); + if (entry.getValue() != 0){ + Item item = getMenuItem(entry.getKey()); + int quantity = entry.getValue(); + float price = item.getItemPrice(); - sum += quantity*price; - discountedSum += quantity*price; + sum += quantity*price; + discountedSum += quantity*price; + + for (int i = 0; i < quantity; i++){ + basket.removeItem(entry.getKey(), false); + } + } } } diff --git a/src/test/java/com/booleanuk/core/BasketTest.java b/src/test/java/com/booleanuk/core/BasketTest.java index 88be6ffe5..8de8ed3f1 100644 --- a/src/test/java/com/booleanuk/core/BasketTest.java +++ b/src/test/java/com/booleanuk/core/BasketTest.java @@ -53,6 +53,23 @@ public void removeItemNotInBasket(){ Assertions.assertEquals("This item does not exist in your basket.", basket.removeItem("COFB", false)); } + @Test + public void totalCostItemsInBasket(){ + Basket basket = new Basket(); + CashRegister register = new CashRegister(basket); + + Assertions.assertEquals("Your basket is empty.", register.sumOrder()); + + basket.addItem("BGLO", 2); + basket.addItem("BGLP", 1); + basket.addItem("FILE", 1); + + Assertions.assertEquals("The sum of your order is: 1.49", register.sumOrder()); + + //basket.removeItem("FILE", false); + //Assertions.assertEquals("The sum of your order is: 1.37", register.sumOrder()); + } + @Test public void getItemCost(){ Menu menu = new Menu(); @@ -61,7 +78,6 @@ public void getItemCost(){ // Extension 1 requirements tests - @Test public void bagelDiscount(){ Basket basket = new Basket(); @@ -73,8 +89,6 @@ public void bagelDiscount(){ Assertions.assertEquals("The sum of your order is: 7.73", register.sumOrder()); - - } @Test From 5e512190b74b667cf1c0d040a0776f7c506262ad Mon Sep 17 00:00:00 2001 From: Tuva Aarseth Date: Fri, 23 Aug 2024 15:21:02 +0200 Subject: [PATCH 09/16] Extension 2: modified and updated tests --- .../java/com/booleanuk/core/CashRegister.java | 41 +++++++++++--- .../com/booleanuk/core/NormalReceipt.java | 56 +++++++++++++++++++ src/main/java/com/booleanuk/core/Receipt.java | 11 ++++ .../java/com/booleanuk/core/BasketTest.java | 34 +++++++++-- 4 files changed, 130 insertions(+), 12 deletions(-) create mode 100644 src/main/java/com/booleanuk/core/NormalReceipt.java create mode 100644 src/main/java/com/booleanuk/core/Receipt.java diff --git a/src/main/java/com/booleanuk/core/CashRegister.java b/src/main/java/com/booleanuk/core/CashRegister.java index 4ffc62635..cc1136307 100644 --- a/src/main/java/com/booleanuk/core/CashRegister.java +++ b/src/main/java/com/booleanuk/core/CashRegister.java @@ -8,19 +8,24 @@ public class CashRegister { Basket basket; + Receipt receipt; private float sum = 0; private float discountedSum = 0; private float totalDiscount = 0; - public CashRegister(Basket basket){ + public CashRegister(Basket basket, Receipt receipt){ this.basket = basket; + this.receipt = receipt; } - public String sumOrder() { - //HashMap basketCopy = basket.getBasketItems(); - HashMap basketCopy; - basketCopy = basket.getBasketItems(); + public void printReceipt(){ + sumOrder(); + receipt.createFinalReceipt(); + receipt.printReceipt(); + + } + public String sumOrder() { sum = 0; discountedSum = 0; totalDiscount = 0; @@ -39,7 +44,7 @@ public String sumOrder() { getRemainingSum(); } - basket.setBasketItems(basketCopy); + receipt.getDiscountedSum(discountedSum); return "The sum of your order is: " + String.format("%.2f", discountedSum); } @@ -49,6 +54,9 @@ public void getDiscountBagel(){ Item bagel = getMenuItem(entry.getKey()); if (bagel.getItemName().equals("Bagel")){ + int bagelOfferCount = 0; + int twelveOfferCount = 0; + int sixOfferCount = 0; while (entry.getValue() >= 12){ sum += (bagel.getItemPrice() * 12); discountedSum += 3.99f; @@ -56,6 +64,8 @@ public void getDiscountBagel(){ for (int i = 0; i<12; i++){ basket.removeItem(bagel.getItemSKU(), false); } + bagelOfferCount += 12; + twelveOfferCount++; } while (entry.getValue() >= 6){ @@ -65,7 +75,15 @@ public void getDiscountBagel(){ for (int i = 0; i<6; i++){ basket.removeItem(bagel.getItemSKU(), false); } + bagelOfferCount += 6; + sixOfferCount++; + } + if (bagelOfferCount>0){ + float totalDiscountPrice = sixOfferCount*2.49f + twelveOfferCount*3.99f; + String fullName = bagel.getItemVariant() + " " + bagel.getItemName(); + receipt.addReceiptLine(fullName, bagelOfferCount, totalDiscountPrice); } + } } } @@ -85,7 +103,7 @@ public void getDiscountCoffeeBagel(){ coffeeCount += entry.getValue(); } } - + int coffeeBagelOffer = 0; while (bagelCount!=0 && coffeeCount!=0){ for (HashMap.Entry entry : basket.getBasketItems().entrySet()){ Item bagel = getMenuItem(entry.getKey()); @@ -104,12 +122,18 @@ public void getDiscountCoffeeBagel(){ sum += (coffee.getItemPrice()); discountedSum += 1.25f; basket.removeItem(coffee.getItemSKU(), false); + coffeeBagelOffer++; break; } } bagelCount--; coffeeCount--; } + + if (coffeeBagelOffer>0){ + String offerName = "Coffee & Bagel"; + receipt.addReceiptLine(offerName, coffeeBagelOffer, 1.25f*coffeeBagelOffer); + } } public void getRemainingSum(){ @@ -121,6 +145,8 @@ public void getRemainingSum(){ sum += quantity*price; discountedSum += quantity*price; + String fullName = item.getItemVariant() + " " + item.getItemName(); + receipt.addReceiptLine(fullName, quantity, quantity*price); for (int i = 0; i < quantity; i++){ basket.removeItem(entry.getKey(), false); @@ -128,5 +154,4 @@ public void getRemainingSum(){ } } } - } diff --git a/src/main/java/com/booleanuk/core/NormalReceipt.java b/src/main/java/com/booleanuk/core/NormalReceipt.java new file mode 100644 index 000000000..90e8e2423 --- /dev/null +++ b/src/main/java/com/booleanuk/core/NormalReceipt.java @@ -0,0 +1,56 @@ +package com.booleanuk.core; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; + +import static java.time.format.DateTimeFormatter.*; + +public class NormalReceipt implements Receipt{ + private ArrayList receiptLines; + private LocalDateTime dateTime; + private float totalSum; + private ArrayList finalReceipt; + + + public NormalReceipt(){ + this.receiptLines = new ArrayList<>(); + this.finalReceipt = new ArrayList<>(); + this.totalSum = 0; + } + + public ArrayList getFinalReceipt() { + return finalReceipt; + } + + + public void addReceiptLine(String itemName, int quantity, float price) { + this.receiptLines.add(String.format("%-18s %3s %8s", itemName, +quantity, "$"+price)); + } + + public void getDiscountedSum(float sum) { + this.totalSum = sum; + } + + public void createFinalReceipt() { + dateTime = LocalDateTime.now(); + this.finalReceipt.add(String.format("%-8s %10s", " ", "~Bob's Bagels~")); + this.finalReceipt.add(String.format("%-5s %10s", " ", dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))); + this.finalReceipt.add("-------------------------------"); + this.finalReceipt.add(" "); + this.finalReceipt.addAll(receiptLines); + this.finalReceipt.add(" "); + this.finalReceipt.add("-------------------------------"); + this.finalReceipt.add(String.format("%-15s %2s %12s", "Total", " ", "$"+totalSum)); + this.finalReceipt.add(" "); + this.finalReceipt.add(String.format("%-10s %10s", " ", "Thank you")); + this.finalReceipt.add(String.format("%-7s %16s", " ", "for your order!")); + + } + + public void printReceipt(){ + for (String s : finalReceipt){ + System.out.println(s); + } + } +} diff --git a/src/main/java/com/booleanuk/core/Receipt.java b/src/main/java/com/booleanuk/core/Receipt.java new file mode 100644 index 000000000..f546ffe86 --- /dev/null +++ b/src/main/java/com/booleanuk/core/Receipt.java @@ -0,0 +1,11 @@ +package com.booleanuk.core; + +import java.util.ArrayList; + +public interface Receipt { + void addReceiptLine(String itemName, int quantity, float price); + void getDiscountedSum(float sum); + void createFinalReceipt(); + void printReceipt(); + ArrayList getFinalReceipt(); +} diff --git a/src/test/java/com/booleanuk/core/BasketTest.java b/src/test/java/com/booleanuk/core/BasketTest.java index 8de8ed3f1..06baefe01 100644 --- a/src/test/java/com/booleanuk/core/BasketTest.java +++ b/src/test/java/com/booleanuk/core/BasketTest.java @@ -56,7 +56,8 @@ public void removeItemNotInBasket(){ @Test public void totalCostItemsInBasket(){ Basket basket = new Basket(); - CashRegister register = new CashRegister(basket); + Receipt receipt = new NormalReceipt(); + CashRegister register = new CashRegister(basket, receipt); Assertions.assertEquals("Your basket is empty.", register.sumOrder()); @@ -81,7 +82,8 @@ public void getItemCost(){ @Test public void bagelDiscount(){ Basket basket = new Basket(); - CashRegister register = new CashRegister(basket); + Receipt receipt = new NormalReceipt(); + CashRegister register = new CashRegister(basket, receipt); basket.setMaxBasketSize(25); basket.addItem("BGLO", 18); basket.addItem("BGLP", 1); @@ -94,7 +96,8 @@ public void bagelDiscount(){ @Test public void bagelCoffeeDiscount(){ Basket basket = new Basket(); - CashRegister register = new CashRegister(basket); + Receipt receipt = new NormalReceipt(); + CashRegister register = new CashRegister(basket, receipt); basket.addItem("BGLO", 2); basket.addItem("COFW", 1); @@ -105,7 +108,8 @@ public void bagelCoffeeDiscount(){ @Test public void allDiscounts(){ Basket basket = new Basket(); - CashRegister register = new CashRegister(basket); + Receipt receipt = new NormalReceipt(); + CashRegister register = new CashRegister(basket, receipt); basket.setMaxBasketSize(25); basket.addItem("BGLS", 6); @@ -115,4 +119,26 @@ public void allDiscounts(){ Assertions.assertEquals("The sum of your order is: 7.85", register.sumOrder()); } + + + // Extension 2 requirements tests + + @Test + public void printingReceipt(){ + Basket basket = new Basket(); + Receipt receipt = new NormalReceipt(); + CashRegister register = new CashRegister(basket, receipt); + basket.setMaxBasketSize(25); + + basket.addItem("BGLS", 6); + basket.addItem("BGLO", 13); + basket.addItem("FILC", 1); + basket.addItem("COFL", 1); + register.printReceipt(); + String receiptFinal = register.receipt.getFinalReceipt().toString(); + + String receiptExcerpt = "Onion Bagel 12 $3.99"; + + Assertions.assertTrue(receiptFinal.contains(receiptExcerpt)); + } } From 7a06e219a4f8aee67ba82c31d482b6ab76c1d8fc Mon Sep 17 00:00:00 2001 From: Tuva Aarseth Date: Fri, 23 Aug 2024 15:22:17 +0200 Subject: [PATCH 10/16] Extension 2: finished creating methods --- src/main/java/com/booleanuk/core/NormalReceipt.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/booleanuk/core/NormalReceipt.java b/src/main/java/com/booleanuk/core/NormalReceipt.java index 90e8e2423..b9ff0b22e 100644 --- a/src/main/java/com/booleanuk/core/NormalReceipt.java +++ b/src/main/java/com/booleanuk/core/NormalReceipt.java @@ -28,6 +28,7 @@ public void addReceiptLine(String itemName, int quantity, float price) { this.receiptLines.add(String.format("%-18s %3s %8s", itemName, +quantity, "$"+price)); } + public void getDiscountedSum(float sum) { this.totalSum = sum; } From 52863cd9f7f54b4aed82a846ef63d157c790c6b2 Mon Sep 17 00:00:00 2001 From: Tuva Aarseth Date: Fri, 23 Aug 2024 15:26:17 +0200 Subject: [PATCH 11/16] Extension 3: updated domain model --- domain-model.md | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/domain-model.md b/domain-model.md index 64923d5c0..f046ad0b9 100644 --- a/domain-model.md +++ b/domain-model.md @@ -8,6 +8,7 @@ |----------|-------------------|--------| | `Item()` | Class constructor | - | + ### Menu class | Method | Scenario | Output | |-------------------------------|-----------------------------------------------------|----------------| @@ -17,15 +18,14 @@ ### Basket class - | Method | Scenario | Outcome | Output | |---------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `addItem(itemId: String, quantity: int)` | Item exists in menu but not in basketItems
Item exists in menu and in basketItems
Item does not exist in menu
Basket is full | Item is added to basketItems with the correct quantity
The quantity of the item in basketItems is changed
-
- | "'quantity' 'itemVariant' 'itemName' added to basket."
"'quantity' 'itemVariant' 'itemName' added to basket."
"This item is not on the menu."
"Basket is full." | | `removeItem(itemId: String, removeDuplicates: Boolean)` | Item exists in basketItems and removeDuplicates=true
Item exists in basketItems and removeDuplicates=false
Item does not exist in basket | Entry is removed from basketItems
The quantity of the item in basketItems is subtracted 1.
- | "'quantity' 'itemVariant' 'itemName's removed from basket."
"'itemVariant' 'itemName' removed from basket."
"This item does not exist in your basket." | | `setBasketSize(int)` | Basket capacity is changed to a positive integer by a "manager"
Basket capacity value is not positive | | Return true
Return false | -### CashRegister class +### CashRegister class | Method | Scenario | Output | |----------------------------|------------------------------------------------------------------|---------------------------------------------------------------| | `sumOrder()` | basketItems is not empty
basketItems is empty | "The sum of your order is: 'sum'"
"Your basket is empty." | @@ -35,15 +35,24 @@ ### Receipt interface +| Method | Scenario | Output | +|-----------------------------------------------------------------|------------------------------------------------------|--------------------------| +| `getReceiptLine(itemName: String, quantity: int, price: float)` | Minimum one coffee and one bagel remaining in basket | Discounted price is 1.25 | +| `getDiscountedSum()` | Remaining items in basket | Calculate price | +| `createFinalReceipt()` | | | +| `printReceipt()` | | | +| `getFinalReceipt()` | | | +### NormalReceipt class (implements Receipt) | Method | Scenario | Output | |-----------------------------------------------------------------|------------------------------------------------------------------|---------------------------------------------------------------| -| `getReceiptLine(itemName: String, quantity: int, price: float)` | Minimum one coffee and one bagel remaining in basket | Discounted price is 1.25 | -| `getDiscountedSum()` | Remaining items in basket | Calculate price | -| `createFinalReceipt()` | | | +### DiscountReceipt class (implements Receipt) +| Method | Scenario | Output | +|-----------------------------------------------------------------|------------------------------------------------------------------|---------------------------------------------------------------| + ### Assumptions: From 5cc3a7057be9c574841073982248346bf57c7b35 Mon Sep 17 00:00:00 2001 From: Tuva Aarseth Date: Fri, 23 Aug 2024 16:45:36 +0200 Subject: [PATCH 12/16] Extension 3: Created tests and implemented methods --- .../java/com/booleanuk/core/CashRegister.java | 15 +++- .../com/booleanuk/core/DiscountReceipt.java | 69 +++++++++++++++++++ .../com/booleanuk/core/NormalReceipt.java | 6 +- src/main/java/com/booleanuk/core/Receipt.java | 1 + .../java/com/booleanuk/core/BasketTest.java | 22 ++++++ 5 files changed, 111 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/booleanuk/core/DiscountReceipt.java diff --git a/src/main/java/com/booleanuk/core/CashRegister.java b/src/main/java/com/booleanuk/core/CashRegister.java index cc1136307..4821832d1 100644 --- a/src/main/java/com/booleanuk/core/CashRegister.java +++ b/src/main/java/com/booleanuk/core/CashRegister.java @@ -45,6 +45,7 @@ public String sumOrder() { } receipt.getDiscountedSum(discountedSum); + receipt.setTotalSaved(totalDiscount); return "The sum of your order is: " + String.format("%.2f", discountedSum); } @@ -80,10 +81,13 @@ public void getDiscountBagel(){ } if (bagelOfferCount>0){ float totalDiscountPrice = sixOfferCount*2.49f + twelveOfferCount*3.99f; + float priceWithoutDiscount = bagelOfferCount*bagel.getItemPrice(); + float saved = priceWithoutDiscount-totalDiscountPrice; String fullName = bagel.getItemVariant() + " " + bagel.getItemName(); receipt.addReceiptLine(fullName, bagelOfferCount, totalDiscountPrice); + receipt.addReceiptLine("", 0, saved); + totalDiscount += saved; } - } } } @@ -104,12 +108,16 @@ public void getDiscountCoffeeBagel(){ } } int coffeeBagelOffer = 0; + + float coffeePrice = 0; + float bagelPrice = 0; while (bagelCount!=0 && coffeeCount!=0){ for (HashMap.Entry entry : basket.getBasketItems().entrySet()){ Item bagel = getMenuItem(entry.getKey()); if (bagel.getItemName().equals("Bagel") && entry.getValue()!= 0){ sum += (bagel.getItemPrice()); + bagelPrice = bagel.getItemPrice(); basket.removeItem(bagel.getItemSKU(), false); break; } @@ -120,6 +128,7 @@ public void getDiscountCoffeeBagel(){ if (coffee.getItemName().equals("Coffee") && entry2.getValue()!= 0){ sum += (coffee.getItemPrice()); + coffeePrice = coffee.getItemPrice(); discountedSum += 1.25f; basket.removeItem(coffee.getItemSKU(), false); coffeeBagelOffer++; @@ -132,7 +141,11 @@ public void getDiscountCoffeeBagel(){ if (coffeeBagelOffer>0){ String offerName = "Coffee & Bagel"; + float originalSum = coffeePrice+bagelPrice; + float saved = originalSum - 1.25f; receipt.addReceiptLine(offerName, coffeeBagelOffer, 1.25f*coffeeBagelOffer); + receipt.addReceiptLine("", 0, saved); + totalDiscount+=saved; } } diff --git a/src/main/java/com/booleanuk/core/DiscountReceipt.java b/src/main/java/com/booleanuk/core/DiscountReceipt.java new file mode 100644 index 000000000..be21dcf8c --- /dev/null +++ b/src/main/java/com/booleanuk/core/DiscountReceipt.java @@ -0,0 +1,69 @@ +package com.booleanuk.core; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; + +public class DiscountReceipt implements Receipt{ + private ArrayList receiptLines; + private LocalDateTime dateTime; + private float totalSum; + private ArrayList finalReceipt; + private float totalSaved; + + public DiscountReceipt(){ + this.receiptLines = new ArrayList<>(); + this.finalReceipt = new ArrayList<>(); + this.totalSum = 0; + this.totalSaved = 0; + } + + public void setTotalSaved(float totalSaved) { + this.totalSaved = totalSaved; + } + + public ArrayList getFinalReceipt() { + return finalReceipt; + } + + public void addReceiptLine(String itemName, int quantity, float price) { + if (price != 0 && quantity != 0){ + this.receiptLines.add(String.format("%-18s %3s %8s", itemName, quantity, "$"+price)); + } + else if (quantity == 0 && price != 0){ + this.receiptLines.add(String.format("%-18s %3s %8s", "", "", "(-$"+String.format("%.2f", price)+")")); + } + + } + + + public void getDiscountedSum(float sum) { + this.totalSum = sum; + } + + + public void createFinalReceipt() { + dateTime = LocalDateTime.now(); + this.finalReceipt.add(String.format("%-8s %10s", " ", "~Bob's Bagels~")); + this.finalReceipt.add(String.format("%-5s %10s", " ", dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))); + this.finalReceipt.add("-------------------------------"); + this.finalReceipt.add(" "); + this.finalReceipt.addAll(receiptLines); + this.finalReceipt.add(" "); + this.finalReceipt.add("-------------------------------"); + this.finalReceipt.add(String.format("%-15s %2s %12s", "Total", " ", "$"+totalSum)); + this.finalReceipt.add(" "); + this.finalReceipt.add(String.format("%-10s %4s", " You saved a total of ", "$"+String.format("%.2f", totalSaved))); + this.finalReceipt.add(String.format("%-10s %10s", " ", "on this shop")); + this.finalReceipt.add(" "); + this.finalReceipt.add(String.format("%-10s %10s", " ", "Thank you")); + this.finalReceipt.add(String.format("%-7s %16s", " ", "for your order!")); + } + + + public void printReceipt() { + for (String s : finalReceipt){ + System.out.println(s); + } + } +} diff --git a/src/main/java/com/booleanuk/core/NormalReceipt.java b/src/main/java/com/booleanuk/core/NormalReceipt.java index b9ff0b22e..2f492e09c 100644 --- a/src/main/java/com/booleanuk/core/NormalReceipt.java +++ b/src/main/java/com/booleanuk/core/NormalReceipt.java @@ -23,9 +23,13 @@ public ArrayList getFinalReceipt() { return finalReceipt; } + public void setTotalSaved(float totalSaved) { + + } + public void addReceiptLine(String itemName, int quantity, float price) { - this.receiptLines.add(String.format("%-18s %3s %8s", itemName, +quantity, "$"+price)); + this.receiptLines.add(String.format("%-18s %3s %8s", itemName, quantity, "$"+price)); } diff --git a/src/main/java/com/booleanuk/core/Receipt.java b/src/main/java/com/booleanuk/core/Receipt.java index f546ffe86..7ad329d7b 100644 --- a/src/main/java/com/booleanuk/core/Receipt.java +++ b/src/main/java/com/booleanuk/core/Receipt.java @@ -8,4 +8,5 @@ public interface Receipt { void createFinalReceipt(); void printReceipt(); ArrayList getFinalReceipt(); + void setTotalSaved(float totalSaved); } diff --git a/src/test/java/com/booleanuk/core/BasketTest.java b/src/test/java/com/booleanuk/core/BasketTest.java index 06baefe01..87e748a19 100644 --- a/src/test/java/com/booleanuk/core/BasketTest.java +++ b/src/test/java/com/booleanuk/core/BasketTest.java @@ -141,4 +141,26 @@ public void printingReceipt(){ Assertions.assertTrue(receiptFinal.contains(receiptExcerpt)); } + + + // Extension 3 requirements tests + + @Test + public void printingDiscountReceipt(){ + Basket basket = new Basket(); + Receipt receipt = new DiscountReceipt(); + CashRegister register = new CashRegister(basket, receipt); + basket.setMaxBasketSize(25); + + basket.addItem("BGLS", 6); + basket.addItem("BGLO", 13); + basket.addItem("FILC", 1); + basket.addItem("COFL", 1); + register.printReceipt(); + String receiptFinal = register.receipt.getFinalReceipt().toString(); + + String receiptExcerpt = " (-$1.89)"; + + Assertions.assertTrue(receiptFinal.contains(receiptExcerpt)); + } } From ae6c8960e72decd0bd941ff1f41a4d0dd8f94daa Mon Sep 17 00:00:00 2001 From: Tuva Aarseth Date: Fri, 23 Aug 2024 16:48:59 +0200 Subject: [PATCH 13/16] Extension 2: updated domain model and class diagram --- class_diagram.jpg | Bin 39050 -> 94975 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/class_diagram.jpg b/class_diagram.jpg index 7cf057185cc7090bd2efe485b608d7d397704fa6..d22eff4daa405306bafae0c34ce78ad13cbf48a9 100644 GIT binary patch literal 94975 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 SZWMTGHF!a{US;Xueg6fLJ!5nL literal 39050 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 TqLj?*Z_9&xryxAW->3fv(EyIW From fe4f19d46404c30617a26dc51d9a79699bca298d Mon Sep 17 00:00:00 2001 From: Tuva Aarseth Date: Mon, 26 Aug 2024 09:00:57 +0200 Subject: [PATCH 14/16] Extension 3: refactoring of methods, tests, and domain model --- src/main/java/com/booleanuk/core/Basket.java | 3 - .../java/com/booleanuk/core/CashRegister.java | 8 -- .../com/booleanuk/core/NormalReceipt.java | 4 +- .../java/com/booleanuk/core/BasketTest.java | 78 +++++++++++++++++-- 4 files changed, 74 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/booleanuk/core/Basket.java b/src/main/java/com/booleanuk/core/Basket.java index 5e610742a..f73dd34c6 100644 --- a/src/main/java/com/booleanuk/core/Basket.java +++ b/src/main/java/com/booleanuk/core/Basket.java @@ -47,9 +47,6 @@ public int getBasketSize(){ } public boolean isEmpty(){ - if (this.basketItems.isEmpty()){ - return true; - } return getBasketSize() == 0; } diff --git a/src/main/java/com/booleanuk/core/CashRegister.java b/src/main/java/com/booleanuk/core/CashRegister.java index 4821832d1..6b1fbf715 100644 --- a/src/main/java/com/booleanuk/core/CashRegister.java +++ b/src/main/java/com/booleanuk/core/CashRegister.java @@ -1,7 +1,6 @@ package com.booleanuk.core; import java.util.HashMap; -import java.util.Map; import static com.booleanuk.core.Menu.*; @@ -9,7 +8,6 @@ public class CashRegister { Basket basket; Receipt receipt; - private float sum = 0; private float discountedSum = 0; private float totalDiscount = 0; @@ -26,7 +24,6 @@ public void printReceipt(){ } public String sumOrder() { - sum = 0; discountedSum = 0; totalDiscount = 0; @@ -59,7 +56,6 @@ public void getDiscountBagel(){ int twelveOfferCount = 0; int sixOfferCount = 0; while (entry.getValue() >= 12){ - sum += (bagel.getItemPrice() * 12); discountedSum += 3.99f; for (int i = 0; i<12; i++){ @@ -70,7 +66,6 @@ public void getDiscountBagel(){ } while (entry.getValue() >= 6){ - sum += (bagel.getItemPrice() * 6); discountedSum += 2.49f; for (int i = 0; i<6; i++){ @@ -116,7 +111,6 @@ public void getDiscountCoffeeBagel(){ Item bagel = getMenuItem(entry.getKey()); if (bagel.getItemName().equals("Bagel") && entry.getValue()!= 0){ - sum += (bagel.getItemPrice()); bagelPrice = bagel.getItemPrice(); basket.removeItem(bagel.getItemSKU(), false); break; @@ -127,7 +121,6 @@ public void getDiscountCoffeeBagel(){ Item coffee = getMenuItem(entry2.getKey()); if (coffee.getItemName().equals("Coffee") && entry2.getValue()!= 0){ - sum += (coffee.getItemPrice()); coffeePrice = coffee.getItemPrice(); discountedSum += 1.25f; basket.removeItem(coffee.getItemSKU(), false); @@ -156,7 +149,6 @@ public void getRemainingSum(){ int quantity = entry.getValue(); float price = item.getItemPrice(); - sum += quantity*price; discountedSum += quantity*price; String fullName = item.getItemVariant() + " " + item.getItemName(); receipt.addReceiptLine(fullName, quantity, quantity*price); diff --git a/src/main/java/com/booleanuk/core/NormalReceipt.java b/src/main/java/com/booleanuk/core/NormalReceipt.java index 2f492e09c..adc842081 100644 --- a/src/main/java/com/booleanuk/core/NormalReceipt.java +++ b/src/main/java/com/booleanuk/core/NormalReceipt.java @@ -29,7 +29,9 @@ public void setTotalSaved(float totalSaved) { public void addReceiptLine(String itemName, int quantity, float price) { - this.receiptLines.add(String.format("%-18s %3s %8s", itemName, quantity, "$"+price)); + if (price != 0 && quantity != 0){ + this.receiptLines.add(String.format("%-18s %3s %8s", itemName, quantity, "$"+price)); + } } diff --git a/src/test/java/com/booleanuk/core/BasketTest.java b/src/test/java/com/booleanuk/core/BasketTest.java index 87e748a19..efc8b32f8 100644 --- a/src/test/java/com/booleanuk/core/BasketTest.java +++ b/src/test/java/com/booleanuk/core/BasketTest.java @@ -5,6 +5,8 @@ public class BasketTest { // Core requirements tests + + // User story 1 @Test public void addBagelToBasket(){ Basket basket = new Basket(); @@ -17,6 +19,7 @@ public void addBagelToBasket(){ Assertions.assertEquals(3, basket.getBasketSize()); } + // User story 2 @Test public void removeBagelFromBasket(){ Basket basket = new Basket(); @@ -29,6 +32,7 @@ public void removeBagelFromBasket(){ Assertions.assertEquals(0, basket.getBasketSize()); } + // User story 3 @Test public void addBagelFullBasket(){ Basket basket = new Basket(); @@ -37,6 +41,7 @@ public void addBagelFullBasket(){ } + // User story 4 @Test public void changeBasketCapacity(){ Basket basket = new Basket(); @@ -46,6 +51,7 @@ public void changeBasketCapacity(){ Assertions.assertFalse(basket.setMaxBasketSize(-2)); } + // User story 5 @Test public void removeItemNotInBasket(){ Basket basket = new Basket(); @@ -53,6 +59,7 @@ public void removeItemNotInBasket(){ Assertions.assertEquals("This item does not exist in your basket.", basket.removeItem("COFB", false)); } + // User story 6 @Test public void totalCostItemsInBasket(){ Basket basket = new Basket(); @@ -67,16 +74,46 @@ public void totalCostItemsInBasket(){ Assertions.assertEquals("The sum of your order is: 1.49", register.sumOrder()); - //basket.removeItem("FILE", false); - //Assertions.assertEquals("The sum of your order is: 1.37", register.sumOrder()); } + // User story 7 @Test - public void getItemCost(){ + public void getBagelCost(){ Menu menu = new Menu(); Assertions.assertEquals("0.49", menu.getItemCost("BGLS")); } + // User story 8 + @Test + public void addFilling(){ + Basket basket = new Basket(); + + Assertions.assertEquals("2 Cheese Filling added to basket.", basket.addItem("FILC", 2)); + Assertions.assertEquals("1 Bacon Filling added to basket.", basket.addItem("FILB", 1)); + + Assertions.assertEquals(2, basket.getBasketItems().get("FILC")); + Assertions.assertEquals(1, basket.getBasketItems().get("FILB")); + Assertions.assertEquals(3, basket.getBasketSize()); + } + + + // User story 9 + @Test + public void getFillingCost(){ + Menu menu = new Menu(); + Assertions.assertEquals("0.12", menu.getItemCost("FILC")); + } + + + // User story 10 + @Test + public void addItemNotInInventory(){ + Basket basket = new Basket(); + + Assertions.assertEquals("This item is not on the menu.", basket.addItem("Not a bagel.", 2)); + } + + // Extension 1 requirements tests @Test @@ -94,7 +131,7 @@ public void bagelDiscount(){ } @Test - public void bagelCoffeeDiscount(){ + public void bagelAndCoffeeDiscount(){ Basket basket = new Basket(); Receipt receipt = new NormalReceipt(); CashRegister register = new CashRegister(basket, receipt); @@ -124,7 +161,7 @@ public void allDiscounts(){ // Extension 2 requirements tests @Test - public void printingReceipt(){ + public void printingNormalReceipt(){ Basket basket = new Basket(); Receipt receipt = new NormalReceipt(); CashRegister register = new CashRegister(basket, receipt); @@ -137,7 +174,19 @@ public void printingReceipt(){ register.printReceipt(); String receiptFinal = register.receipt.getFinalReceipt().toString(); - String receiptExcerpt = "Onion Bagel 12 $3.99"; + String receiptExcerpt = + " -------------------------------," + + " ," + + " Sesame Bagel 6 $2.49," + + " Onion Bagel 12 $3.99," + + " Coffee & Bagel 1 $1.25," + + " Cheese Filling 1 $0.12," + + " ," + + " -------------------------------," + + " Total $7.85," + + " ," + + " Thank you," + + " for your order!"; Assertions.assertTrue(receiptFinal.contains(receiptExcerpt)); } @@ -159,7 +208,22 @@ public void printingDiscountReceipt(){ register.printReceipt(); String receiptFinal = register.receipt.getFinalReceipt().toString(); - String receiptExcerpt = " (-$1.89)"; + String receiptExcerpt = + " -------------------------------," + + " , Sesame Bagel 6 $2.49," + + " (-$0.45)," + + " Onion Bagel 12 $3.99," + + " (-$1.89)," + + " Coffee & Bagel 1 $1.25," + + " (-$0.53)," + + " Cheese Filling 1 $0.12," + + " , -------------------------------," + + " Total $7.85," + + " ," + + " You saved a total of $2.87," + + " on this shop," + + " , Thank you," + + " for your order!]"; Assertions.assertTrue(receiptFinal.contains(receiptExcerpt)); } From d1db644c5cd0b2c399b90c22fc7deed62dd9f9d1 Mon Sep 17 00:00:00 2001 From: Tuva Aarseth Date: Mon, 26 Aug 2024 09:05:19 +0200 Subject: [PATCH 15/16] Moved tests to extension --- .../java/com/booleanuk/core/BasketTest.java | 40 -------------- .../java/com/booleanuk/core/ItemTest.java | 4 -- .../java/com/booleanuk/core/MenuTest.java | 17 ------ .../booleanuk/extension/Extension1Test.java | 53 +++++++++++++++++++ 4 files changed, 53 insertions(+), 61 deletions(-) delete mode 100644 src/test/java/com/booleanuk/core/ItemTest.java delete mode 100644 src/test/java/com/booleanuk/core/MenuTest.java create mode 100644 src/test/java/com/booleanuk/extension/Extension1Test.java diff --git a/src/test/java/com/booleanuk/core/BasketTest.java b/src/test/java/com/booleanuk/core/BasketTest.java index efc8b32f8..e595d21d1 100644 --- a/src/test/java/com/booleanuk/core/BasketTest.java +++ b/src/test/java/com/booleanuk/core/BasketTest.java @@ -115,47 +115,7 @@ public void addItemNotInInventory(){ - // Extension 1 requirements tests - @Test - public void bagelDiscount(){ - Basket basket = new Basket(); - Receipt receipt = new NormalReceipt(); - CashRegister register = new CashRegister(basket, receipt); - basket.setMaxBasketSize(25); - basket.addItem("BGLO", 18); - basket.addItem("BGLP", 1); - basket.addItem("COFB",1); - - Assertions.assertEquals("The sum of your order is: 7.73", register.sumOrder()); - - } - - @Test - public void bagelAndCoffeeDiscount(){ - Basket basket = new Basket(); - Receipt receipt = new NormalReceipt(); - CashRegister register = new CashRegister(basket, receipt); - - basket.addItem("BGLO", 2); - basket.addItem("COFW", 1); - - Assertions.assertEquals("The sum of your order is: 1.74", register.sumOrder()); - } - @Test - public void allDiscounts(){ - Basket basket = new Basket(); - Receipt receipt = new NormalReceipt(); - CashRegister register = new CashRegister(basket, receipt); - basket.setMaxBasketSize(25); - - basket.addItem("BGLS", 6); - basket.addItem("BGLO", 13); - basket.addItem("FILC", 1); - basket.addItem("COFL", 1); - - Assertions.assertEquals("The sum of your order is: 7.85", register.sumOrder()); - } // Extension 2 requirements tests diff --git a/src/test/java/com/booleanuk/core/ItemTest.java b/src/test/java/com/booleanuk/core/ItemTest.java deleted file mode 100644 index be04480f7..000000000 --- a/src/test/java/com/booleanuk/core/ItemTest.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.booleanuk.core; - -public class ItemTest { -} diff --git a/src/test/java/com/booleanuk/core/MenuTest.java b/src/test/java/com/booleanuk/core/MenuTest.java deleted file mode 100644 index 6c6647b0b..000000000 --- a/src/test/java/com/booleanuk/core/MenuTest.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.booleanuk.core; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -class MenuTest { - Menu menu; - - public MenuTest(){ - this.menu = new Menu(); - } - - /*@Test - public void testGetItemPrice(){ - Assertions.assertEquals(0.49f, menu.getItemPrice("BGLO")); - }*/ -} diff --git a/src/test/java/com/booleanuk/extension/Extension1Test.java b/src/test/java/com/booleanuk/extension/Extension1Test.java new file mode 100644 index 000000000..1a09d7225 --- /dev/null +++ b/src/test/java/com/booleanuk/extension/Extension1Test.java @@ -0,0 +1,53 @@ +package com.booleanuk.extension; + +import com.booleanuk.core.Basket; +import com.booleanuk.core.CashRegister; +import com.booleanuk.core.NormalReceipt; +import com.booleanuk.core.Receipt; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class Extension1Test { + + // Extension 1 requirements tests + @Test + public void bagelDiscount(){ + Basket basket = new Basket(); + Receipt receipt = new NormalReceipt(); + CashRegister register = new CashRegister(basket, receipt); + basket.setMaxBasketSize(25); + basket.addItem("BGLO", 18); + basket.addItem("BGLP", 1); + basket.addItem("COFB",1); + + Assertions.assertEquals("The sum of your order is: 7.73", register.sumOrder()); + + } + + @Test + public void bagelAndCoffeeDiscount(){ + Basket basket = new Basket(); + Receipt receipt = new NormalReceipt(); + CashRegister register = new CashRegister(basket, receipt); + + basket.addItem("BGLO", 2); + basket.addItem("COFW", 1); + + Assertions.assertEquals("The sum of your order is: 1.74", register.sumOrder()); + } + + @Test + public void allDiscounts(){ + Basket basket = new Basket(); + Receipt receipt = new NormalReceipt(); + CashRegister register = new CashRegister(basket, receipt); + basket.setMaxBasketSize(25); + + basket.addItem("BGLS", 6); + basket.addItem("BGLO", 13); + basket.addItem("FILC", 1); + basket.addItem("COFL", 1); + + Assertions.assertEquals("The sum of your order is: 7.85", register.sumOrder()); + } +} From 8b5528785d2ebf38afae44dc158d2ae511d8934d Mon Sep 17 00:00:00 2001 From: Tuva Aarseth Date: Mon, 26 Aug 2024 09:14:07 +0200 Subject: [PATCH 16/16] Moved all extension tests to extension folder. --- .../java/com/booleanuk/core/BasketTest.java | 76 ------------------- .../booleanuk/extension/Extension2Test.java | 43 +++++++++++ .../booleanuk/extension/Extension3Test.java | 48 ++++++++++++ 3 files changed, 91 insertions(+), 76 deletions(-) create mode 100644 src/test/java/com/booleanuk/extension/Extension2Test.java create mode 100644 src/test/java/com/booleanuk/extension/Extension3Test.java diff --git a/src/test/java/com/booleanuk/core/BasketTest.java b/src/test/java/com/booleanuk/core/BasketTest.java index e595d21d1..933684d42 100644 --- a/src/test/java/com/booleanuk/core/BasketTest.java +++ b/src/test/java/com/booleanuk/core/BasketTest.java @@ -96,7 +96,6 @@ public void addFilling(){ Assertions.assertEquals(3, basket.getBasketSize()); } - // User story 9 @Test public void getFillingCost(){ @@ -104,7 +103,6 @@ public void getFillingCost(){ Assertions.assertEquals("0.12", menu.getItemCost("FILC")); } - // User story 10 @Test public void addItemNotInInventory(){ @@ -113,78 +111,4 @@ public void addItemNotInInventory(){ Assertions.assertEquals("This item is not on the menu.", basket.addItem("Not a bagel.", 2)); } - - - - - - // Extension 2 requirements tests - - @Test - public void printingNormalReceipt(){ - Basket basket = new Basket(); - Receipt receipt = new NormalReceipt(); - CashRegister register = new CashRegister(basket, receipt); - basket.setMaxBasketSize(25); - - basket.addItem("BGLS", 6); - basket.addItem("BGLO", 13); - basket.addItem("FILC", 1); - basket.addItem("COFL", 1); - register.printReceipt(); - String receiptFinal = register.receipt.getFinalReceipt().toString(); - - String receiptExcerpt = - " -------------------------------," + - " ," + - " Sesame Bagel 6 $2.49," + - " Onion Bagel 12 $3.99," + - " Coffee & Bagel 1 $1.25," + - " Cheese Filling 1 $0.12," + - " ," + - " -------------------------------," + - " Total $7.85," + - " ," + - " Thank you," + - " for your order!"; - - Assertions.assertTrue(receiptFinal.contains(receiptExcerpt)); - } - - - // Extension 3 requirements tests - - @Test - public void printingDiscountReceipt(){ - Basket basket = new Basket(); - Receipt receipt = new DiscountReceipt(); - CashRegister register = new CashRegister(basket, receipt); - basket.setMaxBasketSize(25); - - basket.addItem("BGLS", 6); - basket.addItem("BGLO", 13); - basket.addItem("FILC", 1); - basket.addItem("COFL", 1); - register.printReceipt(); - String receiptFinal = register.receipt.getFinalReceipt().toString(); - - String receiptExcerpt = - " -------------------------------," + - " , Sesame Bagel 6 $2.49," + - " (-$0.45)," + - " Onion Bagel 12 $3.99," + - " (-$1.89)," + - " Coffee & Bagel 1 $1.25," + - " (-$0.53)," + - " Cheese Filling 1 $0.12," + - " , -------------------------------," + - " Total $7.85," + - " ," + - " You saved a total of $2.87," + - " on this shop," + - " , Thank you," + - " for your order!]"; - - Assertions.assertTrue(receiptFinal.contains(receiptExcerpt)); - } } diff --git a/src/test/java/com/booleanuk/extension/Extension2Test.java b/src/test/java/com/booleanuk/extension/Extension2Test.java new file mode 100644 index 000000000..32f373b61 --- /dev/null +++ b/src/test/java/com/booleanuk/extension/Extension2Test.java @@ -0,0 +1,43 @@ +package com.booleanuk.extension; + +import com.booleanuk.core.Basket; +import com.booleanuk.core.CashRegister; +import com.booleanuk.core.NormalReceipt; +import com.booleanuk.core.Receipt; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class Extension2Test { + + // Extension 2 requirements tests + @Test + public void printingNormalReceipt(){ + Basket basket = new Basket(); + Receipt receipt = new NormalReceipt(); + CashRegister register = new CashRegister(basket, receipt); + basket.setMaxBasketSize(25); + + basket.addItem("BGLS", 6); + basket.addItem("BGLO", 13); + basket.addItem("FILC", 1); + basket.addItem("COFL", 1); + register.printReceipt(); + String receiptFinal = receipt.getFinalReceipt().toString(); + + String receiptExcerpt = + " -------------------------------," + + " ," + + " Sesame Bagel 6 $2.49," + + " Onion Bagel 12 $3.99," + + " Coffee & Bagel 1 $1.25," + + " Cheese Filling 1 $0.12," + + " ," + + " -------------------------------," + + " Total $7.85," + + " ," + + " Thank you," + + " for your order!"; + + Assertions.assertTrue(receiptFinal.contains(receiptExcerpt)); + } +} diff --git a/src/test/java/com/booleanuk/extension/Extension3Test.java b/src/test/java/com/booleanuk/extension/Extension3Test.java new file mode 100644 index 000000000..ec6624171 --- /dev/null +++ b/src/test/java/com/booleanuk/extension/Extension3Test.java @@ -0,0 +1,48 @@ +package com.booleanuk.extension; + +import com.booleanuk.core.Basket; +import com.booleanuk.core.CashRegister; +import com.booleanuk.core.DiscountReceipt; +import com.booleanuk.core.Receipt; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class Extension3Test { + + // Extension 3 requirements tests + @Test + public void printingDiscountReceipt(){ + Basket basket = new Basket(); + Receipt receipt = new DiscountReceipt(); + CashRegister register = new CashRegister(basket, receipt); + basket.setMaxBasketSize(25); + + basket.addItem("BGLS", 6); + basket.addItem("BGLO", 13); + basket.addItem("FILC", 1); + basket.addItem("COFL", 1); + register.printReceipt(); + String receiptFinal = receipt.getFinalReceipt().toString(); + + String receiptExcerpt = + " -------------------------------," + + " ," + + " Sesame Bagel 6 $2.49," + + " (-$0.45)," + + " Onion Bagel 12 $3.99," + + " (-$1.89)," + + " Coffee & Bagel 1 $1.25," + + " (-$0.53)," + + " Cheese Filling 1 $0.12," + + " ," + + " -------------------------------," + + " Total $7.85," + + " ," + + " You saved a total of $2.87," + + " on this shop," + + " , Thank you," + + " for your order!]"; + + Assertions.assertTrue(receiptFinal.contains(receiptExcerpt)); + } +}