From 57b97ec25f990a38923c211fee4e546165019855 Mon Sep 17 00:00:00 2001 From: Tein Schoemaker Date: Tue, 12 Aug 2025 00:01:08 +0200 Subject: [PATCH 1/5] Tests + DomainModel --- DomainModel.md | 22 ++++++++++ exercise.sln | 4 ++ exercise.tests/BasketTest.cs | 76 ++++++++++++++++++++++++++++++++++ exercise.tests/CheckoutTest.cs | 35 ++++++++++++++++ exercise.tests/ProductTest.cs | 39 +++++++++++++++++ exercise.tests/UnitTest1.cs | 15 ------- 6 files changed, 176 insertions(+), 15 deletions(-) create mode 100644 DomainModel.md create mode 100644 exercise.tests/BasketTest.cs create mode 100644 exercise.tests/CheckoutTest.cs create mode 100644 exercise.tests/ProductTest.cs delete mode 100644 exercise.tests/UnitTest1.cs diff --git a/DomainModel.md b/DomainModel.md new file mode 100644 index 00000000..e6d09638 --- /dev/null +++ b/DomainModel.md @@ -0,0 +1,22 @@ +# Core Requirements + +| Classes | Methods/Properties | Scenario | Outputs +| ----------- | ------------------------------------------------------ | --------------------------------------- | --------------------------------- +| Product.cs | string SKU | Short code for name + variant | String with SKU code +| Product.cs | float Price | Pricing for each item | float with price in decimal +| Product.cs | enum Name | Product type for each item to get | Bagel, Coffee, Filling +| Product.cs | enum BagelVariant | Types of variant you can get with bagel | Onion, Plain, Everything, Sesame +| Product.cs | enum CoffeeVariant | Types of variant you can get with Coffee| Black, White, Cappucino, Latte +| Product.cs | enum FillingVariant | Types of variant you can get for Filling| Bacon, Egg, Cheese, CreamCheese, SmokedSalmon, Ham +| Basket.cs | List<\ProductList\> Basket | List to add each chosen item to | Task added to list +| Basket.cs | Guid id | Id to keep track of items in basket | Id for each item +| Basket.cs | bool IsFull | Bool to check to see if basket is full | True or False +| Basket.cs | int Capacity | Int to decide max amount of items | Int that dictates max items +| Basket.cs | AddItem(Product prodcut) | Add item to the basket list | Product added to list +| Basket.cs | RemoveItem(Guid itemId) | Remove specific item from basket | Specific item removed from list +| Basket.cs | ChangeCapacity(int Capacity) | Changes the total capacity of the basket| A changed version of the Capacity +| Checkout.cs | int TotalPrice | Int tracking the total price all items | Int in $$$ +| Checkout.cs | string Receipt | Clear version of all total costs written| Each item and it's costs written in console +| Checkout.cs | int Discount | Discount if enough items are bought | New price calculated with new discount +| Checkout.cs | string OrderConfirmation | Using twilio to print a conformation | SMS with order conformation +| Checkout.cs | CashOrCard() | Delivers the user their total | A console log with an overview of the transactions \ No newline at end of file diff --git a/exercise.sln b/exercise.sln index 0efb5453..f9588aed 100644 --- a/exercise.sln +++ b/exercise.sln @@ -9,6 +9,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "exercise.tests", "exercise. EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{825CCFE7-4F2E-4770-8393-FEB732F66EE4}" ProjectSection(SolutionItems) = preProject + DomainModel.md = DomainModel.md extension1.md = extension1.md extension2.md = extension2.md extension3.md = extension3.md @@ -34,4 +35,7 @@ Global GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {F839F4B4-D965-42CF-B457-007972706314} + EndGlobalSection EndGlobal diff --git a/exercise.tests/BasketTest.cs b/exercise.tests/BasketTest.cs new file mode 100644 index 00000000..6cf48ae2 --- /dev/null +++ b/exercise.tests/BasketTest.cs @@ -0,0 +1,76 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection.Emit; +using System.Text; +using System.Threading.Tasks; + +namespace exercise.tests +{ + public class BasketTest + { + [Test] + public void AddBagelToBasketHasCorrectBagel() + { + var basket = new Basket(); + var bagel = new Bagel("Sesame"); + + basket.AddBagel(bagel); + + Assert.Contains(bagel, basket.Items); + } + + [Test] + public void RemoveBagelFromBasketNoLongerHasThatBagel() + { + var basket = new Basket(); + var bagel = new Bagel("Sesame"); + + basket.AddBagel(bagel); + Assert.Contains(bagel, basket); + basket.RemoveBagel(bagel); + + Assert.DoesNotContain(bagel, basket.Items); + } + + [Test] + public void AddBagelPastCapacityThrowsError() + { + var basket = new Basket(); + basket.Capacity = 2; + basket.AddBagel(new Bagel("Plain")); + basket.AddBagel(new Bagel("Sesame")); + + var error = Assert.Throws(() => basket.AddBagel(new Bagel("Onion"))); + + Assert.Equal("Basket is at capacity", error.Message); + } + + [Test] + public void RemoveNonExistantBagelThrowsError() + { + var basket = new Basket(); + var bagel = new Bagel("Sesame"); + + var ex = Assert.Throws(() => + basket.RemoveBagel(bagel)); + + Assert.Equal("There is no such bagel in the basket", ex.Message); + } + + [Test] + public void ChangeCapacity() + { + var basket = new Basket(); + basket.Capacity = 1; + + basket.AddBagel(new Bagel("Plain")); + Assert.Throws(() => basket.AddBagel(new Bagel("Onion"))); + + basket.ChangeCapacity(2); + basket.AddBagel(new Bagel("Plain")); + + Assert.Equal(2, basket.Items.Count); + } + } +} diff --git a/exercise.tests/CheckoutTest.cs b/exercise.tests/CheckoutTest.cs new file mode 100644 index 00000000..97e97fd7 --- /dev/null +++ b/exercise.tests/CheckoutTest.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection.Emit; +using System.Text; +using System.Threading.Tasks; + +namespace exercise.tests +{ + public class CheckoutTest + { + [Test] + public void GetTotalCostIsSumOfAllPrices() + { + var basket = new Basket(); + var checkout = new Checkout(); + basket.AddBagel(new Bagel("Plain")); + basket.AddBagel(new Bagel("Sesame")); + + var total = checkout.GetTotalCost(); + + Assert.Equals(2.20, total); + } + + [Test] + public void AddBagelNotInInventoryThrowsError() + { + var basket = new Basket(); + + var error = Assert.Throws(() => basket.AddBagel(new Bagel("Frozen"))); + + Assert.Equals("Item not in our stock", error.Message); + } + } +} diff --git a/exercise.tests/ProductTest.cs b/exercise.tests/ProductTest.cs new file mode 100644 index 00000000..43aed7e6 --- /dev/null +++ b/exercise.tests/ProductTest.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace exercise.tests +{ + public class ProductTest + { + + [Test] + public void KnowTheCostOfBagelBeforeAdding() + { + var bagel = new Bagel("Plain"); + + Assert.Equals(1.00, bagel.Price); + } + + [Test] + public void KnowTheCostOfFillingBeforeAdding() + { + var bagel = new Bagel("Plain"); + var filling = new Filling("Cream Cheese"); + + bagel.AddFilling(filling); + + Assert.Contains(filling, bagel.Fillings); + } + + [Test] + public void AddFillingToBagelAddsRightFillingToBagel() + { + var filling = new Filling("Bacon"); + + Assert.Equals(0.80, filling.Price); + } + } +} diff --git a/exercise.tests/UnitTest1.cs b/exercise.tests/UnitTest1.cs deleted file mode 100644 index 7bdb8968..00000000 --- a/exercise.tests/UnitTest1.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace exercise.tests; - -public class Tests -{ - [SetUp] - public void Setup() - { - } - - [Test] - public void Test1() - { - Assert.Pass(); - } -} \ No newline at end of file From 28955447994ce1f3e34fbb13039174c1f7c9ac91 Mon Sep 17 00:00:00 2001 From: Tein Schoemaker Date: Tue, 12 Aug 2025 14:54:02 +0200 Subject: [PATCH 2/5] Added base functionality --- exercise.main/Basket.cs | 40 ++++++++++++++++++++++++++ exercise.main/CheckOut.cs | 40 ++++++++++++++++++++++++++ exercise.main/Product.cs | 52 ++++++++++++++++++++++++++++++++++ exercise.main/Program.cs | 22 ++++++++++++-- exercise.tests/CheckoutTest.cs | 4 +-- 5 files changed, 154 insertions(+), 4 deletions(-) create mode 100644 exercise.main/Basket.cs create mode 100644 exercise.main/CheckOut.cs create mode 100644 exercise.main/Product.cs diff --git a/exercise.main/Basket.cs b/exercise.main/Basket.cs new file mode 100644 index 00000000..eb84ff6f --- /dev/null +++ b/exercise.main/Basket.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace exercise.main +{ + public class Basket + { + public List Products { get; set; } + public int Capacity { get; set; } + + public Basket(int capacity) + { + Capacity = capacity; + Products = new List(); + } + + public bool AddItem(Product product) + { + if (Products.Count >= Capacity) return false; + Products.Add(product); + return true; + } + + public bool RemoveItem(Product product) + { + var selectedItem = Products.FirstOrDefault(product => product.Id == product.Id); + if (selectedItem == null) return false; + Products.Remove(selectedItem); + return true; + } + + public void ChangeCapacity(int capacity) + { + Capacity = capacity; + } + } +} diff --git a/exercise.main/CheckOut.cs b/exercise.main/CheckOut.cs new file mode 100644 index 00000000..cb1aaff7 --- /dev/null +++ b/exercise.main/CheckOut.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace exercise.main +{ + public class CheckOut + { + public float TotalPrice(Basket basket) + { + float total = basket.Products.Sum(p => p.Price); + + return total; + } + + public string Receipt(Basket basket) + { + var receipt = new StringBuilder(); + receipt.AppendLine("~~~ Bob's Bagels ~~~\n"); + receipt.AppendLine(DateTime.Now.ToString() + "\n"); + receipt.AppendLine("----------------------------\n"); + foreach (var product in basket.Products) + { + receipt.AppendLine($"{product.Name} ({product.Variant}): ${product.Price}"); + } + receipt.AppendLine("----------------------------\n"); + receipt.AppendLine($"Total: ${TotalPrice(basket):0.00}\n"); + receipt.AppendLine(" Thank you "); + receipt.AppendLine(" for your order "); + return receipt.ToString(); + } + + public void CashOrCard(float total) + { + + } + } +} diff --git a/exercise.main/Product.cs b/exercise.main/Product.cs new file mode 100644 index 00000000..bb47bf00 --- /dev/null +++ b/exercise.main/Product.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace exercise.main +{ + + public enum ProductName + { + Bagel, Coffee, Filling + } + + public enum BagelVariant + { + Onion, Plain, Everything, Sesame + } + + public enum CoffeeVariant + { + Black, White, Cappucino, Latte + } + + public enum FillingVariant + { + Bacon, Egg, Cheese, CreamCheese, SmokedSalmon, Ham + } + + public class Product + { + public string SKU { get; set; } + public float Price { get; set; } + public ProductName Name { get; set; } + public Enum Variant { get; set; } + public Guid Id { get; set; } + + public Product(ProductName name, Enum variant, float price) + { + Name = name; + Variant = variant; + Price = price; + SKU = CreateSKU(); + } + + private string CreateSKU() + { + return $"{Name.ToString().Substring(0, 2)}{Variant.ToString().First()}"; + } + + } +} diff --git a/exercise.main/Program.cs b/exercise.main/Program.cs index 3751555c..dfcf3048 100644 --- a/exercise.main/Program.cs +++ b/exercise.main/Program.cs @@ -1,2 +1,20 @@ -// See https://aka.ms/new-console-template for more information -Console.WriteLine("Hello, World!"); + +using exercise.main; + +class Program +{ + static void Main(string[] args) + { + var bagel = new Product(ProductName.Bagel, BagelVariant.Onion, 0.49f); + var coffee = new Product(ProductName.Coffee, CoffeeVariant.Cappucino, 1.29f); + var filling = new Product(ProductName.Filling, FillingVariant.Egg, 0.12f); + + var basket = new Basket(5); + basket.AddItem(bagel); + basket.AddItem(coffee); + basket.AddItem(filling); + + var checkout = new CheckOut(); + Console.WriteLine(checkout.Receipt(basket)); + } +} \ No newline at end of file diff --git a/exercise.tests/CheckoutTest.cs b/exercise.tests/CheckoutTest.cs index 97e97fd7..b9ba796a 100644 --- a/exercise.tests/CheckoutTest.cs +++ b/exercise.tests/CheckoutTest.cs @@ -7,13 +7,13 @@ namespace exercise.tests { - public class CheckoutTest + public class CheckOutTest { [Test] public void GetTotalCostIsSumOfAllPrices() { var basket = new Basket(); - var checkout = new Checkout(); + var checkout = new CheckOut(); basket.AddBagel(new Bagel("Plain")); basket.AddBagel(new Bagel("Sesame")); From a924b7832b3a6ba25940c9cfac578e086194fc92 Mon Sep 17 00:00:00 2001 From: Tein Schoemaker Date: Tue, 12 Aug 2025 17:27:29 +0200 Subject: [PATCH 3/5] Fixed Tests --- exercise.main/Basket.cs | 14 ++++-- exercise.main/CheckOut.cs | 12 ++--- exercise.main/Inventory.cs | 67 ++++++++++++++++++++++++++++ exercise.main/Product.cs | 1 + exercise.main/Program.cs | 8 ++-- exercise.tests/BasketTest.cs | 61 +++++++++++++------------ exercise.tests/CheckoutTest.cs | 25 +++++------ exercise.tests/ProductTest.cs | 29 ++++++------ exercise.tests/exercise.tests.csproj | 1 + 9 files changed, 145 insertions(+), 73 deletions(-) create mode 100644 exercise.main/Inventory.cs diff --git a/exercise.main/Basket.cs b/exercise.main/Basket.cs index eb84ff6f..9f4047e5 100644 --- a/exercise.main/Basket.cs +++ b/exercise.main/Basket.cs @@ -19,15 +19,23 @@ public Basket(int capacity) public bool AddItem(Product product) { - if (Products.Count >= Capacity) return false; + if (Products.Count >= Capacity) + { + return false; + } + Products.Add(product); return true; } public bool RemoveItem(Product product) { - var selectedItem = Products.FirstOrDefault(product => product.Id == product.Id); - if (selectedItem == null) return false; + var selectedItem = Products.FirstOrDefault(p => p.Id == product.Id); + if (selectedItem == null) + { + return false; + } + Products.Remove(selectedItem); return true; } diff --git a/exercise.main/CheckOut.cs b/exercise.main/CheckOut.cs index cb1aaff7..68914cdc 100644 --- a/exercise.main/CheckOut.cs +++ b/exercise.main/CheckOut.cs @@ -10,31 +10,27 @@ public class CheckOut { public float TotalPrice(Basket basket) { - float total = basket.Products.Sum(p => p.Price); - - return total; + return basket.Products.Sum(p => p.Price); ; } public string Receipt(Basket basket) { + var receipt = new StringBuilder(); receipt.AppendLine("~~~ Bob's Bagels ~~~\n"); receipt.AppendLine(DateTime.Now.ToString() + "\n"); receipt.AppendLine("----------------------------\n"); + foreach (var product in basket.Products) { receipt.AppendLine($"{product.Name} ({product.Variant}): ${product.Price}"); } + receipt.AppendLine("----------------------------\n"); receipt.AppendLine($"Total: ${TotalPrice(basket):0.00}\n"); receipt.AppendLine(" Thank you "); receipt.AppendLine(" for your order "); return receipt.ToString(); } - - public void CashOrCard(float total) - { - - } } } diff --git a/exercise.main/Inventory.cs b/exercise.main/Inventory.cs new file mode 100644 index 00000000..01bcbefb --- /dev/null +++ b/exercise.main/Inventory.cs @@ -0,0 +1,67 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace exercise.main +{ + public static class Inventory + { + public static Dictionary Bagels = new Dictionary() + { + { BagelVariant.Onion, 0.49f }, + { BagelVariant.Plain, 0.39f }, + { BagelVariant.Everything, 0.59f }, + { BagelVariant.Sesame, 0.49f } + }; + + public static Dictionary Coffees = new Dictionary() + { + { CoffeeVariant.Black, 0.99f }, + { CoffeeVariant.White, 1.09f }, + { CoffeeVariant.Cappucino, 1.29f }, + { CoffeeVariant.Latte, 1.49f } + }; + + public static Dictionary Fillings = new Dictionary() + { + { FillingVariant.Bacon, 0.29f }, + { FillingVariant.Egg, 0.12f }, + { FillingVariant.Cheese, 0.15f }, + { FillingVariant.CreamCheese, 0.25f }, + { FillingVariant.SmokedSalmon, 0.50f }, + { FillingVariant.Ham, 0.29f } + }; + + public static Product CreateBagel(BagelVariant variant) + { + if (!Bagels.ContainsKey(variant)) + { + throw new InvalidOperationException("Bagel not in inventory"); + } + + return new Product(ProductName.Bagel, variant, Bagels[variant]); + } + + public static Product CreateCoffee(CoffeeVariant variant) + { + if (!Coffees.ContainsKey(variant)) + { + throw new InvalidOperationException("Coffee not in inventory"); + } + + return new Product(ProductName.Coffee, variant, Coffees[variant]); + } + + public static Product CreateFilling(FillingVariant variant) + { + if (!Fillings.ContainsKey(variant)) + { + throw new InvalidOperationException("Filling not in inventory"); + } + + return new Product(ProductName.Filling, variant, Fillings[variant]); + } + } +} \ No newline at end of file diff --git a/exercise.main/Product.cs b/exercise.main/Product.cs index bb47bf00..164f12da 100644 --- a/exercise.main/Product.cs +++ b/exercise.main/Product.cs @@ -41,6 +41,7 @@ public Product(ProductName name, Enum variant, float price) Variant = variant; Price = price; SKU = CreateSKU(); + Id = Guid.NewGuid(); } private string CreateSKU() diff --git a/exercise.main/Program.cs b/exercise.main/Program.cs index dfcf3048..75faa860 100644 --- a/exercise.main/Program.cs +++ b/exercise.main/Program.cs @@ -5,11 +5,11 @@ class Program { static void Main(string[] args) { - var bagel = new Product(ProductName.Bagel, BagelVariant.Onion, 0.49f); - var coffee = new Product(ProductName.Coffee, CoffeeVariant.Cappucino, 1.29f); - var filling = new Product(ProductName.Filling, FillingVariant.Egg, 0.12f); - + var bagel = Inventory.CreateBagel(BagelVariant.Onion); + var coffee = Inventory.CreateCoffee(CoffeeVariant.Cappucino); + var filling = Inventory.CreateFilling(FillingVariant.Cheese); var basket = new Basket(5); + basket.AddItem(bagel); basket.AddItem(coffee); basket.AddItem(filling); diff --git a/exercise.tests/BasketTest.cs b/exercise.tests/BasketTest.cs index 6cf48ae2..19d6313d 100644 --- a/exercise.tests/BasketTest.cs +++ b/exercise.tests/BasketTest.cs @@ -1,4 +1,5 @@ -using System; +using exercise.main; +using System; using System.Collections.Generic; using System.Linq; using System.Reflection.Emit; @@ -12,65 +13,67 @@ public class BasketTest [Test] public void AddBagelToBasketHasCorrectBagel() { - var basket = new Basket(); - var bagel = new Bagel("Sesame"); + var basket = new Basket(5); + var bagel = Inventory.CreateBagel(BagelVariant.Sesame); - basket.AddBagel(bagel); + var added = basket.AddItem(bagel); - Assert.Contains(bagel, basket.Items); + Assert.IsTrue(added); + Assert.Contains(bagel, basket.Products); } [Test] public void RemoveBagelFromBasketNoLongerHasThatBagel() { - var basket = new Basket(); - var bagel = new Bagel("Sesame"); + var basket = new Basket(5); + var bagel = Inventory.CreateBagel(BagelVariant.Sesame); - basket.AddBagel(bagel); - Assert.Contains(bagel, basket); - basket.RemoveBagel(bagel); + var added = basket.AddItem(bagel); + var removed = basket.RemoveItem(bagel); - Assert.DoesNotContain(bagel, basket.Items); + Assert.IsTrue(removed); + Assert.False(basket.Products.Contains(bagel)); } [Test] public void AddBagelPastCapacityThrowsError() { - var basket = new Basket(); - basket.Capacity = 2; - basket.AddBagel(new Bagel("Plain")); - basket.AddBagel(new Bagel("Sesame")); + var basket = new Basket(2); - var error = Assert.Throws(() => basket.AddBagel(new Bagel("Onion"))); + basket.AddItem(Inventory.CreateBagel(BagelVariant.Plain)); + basket.AddItem(Inventory.CreateBagel(BagelVariant.Onion)); - Assert.Equal("Basket is at capacity", error.Message); + var added = basket.AddItem(Inventory.CreateBagel(BagelVariant.Everything)); + + Assert.IsFalse(added); } [Test] public void RemoveNonExistantBagelThrowsError() { - var basket = new Basket(); - var bagel = new Bagel("Sesame"); + var basket = new Basket(5); + var bagel = Inventory.CreateBagel(BagelVariant.Sesame); - var ex = Assert.Throws(() => - basket.RemoveBagel(bagel)); + var removed = basket.RemoveItem(bagel); - Assert.Equal("There is no such bagel in the basket", ex.Message); + Assert.IsFalse(removed); } [Test] - public void ChangeCapacity() + public void ChangeCapacityAllowsMoreItems() { - var basket = new Basket(); - basket.Capacity = 1; + var basket = new Basket(1); - basket.AddBagel(new Bagel("Plain")); - Assert.Throws(() => basket.AddBagel(new Bagel("Onion"))); + basket.AddItem(Inventory.CreateBagel(BagelVariant.Plain)); + var added = basket.AddItem(Inventory.CreateBagel(BagelVariant.Onion)); + Assert.IsFalse(added); basket.ChangeCapacity(2); - basket.AddBagel(new Bagel("Plain")); - Assert.Equal(2, basket.Items.Count); + added = basket.AddItem(Inventory.CreateCoffee(CoffeeVariant.Black)); + + Assert.IsTrue(added); + Assert.AreEqual(2, basket.Products.Count); } } } diff --git a/exercise.tests/CheckoutTest.cs b/exercise.tests/CheckoutTest.cs index b9ba796a..f5d7ea00 100644 --- a/exercise.tests/CheckoutTest.cs +++ b/exercise.tests/CheckoutTest.cs @@ -1,9 +1,6 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection.Emit; -using System.Text; -using System.Threading.Tasks; +using NUnit.Framework; +using exercise.main; namespace exercise.tests { @@ -12,24 +9,26 @@ public class CheckOutTest [Test] public void GetTotalCostIsSumOfAllPrices() { - var basket = new Basket(); + var basket = new Basket(10); var checkout = new CheckOut(); - basket.AddBagel(new Bagel("Plain")); - basket.AddBagel(new Bagel("Sesame")); - var total = checkout.GetTotalCost(); + basket.AddItem(Inventory.CreateBagel(BagelVariant.Plain)); + basket.AddItem(Inventory.CreateBagel(BagelVariant.Sesame)); - Assert.Equals(2.20, total); + var total = checkout.TotalPrice(basket); + + Assert.AreEqual(0.88f, total); } [Test] public void AddBagelNotInInventoryThrowsError() { - var basket = new Basket(); + var basket = new Basket(5); + var notInInventory = (BagelVariant)20; - var error = Assert.Throws(() => basket.AddBagel(new Bagel("Frozen"))); + var error = Assert.Throws(() => Inventory.CreateBagel(notInInventory)); - Assert.Equals("Item not in our stock", error.Message); + Assert.AreEqual("Bagel not in inventory", error.Message); } } } diff --git a/exercise.tests/ProductTest.cs b/exercise.tests/ProductTest.cs index 43aed7e6..eaf97c6b 100644 --- a/exercise.tests/ProductTest.cs +++ b/exercise.tests/ProductTest.cs @@ -1,4 +1,5 @@ -using System; +using exercise.main; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -10,30 +11,26 @@ public class ProductTest { [Test] - public void KnowTheCostOfBagelBeforeAdding() + public void KnowTheCostOfBagel() { - var bagel = new Bagel("Plain"); + var bagel = Inventory.CreateBagel(BagelVariant.Onion); - Assert.Equals(1.00, bagel.Price); + Assert.AreEqual(0.49f, bagel.Price); } [Test] - public void KnowTheCostOfFillingBeforeAdding() + public void CanAddDifferentTypesToBasket() { - var bagel = new Bagel("Plain"); - var filling = new Filling("Cream Cheese"); + var basket = new Basket(5); - bagel.AddFilling(filling); + var bagel = Inventory.CreateBagel(BagelVariant.Onion); + var filling = Inventory.CreateFilling(FillingVariant.Cheese); - Assert.Contains(filling, bagel.Fillings); - } - - [Test] - public void AddFillingToBagelAddsRightFillingToBagel() - { - var filling = new Filling("Bacon"); + basket.AddItem(bagel); + basket.AddItem(filling); - Assert.Equals(0.80, filling.Price); + Assert.Contains(bagel, basket.Products); + Assert.Contains(filling, basket.Products); } } } diff --git a/exercise.tests/exercise.tests.csproj b/exercise.tests/exercise.tests.csproj index 9fed8e17..4be8063d 100644 --- a/exercise.tests/exercise.tests.csproj +++ b/exercise.tests/exercise.tests.csproj @@ -15,6 +15,7 @@ + From b3df0a976be46dafe3d45143c55ef1dfa0e210ff Mon Sep 17 00:00:00 2001 From: Tein Schoemaker Date: Tue, 12 Aug 2025 22:05:10 +0200 Subject: [PATCH 4/5] Fixed Test, Added Discounts and Attempted Twilio --- exercise.main/CheckOut.cs | 56 ++++++++++++++++++++++++++++-- exercise.main/Discount.cs | 28 +++++++++++++++ exercise.main/Inventory.cs | 23 +++++++----- exercise.main/Product.cs | 9 ++++- exercise.main/TwilioText.cs | 33 ++++++++++++++++++ exercise.main/exercise.main.csproj | 4 +++ exercise.tests/BasketTest.cs | 2 +- exercise.tests/CheckoutTest.cs | 26 ++++++++++++-- exercise.tests/ProductTest.cs | 2 +- 9 files changed, 167 insertions(+), 16 deletions(-) create mode 100644 exercise.main/Discount.cs create mode 100644 exercise.main/TwilioText.cs diff --git a/exercise.main/CheckOut.cs b/exercise.main/CheckOut.cs index 68914cdc..b5db688a 100644 --- a/exercise.main/CheckOut.cs +++ b/exercise.main/CheckOut.cs @@ -10,7 +10,36 @@ public class CheckOut { public float TotalPrice(Basket basket) { - return basket.Products.Sum(p => p.Price); ; + var groupedBySKU = basket.Products.GroupBy(p => p.SKU); + + float total = 0; + + foreach (var group in groupedBySKU) + { + string sku = group.Key; + int amount = group.Count(); + float price = group.First().Price; + + if (Inventory.Discounts.ContainsKey(sku)) + { + var special = Inventory.Discounts[sku]; + int n = special.RequiredAmount; + float discountPrice = special.DiscountPrice; + + int sets = amount / n; + int remainder = amount % n; + + total += (sets * discountPrice) + (remainder * price); + } + else + { + total += amount * price; + } + + + } + + return total; } public string Receipt(Basket basket) @@ -21,15 +50,36 @@ public string Receipt(Basket basket) receipt.AppendLine(DateTime.Now.ToString() + "\n"); receipt.AppendLine("----------------------------\n"); - foreach (var product in basket.Products) + var groupedBySKU = basket.Products.GroupBy(p => p.SKU); + + foreach (var group in groupedBySKU) { - receipt.AppendLine($"{product.Name} ({product.Variant}): ${product.Price}"); + string sku = group.Key; + int amount = group.Count(); + string itemName = group.First().Name.ToString(); + string variant = group.First().Variant.ToString(); + float price = group.First().Price; + + float total = 0; + + if (Inventory.Discounts.ContainsKey(sku)) + { + var special = Inventory.Discounts[sku]; + total = special.CalculateDiscount(amount, price); + } + else + { + total = amount * price; + } + + receipt.AppendLine($"{variant} {itemName} {amount} ${total:0.00}"); } receipt.AppendLine("----------------------------\n"); receipt.AppendLine($"Total: ${TotalPrice(basket):0.00}\n"); receipt.AppendLine(" Thank you "); receipt.AppendLine(" for your order "); + return receipt.ToString(); } } diff --git a/exercise.main/Discount.cs b/exercise.main/Discount.cs new file mode 100644 index 00000000..f5b02606 --- /dev/null +++ b/exercise.main/Discount.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace exercise.main +{ + public class Discount + { + public int RequiredAmount { get; set; } + public float DiscountPrice { get; set; } + + public Discount(int requiredAmount, float discountPrice) + { + RequiredAmount = requiredAmount; + DiscountPrice = discountPrice; + } + + public float CalculateDiscount(int amount, float price) + { + int basketAmount = amount / RequiredAmount; + int remainder = amount % RequiredAmount; + + return (basketAmount * DiscountPrice) + (remainder * price); + } + } +} diff --git a/exercise.main/Inventory.cs b/exercise.main/Inventory.cs index 01bcbefb..c43281aa 100644 --- a/exercise.main/Inventory.cs +++ b/exercise.main/Inventory.cs @@ -12,26 +12,33 @@ public static class Inventory { { BagelVariant.Onion, 0.49f }, { BagelVariant.Plain, 0.39f }, - { BagelVariant.Everything, 0.59f }, + { BagelVariant.Everything, 0.49f }, { BagelVariant.Sesame, 0.49f } }; public static Dictionary Coffees = new Dictionary() { { CoffeeVariant.Black, 0.99f }, - { CoffeeVariant.White, 1.09f }, + { CoffeeVariant.White, 1.19f }, { CoffeeVariant.Cappucino, 1.29f }, - { CoffeeVariant.Latte, 1.49f } + { CoffeeVariant.Latte, 1.29f } }; public static Dictionary Fillings = new Dictionary() { - { FillingVariant.Bacon, 0.29f }, + { FillingVariant.Bacon, 0.12f }, { FillingVariant.Egg, 0.12f }, - { FillingVariant.Cheese, 0.15f }, - { FillingVariant.CreamCheese, 0.25f }, - { FillingVariant.SmokedSalmon, 0.50f }, - { FillingVariant.Ham, 0.29f } + { FillingVariant.Cheese, 0.12f }, + { FillingVariant.CreamCheese, 0.12f }, + { FillingVariant.SmokedSalmon, 0.12f }, + { FillingVariant.Ham, 0.12f } + }; + + public static Dictionary Discounts = new Dictionary() + { + { "BGLO", new Discount(6, 2.49f) }, + { "BGLP", new Discount(12, 3.99f) }, + { "BGLE", new Discount(6, 2.49f) } }; public static Product CreateBagel(BagelVariant variant) diff --git a/exercise.main/Product.cs b/exercise.main/Product.cs index 164f12da..48a2b123 100644 --- a/exercise.main/Product.cs +++ b/exercise.main/Product.cs @@ -46,7 +46,14 @@ public Product(ProductName name, Enum variant, float price) private string CreateSKU() { - return $"{Name.ToString().Substring(0, 2)}{Variant.ToString().First()}"; + string nameCode = Name switch + { + ProductName.Bagel => "BGL", + ProductName.Coffee => "COF", + ProductName.Filling => "FIL" + }; + + return nameCode + Variant.ToString().Substring(0, 1).ToUpper(); } } diff --git a/exercise.main/TwilioText.cs b/exercise.main/TwilioText.cs new file mode 100644 index 00000000..a741e0d4 --- /dev/null +++ b/exercise.main/TwilioText.cs @@ -0,0 +1,33 @@ +using Microsoft.IdentityModel.Tokens; +using System; +using System.Security.Cryptography.X509Certificates; +using System.Threading.Tasks; +using Twilio; +using Twilio.Rest.Api.V2010.Account; +using Twilio.Types; + +namespace exercise.main +{ + class TwilioText + { + + private string accountSid = ""; + private string authToken = ""; + private string twilioNumber = "+18159494221"; + private string myNumber = "+1234567890"; + + public async Task SendOrder() + { + var messageContent = "Yello"; + + TwilioClient.Init(accountSid, authToken); + + var message = await MessageResource.CreateAsync( + body: messageContent, + from: new Twilio.Types.PhoneNumber(twilioNumber), + to: new Twilio.Types.PhoneNumber(myNumber)); + + Console.WriteLine(message.Body); + } + } +} diff --git a/exercise.main/exercise.main.csproj b/exercise.main/exercise.main.csproj index fd4bd08d..2e5676af 100644 --- a/exercise.main/exercise.main.csproj +++ b/exercise.main/exercise.main.csproj @@ -7,4 +7,8 @@ enable + + + + diff --git a/exercise.tests/BasketTest.cs b/exercise.tests/BasketTest.cs index 19d6313d..6f3bbe68 100644 --- a/exercise.tests/BasketTest.cs +++ b/exercise.tests/BasketTest.cs @@ -73,7 +73,7 @@ public void ChangeCapacityAllowsMoreItems() added = basket.AddItem(Inventory.CreateCoffee(CoffeeVariant.Black)); Assert.IsTrue(added); - Assert.AreEqual(2, basket.Products.Count); + Assert.That(basket.Products.Count, Is.EqualTo(2)); } } } diff --git a/exercise.tests/CheckoutTest.cs b/exercise.tests/CheckoutTest.cs index f5d7ea00..444ce75a 100644 --- a/exercise.tests/CheckoutTest.cs +++ b/exercise.tests/CheckoutTest.cs @@ -17,7 +17,7 @@ public void GetTotalCostIsSumOfAllPrices() var total = checkout.TotalPrice(basket); - Assert.AreEqual(0.88f, total); + Assert.That(total, Is.EqualTo(0.88f)); } [Test] @@ -28,7 +28,29 @@ public void AddBagelNotInInventoryThrowsError() var error = Assert.Throws(() => Inventory.CreateBagel(notInInventory)); - Assert.AreEqual("Bagel not in inventory", error.Message); + Assert.That(error.Message, Is.EqualTo("Bagel not in inventory")); + } + + [Test] + public void TotalPriceCalculatedWithSpecialDiscount() + { + var basket = new Basket(20); + + for (int i = 0; i < 6; i++) + { + basket.AddItem(Inventory.CreateBagel(BagelVariant.Onion)); + } + + for (int i = 0; i < 12; i++) + { + basket.AddItem(Inventory.CreateBagel(BagelVariant.Plain)); + } + + var checkout = new CheckOut(); + var total = checkout.TotalPrice(basket); + var receipt = checkout.Receipt(basket); + + Assert.That(total, Is.EqualTo(2.49f + 3.99f)); } } } diff --git a/exercise.tests/ProductTest.cs b/exercise.tests/ProductTest.cs index eaf97c6b..d682d109 100644 --- a/exercise.tests/ProductTest.cs +++ b/exercise.tests/ProductTest.cs @@ -15,7 +15,7 @@ public void KnowTheCostOfBagel() { var bagel = Inventory.CreateBagel(BagelVariant.Onion); - Assert.AreEqual(0.49f, bagel.Price); + Assert.That(bagel.Price, Is.EqualTo(0.49f)); } [Test] From d4d2a55667cfb971696ca93edac6c337e142b64b Mon Sep 17 00:00:00 2001 From: TeinSchoemaker Date: Wed, 13 Aug 2025 16:45:31 +0200 Subject: [PATCH 5/5] Added Interactivity --- exercise.main/CheckOut.cs | 2 +- exercise.main/Program.cs | 179 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 172 insertions(+), 9 deletions(-) diff --git a/exercise.main/CheckOut.cs b/exercise.main/CheckOut.cs index b5db688a..dec9cf59 100644 --- a/exercise.main/CheckOut.cs +++ b/exercise.main/CheckOut.cs @@ -46,7 +46,7 @@ public string Receipt(Basket basket) { var receipt = new StringBuilder(); - receipt.AppendLine("~~~ Bob's Bagels ~~~\n"); + receipt.AppendLine("\n~~~ Bob's Bagels ~~~\n"); receipt.AppendLine(DateTime.Now.ToString() + "\n"); receipt.AppendLine("----------------------------\n"); diff --git a/exercise.main/Program.cs b/exercise.main/Program.cs index 75faa860..fe1bf96b 100644 --- a/exercise.main/Program.cs +++ b/exercise.main/Program.cs @@ -1,20 +1,183 @@  using exercise.main; +using Twilio.TwiML.Voice; class Program { static void Main(string[] args) { - var bagel = Inventory.CreateBagel(BagelVariant.Onion); - var coffee = Inventory.CreateCoffee(CoffeeVariant.Cappucino); - var filling = Inventory.CreateFilling(FillingVariant.Cheese); var basket = new Basket(5); - basket.AddItem(bagel); - basket.AddItem(coffee); - basket.AddItem(filling); + Console.WriteLine("Welcome To Bob's Burgers!\n"); - var checkout = new CheckOut(); - Console.WriteLine(checkout.Receipt(basket)); + while (true) + { + Console.WriteLine("What would you like: \n"); + Console.WriteLine("1. Add bagel to basket"); + Console.WriteLine("2. Add coffee to basket"); + Console.WriteLine("3. Remove bagel from basket"); + Console.WriteLine("4. Change basket capacity"); + Console.WriteLine("5. Show total cost"); + Console.WriteLine("6. Checkout basket"); + Console.WriteLine("7. Leave emptyhanded\n"); + + var checkout = new CheckOut(); + var input = Console.ReadLine(); + + switch (input) + { + case "1": + Console.WriteLine("\nWhat bagel do you want?\n"); + Console.WriteLine("1. Onion"); + Console.WriteLine("2. Plain"); + Console.WriteLine("3. Everything"); + Console.WriteLine("4. Sesame\n"); + var bagelInput = Console.ReadLine(); + switch (bagelInput) + { + case "1": + basket.AddItem(Inventory.CreateBagel(BagelVariant.Onion)); + Console.WriteLine("\nOnion bagel added!\n"); + break; + + case "2": + basket.AddItem(Inventory.CreateBagel(BagelVariant.Plain)); + Console.WriteLine("\nPlain bagel added!\n"); + break; + + case "3": + basket.AddItem(Inventory.CreateBagel(BagelVariant.Everything)); + Console.WriteLine("\nEverything bagel added!\n"); + break; + + case "4": + basket.AddItem(Inventory.CreateBagel(BagelVariant.Sesame)); + Console.WriteLine("\nSesame bagel added!\n"); + break; + } + Console.WriteLine("Would you like a filling with that? Y/N\n"); + var wouldYouInput = Console.ReadLine(); + switch (wouldYouInput.ToLower()) + { + case "y": + Console.WriteLine("\nWhat filling do you want?\n"); + Console.WriteLine("1. Bacon"); + Console.WriteLine("2. Egg"); + Console.WriteLine("3. Cheese"); + Console.WriteLine("4. Cream Cheese"); + Console.WriteLine("5. Smoked Salmon"); + Console.WriteLine("6. Ham\n"); + var fillingInput = Console.ReadLine(); + switch (fillingInput) + { + case "1": + basket.AddItem(Inventory.CreateFilling(FillingVariant.Bacon)); + Console.WriteLine("\nBacon added!\n"); + break; + + case "2": + basket.AddItem(Inventory.CreateFilling(FillingVariant.Egg)); + Console.WriteLine("\nEgg added!\n"); + break; + + case "3": + basket.AddItem(Inventory.CreateFilling(FillingVariant.Cheese)); + Console.WriteLine("\nCheese added!\n"); + break; + + case "4": + basket.AddItem(Inventory.CreateFilling(FillingVariant.CreamCheese)); + Console.WriteLine("\nCream Cheese added!\n"); + break; + + case "5": + basket.AddItem(Inventory.CreateFilling(FillingVariant.SmokedSalmon)); + Console.WriteLine("\nSmoked Salmon added!\n"); + break; + + case "6": + basket.AddItem(Inventory.CreateFilling(FillingVariant.Ham)); + Console.WriteLine("\nHam added!\n"); + break; + } + break; + + case "n": + break; + + default: + Console.WriteLine("Invalid input"); + break; + } + break; + + case "2": + Console.WriteLine("\nWhat coffee do you want?\n"); + Console.WriteLine("1. Black"); + Console.WriteLine("2. White"); + Console.WriteLine("3. Cappucino"); + Console.WriteLine("4. Latte\n"); + var coffeeInput = Console.ReadLine(); + switch (coffeeInput) + { + case "1": + basket.AddItem(Inventory.CreateCoffee(CoffeeVariant.Black)); + Console.WriteLine("\nBlack coffee added!\n"); + break; + + case "2": + basket.AddItem(Inventory.CreateCoffee(CoffeeVariant.White)); + Console.WriteLine("\nWhite coffee added!\n"); + break; + + case "3": + basket.AddItem(Inventory.CreateCoffee(CoffeeVariant.Cappucino)); + Console.WriteLine("\nCappucino added!\n"); + break; + + case "4": + basket.AddItem(Inventory.CreateCoffee(CoffeeVariant.Latte)); + Console.WriteLine("\nLatte added!\n"); + break; + } + break; + + case "3": + Console.WriteLine("Removing bagel UNFINISHED"); + //basket.RemoveItem(); + break; + + case "4": + Console.WriteLine("What should the new capacity be?\n"); + var newCapacity = int.Parse(Console.ReadLine()); + basket.ChangeCapacity(newCapacity); + Console.WriteLine($"The new capacity is:{newCapacity}\n"); + break; + + case "5": + Console.WriteLine("The current total cost is: "); + Console.WriteLine(checkout.TotalPrice(basket) + "\n"); + break; + + case "6": + + Console.WriteLine(checkout.Receipt(basket)); + Environment.Exit(0); + break; + + case "7": + Environment.Exit(0); + break; + + case "exit": + Environment.Exit(0); + break; + + default: + Console.WriteLine("\nInvalid input\n"); + break; + + } + } } } \ No newline at end of file