From c5fe5d17310544dec7711a703cbf26ff3a70632c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20S=C3=B6nnergaard?= Date: Fri, 10 Jan 2025 12:49:29 +0100 Subject: [PATCH 01/43] Create a domain model draft --- domain-model.md | 62 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 domain-model.md diff --git a/domain-model.md b/domain-model.md new file mode 100644 index 000000000..f11d5d529 --- /dev/null +++ b/domain-model.md @@ -0,0 +1,62 @@ +# Bob's Bagels -- Domain model + +## Class: Item + +### Member variables + +- sku: String +- price: double +- name: String +- variant: String +- size: int (e.g., fillings maybe don't take up capacity) + +### Methods + +| Method | Scenario | Result | +|--------|----------|--------| +| | | | +| | | | +| | | | + + +## Class: Basket + +### Member variables + +- capacity: static int +- items: List + +### Methods + +| Method | Scenario | Result | +|----------------------------------------------------|-----------------------------------------------------|-------------------------------------------------------------| +| addItem(name: String, variant: String): boolean | Basket is full | Return false. Print error message, don't add item to basket | +| | Basket is not full | Return true. Add item to basket. | +| | One or more fields are invalid (shop doesn't stock) | Return false. Print error message. | +| removeItem(name: String, variant: String): boolean | Item is not found in basket | Return false. Print error message. | +| | Item is found in basket | Return true. Remove item from basket. | +| setCapacity(newCapacity: int): static void | newCapacity is valid (> 0) | Update the basket capacity. | +| | newCapacity is not valid (<= 0) | Don't change the basket capacity. | +| getCapacity(): int | | | +| getTotalCost(): double | | Calculate and return the cost of items in basket. | +| | | | + +## Class: ShopHandler + +This is the public interface that a customer or manager interacts with the Bob's Bagels system through. + +### Member variables + +- basket: Basket +- stockedItems: `List>()` + +### Methods + +| Method | Scenario | Result | +|--------------------------------|----------|--------------------------------------------------------------| +| placeOrder(): void (boolean?) | | Guide the customer through selecting items to order. | +| showItems(): void | | Print bagels and coffee w/ prices | +| showFillings(): void | | Print fillings w/ prices | +| orderBagel(): void | | Let customer choose a bagel. Then, let customer add filling. | +| orderCoffee(): void | | Let customer choose a variant. | +| setBasketCapacity(): void | | Update the basket capacity for all baskets. | \ No newline at end of file From b962f922eb3d5c24d1446b2c4c2f1f95664ebc76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20S=C3=B6nnergaard?= Date: Fri, 10 Jan 2025 13:04:14 +0100 Subject: [PATCH 02/43] Create class diagram --- class_diagram.png | Bin 0 -> 42299 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 class_diagram.png diff --git a/class_diagram.png b/class_diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..3dd76fb6227b9d6cda43f7e4cbbba5651309bebf GIT binary patch literal 42299 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�u?tEhhR)T%I3eVtO&Ce(u~gs^|gTPs`a2 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 Date: Fri, 10 Jan 2025 13:20:39 +0100 Subject: [PATCH 03/43] Add class files, add test for successfully adding an item to basket --- src/main/java/com/booleanuk/core/Basket.java | 4 ++++ src/main/java/com/booleanuk/core/Item.java | 4 ++++ src/main/java/com/booleanuk/core/ShopHandler.java | 4 ++++ src/test/java/com/booleanuk/core/BasketTest.java | 13 +++++++++++++ src/test/java/com/booleanuk/core/ItemTest.java | 7 +++++++ .../java/com/booleanuk/core/ShopHandlerTest.java | 11 +++++++++++ 6 files changed, 43 insertions(+) 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/ShopHandler.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/ShopHandlerTest.java diff --git a/src/main/java/com/booleanuk/core/Basket.java b/src/main/java/com/booleanuk/core/Basket.java new file mode 100644 index 000000000..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/ShopHandler.java b/src/main/java/com/booleanuk/core/ShopHandler.java new file mode 100644 index 000000000..aff2375c0 --- /dev/null +++ b/src/main/java/com/booleanuk/core/ShopHandler.java @@ -0,0 +1,4 @@ +package com.booleanuk.core; + +public class ShopHandler { +} 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..d7448c997 --- /dev/null +++ b/src/test/java/com/booleanuk/core/BasketTest.java @@ -0,0 +1,13 @@ +package com.booleanuk.core; + +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; + +public class BasketTest { + + @Test + public void canAddBagel() { + Basket basket = new Basket(); + assertTrue(basket.addItem("BGLO", 0.49, "Bagel", "Onion")); + } +} 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..a6d09b14c --- /dev/null +++ b/src/test/java/com/booleanuk/core/ItemTest.java @@ -0,0 +1,7 @@ +package com.booleanuk.core; + +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; + +public class ItemTest { +} diff --git a/src/test/java/com/booleanuk/core/ShopHandlerTest.java b/src/test/java/com/booleanuk/core/ShopHandlerTest.java new file mode 100644 index 000000000..8e9fdc881 --- /dev/null +++ b/src/test/java/com/booleanuk/core/ShopHandlerTest.java @@ -0,0 +1,11 @@ +package com.booleanuk.core; + +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; + +public class ShopHandlerTest { + @Test + public void test() { + + } +} From 4457831a2ae403a562a3c6c4ba350a319c89ab3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20S=C3=B6nnergaard?= Date: Fri, 10 Jan 2025 13:22:58 +0100 Subject: [PATCH 04/43] Add basket method for adding an item --- src/main/java/com/booleanuk/core/Basket.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/com/booleanuk/core/Basket.java b/src/main/java/com/booleanuk/core/Basket.java index 4aab45ed7..a70cb1758 100644 --- a/src/main/java/com/booleanuk/core/Basket.java +++ b/src/main/java/com/booleanuk/core/Basket.java @@ -1,4 +1,7 @@ package com.booleanuk.core; public class Basket { + public boolean addItem(String sku, double price, String name, String variant) { + return true; + } } From a08bac1c585a5c04019c22e4f89a050f2071c45d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20S=C3=B6nnergaard?= Date: Fri, 10 Jan 2025 13:28:19 +0100 Subject: [PATCH 05/43] Add test for successfully removing an item --- src/test/java/com/booleanuk/core/BasketTest.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/test/java/com/booleanuk/core/BasketTest.java b/src/test/java/com/booleanuk/core/BasketTest.java index d7448c997..a2999aa4d 100644 --- a/src/test/java/com/booleanuk/core/BasketTest.java +++ b/src/test/java/com/booleanuk/core/BasketTest.java @@ -10,4 +10,11 @@ public void canAddBagel() { Basket basket = new Basket(); assertTrue(basket.addItem("BGLO", 0.49, "Bagel", "Onion")); } + + @Test + public void canRemoveBagel() { + Basket basket = new Basket(); + assertTrue(basket.addItem("BGLO", 0.49, "Bagel", "Onion")); + assertTrue(basket.removeItem("BGLO")); + } } From 54a540d475e483a7bca3357e2df4e3ade5d9ad38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20S=C3=B6nnergaard?= Date: Fri, 10 Jan 2025 13:28:47 +0100 Subject: [PATCH 06/43] Add basket method for removing item --- src/main/java/com/booleanuk/core/Basket.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/booleanuk/core/Basket.java b/src/main/java/com/booleanuk/core/Basket.java index a70cb1758..3fd918f51 100644 --- a/src/main/java/com/booleanuk/core/Basket.java +++ b/src/main/java/com/booleanuk/core/Basket.java @@ -4,4 +4,8 @@ public class Basket { public boolean addItem(String sku, double price, String name, String variant) { return true; } + + public boolean removeItem(String sku) { + return true; + } } From d5cfabdb26b310fda52a4d09d7c865effad7118e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20S=C3=B6nnergaard?= Date: Fri, 10 Jan 2025 13:30:34 +0100 Subject: [PATCH 07/43] Modify test to make sure basket is empty after removing the only item that was added --- src/test/java/com/booleanuk/core/BasketTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/booleanuk/core/BasketTest.java b/src/test/java/com/booleanuk/core/BasketTest.java index a2999aa4d..30cb29dda 100644 --- a/src/test/java/com/booleanuk/core/BasketTest.java +++ b/src/test/java/com/booleanuk/core/BasketTest.java @@ -12,9 +12,10 @@ public void canAddBagel() { } @Test - public void canRemoveBagel() { + public void canAndDoesRemoveBagel() { Basket basket = new Basket(); assertTrue(basket.addItem("BGLO", 0.49, "Bagel", "Onion")); assertTrue(basket.removeItem("BGLO")); + assertTrue(basket.getItems().size() == 0); } } From 1e71212239b3b201e593b199772e52d091f0f29a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20S=C3=B6nnergaard?= Date: Fri, 10 Jan 2025 13:49:14 +0100 Subject: [PATCH 08/43] Fix basket should be empty after removing the only item that was added --- src/main/java/com/booleanuk/core/Basket.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/com/booleanuk/core/Basket.java b/src/main/java/com/booleanuk/core/Basket.java index 3fd918f51..b77fcec92 100644 --- a/src/main/java/com/booleanuk/core/Basket.java +++ b/src/main/java/com/booleanuk/core/Basket.java @@ -1,5 +1,8 @@ package com.booleanuk.core; +import java.util.ArrayList; +import java.util.List; + public class Basket { public boolean addItem(String sku, double price, String name, String variant) { return true; @@ -8,4 +11,8 @@ public boolean addItem(String sku, double price, String name, String variant) { public boolean removeItem(String sku) { return true; } + + public List getItems() { + return new ArrayList<>(); + } } From e11c5554463028a9551f4d6bbc3fcd6e832da62a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20S=C3=B6nnergaard?= Date: Fri, 10 Jan 2025 13:49:35 +0100 Subject: [PATCH 09/43] Add test for increasing the basket size when adding a bagel --- src/test/java/com/booleanuk/core/BasketTest.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/booleanuk/core/BasketTest.java b/src/test/java/com/booleanuk/core/BasketTest.java index 30cb29dda..78debcce8 100644 --- a/src/test/java/com/booleanuk/core/BasketTest.java +++ b/src/test/java/com/booleanuk/core/BasketTest.java @@ -11,11 +11,18 @@ public void canAddBagel() { assertTrue(basket.addItem("BGLO", 0.49, "Bagel", "Onion")); } + @Test + public void addingBagelIncreasesBasketSize() { + Basket basket = new Basket(); + basket.addItem("BGLO", 0.49, "Bagel", "Onion"); + assertEquals(1, basket.getItems().size()); + } + @Test public void canAndDoesRemoveBagel() { Basket basket = new Basket(); assertTrue(basket.addItem("BGLO", 0.49, "Bagel", "Onion")); assertTrue(basket.removeItem("BGLO")); - assertTrue(basket.getItems().size() == 0); + assertTrue(basket.getItems().isEmpty()); } } From 5a469e354bf04f5aa7f02ab402cae97a6172a6a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20S=C3=B6nnergaard?= Date: Fri, 10 Jan 2025 13:52:13 +0100 Subject: [PATCH 10/43] Fix adding a bagel increases the basket size --- src/main/java/com/booleanuk/core/Basket.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/booleanuk/core/Basket.java b/src/main/java/com/booleanuk/core/Basket.java index b77fcec92..e14ac9916 100644 --- a/src/main/java/com/booleanuk/core/Basket.java +++ b/src/main/java/com/booleanuk/core/Basket.java @@ -4,7 +4,10 @@ import java.util.List; public class Basket { + private List items = new ArrayList<>(); + public boolean addItem(String sku, double price, String name, String variant) { + items.add(new Item()); return true; } @@ -13,6 +16,6 @@ public boolean removeItem(String sku) { } public List getItems() { - return new ArrayList<>(); + return items; } } From b7fb96baf6374bae0d7183d7bb44070e92de0d9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20S=C3=B6nnergaard?= Date: Fri, 10 Jan 2025 13:53:43 +0100 Subject: [PATCH 11/43] Fix removing the last bagel gives empty basket --- src/main/java/com/booleanuk/core/Basket.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/booleanuk/core/Basket.java b/src/main/java/com/booleanuk/core/Basket.java index e14ac9916..2fd614637 100644 --- a/src/main/java/com/booleanuk/core/Basket.java +++ b/src/main/java/com/booleanuk/core/Basket.java @@ -12,6 +12,7 @@ public boolean addItem(String sku, double price, String name, String variant) { } public boolean removeItem(String sku) { + items.removeFirst(); return true; } From f953218b0d5087f63cd02a68472e60e47561c450 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20S=C3=B6nnergaard?= Date: Fri, 10 Jan 2025 14:43:50 +0100 Subject: [PATCH 12/43] Add test for making sure the correct bagel is removed from the basket --- src/test/java/com/booleanuk/core/BasketTest.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/test/java/com/booleanuk/core/BasketTest.java b/src/test/java/com/booleanuk/core/BasketTest.java index 78debcce8..6e3baf77d 100644 --- a/src/test/java/com/booleanuk/core/BasketTest.java +++ b/src/test/java/com/booleanuk/core/BasketTest.java @@ -25,4 +25,13 @@ public void canAndDoesRemoveBagel() { assertTrue(basket.removeItem("BGLO")); assertTrue(basket.getItems().isEmpty()); } + + @Test + public void removesCorrectBagel() { + Basket basket = new Basket(); + basket.addItem("BGLO", 0.49, "Bagel", "Onion"); + basket.addItem("BGLP", 0.39, "Bagel", "Plain"); + basket.removeItem("BGLP"); + assertNotEquals("BGLP", basket.getItems().getFirst().getSKU()); + } } From 28090769ed35ad42ccddbb9d4d975402bcb445bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20S=C3=B6nnergaard?= Date: Fri, 10 Jan 2025 14:46:58 +0100 Subject: [PATCH 13/43] Add member fields and accessors for Item --- src/main/java/com/booleanuk/core/Item.java | 25 +++++++++++++++++++ .../java/com/booleanuk/core/BasketTest.java | 2 +- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/booleanuk/core/Item.java b/src/main/java/com/booleanuk/core/Item.java index b85344c21..7db6411ae 100644 --- a/src/main/java/com/booleanuk/core/Item.java +++ b/src/main/java/com/booleanuk/core/Item.java @@ -1,4 +1,29 @@ package com.booleanuk.core; public class Item { + private String sku; + private double price; + private String name; + private String variant; + private int size; + + public String getSku() { + return sku; + } + + public double getPrice() { + return price; + } + + public String getName() { + return name; + } + + public String getVariant() { + return variant; + } + + public int getSize() { + return size; + } } diff --git a/src/test/java/com/booleanuk/core/BasketTest.java b/src/test/java/com/booleanuk/core/BasketTest.java index 6e3baf77d..c0c5d4c40 100644 --- a/src/test/java/com/booleanuk/core/BasketTest.java +++ b/src/test/java/com/booleanuk/core/BasketTest.java @@ -32,6 +32,6 @@ public void removesCorrectBagel() { basket.addItem("BGLO", 0.49, "Bagel", "Onion"); basket.addItem("BGLP", 0.39, "Bagel", "Plain"); basket.removeItem("BGLP"); - assertNotEquals("BGLP", basket.getItems().getFirst().getSKU()); + assertNotEquals("BGLP", basket.getItems().getFirst().getSku()); } } From 51d5a8b71bbee7f8def4aadf6c2fd2d91a8516c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20S=C3=B6nnergaard?= Date: Fri, 10 Jan 2025 14:55:55 +0100 Subject: [PATCH 14/43] Add test to ensure not adding past basket capacity --- src/test/java/com/booleanuk/core/BasketTest.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/test/java/com/booleanuk/core/BasketTest.java b/src/test/java/com/booleanuk/core/BasketTest.java index c0c5d4c40..0fd3cc274 100644 --- a/src/test/java/com/booleanuk/core/BasketTest.java +++ b/src/test/java/com/booleanuk/core/BasketTest.java @@ -34,4 +34,12 @@ public void removesCorrectBagel() { basket.removeItem("BGLP"); assertNotEquals("BGLP", basket.getItems().getFirst().getSku()); } + + public void cannotAddPastCapacity() { + Basket.setCapacity(2); + Basket basket = new Basket(); + basket.addItem("BGLO", 0.49, "Bagel", "Onion"); + basket.addItem("BGLO", 0.49, "Bagel", "Onion"); + assertFalse(basket.addItem("BGLO", 0.49, "Bagel", "Onion")); + } } From 61e1f6dee7552c1a54c9b0f73c9bd2071464373f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20S=C3=B6nnergaard?= Date: Fri, 10 Jan 2025 15:01:32 +0100 Subject: [PATCH 15/43] Add check when adding to basket to ensure not adding past capacity --- src/main/java/com/booleanuk/core/Basket.java | 9 +++++++++ src/test/java/com/booleanuk/core/BasketTest.java | 1 + 2 files changed, 10 insertions(+) diff --git a/src/main/java/com/booleanuk/core/Basket.java b/src/main/java/com/booleanuk/core/Basket.java index 2fd614637..f30210a0a 100644 --- a/src/main/java/com/booleanuk/core/Basket.java +++ b/src/main/java/com/booleanuk/core/Basket.java @@ -4,9 +4,14 @@ import java.util.List; public class Basket { + private static int capacity = 5; private List items = new ArrayList<>(); public boolean addItem(String sku, double price, String name, String variant) { + if (items.size() >= capacity) { + System.out.println("You cannot fit more items in your basket."); + return false; + } items.add(new Item()); return true; } @@ -19,4 +24,8 @@ public boolean removeItem(String sku) { public List getItems() { return items; } + + public static void setCapacity(int newCapacity) { + capacity = newCapacity; + } } diff --git a/src/test/java/com/booleanuk/core/BasketTest.java b/src/test/java/com/booleanuk/core/BasketTest.java index 0fd3cc274..f1ff4eb2c 100644 --- a/src/test/java/com/booleanuk/core/BasketTest.java +++ b/src/test/java/com/booleanuk/core/BasketTest.java @@ -35,6 +35,7 @@ public void removesCorrectBagel() { assertNotEquals("BGLP", basket.getItems().getFirst().getSku()); } + @Test public void cannotAddPastCapacity() { Basket.setCapacity(2); Basket basket = new Basket(); From 91673fdd72f706227c7785ebaa13d568c762748e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20S=C3=B6nnergaard?= Date: Fri, 10 Jan 2025 15:05:42 +0100 Subject: [PATCH 16/43] Add test for cost of empty basket --- src/main/java/com/booleanuk/core/Basket.java | 4 ++++ src/test/java/com/booleanuk/core/BasketTest.java | 10 ++++++++++ 2 files changed, 14 insertions(+) diff --git a/src/main/java/com/booleanuk/core/Basket.java b/src/main/java/com/booleanuk/core/Basket.java index f30210a0a..33fbdcb38 100644 --- a/src/main/java/com/booleanuk/core/Basket.java +++ b/src/main/java/com/booleanuk/core/Basket.java @@ -28,4 +28,8 @@ public List getItems() { public static void setCapacity(int newCapacity) { capacity = newCapacity; } + + public static int getCapacity() { + return capacity; + } } diff --git a/src/test/java/com/booleanuk/core/BasketTest.java b/src/test/java/com/booleanuk/core/BasketTest.java index f1ff4eb2c..b7185bdc1 100644 --- a/src/test/java/com/booleanuk/core/BasketTest.java +++ b/src/test/java/com/booleanuk/core/BasketTest.java @@ -37,10 +37,20 @@ public void removesCorrectBagel() { @Test public void cannotAddPastCapacity() { + int originalCapacity = Basket.getCapacity(); Basket.setCapacity(2); Basket basket = new Basket(); basket.addItem("BGLO", 0.49, "Bagel", "Onion"); basket.addItem("BGLO", 0.49, "Bagel", "Onion"); assertFalse(basket.addItem("BGLO", 0.49, "Bagel", "Onion")); + + // Reset the capacity, since it's static + Basket.setCapacity(originalCapacity); + } + + @Test + public void costOfEmptyBasketShouldBeZero() { + Basket basket = new Basket(); + assertEquals(0, basket.getTotalCost()); } } From 5a7d685395975f282c2f21caf32a54128b2fc21b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20S=C3=B6nnergaard?= Date: Fri, 10 Jan 2025 15:06:18 +0100 Subject: [PATCH 17/43] Add basket method for calculating total cost --- src/main/java/com/booleanuk/core/Basket.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/booleanuk/core/Basket.java b/src/main/java/com/booleanuk/core/Basket.java index 33fbdcb38..16ca91ae6 100644 --- a/src/main/java/com/booleanuk/core/Basket.java +++ b/src/main/java/com/booleanuk/core/Basket.java @@ -21,6 +21,10 @@ public boolean removeItem(String sku) { return true; } + public double getTotalCost() { + return 0; + } + public List getItems() { return items; } From 672b8885cb5cea3964ddd67bcbc7cf1eb92b49aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20S=C3=B6nnergaard?= Date: Fri, 10 Jan 2025 15:08:13 +0100 Subject: [PATCH 18/43] Add test for calculating total cost of multiple items --- src/test/java/com/booleanuk/core/BasketTest.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/test/java/com/booleanuk/core/BasketTest.java b/src/test/java/com/booleanuk/core/BasketTest.java index b7185bdc1..d7a60bffd 100644 --- a/src/test/java/com/booleanuk/core/BasketTest.java +++ b/src/test/java/com/booleanuk/core/BasketTest.java @@ -53,4 +53,13 @@ public void costOfEmptyBasketShouldBeZero() { Basket basket = new Basket(); assertEquals(0, basket.getTotalCost()); } + + @Test + public void totalCostShouldBeSomething() { + Basket basket = new Basket(); + basket.addItem("BGLO", 0.49, "Bagel", "Onion"); + basket.addItem("BGLO", 0.49, "Bagel", "Onion"); + basket.addItem("BGLO", 0.49, "Bagel", "Onion"); + assertEquals(1.47, basket.getTotalCost()); + } } From 93462763779ee80e8c70020f98c5e7061dd28e14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20S=C3=B6nnergaard?= Date: Fri, 10 Jan 2025 15:16:39 +0100 Subject: [PATCH 19/43] Implement calculating total cost of basket --- src/main/java/com/booleanuk/core/Basket.java | 18 ++++++++++++++---- src/main/java/com/booleanuk/core/Item.java | 8 ++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/booleanuk/core/Basket.java b/src/main/java/com/booleanuk/core/Basket.java index 16ca91ae6..347da2e9c 100644 --- a/src/main/java/com/booleanuk/core/Basket.java +++ b/src/main/java/com/booleanuk/core/Basket.java @@ -7,22 +7,32 @@ public class Basket { private static int capacity = 5; private List items = new ArrayList<>(); - public boolean addItem(String sku, double price, String name, String variant) { + public boolean addItem(String sku, double price, String name, String variant, int size) { if (items.size() >= capacity) { System.out.println("You cannot fit more items in your basket."); return false; } - items.add(new Item()); + items.add(new Item(sku, price, name, variant, size)); return true; } - public boolean removeItem(String sku) { + public boolean addItem(String sku, double price, String name, String variant) { + // Shorthand, assuming size=1 + return addItem(sku, price, name, variant, 1); + } + + + public boolean removeItem(String sku) { items.removeFirst(); return true; } public double getTotalCost() { - return 0; + double totalCost = 0; + for (Item item : items) { + totalCost += item.getPrice(); + } + return totalCost; } public List getItems() { diff --git a/src/main/java/com/booleanuk/core/Item.java b/src/main/java/com/booleanuk/core/Item.java index 7db6411ae..4ca85926d 100644 --- a/src/main/java/com/booleanuk/core/Item.java +++ b/src/main/java/com/booleanuk/core/Item.java @@ -7,6 +7,14 @@ public class Item { private String variant; private int size; + public Item(String sku, double price, String name, String variant, int size) { + this.sku = sku; + this.price = price; + this.name = name; + this.variant = variant; + this.size = size; + } + public String getSku() { return sku; } From 2f48146f2878317b273ab420e0a87ad75257ed07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20S=C3=B6nnergaard?= Date: Fri, 10 Jan 2025 15:22:34 +0100 Subject: [PATCH 20/43] Fix remove method not removing the correct item --- src/main/java/com/booleanuk/core/Basket.java | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/booleanuk/core/Basket.java b/src/main/java/com/booleanuk/core/Basket.java index 347da2e9c..cf69cc87e 100644 --- a/src/main/java/com/booleanuk/core/Basket.java +++ b/src/main/java/com/booleanuk/core/Basket.java @@ -23,8 +23,20 @@ public boolean addItem(String sku, double price, String name, String variant) { public boolean removeItem(String sku) { - items.removeFirst(); - return true; + int indexToRemove = 0; + boolean foundItem = false; + for (int i=0; i Date: Fri, 10 Jan 2025 15:29:19 +0100 Subject: [PATCH 21/43] Update class diagram and domain model to reflect code --- class_diagram.png | Bin 42299 -> 47299 bytes domain-model.md | 7 ++++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/class_diagram.png b/class_diagram.png index 3dd76fb6227b9d6cda43f7e4cbbba5651309bebf..cd5c7fb1e97b1ed93af88dcde5ba8245fba75574 100644 GIT binary patch literal 47299 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 literal 42299 zcmeEv2Ut`|*0v%NL?pCeAU6$-BN?Fyf`lfCG+-iwO-5ojNkF2gG&!iCG(k{7B}Ryt4eB%tq!fd-j}>byn1Iw!3CwZEL=V zOGIJ&ic46~%E8H*O9aU!ER1$^#N2AX-)R4%HY;}TW?*S6L+=HL%yb5k1!;v))HSO+`Mq9i0D#1Dr4{>}?%3pCdH z#~~EWEPvaFIBQpPtdq5a{r19y#lXX-wwL2%incZ1ZWh{ZF>%0}nPaz`z^a6~L=?FM z<-i!ke?=5_b_D#eHrwu`AbMWj>6C~A63wS(=Ambfa&~dw9?BjK=KFmwHNm#=eSg7^ zqwS7qcTE|KcC=D=Ff+FW1Djpjen>)CbbA~#_w5Ez5%KK?OYH8;cP342xM1zEyOQto z78bO0u{JYz+J1JYqqBp9t+Tb`ZyQY=?Cs4>cfRUQM>G~o{FL8kztd#lV7s&Aod!p+ zs^9b=HeC3_juKn7t<9XRw)=_;BeqvTY*#V2wzS%Pvyhm?_8mL)Zs(nqI9Z{AWNknH zhmW$ojk}wPb#MUV{qW6xyuI7W?wW$REpe}R_fcEbUEB7YjhOOTEhh~6lDyhQ)MdV% zmjiM72Mzd_eZ&6c5dFhn>|tY}q;mPxRUJo7B`r5WWjT|xe7h@gMccaUd@*^nlg;j# zc5-&#Jp@i})^@gNd(cVV!olA8!pUL5YY#9i+7{dr0-eEatn-fG3X6e;Uwd32J_))J zUyU_)0>Z6{-q|+dliN+_(BHKcv5%<(&_#|;)+XPVLhNFP##&n2%R4wbJJ{_G@XEwh+z1d7u!`_Lg8X zf1Q@d@1}L?kJAzo+iCl8THwoW+m4-Cp>2Tx*`uA!<%ypI*bAbH{@bT)cgsLepfPt> z_CIg42(Toe_xIEOw|f3TDg5*(?SAfGj}jl4y(!ueZEEcdJ{ZwdSOXLJeNjK0EFc`< zK>Xzt*_vArfByUoIS~i5w>0isYlI)JHs-*r)WE>U@~$qIt}qFkcDzAJ#=U@g19K@+h%)>*;9-pLt@CN4n) zX%5bpn>q1}{p2+KbbEF_|3Bh1>`4Ev^!zR1-|hD^+5daQ>whIGPAEY^b8RIRYYj_t zQBySq6=5CBPqZ#kRIHuN?Z77?%E>uvu(iTsw#5Ba1%#RvALCsm@q>mC7Tm>8K+h0W&7WG5e!B1-wEBbn{)2w8wf=6kt(@(C zHLkz6XuBr-uP7fophk$+b64A3BpP%iz^#92+0jTMzqagZBx2L=wT~^@#N1ZX!O7Zr z8+&87wb$>o(w|oGAa>C9-x8OdZvPU!^HXWraT|UkEkrjAZDvN)GCbRU2~h!EaK-{V zv+ZxW0!Io>)cU{PII;c11UL=mX!}2i+<#5lUmU}2we!dS5~0*zpvqqqk@yZE`dgCq zFEwd$wwJDIDeGyW?S;)y3f4|;eCM=&V$!&TiK2xyw*z?OztZ(*08Bzc{|z54vdEMFToY@CVoIzl_;7 zv-_uF%tZcP#!Q$9*@$2CXXyR!@iey~-(O+Ognq}EiHPsK?FSY6e}FOD<%E7qnK{|G z{OD`^#~JdUDB!0Ki=Z=EOc4FLj5A&}i$^E;#3fsEk zZ;}y0y9(!@%SQZE{&&vA&&2$Cgkf4)Qd|C95xEroxN&ii?+{bxkRpHAd{3J`@wwh!tLGWQ27|9>4J{u6Z6 z&nS$a3Cy1^?ML`$Sz^TG3`bkEsksKRtYJ5H?&<&%-~ZDhp8qsel;T9J93B~@e5}ofwU4Nw{c&Fe? z`PbU(A6bU)cXzA3w{Pq`K&+YHE(pG@M00h|9`-$|NV$vGjHcp^tuE=_+j5gW{_GCN z!*#jrsu&6p=cD?M*eMx1t}w?wl;wyNyYC&L)aJ}?a#i-E5I2wdv5){Oy5np?M+N06 zH!rHn=^Li8-z4R=(u}x59+0W@>KXlf?BGnPWygJ&!cn~Ebn)oG{EX*Ao@mdd0UMu= zf%WUlJrnq{7j82Hp$?Us9kU7~FimC>&*f=RpVjxqSErkAvw2$;v9^VT?pN_8rHA=0 zPOzBPzkT~w$-h1K7kYNTJj$~9Myc2?(Kxz7g9hrHJ(Ll9C`oBwN+L0@Kgp5ohtX=A zRq<)d229dZM#!EeAg%o{0-p|&d0p7_gz-k&(zQAae*fVPb^}_~0cXq!=6q)dY6#E`XW2~ik`lHLo{5Yer2WTetdlXna=gd0wrZ-bxX@sZI&K= zLqpLOFZ#sw<(as;I@R9rnsBzb)m3*9X=yt#yPiA9#q<=^_G(-nyeAxE_svhs%4$08 zu~7R$DeF@HgQAKG`&+kfH@ti)TdjBaGEGO;t5CK}L`Myo&L;6+UFG%q?|xw!F5xnM=gZibU~q8o0Ku0+QCmAEf1xYKR7}#3#uZlT zIwjnhY4}1ao(W;EGY1jHlAzlL2OTD�u?tEhhR)T%I3eVtO&Ce(u~gs^|gTPs`a2 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 Date: Mon, 13 Jan 2025 11:35:05 +0100 Subject: [PATCH 22/43] Add test for showing stock (excl. filling) --- .../java/com/booleanuk/core/ShopHandlerTest.java | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/test/java/com/booleanuk/core/ShopHandlerTest.java b/src/test/java/com/booleanuk/core/ShopHandlerTest.java index 8e9fdc881..71003e418 100644 --- a/src/test/java/com/booleanuk/core/ShopHandlerTest.java +++ b/src/test/java/com/booleanuk/core/ShopHandlerTest.java @@ -1,11 +1,19 @@ package com.booleanuk.core; import static org.junit.jupiter.api.Assertions.*; -import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.*; public class ShopHandlerTest { @Test - public void test() { - + public void showItemsShowsAllItemsThatAreNotFillings() { + ShopHandler sh = new ShopHandler(); + String list = sh.showItems(); + System.out.println(list); + for (Item item : ShopHandler.getStock()) { + if (!item.getName().equals("Filling")) { + // if item.name & price is in list, good + assertTrue(list.contains(item.getName() + "\t" + item.getVariant() + (item.getVariant().length() > 6 ? "\t" : "\t\t") + item.getPrice())); + } + } } } From 599befb495c93fecb3b646bdc004f44d7125e3b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20S=C3=B6nnergaard?= Date: Mon, 13 Jan 2025 11:35:25 +0100 Subject: [PATCH 23/43] Implement showItems --- src/main/java/com/booleanuk/core/Item.java | 4 +++ .../java/com/booleanuk/core/ShopHandler.java | 34 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/src/main/java/com/booleanuk/core/Item.java b/src/main/java/com/booleanuk/core/Item.java index 4ca85926d..b72131de5 100644 --- a/src/main/java/com/booleanuk/core/Item.java +++ b/src/main/java/com/booleanuk/core/Item.java @@ -15,6 +15,10 @@ public Item(String sku, double price, String name, String variant, int size) { this.size = size; } + public Item(String sku, double price, String name, String variant) { + this(sku, price, name, variant, 1); + } + public String getSku() { return sku; } diff --git a/src/main/java/com/booleanuk/core/ShopHandler.java b/src/main/java/com/booleanuk/core/ShopHandler.java index aff2375c0..a66a4c330 100644 --- a/src/main/java/com/booleanuk/core/ShopHandler.java +++ b/src/main/java/com/booleanuk/core/ShopHandler.java @@ -1,4 +1,38 @@ package com.booleanuk.core; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + public class ShopHandler { + private static List stock = new ArrayList<>(Arrays.asList( + new Item("BGLO", 0.49, "Bagel", "Onion"), + new Item("BGLP", 0.39, "Bagel", "Plain"), + new Item("BGLE", 0.49, "Bagel", "Everything"), + new Item("BGLS", 0.49, "Bagel", "Sesame"), + new Item("COFB", 0.99, "Coffee", "Black"), + new Item("COFW", 1.19, "Coffee", "White"), + new Item("COFC", 1.29, "Coffee", "Cappuccino"), + new Item("COFL", 1.29, "Coffee", "Latte"), + new Item("FILB", 0.12, "Filling", "Bacon"), + new Item("FILE", 0.12, "Filling", "Egg"), + new Item("FILC", 0.12, "Filling", "Cheese"), + new Item("FILX", 0.12, "Filling", "Cream Cheese"), + new Item("FILS", 0.12, "Filling", "Smoked Salmon"), + new Item("FILH", 0.12, "Filling", "Ham") + )); + + public String showItems() { + StringBuilder sb = new StringBuilder(); + for (Item item : stock) { + if (!item.getName().equals("Filling")) { + sb.append(item.getName()).append("\t").append(item.getVariant()).append(item.getVariant().length() > 6 ? "\t" : "\t\t").append(item.getPrice()).append("\n"); + } + } + return sb.toString(); + } + + public static List getStock() { + return stock; + } } From 13220ef3a7d816c564a0d4d11a81d31a5c77608b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20S=C3=B6nnergaard?= Date: Mon, 13 Jan 2025 11:44:41 +0100 Subject: [PATCH 24/43] Add test and implementation for showFillings --- src/main/java/com/booleanuk/core/ShopHandler.java | 10 ++++++++++ .../java/com/booleanuk/core/ShopHandlerTest.java | 15 ++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/booleanuk/core/ShopHandler.java b/src/main/java/com/booleanuk/core/ShopHandler.java index a66a4c330..10d352306 100644 --- a/src/main/java/com/booleanuk/core/ShopHandler.java +++ b/src/main/java/com/booleanuk/core/ShopHandler.java @@ -32,6 +32,16 @@ public String showItems() { return sb.toString(); } + public String showFillings() { + StringBuilder sb = new StringBuilder(); + for (Item item : stock) { + if (item.getName().equals("Filling")) { + sb.append(item.getVariant()).append("\n"); + } + } + return sb.toString(); + } + public static List getStock() { return stock; } diff --git a/src/test/java/com/booleanuk/core/ShopHandlerTest.java b/src/test/java/com/booleanuk/core/ShopHandlerTest.java index 71003e418..d91003bf3 100644 --- a/src/test/java/com/booleanuk/core/ShopHandlerTest.java +++ b/src/test/java/com/booleanuk/core/ShopHandlerTest.java @@ -8,7 +8,7 @@ public class ShopHandlerTest { public void showItemsShowsAllItemsThatAreNotFillings() { ShopHandler sh = new ShopHandler(); String list = sh.showItems(); - System.out.println(list); +// System.out.println(list); for (Item item : ShopHandler.getStock()) { if (!item.getName().equals("Filling")) { // if item.name & price is in list, good @@ -16,4 +16,17 @@ public void showItemsShowsAllItemsThatAreNotFillings() { } } } + + @Test + public void showFillingsWorks() { + ShopHandler sh = new ShopHandler(); + String list = sh.showFillings(); + System.out.println(list); + for (Item item : ShopHandler.getStock()) { + if (item.getName().equals("Filling")) { + // if item.name & price is in list, good + assertTrue(list.contains(item.getVariant())); + } + } + } } From 54d8f2b3915ea1130fd19b8235f854320efff124 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20S=C3=B6nnergaard?= Date: Mon, 13 Jan 2025 12:35:59 +0100 Subject: [PATCH 25/43] Add test and implementation for listing bagels and drinks --- .../java/com/booleanuk/core/ShopHandler.java | 31 ++++++++++++++++++- .../com/booleanuk/core/ShopHandlerTest.java | 28 ++++++++++++++++- 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/booleanuk/core/ShopHandler.java b/src/main/java/com/booleanuk/core/ShopHandler.java index 10d352306..c86d53d0e 100644 --- a/src/main/java/com/booleanuk/core/ShopHandler.java +++ b/src/main/java/com/booleanuk/core/ShopHandler.java @@ -3,9 +3,10 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Scanner; public class ShopHandler { - private static List stock = new ArrayList<>(Arrays.asList( + private static final List stock = new ArrayList<>(Arrays.asList( new Item("BGLO", 0.49, "Bagel", "Onion"), new Item("BGLP", 0.39, "Bagel", "Plain"), new Item("BGLE", 0.49, "Bagel", "Everything"), @@ -21,8 +22,14 @@ public class ShopHandler { new Item("FILS", 0.12, "Filling", "Smoked Salmon"), new Item("FILH", 0.12, "Filling", "Ham") )); + Scanner scanner; + + public ShopHandler() { + this.scanner = new Scanner(System.in); + } public String showItems() { + // Maybe this method isn't useful, may remove StringBuilder sb = new StringBuilder(); for (Item item : stock) { if (!item.getName().equals("Filling")) { @@ -42,6 +49,28 @@ public String showFillings() { return sb.toString(); } + public String showBagels() { + StringBuilder sb = new StringBuilder(); + for (Item item : stock) { + if (item.getName().equals("Bagel")) { + sb.append(item.getVariant()).append(item.getVariant().length() > 6 ? "\t" : "\t\t").append(item.getPrice()).append("\n"); + } + } + return sb.toString(); + } + + public String showCoffees() { + StringBuilder sb = new StringBuilder(); + for (Item item : stock) { + if (item.getName().equals("Coffee")) { + sb.append(item.getVariant()).append(item.getVariant().length() > 6 ? "\t" : "\t\t").append(item.getPrice()).append("\n"); + } + } + return sb.toString(); + } + + + public static List getStock() { return stock; } diff --git a/src/test/java/com/booleanuk/core/ShopHandlerTest.java b/src/test/java/com/booleanuk/core/ShopHandlerTest.java index d91003bf3..dd00d7262 100644 --- a/src/test/java/com/booleanuk/core/ShopHandlerTest.java +++ b/src/test/java/com/booleanuk/core/ShopHandlerTest.java @@ -21,7 +21,7 @@ public void showItemsShowsAllItemsThatAreNotFillings() { public void showFillingsWorks() { ShopHandler sh = new ShopHandler(); String list = sh.showFillings(); - System.out.println(list); +// System.out.println(list); for (Item item : ShopHandler.getStock()) { if (item.getName().equals("Filling")) { // if item.name & price is in list, good @@ -29,4 +29,30 @@ public void showFillingsWorks() { } } } + + @Test + public void showBagelsWorks() { + ShopHandler sh = new ShopHandler(); + String list = sh.showBagels(); +// System.out.println(list); + for (Item item : ShopHandler.getStock()) { + if (item.getName().equals("Bagel")) { + // if item.name & price is in list, good + assertTrue(list.contains(item.getVariant() + (item.getVariant().length() > 6 ? "\t" : "\t\t") + item.getPrice())); + } + } + } + + @Test + public void showCoffeesWorks() { + ShopHandler sh = new ShopHandler(); + String list = sh.showCoffees(); +// System.out.println(list); + for (Item item : ShopHandler.getStock()) { + if (item.getName().equals("Coffee")) { + // if item.name & price is in list, good + assertTrue(list.contains(item.getVariant() + (item.getVariant().length() > 6 ? "\t" : "\t\t") + item.getPrice())); + } + } + } } From c18a1c01fd84dcf40a7d29b95b27bbf6609f2093 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20S=C3=B6nnergaard?= Date: Mon, 13 Jan 2025 13:27:30 +0100 Subject: [PATCH 26/43] Implement menu for placing an order --- src/main/java/com/booleanuk/core/Basket.java | 16 ++- src/main/java/com/booleanuk/core/Main.java | 8 ++ .../java/com/booleanuk/core/ShopHandler.java | 114 +++++++++++++++++- 3 files changed, 135 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/booleanuk/core/Main.java diff --git a/src/main/java/com/booleanuk/core/Basket.java b/src/main/java/com/booleanuk/core/Basket.java index cf69cc87e..8f0f36541 100644 --- a/src/main/java/com/booleanuk/core/Basket.java +++ b/src/main/java/com/booleanuk/core/Basket.java @@ -8,11 +8,23 @@ public class Basket { private List items = new ArrayList<>(); public boolean addItem(String sku, double price, String name, String variant, int size) { - if (items.size() >= capacity) { + Item item = new Item(sku, price, name, variant, size); + return addItem(item); + } + + public boolean addItem(Item item) { + if (canFitItem(item)) { + items.add(item); + return true; + } + return false; + } + + public boolean canFitItem(Item item) { + if (items.size() + item.getSize() > capacity) { System.out.println("You cannot fit more items in your basket."); return false; } - items.add(new Item(sku, price, name, variant, size)); return true; } diff --git a/src/main/java/com/booleanuk/core/Main.java b/src/main/java/com/booleanuk/core/Main.java new file mode 100644 index 000000000..e3b0eb665 --- /dev/null +++ b/src/main/java/com/booleanuk/core/Main.java @@ -0,0 +1,8 @@ +package com.booleanuk.core; + +public class Main { + public static void main(String[] args) { + ShopHandler sh = new ShopHandler(); + sh.placeOrder(); + } +} diff --git a/src/main/java/com/booleanuk/core/ShopHandler.java b/src/main/java/com/booleanuk/core/ShopHandler.java index c86d53d0e..e0f85355b 100644 --- a/src/main/java/com/booleanuk/core/ShopHandler.java +++ b/src/main/java/com/booleanuk/core/ShopHandler.java @@ -22,10 +22,33 @@ public class ShopHandler { new Item("FILS", 0.12, "Filling", "Smoked Salmon"), new Item("FILH", 0.12, "Filling", "Ham") )); - Scanner scanner; + private Scanner scanner; + private Basket basket; public ShopHandler() { this.scanner = new Scanner(System.in); + this.basket = new Basket(); + } + + public void placeOrder() { + while (true) { + String in; + do { + System.out.println("Do you want to add a bagel or coffee? (\"pay\" when done)"); + in = scanner.next(); + } while (!"bagel coffee pay".contains(in)); + switch (in) { + case "bagel": + orderBagel(); + break; + case "coffee": + orderCoffee(); + break; + case "pay": + System.out.println("Print receipt tbd. total cost " + basket.getTotalCost()); + return; + } + } } public String showItems() { @@ -69,7 +92,96 @@ public String showCoffees() { return sb.toString(); } + public void orderBagel() { + System.out.println("Select bagel variant:"); + System.out.println(showBagels()); + String in = ""; + do { + in = this.scanner.next(); + } while (!isValidBagel(in)); + boolean success = basket.addItem(bagelFromVariant(in)); + if (success) { + System.out.println("Add filling? Available fillings:"); + System.out.println(showFillings()); + do { + in = this.scanner.next(); + } while(!isValidFilling(in) && !in.equals("no")); + if (!in.equals("no")) { + basket.addItem(fillingFromVariant(in)); + } + } else { + System.out.println("Not able to add bagel to basket."); + } + } + + public void orderCoffee() { + System.out.println("Select coffee variant:"); + System.out.println(showCoffees()); + String in = ""; + do { + in = this.scanner.next(); + } while (!isValidCoffee(in)); + boolean success = basket.addItem(coffeeFromVariant(in)); + if (success) { + System.out.println("Coffee added to basket."); + } else { + System.out.println("Not able to add coffee to basket."); + } + } + + private Item bagelFromVariant(String variant) { + for (Item item : stock) { + if (item.getVariant().equals(variant)) { + return new Item(item.getSku(), item.getPrice(), item.getName(), item.getVariant()); + } + } + return null; + } + + private Item coffeeFromVariant(String variant) { + for (Item item : stock) { + if (item.getVariant().equals(variant)) { + return new Item(item.getSku(), item.getPrice(), item.getName(), item.getVariant()); + } + } + return null; + } + + private Item fillingFromVariant(String variant) { + for (Item item : stock) { + if (item.getVariant().equals(variant)) { + return new Item(item.getSku(), item.getPrice(), item.getName(), item.getVariant()); + } + } + return null; + } + + private static boolean isValidBagel(String variant) { + for (Item item: stock) { + if (item.getName().equals("Bagel") && item.getVariant().equals(variant)) { + return true; + } + } + return false; + } + + private static boolean isValidCoffee(String variant) { + for (Item item: stock) { + if (item.getName().equals("Coffee") && item.getVariant().equals(variant)) { + return true; + } + } + return false; + } + private static boolean isValidFilling(String variant) { + for (Item item: stock) { + if (item.getName().equals("Filling") && item.getVariant().equals(variant)) { + return true; + } + } + return false; + } public static List getStock() { return stock; From fca402acf7bdd4288b2b14ef0ce185efb68f6345 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20S=C3=B6nnergaard?= Date: Mon, 13 Jan 2025 14:07:18 +0100 Subject: [PATCH 27/43] Implement menu for removing from basket --- .../java/com/booleanuk/core/ShopHandler.java | 32 +++++++++++++++++-- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/booleanuk/core/ShopHandler.java b/src/main/java/com/booleanuk/core/ShopHandler.java index e0f85355b..70819f24a 100644 --- a/src/main/java/com/booleanuk/core/ShopHandler.java +++ b/src/main/java/com/booleanuk/core/ShopHandler.java @@ -34,9 +34,9 @@ public void placeOrder() { while (true) { String in; do { - System.out.println("Do you want to add a bagel or coffee? (\"pay\" when done)"); + System.out.println("bagel/coffee/remove/pay"); in = scanner.next(); - } while (!"bagel coffee pay".contains(in)); + } while (!"bagel coffee remove pay".contains(in)); switch (in) { case "bagel": orderBagel(); @@ -44,6 +44,9 @@ public void placeOrder() { case "coffee": orderCoffee(); break; + case "remove": + removeItem(); + break; case "pay": System.out.println("Print receipt tbd. total cost " + basket.getTotalCost()); return; @@ -51,6 +54,29 @@ public void placeOrder() { } } + public void removeItem() { + if (basket.getItems().isEmpty()) { + System.out.println("No items in basket."); + return; + } + System.out.println("Enter number of item to remove (0 to cancel):"); + System.out.println(showBasket()); + int in; + do { + in = scanner.nextInt(); + } while (in < 0 || in > basket.getItems().size()); + if (in == 0) return; + basket.removeItem(basket.getItems().get(in-1).getSku()); + } + + public String showBasket() { + StringBuilder sb = new StringBuilder(); + for (Item item : basket.getItems()) { + sb.append(item.getName()).append(", ").append(item.getVariant()).append(", ").append(item.getPrice()).append("\n"); + } + return sb.toString(); + } + public String showItems() { // Maybe this method isn't useful, may remove StringBuilder sb = new StringBuilder(); @@ -101,7 +127,7 @@ public void orderBagel() { } while (!isValidBagel(in)); boolean success = basket.addItem(bagelFromVariant(in)); if (success) { - System.out.println("Add filling? Available fillings:"); + System.out.println("Add filling (0.12) ([filling], no)? Available fillings:"); System.out.println(showFillings()); do { in = this.scanner.next(); From 51443ccf78539efdb3b014eeffacfb3382b04a4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20S=C3=B6nnergaard?= Date: Mon, 13 Jan 2025 14:07:43 +0100 Subject: [PATCH 28/43] Update domain model to fit with implementation --- domain-model.md | 39 +++++++++++++++++---------------------- 1 file changed, 17 insertions(+), 22 deletions(-) diff --git a/domain-model.md b/domain-model.md index c8cbfd4e7..96bc62182 100644 --- a/domain-model.md +++ b/domain-model.md @@ -12,12 +12,7 @@ ### Methods -| Method | Scenario | Result | -|--------|----------|--------| -| | | | -| | | | -| | | | - +Accessors for all fields. ## Class: Basket @@ -31,7 +26,7 @@ | Method | Scenario | Result | |----------------------------------------------------|-----------------------------------------------------|-------------------------------------------------------------| | addItem(name: String, variant: String): boolean | Basket is full | Return false. Print error message, don't add item to basket | -| | Basket is not full | Return true. Add item to basket. | +| addItem(item: Item): boolean | Basket is not full | Return true. Add item to basket. | | | One or more fields are invalid (shop doesn't stock) | Return false. Print error message. | | removeItem(name: String, variant: String): boolean | Item is not found in basket | Return false. Print error message. | | | Item is found in basket | Return true. Remove item from basket. | @@ -39,7 +34,6 @@ | | newCapacity is not valid (<= 0) | Don't change the basket capacity. | | getCapacity(): int | | | | getTotalCost(): double | | Calculate and return the cost of items in basket. | -| | | | ## Class: ShopHandler @@ -48,20 +42,21 @@ This is the public interface that a customer or manager interacts with the Bob's ### Member variables - basket: Basket -- stockedItems: `List>()` +- ~~stockedItems: `List>()`~~ +- - stockedItems: `List` (copy existing items when adding new items) ### Methods -| Method | Scenario | Result | -|--------------------------------|----------|--------------------------------------------------------------| -| placeOrder(): void (boolean?) | | Guide the customer through selecting items to order. | -| showItems(): void | | Print bagels and coffee w/ prices | -| showFillings(): void | | Print fillings w/ prices | -| orderBagel(): void | | Let customer choose a bagel. Then, let customer add filling. | -| orderCoffee(): void | | Let customer choose a variant. | -| setBasketCapacity(): void | | Update the basket capacity for all baskets. | - -# Notes for myself (will be deleted later) -- Basket methods protected? -- method for counting total size of items (not strictly needed)? -- Changing capacity of existing baskets doesn't make sense. Set individually to static value at construction time, make final? \ No newline at end of file +| Method | Scenario | Result | +|-------------------------------|----------|-----------------------------------------------------------------------| +| placeOrder(): void (boolean?) | | Guide the customer through selecting items to order. | +| showItems(): String | | Return String of bagels and coffee w/ prices | +| showFillings(): String | | Return String of fillings w/ prices | +| orderBagel(): void | | Let customer choose a bagel. Then, let customer add optional filling. | +| orderCoffee(): void | | Let customer choose a variant. | +| setBasketCapacity(): void | | Update the basket capacity for all baskets. | +| Some private helper functions | | | + +# Class: Main + +Run interactive interface. \ No newline at end of file From 2f6547e9a7ca4412de8d23e334c34b7bbb9a2ed0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20S=C3=B6nnergaard?= Date: Mon, 13 Jan 2025 14:11:37 +0100 Subject: [PATCH 29/43] Finish core --- src/main/java/com/booleanuk/core/ShopHandler.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/booleanuk/core/ShopHandler.java b/src/main/java/com/booleanuk/core/ShopHandler.java index 70819f24a..b1f5b82e1 100644 --- a/src/main/java/com/booleanuk/core/ShopHandler.java +++ b/src/main/java/com/booleanuk/core/ShopHandler.java @@ -92,7 +92,7 @@ public String showFillings() { StringBuilder sb = new StringBuilder(); for (Item item : stock) { if (item.getName().equals("Filling")) { - sb.append(item.getVariant()).append("\n"); + sb.append(item.getVariant()).append(" (").append(item.getPrice()).append(")").append("\n"); } } return sb.toString(); @@ -127,7 +127,7 @@ public void orderBagel() { } while (!isValidBagel(in)); boolean success = basket.addItem(bagelFromVariant(in)); if (success) { - System.out.println("Add filling (0.12) ([filling], no)? Available fillings:"); + System.out.println("Add filling ([filling], no)? Available fillings:"); System.out.println(showFillings()); do { in = this.scanner.next(); From 96fdb43ff8d7986daa4e3265b2aad9f02def5e5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20S=C3=B6nnergaard?= Date: Mon, 13 Jan 2025 15:42:27 +0100 Subject: [PATCH 30/43] Add domain model for extension --- domain-model-extension.md | 94 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 domain-model-extension.md diff --git a/domain-model-extension.md b/domain-model-extension.md new file mode 100644 index 000000000..d0f0c6923 --- /dev/null +++ b/domain-model-extension.md @@ -0,0 +1,94 @@ +# Bob's Bagels -- Domain model + +## Class: Item + +### Member variables + +- sku: String +- price: double +- name: String +- variant: String +- size: int (e.g., fillings maybe don't take up capacity) + +### Methods + +Accessors for all fields. + +## Class: Basket + +### Member variables + +- capacity: static int +- items: List + +### Methods + +| Method | Scenario | Result | +|----------------------------------------------------|-----------------------------------------------------|-------------------------------------------------------------| +| addItem(name: String, variant: String): boolean | Basket is full | Return false. Print error message, don't add item to basket | +| addItem(item: Item): boolean | Basket is not full | Return true. Add item to basket. | +| | One or more fields are invalid (shop doesn't stock) | Return false. Print error message. | +| removeItem(name: String, variant: String): boolean | Item is not found in basket | Return false. Print error message. | +| | Item is found in basket | Return true. Remove item from basket. | +| setCapacity(newCapacity: int): static void | newCapacity is valid (> 0) | Update the basket capacity. | +| | newCapacity is not valid (<= 0) | Don't change the basket capacity. | +| getCapacity(): int | | | +| getTotalCost(): double | | Calculate and return the cost of items in basket. | + +## Class: ShopHandler + +This is the public interface that a customer or manager interacts with the Bob's Bagels system through. + +### Member variables + +- basket: Basket +- ~~stockedItems: `List>()`~~ +- - stockedItems: `List` (copy existing items when adding new items) + +### Methods + +| Method | Scenario | Result | +|------------------------------------|----------|-----------------------------------------------------------------------| +| placeOrder(): void (boolean?) | | Guide the customer through selecting items to order. | +| showItems(): String | | Return String of bagels and coffee w/ prices | +| showFillings(): String | | Return String of fillings w/ prices | +| orderBagel(): void | | Let customer choose a bagel. Then, let customer add optional filling. | +| orderCoffee(): void | | Let customer choose a variant. | +| setBasketCapacity(): void | | Update the basket capacity for all baskets. | +| applyDiscounts(): ?? | | | +| printReceipt(basket: Basket): void | | | +| Some private helper functions | | | + +## Class: Coffee + +Inherits from: Item. + +### Member variables: +- discountBagel: Bagel + +### Methods + +getSize(): includes optional discountBagel + +getPrice(): includes optional discountBagel + +## Class: Bagel + +Inherits from: Item + +### Member variables: + +- filling: Item + +### Methods + +# Class: Main + +Run interactive interface. + +# User stories (extension) + +## Discounts + +- As a customer, I want to be able to have a bagel with my coffee for a discount. +- As a customer, I want multi-priced discounts to apply at checkout. From 0ee6ece9e860bee5481bd599d9db28265dd8d738 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20S=C3=B6nnergaard?= Date: Mon, 13 Jan 2025 15:43:01 +0100 Subject: [PATCH 31/43] Refactor Bagel and Coffee to distinct classes --- .../java/com/booleanuk/extension/Bagel.java | 20 +++++++++ .../java/com/booleanuk/extension/Coffee.java | 21 ++++++++++ .../java/com/booleanuk/extension/Item.java | 41 +++++++++++++++++++ 3 files changed, 82 insertions(+) create mode 100644 src/main/java/com/booleanuk/extension/Bagel.java create mode 100644 src/main/java/com/booleanuk/extension/Coffee.java create mode 100644 src/main/java/com/booleanuk/extension/Item.java diff --git a/src/main/java/com/booleanuk/extension/Bagel.java b/src/main/java/com/booleanuk/extension/Bagel.java new file mode 100644 index 000000000..8f4e5730a --- /dev/null +++ b/src/main/java/com/booleanuk/extension/Bagel.java @@ -0,0 +1,20 @@ +package com.booleanuk.extension; + +public class Bagel extends Item { + private Item filling = null; + public Bagel(String sku, double price, String name, String variant, int size) { + super(sku, price, name, variant, size); + } + + public Bagel(String sku, double price, String name, String variant) { + super(sku, price, name, variant); + } + + public void setFilling(Item filling) { + this.filling = filling; + } + + public Item getFilling() { + return this.filling; + } +} diff --git a/src/main/java/com/booleanuk/extension/Coffee.java b/src/main/java/com/booleanuk/extension/Coffee.java new file mode 100644 index 000000000..47fb697c8 --- /dev/null +++ b/src/main/java/com/booleanuk/extension/Coffee.java @@ -0,0 +1,21 @@ +package com.booleanuk.extension; + +public class Coffee extends Item { + private Bagel discountBagel = null; + + public Coffee(String sku, double price, String name, String variant, int size) { + super(sku, price, name, variant, size); + } + + public Coffee(String sku, double price, String name, String variant) { + super(sku, price, name, variant); + } + + public Bagel getDiscountBagel() { + return discountBagel; + } + + public void setDiscountBagel(Bagel discountBagel) { + this.discountBagel = discountBagel; + } +} diff --git a/src/main/java/com/booleanuk/extension/Item.java b/src/main/java/com/booleanuk/extension/Item.java new file mode 100644 index 000000000..9bc14ede9 --- /dev/null +++ b/src/main/java/com/booleanuk/extension/Item.java @@ -0,0 +1,41 @@ +package com.booleanuk.extension; + +public class Item { + private String sku; + private double price; + private String name; + private String variant; + private int size; + + public Item(String sku, double price, String name, String variant, int size) { + this.sku = sku; + this.price = price; + this.name = name; + this.variant = variant; + this.size = size; + } + + public Item(String sku, double price, String name, String variant) { + this(sku, price, name, variant, 1); + } + + public String getSku() { + return sku; + } + + public double getPrice() { + return price; + } + + public String getName() { + return name; + } + + public String getVariant() { + return variant; + } + + public int getSize() { + return size; + } +} From a533928c9b94d8040b9dda49b577ea362db1dc51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20S=C3=B6nnergaard?= Date: Mon, 13 Jan 2025 15:43:36 +0100 Subject: [PATCH 32/43] Add option to order discount bagel with coffee --- .../java/com/booleanuk/extension/Basket.java | 73 ++++++ .../java/com/booleanuk/extension/Main.java | 8 + .../com/booleanuk/extension/ShopHandler.java | 231 ++++++++++++++++++ 3 files changed, 312 insertions(+) create mode 100644 src/main/java/com/booleanuk/extension/Basket.java create mode 100644 src/main/java/com/booleanuk/extension/Main.java create mode 100644 src/main/java/com/booleanuk/extension/ShopHandler.java diff --git a/src/main/java/com/booleanuk/extension/Basket.java b/src/main/java/com/booleanuk/extension/Basket.java new file mode 100644 index 000000000..5cb1b509f --- /dev/null +++ b/src/main/java/com/booleanuk/extension/Basket.java @@ -0,0 +1,73 @@ +package com.booleanuk.extension; + +import java.util.ArrayList; +import java.util.List; + +public class Basket { + private static int capacity = 5; + private List items = new ArrayList<>(); + + public boolean addItem(String sku, double price, String name, String variant, int size) { + Item item = new Item(sku, price, name, variant, size); + return addItem(item); + } + + public boolean addItem(Item item) { + if (canFitItem(item)) { + items.add(item); + return true; + } + return false; + } + + public boolean canFitItem(Item item) { + if (items.size() + item.getSize() > capacity) { + System.out.println("You cannot fit more items in your basket."); + return false; + } + return true; + } + + public boolean addItem(String sku, double price, String name, String variant) { + // Shorthand, assuming size=1 + return addItem(sku, price, name, variant, 1); + } + + + public boolean removeItem(String sku) { + int indexToRemove = 0; + boolean foundItem = false; + for (int i=0; i getItems() { + return items; + } + + public static void setCapacity(int newCapacity) { + capacity = newCapacity; + } + + public static int getCapacity() { + return capacity; + } +} diff --git a/src/main/java/com/booleanuk/extension/Main.java b/src/main/java/com/booleanuk/extension/Main.java new file mode 100644 index 000000000..bd3cb8bc8 --- /dev/null +++ b/src/main/java/com/booleanuk/extension/Main.java @@ -0,0 +1,8 @@ +package com.booleanuk.extension; + +public class Main { + public static void main(String[] args) { + ShopHandler sh = new ShopHandler(); + sh.placeOrder(); + } +} diff --git a/src/main/java/com/booleanuk/extension/ShopHandler.java b/src/main/java/com/booleanuk/extension/ShopHandler.java new file mode 100644 index 000000000..b6f96a8d9 --- /dev/null +++ b/src/main/java/com/booleanuk/extension/ShopHandler.java @@ -0,0 +1,231 @@ +package com.booleanuk.extension; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Scanner; + +public class ShopHandler { + private static final List stock = new ArrayList<>(Arrays.asList( + new Item("BGLO", 0.49, "Bagel", "Onion"), + new Item("BGLP", 0.39, "Bagel", "Plain"), + new Item("BGLE", 0.49, "Bagel", "Everything"), + new Item("BGLS", 0.49, "Bagel", "Sesame"), + new Item("COFB", 0.99, "Coffee", "Black"), + new Item("COFW", 1.19, "Coffee", "White"), + new Item("COFC", 1.29, "Coffee", "Cappuccino"), + new Item("COFL", 1.29, "Coffee", "Latte"), + new Item("FILB", 0.12, "Filling", "Bacon"), + new Item("FILE", 0.12, "Filling", "Egg"), + new Item("FILC", 0.12, "Filling", "Cheese"), + new Item("FILX", 0.12, "Filling", "Cream Cheese"), + new Item("FILS", 0.12, "Filling", "Smoked Salmon"), + new Item("FILH", 0.12, "Filling", "Ham") + )); + private Scanner scanner; + private Basket basket; + + public ShopHandler() { + this.scanner = new Scanner(System.in); + this.basket = new Basket(); + } + + public void placeOrder() { + while (true) { + String in; + do { + System.out.println("bagel/coffee/remove/pay"); + in = scanner.next(); + } while (!"bagel coffee remove pay".contains(in)); + switch (in) { + case "bagel": + orderBagel(); + break; + case "coffee": + orderCoffee(); + break; + case "remove": + removeItem(); + break; + case "pay": + System.out.println("Print receipt tbd. total cost " + basket.getTotalCost()); + return; + } + } + } + + public void removeItem() { + if (basket.getItems().isEmpty()) { + System.out.println("No items in basket."); + return; + } + System.out.println("Enter number of item to remove (0 to cancel):"); + System.out.println(showBasket()); + int in; + do { + in = scanner.nextInt(); + } while (in < 0 || in > basket.getItems().size()); + if (in == 0) return; + basket.removeItem(basket.getItems().get(in-1).getSku()); + } + + public String showBasket() { + StringBuilder sb = new StringBuilder(); + for (Item item : basket.getItems()) { + sb.append(item.getName()).append(", ").append(item.getVariant()).append(", ").append(item.getPrice()).append("\n"); + } + return sb.toString(); + } + + public String showItems() { + // Maybe this method isn't useful, may remove + StringBuilder sb = new StringBuilder(); + for (Item item : stock) { + if (!item.getName().equals("Filling")) { + sb.append(item.getName()).append("\t").append(item.getVariant()).append(item.getVariant().length() > 6 ? "\t" : "\t\t").append(item.getPrice()).append("\n"); + } + } + return sb.toString(); + } + + public String showFillings() { + StringBuilder sb = new StringBuilder(); + for (Item item : stock) { + if (item.getName().equals("Filling")) { + sb.append(item.getVariant()).append(" (").append(item.getPrice()).append(")").append("\n"); + } + } + return sb.toString(); + } + + public String showBagels() { + StringBuilder sb = new StringBuilder(); + for (Item item : stock) { + if (item.getName().equals("Bagel")) { + sb.append(item.getVariant()).append(item.getVariant().length() > 6 ? "\t" : "\t\t").append(item.getPrice()).append("\n"); + } + } + return sb.toString(); + } + + public String showCoffees() { + StringBuilder sb = new StringBuilder(); + for (Item item : stock) { + if (item.getName().equals("Coffee")) { + sb.append(item.getVariant()).append(item.getVariant().length() > 6 ? "\t" : "\t\t").append(item.getPrice()).append("\n"); + } + } + return sb.toString(); + } + + public void orderBagel() { + Bagel b = selectBagel(); + if (basket.addItem(b)) { + System.out.println("Bagel added to basket."); + } else { + System.out.println("Not able to add bagel to basket."); + } + } + public Bagel selectBagel() { + System.out.println("Select bagel variant:"); + System.out.println(showBagels()); + String in; + do { + in = this.scanner.next(); + } while (!isValidBagel(in)); + Bagel bagel = bagelFromVariant(in); + System.out.println("Add filling ([filling], no)? Available fillings:"); + System.out.println(showFillings()); + do { + in = this.scanner.next(); + } while(!isValidFilling(in) && !in.equals("no")); + if (!in.equals("no")) { + bagel.setFilling(fillingFromVariant(in)); + } + return bagel; + } + + public void orderCoffee() { + System.out.println("Select coffee variant:"); + System.out.println(showCoffees()); + String in; + do { + in = this.scanner.next(); + } while (!isValidCoffee(in)); + Coffee coffee = coffeeFromVariant(in); + System.out.println("Add bagel for a discount?"); + do { + in = this.scanner.next(); + } while (!"yes no".contains(in)); + + if (in.equals("yes")) { + Bagel b = selectBagel(); + coffee.setDiscountBagel(b); + } + + boolean success = basket.addItem(coffee); + if (success) { + System.out.println("Coffee added to basket."); + } else { + System.out.println("Not able to add coffee to basket."); + } + } + + private Bagel bagelFromVariant(String variant) { + for (Item item : stock) { + if (item.getVariant().equals(variant)) { + return new Bagel(item.getSku(), item.getPrice(), item.getName(), item.getVariant()); + } + } + return null; + } + + private Coffee coffeeFromVariant(String variant) { + for (Item item : stock) { + if (item.getVariant().equals(variant)) { + return new Coffee(item.getSku(), item.getPrice(), item.getName(), item.getVariant()); + } + } + return null; + } + + private Item fillingFromVariant(String variant) { + for (Item item : stock) { + if (item.getVariant().equals(variant)) { + return new Item(item.getSku(), item.getPrice(), item.getName(), item.getVariant()); + } + } + return null; + } + + private static boolean isValidBagel(String variant) { + for (Item item: stock) { + if (item.getName().equals("Bagel") && item.getVariant().equals(variant)) { + return true; + } + } + return false; + } + + private static boolean isValidCoffee(String variant) { + for (Item item: stock) { + if (item.getName().equals("Coffee") && item.getVariant().equals(variant)) { + return true; + } + } + return false; + } + + private static boolean isValidFilling(String variant) { + for (Item item: stock) { + if (item.getName().equals("Filling") && item.getVariant().equals(variant)) { + return true; + } + } + return false; + } + + public static List getStock() { + return stock; + } +} From b2b39495102f1c50e1b11f21bf08cd955e71870e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20S=C3=B6nnergaard?= Date: Mon, 13 Jan 2025 15:46:46 +0100 Subject: [PATCH 33/43] Update getting size of coffee to account for discount bagel --- src/main/java/com/booleanuk/extension/Coffee.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/com/booleanuk/extension/Coffee.java b/src/main/java/com/booleanuk/extension/Coffee.java index 47fb697c8..5c1d8b76f 100644 --- a/src/main/java/com/booleanuk/extension/Coffee.java +++ b/src/main/java/com/booleanuk/extension/Coffee.java @@ -18,4 +18,12 @@ public Bagel getDiscountBagel() { public void setDiscountBagel(Bagel discountBagel) { this.discountBagel = discountBagel; } + + @Override + public int getSize() { + if (discountBagel == null) { + return super.getSize(); + } + return super.getSize() + discountBagel.getSize(); + } } From 4895a5639a0ee3e05b034e46a5cef5ef0c477f80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20S=C3=B6nnergaard?= Date: Mon, 13 Jan 2025 16:29:52 +0100 Subject: [PATCH 34/43] Copy core test to extension test (ShopHandler) --- .../booleanuk/extension/ShopHandlerTest.java | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 src/test/java/com/booleanuk/extension/ShopHandlerTest.java diff --git a/src/test/java/com/booleanuk/extension/ShopHandlerTest.java b/src/test/java/com/booleanuk/extension/ShopHandlerTest.java new file mode 100644 index 000000000..bc0775712 --- /dev/null +++ b/src/test/java/com/booleanuk/extension/ShopHandlerTest.java @@ -0,0 +1,59 @@ +package com.booleanuk.extension; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class ShopHandlerTest { + @Test + public void showItemsShowsAllItemsThatAreNotFillings() { + ShopHandler sh = new ShopHandler(); + String list = sh.showItems(); +// System.out.println(list); + for (Item item : ShopHandler.getStock()) { + if (!item.getName().equals("Filling")) { + // if item.name & price is in list, good + assertTrue(list.contains(item.getName() + "\t" + item.getVariant() + (item.getVariant().length() > 6 ? "\t" : "\t\t") + item.getPrice())); + } + } + } + + @Test + public void showFillingsWorks() { + ShopHandler sh = new ShopHandler(); + String list = sh.showFillings(); +// System.out.println(list); + for (Item item : ShopHandler.getStock()) { + if (item.getName().equals("Filling")) { + // if item.name & price is in list, good + assertTrue(list.contains(item.getVariant())); + } + } + } + + @Test + public void showBagelsWorks() { + ShopHandler sh = new ShopHandler(); + String list = sh.showBagels(); +// System.out.println(list); + for (Item item : ShopHandler.getStock()) { + if (item.getName().equals("Bagel")) { + // if item.name & price is in list, good + assertTrue(list.contains(item.getVariant() + (item.getVariant().length() > 6 ? "\t" : "\t\t") + item.getPrice())); + } + } + } + + @Test + public void showCoffeesWorks() { + ShopHandler sh = new ShopHandler(); + String list = sh.showCoffees(); +// System.out.println(list); + for (Item item : ShopHandler.getStock()) { + if (item.getName().equals("Coffee")) { + // if item.name & price is in list, good + assertTrue(list.contains(item.getVariant() + (item.getVariant().length() > 6 ? "\t" : "\t\t") + item.getPrice())); + } + } + } +} From 08ea0a6d1dcca1f798c7168b9afd4e4b9da8802c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20S=C3=B6nnergaard?= Date: Tue, 14 Jan 2025 09:16:28 +0100 Subject: [PATCH 35/43] Add menu-less methods for ordering bagels and coffee --- .../java/com/booleanuk/core/ShopHandler.java | 25 +++++++++ .../com/booleanuk/extension/ShopHandler.java | 53 +++++++++++++++++-- 2 files changed, 75 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/booleanuk/core/ShopHandler.java b/src/main/java/com/booleanuk/core/ShopHandler.java index b1f5b82e1..f38608e38 100644 --- a/src/main/java/com/booleanuk/core/ShopHandler.java +++ b/src/main/java/com/booleanuk/core/ShopHandler.java @@ -1,5 +1,7 @@ package com.booleanuk.core; +import com.booleanuk.extension.Bagel; + import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -140,6 +142,22 @@ public void orderBagel() { } } + public boolean orderBagel(String variant, String fillingVar) { + if (!isValidFilling(fillingVar) || !isValidBagel(variant)) { + return false; + } + Item bagel = bagelFromVariant(variant); + Item filling = fillingFromVariant(fillingVar); + return basket.addItem(bagel) && basket.addItem(filling); + } + + public boolean orderBagel(String variant) { + if (!isValidBagel(variant)) { + return false; + } + return basket.addItem(bagelFromVariant(variant)); + } + public void orderCoffee() { System.out.println("Select coffee variant:"); System.out.println(showCoffees()); @@ -155,6 +173,13 @@ public void orderCoffee() { } } + public boolean orderCoffee(String variant) { + if (!isValidCoffee(variant)) { + return false; + } + return basket.addItem(coffeeFromVariant(variant)); + } + private Item bagelFromVariant(String variant) { for (Item item : stock) { if (item.getVariant().equals(variant)) { diff --git a/src/main/java/com/booleanuk/extension/ShopHandler.java b/src/main/java/com/booleanuk/extension/ShopHandler.java index b6f96a8d9..80814f875 100644 --- a/src/main/java/com/booleanuk/extension/ShopHandler.java +++ b/src/main/java/com/booleanuk/extension/ShopHandler.java @@ -25,11 +25,15 @@ public class ShopHandler { private Scanner scanner; private Basket basket; - public ShopHandler() { - this.scanner = new Scanner(System.in); + public ShopHandler(Scanner in) { + this.scanner = in; this.basket = new Basket(); } + public ShopHandler() { + this(new Scanner(System.in)); + } + public void placeOrder() { while (true) { String in; @@ -48,12 +52,31 @@ public void placeOrder() { removeItem(); break; case "pay": - System.out.println("Print receipt tbd. total cost " + basket.getTotalCost()); + System.out.println("Print receipt tbd. total cost " + basket.getTotalCost() + " - " + calculateDiscounts() + " = " + (basket.getTotalCost() - calculateDiscounts())); return; } } } + public double calculateDiscounts() { + double totalDiscount = 0; + for (Item item : basket.getItems()) { + if (item.getName().equals("Coffee")) { + Coffee coffee = (Coffee) item; // not nice! + totalDiscount += coffee.getPrice() + coffee.getDiscountBagel().getPrice() - 1.25; // hardcoded + } + } + for (Item item : stock) { + if (item.getName().equals("Bagel")) { + String sku = item.getSku(); + int n = basket.getItems().stream().filter(i -> i.getSku().equals(sku)).toList().size(); + double discount = (12 * item.getPrice() * (n % 12)) + (6 * item.getPrice() * ((n - 12 * (n % 12)) % 6)); // don't do this pls + totalDiscount += discount; + } + } + return totalDiscount; + } + public void removeItem() { if (basket.getItems().isEmpty()) { System.out.println("No items in basket."); @@ -126,6 +149,23 @@ public void orderBagel() { System.out.println("Not able to add bagel to basket."); } } + + public boolean orderBagel(String variant, String filling) { + if (!isValidFilling(filling) || !isValidBagel(variant)) { + return false; + } + Bagel bagel = bagelFromVariant(variant); + bagel.setFilling(fillingFromVariant(filling)); + return basket.addItem(bagel); + } + + public boolean orderBagel(String variant) { + if (!isValidBagel(variant)) { + return false; + } + return basket.addItem(bagelFromVariant(variant)); + } + public Bagel selectBagel() { System.out.println("Select bagel variant:"); System.out.println(showBagels()); @@ -171,6 +211,13 @@ public void orderCoffee() { } } + public boolean orderCoffee(String variant) { + if (!isValidCoffee(variant)) { + return false; + } + return basket.addItem(coffeeFromVariant(variant)); + } + private Bagel bagelFromVariant(String variant) { for (Item item : stock) { if (item.getVariant().equals(variant)) { From 4ddeb94c0875e91077749e58bba9ad26ed8d89b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20S=C3=B6nnergaard?= Date: Tue, 14 Jan 2025 09:58:59 +0100 Subject: [PATCH 36/43] Add test for calculating 6-pack bagel discount --- .../java/com/booleanuk/extension/ShopHandlerTest.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/booleanuk/extension/ShopHandlerTest.java b/src/test/java/com/booleanuk/extension/ShopHandlerTest.java index bc0775712..4de9b9169 100644 --- a/src/test/java/com/booleanuk/extension/ShopHandlerTest.java +++ b/src/test/java/com/booleanuk/extension/ShopHandlerTest.java @@ -1,7 +1,7 @@ package com.booleanuk.extension; import org.junit.jupiter.api.Test; - +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; public class ShopHandlerTest { @@ -56,4 +56,13 @@ public void showCoffeesWorks() { } } } + + @Test + public void multipackBagelsDiscount() { + ShopHandler sh = new ShopHandler(); + for (int i=0; i<7; i++) { + sh.orderBagel("Onion"); + } + assertEquals(0.45, sh.calculateDiscounts()); + } } From 3330521412cf53cc3635533c55d48c74e52a35c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20S=C3=B6nnergaard?= Date: Tue, 14 Jan 2025 11:13:34 +0100 Subject: [PATCH 37/43] Add test for 12-pack bagels --- .../java/com/booleanuk/extension/Bagel.java | 10 ++++++ .../java/com/booleanuk/extension/Basket.java | 6 +++- .../java/com/booleanuk/extension/Main.java | 4 ++- .../com/booleanuk/extension/ShopHandler.java | 8 ++++- .../booleanuk/extension/ShopHandlerTest.java | 31 +++++++++++++++++-- 5 files changed, 54 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/booleanuk/extension/Bagel.java b/src/main/java/com/booleanuk/extension/Bagel.java index 8f4e5730a..a6d4bcb34 100644 --- a/src/main/java/com/booleanuk/extension/Bagel.java +++ b/src/main/java/com/booleanuk/extension/Bagel.java @@ -17,4 +17,14 @@ public void setFilling(Item filling) { public Item getFilling() { return this.filling; } + +// @Override +// public double getPrice() { +// if (filling == null) return getBasePrice(); +// return super.getPrice() + filling.getPrice(); +// } + +// public double getBasePrice() { +// return super.getPrice(); +// } } diff --git a/src/main/java/com/booleanuk/extension/Basket.java b/src/main/java/com/booleanuk/extension/Basket.java index 5cb1b509f..f8bab49dc 100644 --- a/src/main/java/com/booleanuk/extension/Basket.java +++ b/src/main/java/com/booleanuk/extension/Basket.java @@ -4,7 +4,7 @@ import java.util.List; public class Basket { - private static int capacity = 5; + private static int capacity = 10; private List items = new ArrayList<>(); public boolean addItem(String sku, double price, String name, String variant, int size) { @@ -54,6 +54,10 @@ public boolean removeItem(String sku) { public double getTotalCost() { double totalCost = 0; for (Item item : items) { + if (item.getName().equals("Bagel")) + totalCost += ((Bagel) item).getFilling().getPrice(); + else if (item.getName().equals("Coffee")) + totalCost += ((Coffee) item).getDiscountBagel().getPrice(); totalCost += item.getPrice(); } return totalCost; diff --git a/src/main/java/com/booleanuk/extension/Main.java b/src/main/java/com/booleanuk/extension/Main.java index bd3cb8bc8..342b4f6f7 100644 --- a/src/main/java/com/booleanuk/extension/Main.java +++ b/src/main/java/com/booleanuk/extension/Main.java @@ -1,8 +1,10 @@ package com.booleanuk.extension; +import java.util.Scanner; + public class Main { public static void main(String[] args) { - ShopHandler sh = new ShopHandler(); + ShopHandler sh = new ShopHandler(new Scanner(System.in)); sh.placeOrder(); } } diff --git a/src/main/java/com/booleanuk/extension/ShopHandler.java b/src/main/java/com/booleanuk/extension/ShopHandler.java index 80814f875..df7a323e4 100644 --- a/src/main/java/com/booleanuk/extension/ShopHandler.java +++ b/src/main/java/com/booleanuk/extension/ShopHandler.java @@ -22,6 +22,9 @@ public class ShopHandler { new Item("FILS", 0.12, "Filling", "Smoked Salmon"), new Item("FILH", 0.12, "Filling", "Ham") )); + + private static final double SIX_BAGEL_DISCOUNT = 2.49; + private static final double DOZEN_BAGEL_DISCOUNT = 3.99; private Scanner scanner; private Basket basket; @@ -70,7 +73,10 @@ public double calculateDiscounts() { if (item.getName().equals("Bagel")) { String sku = item.getSku(); int n = basket.getItems().stream().filter(i -> i.getSku().equals(sku)).toList().size(); - double discount = (12 * item.getPrice() * (n % 12)) + (6 * item.getPrice() * ((n - 12 * (n % 12)) % 6)); // don't do this pls + double discount = ((int) (n/12)) * item.getPrice() * 12 - ((int) n/12) * DOZEN_BAGEL_DISCOUNT; + int bagelsLeft = n % 12; + discount += ((int) (bagelsLeft/6)) * item.getPrice() * 6 - ((int) bagelsLeft/6) * SIX_BAGEL_DISCOUNT; + System.out.println(discount); totalDiscount += discount; } } diff --git a/src/test/java/com/booleanuk/extension/ShopHandlerTest.java b/src/test/java/com/booleanuk/extension/ShopHandlerTest.java index 4de9b9169..e0ae5d58e 100644 --- a/src/test/java/com/booleanuk/extension/ShopHandlerTest.java +++ b/src/test/java/com/booleanuk/extension/ShopHandlerTest.java @@ -58,11 +58,38 @@ public void showCoffeesWorks() { } @Test - public void multipackBagelsDiscount() { + public void sixpackBagelsDiscount() { + double delta = 0.0001; ShopHandler sh = new ShopHandler(); for (int i=0; i<7; i++) { sh.orderBagel("Onion"); } - assertEquals(0.45, sh.calculateDiscounts()); + assertEquals(0.45, sh.calculateDiscounts(), delta); + } + + @Test + public void dozenBagelsDiscount() { + double delta = 0.0001; + ShopHandler sh = new ShopHandler(); + int oldCapacity = Basket.getCapacity(); + Basket.setCapacity(20); + for (int i=0; i<13; i++) { + sh.orderBagel("Onion"); + } + assertEquals(1.89, sh.calculateDiscounts(), delta); + Basket.setCapacity(oldCapacity); + } + + @Test + public void dozenAndSixBagelsDiscount() { + double delta = 0.0001; + ShopHandler sh = new ShopHandler(); + int oldCapacity = Basket.getCapacity(); + Basket.setCapacity(20); + for (int i=0; i<19; i++) { + sh.orderBagel("Onion"); + } + assertEquals(2.34, sh.calculateDiscounts(), delta); + Basket.setCapacity(oldCapacity); } } From 8308fa0ebfea9c44523f6cd41bc34d970dd4c2fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20S=C3=B6nnergaard?= Date: Tue, 14 Jan 2025 11:24:25 +0100 Subject: [PATCH 38/43] Add test for coffe & bagel discount --- .../com/booleanuk/extension/ShopHandler.java | 25 +++++++++++++++++-- .../booleanuk/extension/ShopHandlerTest.java | 11 +++++++- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/booleanuk/extension/ShopHandler.java b/src/main/java/com/booleanuk/extension/ShopHandler.java index df7a323e4..844a4a671 100644 --- a/src/main/java/com/booleanuk/extension/ShopHandler.java +++ b/src/main/java/com/booleanuk/extension/ShopHandler.java @@ -25,6 +25,7 @@ public class ShopHandler { private static final double SIX_BAGEL_DISCOUNT = 2.49; private static final double DOZEN_BAGEL_DISCOUNT = 3.99; + private static final double COFFEE_DISCOUNT = 1.25; private Scanner scanner; private Basket basket; @@ -66,7 +67,7 @@ public double calculateDiscounts() { for (Item item : basket.getItems()) { if (item.getName().equals("Coffee")) { Coffee coffee = (Coffee) item; // not nice! - totalDiscount += coffee.getPrice() + coffee.getDiscountBagel().getPrice() - 1.25; // hardcoded + totalDiscount += coffee.getPrice() + coffee.getDiscountBagel().getPrice() - COFFEE_DISCOUNT; } } for (Item item : stock) { @@ -76,7 +77,6 @@ public double calculateDiscounts() { double discount = ((int) (n/12)) * item.getPrice() * 12 - ((int) n/12) * DOZEN_BAGEL_DISCOUNT; int bagelsLeft = n % 12; discount += ((int) (bagelsLeft/6)) * item.getPrice() * 6 - ((int) bagelsLeft/6) * SIX_BAGEL_DISCOUNT; - System.out.println(discount); totalDiscount += discount; } } @@ -224,6 +224,27 @@ public boolean orderCoffee(String variant) { return basket.addItem(coffeeFromVariant(variant)); } + public boolean orderCoffee(String coffeeVariant, String bagelVariant, String fillingVariant) { + if (!isValidCoffee(coffeeVariant) || !isValidBagel(bagelVariant) || !isValidFilling(fillingVariant)) { + return false; + } + Coffee coffee = coffeeFromVariant(coffeeVariant); + Bagel bagel = bagelFromVariant(bagelVariant); + bagel.setFilling(fillingFromVariant(fillingVariant)); + coffee.setDiscountBagel(bagel); + return basket.addItem(coffee); + } + + public boolean orderCoffee(String coffeeVariant, String bagelVariant) { + if (!isValidCoffee(coffeeVariant) || !isValidBagel(bagelVariant)) { + return false; + } + Coffee coffee = coffeeFromVariant(coffeeVariant); + Bagel bagel = bagelFromVariant(bagelVariant); + coffee.setDiscountBagel(bagel); + return basket.addItem(coffee); + } + private Bagel bagelFromVariant(String variant) { for (Item item : stock) { if (item.getVariant().equals(variant)) { diff --git a/src/test/java/com/booleanuk/extension/ShopHandlerTest.java b/src/test/java/com/booleanuk/extension/ShopHandlerTest.java index e0ae5d58e..c08cb8975 100644 --- a/src/test/java/com/booleanuk/extension/ShopHandlerTest.java +++ b/src/test/java/com/booleanuk/extension/ShopHandlerTest.java @@ -5,6 +5,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; public class ShopHandlerTest { + double delta = 0.0001; @Test public void showItemsShowsAllItemsThatAreNotFillings() { ShopHandler sh = new ShopHandler(); @@ -82,7 +83,6 @@ public void dozenBagelsDiscount() { @Test public void dozenAndSixBagelsDiscount() { - double delta = 0.0001; ShopHandler sh = new ShopHandler(); int oldCapacity = Basket.getCapacity(); Basket.setCapacity(20); @@ -92,4 +92,13 @@ public void dozenAndSixBagelsDiscount() { assertEquals(2.34, sh.calculateDiscounts(), delta); Basket.setCapacity(oldCapacity); } + + @Test + public void coffeeDiscount() { + ShopHandler sh = new ShopHandler(); + sh.orderCoffee("Black", "Onion"); + assertEquals(0.23, sh.calculateDiscounts(), delta); + } + + } From dbca87928cdb0bacfef1235ea90823eac9d68128 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20S=C3=B6nnergaard?= Date: Tue, 14 Jan 2025 11:48:53 +0100 Subject: [PATCH 39/43] Add test for some combo of coffees and bagels --- .../java/com/booleanuk/extension/Bagel.java | 14 +++++-------- .../java/com/booleanuk/extension/Basket.java | 4 ---- .../java/com/booleanuk/extension/Coffee.java | 6 ++++++ .../com/booleanuk/extension/ShopHandler.java | 11 +++++++++- .../booleanuk/extension/ShopHandlerTest.java | 20 ++++++++++++++++++- 5 files changed, 40 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/booleanuk/extension/Bagel.java b/src/main/java/com/booleanuk/extension/Bagel.java index a6d4bcb34..716896f72 100644 --- a/src/main/java/com/booleanuk/extension/Bagel.java +++ b/src/main/java/com/booleanuk/extension/Bagel.java @@ -18,13 +18,9 @@ public Item getFilling() { return this.filling; } -// @Override -// public double getPrice() { -// if (filling == null) return getBasePrice(); -// return super.getPrice() + filling.getPrice(); -// } - -// public double getBasePrice() { -// return super.getPrice(); -// } + @Override + public double getPrice() { + if (filling == null) return super.getPrice(); + return super.getPrice() + filling.getPrice(); + } } diff --git a/src/main/java/com/booleanuk/extension/Basket.java b/src/main/java/com/booleanuk/extension/Basket.java index f8bab49dc..949620fcc 100644 --- a/src/main/java/com/booleanuk/extension/Basket.java +++ b/src/main/java/com/booleanuk/extension/Basket.java @@ -54,10 +54,6 @@ public boolean removeItem(String sku) { public double getTotalCost() { double totalCost = 0; for (Item item : items) { - if (item.getName().equals("Bagel")) - totalCost += ((Bagel) item).getFilling().getPrice(); - else if (item.getName().equals("Coffee")) - totalCost += ((Coffee) item).getDiscountBagel().getPrice(); totalCost += item.getPrice(); } return totalCost; diff --git a/src/main/java/com/booleanuk/extension/Coffee.java b/src/main/java/com/booleanuk/extension/Coffee.java index 5c1d8b76f..15bec36af 100644 --- a/src/main/java/com/booleanuk/extension/Coffee.java +++ b/src/main/java/com/booleanuk/extension/Coffee.java @@ -26,4 +26,10 @@ public int getSize() { } return super.getSize() + discountBagel.getSize(); } + + @Override + public double getPrice() { + if (discountBagel == null) return super.getPrice(); + return super.getPrice() + discountBagel.getPrice(); + } } diff --git a/src/main/java/com/booleanuk/extension/ShopHandler.java b/src/main/java/com/booleanuk/extension/ShopHandler.java index 844a4a671..7e1105676 100644 --- a/src/main/java/com/booleanuk/extension/ShopHandler.java +++ b/src/main/java/com/booleanuk/extension/ShopHandler.java @@ -67,7 +67,8 @@ public double calculateDiscounts() { for (Item item : basket.getItems()) { if (item.getName().equals("Coffee")) { Coffee coffee = (Coffee) item; // not nice! - totalDiscount += coffee.getPrice() + coffee.getDiscountBagel().getPrice() - COFFEE_DISCOUNT; + if (coffee.getDiscountBagel() != null) + totalDiscount += coffee.getPrice() - COFFEE_DISCOUNT; } } for (Item item : stock) { @@ -302,4 +303,12 @@ private static boolean isValidFilling(String variant) { public static List getStock() { return stock; } + + public double getCostBeforeDiscounts() { + return basket.getTotalCost(); + } + + public double getCostAfterDiscounts() { + return basket.getTotalCost() - calculateDiscounts(); + } } diff --git a/src/test/java/com/booleanuk/extension/ShopHandlerTest.java b/src/test/java/com/booleanuk/extension/ShopHandlerTest.java index c08cb8975..1b10cc1e6 100644 --- a/src/test/java/com/booleanuk/extension/ShopHandlerTest.java +++ b/src/test/java/com/booleanuk/extension/ShopHandlerTest.java @@ -100,5 +100,23 @@ public void coffeeDiscount() { assertEquals(0.23, sh.calculateDiscounts(), delta); } - + @Test + public void comboTest() { + ShopHandler sh = new ShopHandler(); + int oldCapacity = Basket.getCapacity(); + Basket.setCapacity(100); + sh.orderBagel("Onion"); + sh.orderBagel("Onion"); + for (int i=0; i<12; i++) { + sh.orderBagel("Plain"); + } + for (int i=0; i<6; i++) { + sh.orderBagel("Everything"); + } + for (int i=0; i<3; i++) { + sh.orderCoffee("Black"); + } + assertEquals(10.43, sh.getCostAfterDiscounts(), delta); + Basket.setCapacity(oldCapacity); + } } From 90223083be2d3df1fe4231a311de9ab215cd3b0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20S=C3=B6nnergaard?= Date: Tue, 14 Jan 2025 14:14:34 +0100 Subject: [PATCH 40/43] Add test for non-empty receipt --- .../booleanuk/extension/ShopHandlerTest.java | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/booleanuk/extension/ShopHandlerTest.java b/src/test/java/com/booleanuk/extension/ShopHandlerTest.java index 1b10cc1e6..1997a86c6 100644 --- a/src/test/java/com/booleanuk/extension/ShopHandlerTest.java +++ b/src/test/java/com/booleanuk/extension/ShopHandlerTest.java @@ -1,8 +1,8 @@ package com.booleanuk.extension; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; + +import static org.junit.jupiter.api.Assertions.*; public class ShopHandlerTest { double delta = 0.0001; @@ -119,4 +119,26 @@ public void comboTest() { assertEquals(10.43, sh.getCostAfterDiscounts(), delta); Basket.setCapacity(oldCapacity); } + + @Test + public void nonemptyBasketPrintsNonemptyReceipt() { + ShopHandler sh = new ShopHandler(); + int oldCapacity = Basket.getCapacity(); + Basket.setCapacity(100); + sh.orderBagel("Onion"); + sh.orderBagel("Onion"); + for (int i=0; i<12; i++) { + sh.orderBagel("Plain"); + } + for (int i=0; i<6; i++) { + sh.orderBagel("Everything"); + } + for (int i=0; i<3; i++) { + sh.orderCoffee("Black"); + } + sh.orderCoffee("Cappuccino", "Plain"); + System.out.println(sh.showReceiptWithDiscounts()); + assertNotEquals("", sh.showReceiptWithDiscounts()); + Basket.setCapacity(oldCapacity); + } } From 70236cf823021ac7f0183800bfc7586ac2ef27c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20S=C3=B6nnergaard?= Date: Tue, 14 Jan 2025 14:36:31 +0100 Subject: [PATCH 41/43] Add test and implementation for some order --- .../com/booleanuk/extension/ShopHandler.java | 91 +++++++++++++++++-- .../booleanuk/extension/ShopHandlerTest.java | 40 +++++++- 2 files changed, 122 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/booleanuk/extension/ShopHandler.java b/src/main/java/com/booleanuk/extension/ShopHandler.java index 7e1105676..14c4685f2 100644 --- a/src/main/java/com/booleanuk/extension/ShopHandler.java +++ b/src/main/java/com/booleanuk/extension/ShopHandler.java @@ -7,14 +7,14 @@ public class ShopHandler { private static final List stock = new ArrayList<>(Arrays.asList( - new Item("BGLO", 0.49, "Bagel", "Onion"), - new Item("BGLP", 0.39, "Bagel", "Plain"), - new Item("BGLE", 0.49, "Bagel", "Everything"), - new Item("BGLS", 0.49, "Bagel", "Sesame"), - new Item("COFB", 0.99, "Coffee", "Black"), - new Item("COFW", 1.19, "Coffee", "White"), - new Item("COFC", 1.29, "Coffee", "Cappuccino"), - new Item("COFL", 1.29, "Coffee", "Latte"), + new Bagel("BGLO", 0.49, "Bagel", "Onion"), + new Bagel("BGLP", 0.39, "Bagel", "Plain"), + new Bagel("BGLE", 0.49, "Bagel", "Everything"), + new Bagel("BGLS", 0.49, "Bagel", "Sesame"), + new Coffee("COFB", 0.99, "Coffee", "Black"), + new Coffee("COFW", 1.19, "Coffee", "White"), + new Coffee("COFC", 1.29, "Coffee", "Cappuccino"), + new Coffee("COFL", 1.29, "Coffee", "Latte"), new Item("FILB", 0.12, "Filling", "Bacon"), new Item("FILE", 0.12, "Filling", "Egg"), new Item("FILC", 0.12, "Filling", "Cheese"), @@ -84,6 +84,81 @@ public double calculateDiscounts() { return totalDiscount; } + public String showReceiptWithDiscounts() { + double totalDiscount = 0; + StringBuilder sb = new StringBuilder(); + + sb.append("Bob's Bagels\n--------\n"); + + // Recursively collect all fillings + List fillings = new ArrayList<>(); + for (Item item : basket.getItems()) { + if (item.getName().equals("Coffee")) { + Bagel b = ((Coffee) item).getDiscountBagel(); + if (b != null) { + Item f = b.getFilling(); + if (f != null) { + fillings.add(f); + } + } + } else if (item.getName().equals("Bagel")) { + Item f = ((Bagel) item).getFilling(); + if (f != null) { + fillings.add(f); + } + } + } + + for (Item item : stock) { + String sku = item.getSku(); + + if (item.getName().equals("Filling")) { + int n = fillings.stream().filter(i -> i.getSku().equals(sku)).toList().size(); + if (n > 0) { + sb.append(n).append(" ").append(item.getName()).append(" ").append(item.getVariant()).append(" ").append(String.format("%.2f", item.getPrice() * n)).append("\n"); + } + } + + if (item.getName().equals("Coffee")) { + double discount = 0; + double price = 0; + List coffees = basket.getItems().stream().filter(i -> i.getSku().equals(sku)).toList(); + for (Item coffee : coffees) { // not nice! + if (((Coffee) coffee).getDiscountBagel() != null) { + discount += coffee.getPrice() - COFFEE_DISCOUNT; + price += COFFEE_DISCOUNT; + totalDiscount += discount; + } else { + price += coffee.getPrice(); + } + } + if (!coffees.isEmpty()) { + sb.append(coffees.size()).append(" ").append(item.getName()).append(" ").append(item.getVariant()).append(" ").append(String.format("%.2f", price)).append("\n"); + if (discount > 0) { + sb.append("(-").append(String.format("%.2f", discount)).append(")").append("\n"); + } + } + } else if (item.getName().equals("Bagel")) { + int n = basket.getItems().stream().filter(i -> i.getSku().equals(sku)).toList().size(); + double discount = ((int) (n/12)) * item.getPrice() * 12 - ((int) n/12) * DOZEN_BAGEL_DISCOUNT; + int bagelsLeft = n % 12; + discount += ((int) (bagelsLeft/6)) * item.getPrice() * 6 - ((int) bagelsLeft/6) * SIX_BAGEL_DISCOUNT; + totalDiscount += discount; + if (n > 0) { + sb.append(n).append(" ").append(item.getName()).append(" ").append(item.getVariant()).append(" ").append(String.format("%.2f", item.getPrice() * n - discount)).append("\n"); + if (discount > 0) { + sb.append("(-").append(String.format("%.2f", discount)).append(")").append("\n"); + } + } + } + } + sb.append("--------\n") + .append("Total: ").append(String.format("%.2f", getCostAfterDiscounts())) + .append("\nSavings: ").append(String.format("%.2f", getCostBeforeDiscounts() - getCostAfterDiscounts())); + + return sb.toString(); + } + public void removeItem() { if (basket.getItems().isEmpty()) { System.out.println("No items in basket."); diff --git a/src/test/java/com/booleanuk/extension/ShopHandlerTest.java b/src/test/java/com/booleanuk/extension/ShopHandlerTest.java index 1997a86c6..be304408e 100644 --- a/src/test/java/com/booleanuk/extension/ShopHandlerTest.java +++ b/src/test/java/com/booleanuk/extension/ShopHandlerTest.java @@ -137,8 +137,46 @@ public void nonemptyBasketPrintsNonemptyReceipt() { sh.orderCoffee("Black"); } sh.orderCoffee("Cappuccino", "Plain"); - System.out.println(sh.showReceiptWithDiscounts()); assertNotEquals("", sh.showReceiptWithDiscounts()); Basket.setCapacity(oldCapacity); } + + @Test + public void comboBasketPrintsNonemptyReceipt() { + ShopHandler sh = new ShopHandler(); + int oldCapacity = Basket.getCapacity(); + Basket.setCapacity(100); + sh.orderBagel("Onion", "Ham"); + sh.orderBagel("Onion", "Ham"); + for (int i=0; i<12; i++) { + sh.orderBagel("Plain", "Cheese"); + } + for (int i=0; i<6; i++) { + sh.orderBagel("Everything"); + } + for (int i=0; i<3; i++) { + sh.orderCoffee("Black"); + } + sh.orderCoffee("Cappuccino", "Plain"); +// System.out.println(sh.showReceiptWithDiscounts()); + assertEquals( + """ + Bob's Bagels + -------- + 2 Bagel Onion 0.98 + 12 Bagel Plain 3.99 + (-0.69) + 6 Bagel Everything 2.49 + (-0.45) + 3 Coffee Black 2.97 + 1 Coffee Cappuccino 1.25 + (-0.43) + 12 Filling Cheese 1.44 + 2 Filling Ham 0.24 + -------- + Total: 13.36 + Savings: 1.57""" + , sh.showReceiptWithDiscounts()); + Basket.setCapacity(oldCapacity); + } } From a5f479656dbb9b2e5c552d8cae422bca06c69282 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20S=C3=B6nnergaard?= Date: Tue, 14 Jan 2025 15:02:42 +0100 Subject: [PATCH 42/43] Update domain model and class diagram to reflect implementation --- class_diagram_extension.png | Bin 0 -> 42541 bytes domain-model-extension.md | 43 ++++++++++++++++++++++-------------- 2 files changed, 26 insertions(+), 17 deletions(-) create mode 100644 class_diagram_extension.png diff --git a/class_diagram_extension.png b/class_diagram_extension.png new file mode 100644 index 0000000000000000000000000000000000000000..3dbca706b5da2ca45285de31eb702051486f9ea4 GIT binary patch literal 42541 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 literal 0 HcmV?d00001 diff --git a/domain-model-extension.md b/domain-model-extension.md index d0f0c6923..552a59867 100644 --- a/domain-model-extension.md +++ b/domain-model-extension.md @@ -47,17 +47,18 @@ This is the public interface that a customer or manager interacts with the Bob's ### Methods -| Method | Scenario | Result | -|------------------------------------|----------|-----------------------------------------------------------------------| -| placeOrder(): void (boolean?) | | Guide the customer through selecting items to order. | -| showItems(): String | | Return String of bagels and coffee w/ prices | -| showFillings(): String | | Return String of fillings w/ prices | -| orderBagel(): void | | Let customer choose a bagel. Then, let customer add optional filling. | -| orderCoffee(): void | | Let customer choose a variant. | -| setBasketCapacity(): void | | Update the basket capacity for all baskets. | -| applyDiscounts(): ?? | | | -| printReceipt(basket: Basket): void | | | -| Some private helper functions | | | +| Method | Scenario | Result | +|--------------------------------------------------------------------------|----------|-------------------------------------------------------------------| +| placeOrder(): void | | Guide the customer through selecting items to order (interactive) | +| showItems(): String | | Return String of bagels and coffee w/ prices | +| showFillings(): String | | Return String of fillings w/ prices | +| orderBagel(): boolean | | Add a bagel with optional filling to basket if it's not full. | +| orderCoffee(): boolean | | Add coffee with optional bagel for a discount if it's not full. | +| setBasketCapacity(): void | | Update the basket capacity for all baskets. | +| calculateDiscounts(): double | | Apply the discounts and return savings. | +| showReceiptWithDiscounts(): String | | Return String with receipt, including discounts. | +| show/Fillings/Bagels/Coffees(): String | | Return String showing possible orders and prices | +| Some helper functions that I don't think are important enough to mention | | | ## Class: Coffee @@ -68,9 +69,11 @@ Inherits from: Item. ### Methods -getSize(): includes optional discountBagel - -getPrice(): includes optional discountBagel +| Method | Scenario | Result | +|---------------------------|------------------------------------|-----------------------------------------------| +| getSize(): int | | Returns size, includes optional discountBagel | | | +| getPrice(): double | | includes optional discountBagel | +| getDiscountBagel(): Bagel | There is a bagel/there is no bagel | Returns the bagel/returns null | ## Class: Bagel @@ -82,13 +85,19 @@ Inherits from: Item ### Methods +| Method | Scenario | Result | +|--------------------|--------------------------------------|----------------------------------| +| getSize(): int | | Returns size | +| getPrice(): double | | includes optional filling | +| getFilling(): Item | There is filling/there is no filling | Returns the filling/returns null | + # Class: Main -Run interactive interface. +Run interactive interface to interactively place an order. (Not up to date with extensions.) # User stories (extension) -## Discounts - - As a customer, I want to be able to have a bagel with my coffee for a discount. - As a customer, I want multi-priced discounts to apply at checkout. +- As a customer, I want to get a receipt when paying. +- As a concerned customer, I want to know how much I saved using discounts. \ No newline at end of file From 990380cd01a7e0bbd8926cf89e7d7fb8b9f447a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20S=C3=B6nnergaard?= Date: Tue, 14 Jan 2025 15:12:39 +0100 Subject: [PATCH 43/43] Add tests for Bagel and Coffee --- .../java/com/booleanuk/extension/BagelTest.java | 13 +++++++++++++ .../java/com/booleanuk/extension/CoffeeTest.java | 16 ++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 src/test/java/com/booleanuk/extension/BagelTest.java create mode 100644 src/test/java/com/booleanuk/extension/CoffeeTest.java diff --git a/src/test/java/com/booleanuk/extension/BagelTest.java b/src/test/java/com/booleanuk/extension/BagelTest.java new file mode 100644 index 000000000..f2a7af7b0 --- /dev/null +++ b/src/test/java/com/booleanuk/extension/BagelTest.java @@ -0,0 +1,13 @@ +package com.booleanuk.extension; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; + +public class BagelTest { + @Test + public void testCountsFilling() { + Bagel b = new Bagel("A", 11, "Name", "Onion"); + b.setFilling(new Item("B" , 5, "Name", "Variant")); + assertEquals(16, b.getPrice()); + } +} diff --git a/src/test/java/com/booleanuk/extension/CoffeeTest.java b/src/test/java/com/booleanuk/extension/CoffeeTest.java new file mode 100644 index 000000000..9499594e6 --- /dev/null +++ b/src/test/java/com/booleanuk/extension/CoffeeTest.java @@ -0,0 +1,16 @@ +package com.booleanuk.extension; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class CoffeeTest { + @Test + public void testCountsDiscountBagel() { + Coffee c = new Coffee("A", 11, "Name", "Onion"); + Bagel b = new Bagel("A", 11, "Name", "Onion"); + b.setFilling(new Item("B" , 5, "Name", "Variant")); + c.setDiscountBagel(b); + assertEquals(27, c.getPrice()); + } +}