diff --git a/DomainModel.md b/DomainModel.md new file mode 100644 index 00000000..23c3418a --- /dev/null +++ b/DomainModel.md @@ -0,0 +1,119 @@ +For both core and extensions! + +User Stories + +# Core +1. +As a member of the public, +So I can order a bagel before work, +I'd like to add a specific type of bagel to my basket. + +2. +As a member of the public, +So I can change my order, +I'd like to remove a bagel from my basket. + +3. +As a member of the public, +So that I can not overfill my small bagel basket +I'd like to know when my basket is full when I try adding an item beyond my basket capacity. + +4. +As a Bob's Bagels manager, +So that I can expand my business, +I’d like to change the capacity of baskets. + +5. +As a member of the public +So that I can maintain my sanity +I'd like to know if I try to remove an item that doesn't exist in my basket. + +6. +As a customer, +So I know how much money I need, +I'd like to know the total cost of items in my basket. + +7. +As a customer, +So I know what the damage will be, +I'd like to know the cost of a bagel before I add it to my basket. + +8. +As a customer, +So I can shake things up a bit, +I'd like to be able to choose fillings for my bagel. + +9. +As a customer, +So I don't over-spend, +I'd like to know the cost of each filling before I add it to my bagel order. + +10. +As the manager, +So we don't get any weird requests, +I want customers to only be able to order things that we stock in our inventory. + +# Extension 1 + +11. +As a customer, +So I can see if I saved money +So I can see the discount in my basket + +# Extension 2 + +12. +As a customer, +So I can show my wife what I bouht, +I want to see a reciept of what I bought + +# Extension 3 + +13. +As a customer, +So I can see if I saved money, +I want be able to see potencial discounts on my reciept + +# Domain Model + +| Classes | Methods | Scenario | Outputs | +|-----------------|-----------------------------------------------------------------------------------------|-------------------------------------------|-------------| +| `Item` | Public Item(string id, double price, string name, string variant) | Can either be a bagel, coffee or fillings | Item | +| | | | | +|-----------------|-----------------------------------------------------------------------------------------|-------------------------------------------|-------------| +| `Inventory` | Public List Inventory | List over all of the available items | List | +| | | Can only order from the inventory | | +| | List getInventory() | Returns the full inventory | List | +| | | | | +| | findItemByName(string itemName) | Lets the user find item using only its name|Item | +| | | | | +|-----------------|-----------------------------------------------------------------------------------------|-------------------------------------------|-------------| +| `Person` | Public Person(string name, Role role) | Person can be a Manager or a Customer | Person | +| | Public Enum Role {CUSTOMER, MANAGER} | | | +| | | | | +|-----------------|-----------------------------------------------------------------------------------------|-------------------------------------------|-------------| +| `Basket` | addItem(Item bagel, Item filling?, Item coffee?) | User ordered bagel based on the type | bool | +| | | Item not in inventory | bool | +| | | User adds filling and/or coffee | bool | +| | | | | +| | removeBagels(Item item) | User removed item from basket | string | +| | | The item didnt exist | string | +| | | | | +| | public int basketMaxSize | Property to holding/setting the basket | int | +| | Modify addItem to check if full | | bool | +| | | | | +| | changeCapacity(int capacity, Role role) | Manager wants to change the basket size | void (none) | +| | | | | +| | checkPriceForType(string type) | Customers wants to see prices | double | +| | | | | +| | | | | +| | checkTotal() | Customer wants to see the total basket cost|double | +| | | | | +| | reciept() | Customer wants to see what he/she bought | string | +| | | | | +| | recieptWithDiscount() | Cheaper total because of discounts | string | +| | | | | +| | discount() | Customer wants to see discount | double | +| | | | | +| | | | | +| | | | | \ No newline at end of file diff --git a/exercise.main/Basket.cs b/exercise.main/Basket.cs new file mode 100644 index 00000000..a6740700 --- /dev/null +++ b/exercise.main/Basket.cs @@ -0,0 +1,288 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.ConstrainedExecution; +using System.Text; +using System.Threading.Tasks; + +namespace exercise.main +{ + public class Basket + { + Inventory inventory = new Inventory(); + public int MAX_BASKET_SIZE { get; set; } = 3; + public List yourBasket = new List(); + public Dictionary itemCount = new Dictionary(); + public int items_in_basket = 0; + + public bool addItem(string itemType, string variant) + { + + Item item = inventory.findItemByName(variant); + + if (items_in_basket >= MAX_BASKET_SIZE) + { + Console.WriteLine("Basket is full..."); + return false; + } + if (item != null) { + yourBasket.Add(item); + items_in_basket++; + return true; + } + else + { + Console.WriteLine("No such item..."); + return false; + } + } + + public void removeItem(string itemName) + { + Item item = inventory.findItemByName(itemName); + if (!yourBasket.Contains(item)) + { + Console.WriteLine("Your basket does not contain this item..."); + return; + } + else + { + yourBasket.Remove(item); + } + } + + public void changeCapacity(int newCapacity, Person person) + { + if ((newCapacity <= 0) || (person.role == Role.CUSTOMER)) + { + Console.WriteLine("Cannot change capacity to 0 or lower or you do not have the permission to do this action..."); + } + else + { + MAX_BASKET_SIZE = newCapacity; + } + } + + public double checkTotal() + { + return Math.Round(yourBasket.Sum(item => item.price), 2); + } + + public double checkPriceForType(string type) + { + return inventory.findItemByName(type).price; + } + + + //extension 2 + public string Reciept() + { + string reciept = $"\n\n\n---- Reciept ----\n"; + reciept += $" {DateTime.Now.ToString()} \n\n"; + reciept += $"-------------------------\n\n"; + double totalPrice = checkTotal(); + List allreadyCountedItems = []; + foreach (Item item in yourBasket) + { + double totalPriceForSpecifiedItem = 0; + double itemCount = 0; + + if (!allreadyCountedItems.Contains(item.id)) + { + + foreach (Item specificItem in yourBasket) + { + if (specificItem.id == item.id) + { + itemCount++; + } + } + + + totalPriceForSpecifiedItem = itemCount * item.price; + reciept += $"{item.name}, {item.variant} {itemCount}x - {totalPriceForSpecifiedItem}\n"; + allreadyCountedItems.Add(item.id); + } + } + reciept += $"-------------------------\ntotal: {totalPrice}"; + + //Console.WriteLine(reciept); + return reciept; + } + + + public double Discount() + { + foreach (Item item in yourBasket) + { + if (itemCount.ContainsKey(item)) + { + int count = itemCount[item] + 1; + itemCount[item] = count; + } + else + { + itemCount.Add(item, 1); + } + } + + double coffeeDeal = 1.25; + double sixBagels = 2.49; + double twelveBagels = 3.99; + + List coffee = inventory._inventory.Where(item => item.id.Contains("BGL")).ToList(); + List bagel = inventory._inventory.Where(item => item.id.Contains("COF")).ToList(); + + //my assumption here is that the coffee + bagel discounts only counts if those are the only things a customer is buying + if(yourBasket.Count == 2 && (coffee.Any(x => x.id.Contains(itemCount.First().Key.id) || x.id.Contains(itemCount.Last().Key.id) + && (bagel.Any(x => x.id.Contains(itemCount.First().Key.id) || x.id.Contains(itemCount.Last().Key.id)))))) + { + return coffeeDeal; + } + + foreach(var item in itemCount) + { + if(item.Key.name == "Bagel" && item.Value == 6) + { + return sixBagels; + } + else if (item.Key.name == "Bagel" && item.Value == 12) + { + return twelveBagels; + } + + } + return 0; + + } + + public string recieptWithDiscount() + { + + double coffeeDeal = 1.25; + double sixBagels = 2.49; + double twelveBagels = 3.99; + + double moneys = Discount(); + double moneySaved = 0; + if (moneys == 0) + { + return Reciept(); + } + + string reciept = $"\n\n\n---- Reciept ----\n\n"; + reciept += $" {DateTime.Now.ToString()} \n\n"; + reciept += $"-------------------------\n\n"; + double totalPrice = 0; + + if (moneys == sixBagels || moneys == twelveBagels) + { + + + foreach(var item in itemCount) + { + double usualTotal = (Math.Round((item.Key.price * item.Value), 2)); + if (item.Value == 6 || item.Value == 12) + { + reciept += $"{item.Key.name}, {item.Key.variant} {item.Value}x - {moneys}\n"; + + double moneySavedOnTheseItems = Math.Round((usualTotal - moneys), 2); + reciept += $" discount: ({moneySavedOnTheseItems})\n\n"; + moneySaved += moneySavedOnTheseItems; + totalPrice += moneys; + + } + else + { + reciept += $"{item.Key.name}, {item.Key.variant} {item.Value}x - {usualTotal}\n\n"; + totalPrice += usualTotal; + } + } + + + } + else if (moneys == coffeeDeal){ + reciept += $"coffeeNbagelDeal! {moneys} \n{itemCount.First().Key.name}, {itemCount.First().Key.variant}\n{itemCount.Last().Key.name}, {itemCount.Last().Key.variant}\n\n"; + double usualTotal = itemCount.First().Key.price + itemCount.Last().Key.price; + double moneySavedOnTheseItems = usualTotal - moneys; + moneySaved += moneySavedOnTheseItems; + totalPrice += moneys; + } + reciept += $"-------------------------\ntotal: {Math.Round(totalPrice, 2)}\n"; + reciept += $"money saved: {Math.Round(moneySaved,2)}\n"; + + + //Console.WriteLine(reciept); + return reciept; + } + + + // LEGACY CODE + + //old method - extension 1 and 3 made into one method. Not pretty :) + public string oldRecieptWithDiscount() + { + string reciept = $"---- Reciept ----\n\n"; + reciept += $" {DateTime.Now.ToString()} \n"; + reciept += $"-------------------------\n"; + double totalPrice = 0; + List allreadyCountedItems = []; + foreach (Item item in yourBasket) + { + double totalPriceForSpecifiedItem = 0; + double discountedPrice = 0; + double itemCount = 0; + double discount = 0; + + if (!allreadyCountedItems.Contains(item.id)) + { + + foreach (Item specificItem in yourBasket) + { + if (specificItem.id == item.id) + { + itemCount++; + } + } + if (itemCount == 6) + { + totalPriceForSpecifiedItem = itemCount * item.price; + discountedPrice = 2.49; + discount = totalPriceForSpecifiedItem - discount; + totalPrice += discountedPrice; + reciept += $"{item.name}: {item.variant} {itemCount}x - {discountedPrice}\n"; + reciept += $" discount ({discount})\n"; + allreadyCountedItems.Add(item.id); + } + else if (itemCount == 12) + { + totalPriceForSpecifiedItem = itemCount * item.price; + discountedPrice = 3.99; + discount = totalPriceForSpecifiedItem - discount; + totalPrice += discountedPrice; + reciept += $"{item.name}: {item.variant} {itemCount}x - {discountedPrice}\n"; + reciept += $" discount ({discount})\n"; + allreadyCountedItems.Add(item.id); + } + else + { + totalPriceForSpecifiedItem = itemCount * item.price; + reciept += $"{item.name}: {item.variant} {itemCount}x - {totalPriceForSpecifiedItem}\n"; + totalPrice += totalPriceForSpecifiedItem; + allreadyCountedItems.Add(item.id); + } + + } + } + + + reciept += $"-------------------------\ntotal: {totalPrice}"; + + Console.WriteLine(reciept); + return reciept; + } + } +} + + + diff --git a/exercise.main/ClassDiagram.cd b/exercise.main/ClassDiagram.cd new file mode 100644 index 00000000..5657772e --- /dev/null +++ b/exercise.main/ClassDiagram.cd @@ -0,0 +1,39 @@ + + + + + + CAAIAAAAAAABAAAEAACAAAMAAAEAAAACAgAAAAABAAE= + Basket.cs + + + + + + IAAAACAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAA= + Inventory.cs + + + + + + AAABAAAAAAAAAAAAAAAAAIAAAAAEAAAAAAAAAAAAAgA= + Item.cs + + + + + + AAAAAAAAAAAAAAAAAAAAABAAAAAEAAAAAAAAAAAAAAA= + Person.cs + + + + + + AAAAAAAAAAAAAAAAAAAAAAAAQAAAAQAAAAAAAAAAAAA= + Person.cs + + + + \ No newline at end of file diff --git a/exercise.main/Inventory.cs b/exercise.main/Inventory.cs new file mode 100644 index 00000000..d9756425 --- /dev/null +++ b/exercise.main/Inventory.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace exercise.main +{ + public class Inventory + { + public List _inventory = new List(); + + public List getInventory() + { + if (_inventory.Count != 0) + { + return _inventory; + } + _inventory.Add(new Item("BGLO", "Bagel", 0.49, "Onion")); + _inventory.Add(new Item("BGLP", "Bagel", 0.39, "Plain")); + _inventory.Add(new Item("BGLE", "Bagel", 0.49, "Everything")); + _inventory.Add(new Item("BGLS", "Bagel", 0.49, "Sesame")); + _inventory.Add(new Item("COFB", "Coffee", 0.99, "Black")); + _inventory.Add(new Item("COFW", "Coffee", 1.19, "White")); + _inventory.Add(new Item("COFC", "Coffee", 1.29, "Capuccino")); + _inventory.Add(new Item("COFL", "Coffee", 1.29, "Latte")); + _inventory.Add(new Item("FILB", "Filling", 0.12, "Bacon")); + _inventory.Add(new Item("FILE", "Filling", 0.12, "Egg")); + _inventory.Add(new Item("FILC", "Filling", 0.12, "Cheese")); + _inventory.Add(new Item("FILX", "Filling", 0.12, "Chream Cheese")); + _inventory.Add(new Item("FILS", "Filling", 0.12, "Smoked Salmon")); + _inventory.Add(new Item("FILH", "Filling", 0.12, "Ham")); + + return _inventory; + } + + public Item findItemByName(string itemName) + { + + List items = getInventory(); + foreach(var item in items) + { + if(item.variant == itemName) + { + Console.WriteLine($"{itemName} is available"); + return item; + } + } + Console.WriteLine($"{itemName} is not available"); + return null; + + } + } +} diff --git a/exercise.main/Item.cs b/exercise.main/Item.cs new file mode 100644 index 00000000..49207cea --- /dev/null +++ b/exercise.main/Item.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace exercise.main +{ + public class Item + { + public string id { get; set; } + public string name { get; set; } + public double price { get; set; } + public string variant { get; set; } + + public Item() { } + public Item(string id, string name, double price, string variant) + { + this.id = id; + this.name = name; + this.price = price; + this.variant = variant; + } + } +} diff --git a/exercise.main/Person.cs b/exercise.main/Person.cs new file mode 100644 index 00000000..6e07fc40 --- /dev/null +++ b/exercise.main/Person.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace exercise.main +{ + public enum Role { MANAGER, CUSTOMER} + public class Person + { + public string name { get; set; } + public Role role { get; set; } + + public Person() { } + + public Person(string name, Role role) + { + this.name = name; + this.role = role; + } + } +} diff --git a/exercise.main/Program.cs b/exercise.main/Program.cs index 3751555c..aa2920b6 100644 --- a/exercise.main/Program.cs +++ b/exercise.main/Program.cs @@ -1,2 +1,32 @@ // See https://aka.ms/new-console-template for more information +using exercise.main; + Console.WriteLine("Hello, World!"); +Inventory inventory = new Inventory(); +Basket basket = new Basket(); +Item expectedItem = new Item("BGLO", "Bagel", 0.49, "Onion"); +Person flier = new Person("Flier", Role.MANAGER); +basket.changeCapacity(12, flier); + +basket.addItem("Bagel", "Onion"); +basket.addItem("Bagel", "Onion"); +basket.addItem("Bagel", "Onion"); +basket.addItem("Bagel", "Onion"); +basket.addItem("Coffee", "Black"); +basket.addItem("Bagel", "Onion"); +basket.addItem("Bagel", "Plain"); +basket.addItem("Bagel", "Onion"); +basket.addItem("Coffee", "White"); +basket.addItem("Coffee", "Black"); + +/* +basket.addItem("Bagel", "Onion"); +basket.addItem("Coffee", "Black"); +*/ +Console.WriteLine(basket.recieptWithDiscount()); + + +//Console.WriteLine(basket.recieptWithDiscount()); + + + diff --git a/exercise.sln b/exercise.sln index 0efb5453..e251a810 100644 --- a/exercise.sln +++ b/exercise.sln @@ -10,6 +10,7 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{825CCFE7-4F2E-4770-8393-FEB732F66EE4}" ProjectSection(SolutionItems) = preProject extension1.md = extension1.md + DomainModel.md = DomainModel.md extension2.md = extension2.md extension3.md = extension3.md extension4.md = extension4.md @@ -34,4 +35,7 @@ Global GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {AFAC51EF-C4AC-46E1-9B58-F24AECAFB982} + EndGlobalSection EndGlobal diff --git a/exercise.tests/CoreTests.cs b/exercise.tests/CoreTests.cs new file mode 100644 index 00000000..3257eb93 --- /dev/null +++ b/exercise.tests/CoreTests.cs @@ -0,0 +1,135 @@ +namespace exercise.tests; +using exercise.main; +public class Tests +{ + + + [Test] + public void findItemByNameTest() + { + Inventory inventory = new Inventory(); + + Item expected = new Item("BGLO", "Bagel", 0.49, "Onion"); + Item result = inventory.findItemByName("Onion"); + + Assert.That(expected.id == result.id); + } + + + [Test] + public void addItemTest() + { + Inventory inventory = new Inventory(); + Basket basket = new Basket(); + Item expectedItem = new Item("BGLO", "Bagel", 0.49, "Onion"); + basket.addItem("Bagel", "Onion"); + //for checking that a non existant item doesnt get added to the basket + bool expected = false; + bool result1 = basket.addItem("Bagel", "Leverpostei"); + + //for checking that something doesnt get added to a full basket + basket.addItem("Bagel", "Sesame"); + basket.addItem("Bagel", "Sesame"); + bool result2 = basket.addItem("Bagel", "Plain"); + + Assert.That(basket.yourBasket.First().id == expectedItem.id); + Assert.That(result1 == expected); + Assert.That(result2 == expected); + + } + + [Test] + public void removeItemTest() + { + Basket basket = new Basket(); + basket.removeItem("Onion"); + + + Assert.That(basket.yourBasket.Count == 0); + + } + + + [Test] + public void changeCapacityTest() + { + Basket basket = new Basket(); + Person manager = new Person("Flier", Role.MANAGER); + + basket.changeCapacity(4, manager); + + Assert.That(basket.MAX_BASKET_SIZE == 4); + + //someone who isnt the manager tries to change the basket properties + Person notManager = new Person("Dennis", Role.CUSTOMER); + basket.changeCapacity(3, notManager); + Assert.That(basket.MAX_BASKET_SIZE == 4); + + } + + [Test] + public void checkTotalTest() + { + Basket basket = new Basket(); + + basket.addItem("Coffee", "Black"); + basket.addItem("Bagel", "Plain"); + basket.addItem("Filling", "Ham"); + + double expected = 1.50; + double result = basket.checkTotal(); + + Assert.That(expected == result); + + } + + [Test] + public void checkPriceForTypeTest() + { + Basket basket = new Basket(); + + //check bagel price + double expectedPrice1 = 0.39; + double resultPrice1 = basket.checkPriceForType("Plain"); + Assert.That(expectedPrice1 == resultPrice1); + + //check filling price + double expectedPrice2 = 0.12; + double resultPrice2 = basket.checkPriceForType("Egg"); + Assert.That(expectedPrice2 == resultPrice2); + + } + + [Test] + public void discountCheck() + { + Basket basket = new Basket(); + Basket basket2 = new Basket(); + Person flier = new Person("Flier", Role.MANAGER); + + basket.changeCapacity(10, flier); + basket.addItem("Bagel", "Plain"); + basket.addItem("Bagel", "Plain"); + basket.addItem("Bagel", "Plain"); + basket.addItem("Bagel", "Plain"); + basket.addItem("Bagel", "Plain"); + basket.addItem("Bagel", "Plain"); + + basket2.addItem("Coffee", "Black"); + basket2.addItem("Bagel", "Onion"); + + double expected = 2.49; + double result = basket.Discount(); + + double expected2 = 1.25; + double result2 = basket2.Discount(); + + + Assert.That(expected == result); + Assert.That(expected2 == result2); + + + + } + +} \ No newline at end of file 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 diff --git a/exercise.tests/exercise.tests.csproj b/exercise.tests/exercise.tests.csproj index 0072a6d1..93317f6f 100644 --- a/exercise.tests/exercise.tests.csproj +++ b/exercise.tests/exercise.tests.csproj @@ -17,4 +17,8 @@ + + + +