From 66cc7055faf980b6ac5020f88171a93a90fb2813 Mon Sep 17 00:00:00 2001 From: MarcUs7i <96580944+MarcUs7i@users.noreply.github.com> Date: Mon, 18 Nov 2024 08:45:15 +0100 Subject: [PATCH] Removed Bugs from cs files & almost completed CoffeeVendingMachine.cs --- CoffeeVendingMachines/CoffeeVendingMachine.cs | 287 ++++++++++++++++-- CoffeeVendingMachines/CoinDepot.cs | 2 +- CoffeeVendingMachines/Model.cs | 12 +- CoffeeVendingMachines/Product.cs | 13 +- 4 files changed, 273 insertions(+), 41 deletions(-) diff --git a/CoffeeVendingMachines/CoffeeVendingMachine.cs b/CoffeeVendingMachines/CoffeeVendingMachine.cs index ee791ed..7b88ded 100644 --- a/CoffeeVendingMachines/CoffeeVendingMachine.cs +++ b/CoffeeVendingMachines/CoffeeVendingMachine.cs @@ -2,24 +2,45 @@ public class CoffeeVendingMachine { - private static readonly CoinType[] withdrawalOrder; + private static readonly CoinType[] withdrawalOrder = + [ + CoinType.Euro02, + CoinType.Euro01, + CoinType.Cent50, + CoinType.Cent20, + CoinType.Cent10, + CoinType.Cent05 + ]; private readonly CoinDepot[] _currentChangeCoins; private readonly CoinDepot[] _currentInputCoins; private readonly Product[] _products; - public readonly string Location; - public readonly int TotalChangeAmountInMachine; - public readonly int TotalMoneyCurrentlyInput; - public readonly Product[] AvailableProducts; + public string Location { get; } + public int TotalChangeAmountInMachine => SumDepotValue(_currentChangeCoins); + public int TotalMoneyCurrentlyInput => SumDepotValue(_currentInputCoins); + public Product[] AvailableProducts => GetAvailableProducts(); + /// + /// Creates a new coffee vending machine. + /// + /// + /// + /// public CoffeeVendingMachine(CoinDepot[] coinDepots, Product[] products, string location) { - //TODO + Location = location; + _currentChangeCoins = coinDepots; + _products = products; + _currentInputCoins = CreateCoinDepots(6); } - public CoffeeVendingMachine(string location) + /// + /// Creates a new coffee vending machine with default products. + /// + /// + public CoffeeVendingMachine(string location) : this(CreateCoinDepots(6, true), CreateDefaultProducts(), location) { - //TODO + // no need to implement anything here } public CoinDepot[] Cancel() @@ -28,66 +49,274 @@ public class CoffeeVendingMachine return []; } + /// + /// Inserts the given coin into the machine. + /// + /// + /// True if the coin was inserted, false otherwise. public bool InsertCoin(CoinType coin) { - //TODO + foreach (var inputDepot in _currentInputCoins) + { + if (inputDepot.Coin == coin) + { + inputDepot.Add(); + return true; + } + } + return false; } - public bool SelectProduct(string productName, out CoinDepot[]? change, out int? price) + /// + /// Withdraws the change from the machine. + /// + /// + /// + /// + /// True if the change was withdrawn, false otherwise. + public bool SelectProduct(string productName, out CoinDepot[]? change, out int? remainder) { - //TODO - change = null; - price = null; - return false; + if(!TryFindProduct(productName, out Product? product) || product == null || !product.InStock || TotalMoneyCurrentlyInput < product.Price) + { + change = null; + remainder = null; + return false; + } + + int returnAmount = TotalMoneyCurrentlyInput - product.Price; + AddInputToChange(); + product.AddSale(); + int? remainingAmount = PrepareChangeCoins(returnAmount, out CoinDepot[] changeCoins); + + change = changeCoins; + remainder = remainingAmount; + + return true; } + /// + /// Withdraws the input coins from the machine. + /// + /// The withdrawn coins. public override string ToString() { - //TODO - return ""; + string coinString = ""; + string productString = ""; + foreach (var coin in CoinType.GetValues(typeof(CoinType))) + { + CoinDepot? depot = GetDepotByType(_currentChangeCoins, (CoinType)coin); + if (depot != null) + { + coinString += $"|{depot.ToString()}".PadRight(40) + $"|{Environment.NewLine}"; + } + } + foreach (var product in _products) + { + productString += $"|{product.ToString()}".PadRight(40) + $"|{Environment.NewLine}"; + } + return $"|=======================================|{Environment.NewLine}" + + $"|Machine located at: {Location}".PadRight(40) + $"|{Environment.NewLine}" + + $"|=======================================|{Environment.NewLine}" + + coinString + + $"|=======================================|{Environment.NewLine}" + + productString + + "|=======================================|"; } + /// + /// Adds the input coins to the change coins. + /// private void AddInputToChange() { - //TODO + for (int i = 0; i < _currentInputCoins.Length; i++) + { + while (_currentInputCoins[i].Count > 0) + { + _currentChangeCoins[i].Add(); + _currentInputCoins[i].Withdraw(); + } + } } - private static CoinDepot[] CreateCoinDepots(int count) + /// + /// Creates the coin depots. + /// + /// + /// The created coin depots. + private static CoinDepot[] CreateCoinDepots(int count, bool fill = false) { - //TODO - return []; + CoinDepot[] coinDepots = new CoinDepot[count]; + CoinType[] coinTypes = (CoinType[])Enum.GetValues(typeof(CoinType)); + for (int i = 0; i < count; i++) + { + coinDepots[i] = new CoinDepot(coinTypes[i]); + } + + if (fill) + { + for (int i = 0; i < coinDepots.Length; i++) + { + while(coinDepots[i].Count < 3) // magic number + { + coinDepots[i].Add(); + } + } + } + + return coinDepots; } + /// + /// Creates the default products. + /// + /// The default products. private static Product[] CreateDefaultProducts() { - //TODO - return []; + Product[] products = new Product[3]; // magic number + products[0] = new Product("Cappuccino", 085, 10); + products[1] = new Product("Mocca", 100, 10); + products[2] = new Product("Cacao", 060, 10); + + return products; } + /// + /// Gets the depot by the given coin type. + /// + /// + /// + /// The depot with the given coin type or null if not found. private static CoinDepot? GetDepotByType(CoinDepot[] coinDepots, CoinType coinType) { - //TODO + foreach (var coinDepot in coinDepots) + { + if (coinDepot.Coin == coinType) + { + return coinDepot; + } + } return null; } + /// + /// Prepares the change coins for the given amount. + /// + /// + /// + /// The remaining amount that could not be changed. private int? PrepareChangeCoins(int amount, out CoinDepot[] changeCoins) { - //TODO - changeCoins = []; - return null; + changeCoins = CreateCoinDepots(_currentChangeCoins.Length); + + foreach (var coinType in withdrawalOrder) + { + CoinDepot? depot = GetDepotByType(_currentChangeCoins, coinType); + if (depot == null) + { + continue; + } + + while (amount >= (int)coinType && depot.Count > 0) + { + amount -= (int)coinType; + depot.Withdraw(); + CoinDepot? changeDepot = GetDepotByType(changeCoins, coinType); + changeDepot?.Add(); + } + } + + changeCoins = RemoveUnusedCoins(changeCoins); + return amount > 0 ? amount : null; + } + + private CoinDepot[] RemoveUnusedCoins(CoinDepot[] coins) + { + int count = 0; + foreach (var coin in coins) + { + if (coin.Count > 0) + { + count++; + } + } + + CoinDepot[] usedCoins = new CoinDepot[count]; + int j = 0; + for (int i = 0; i < coins.Length; i++) + { + if (coins[i].Count > 0) + { + usedCoins[j] = coins[i]; + j++; + } + } + + return usedCoins; } + /// + /// Sums the value of all coins in the coin depots. + /// + /// + /// The sum of all coins in the coin depots. private static int SumDepotValue(CoinDepot[] coinDepots) { - //TODO - return 0; + int sum = 0; + foreach (var coinDepot in coinDepots) + { + sum += coinDepot.Count * (int)coinDepot.Coin; + } + return sum; } + /// + /// Tries to find a product by its name. + /// + /// + /// + /// True if the product was found, false otherwise. private bool TryFindProduct(string productName, out Product? product) { - //TODO + foreach (var _product in _products) + { + if(_product.Name == productName) + { + product = _product; + return true; + } + } + product = null; return false; } + + /// + /// Gets the available products. + /// + /// The available products. + private Product[] GetAvailableProducts() + { + int count = 0; + foreach (var product in _products) + { + if (product.InStock) + { + count++; + } + } + + Product[] availableProducts = new Product[count]; + int j = 0; + for (int i = 0; i < _products.Length; i++) + { + if (_products[i].InStock) + { + availableProducts[j] = _products[i]; + j++; + } + } + + return availableProducts; + } } diff --git a/CoffeeVendingMachines/CoinDepot.cs b/CoffeeVendingMachines/CoinDepot.cs index f51b62a..d2e650c 100644 --- a/CoffeeVendingMachines/CoinDepot.cs +++ b/CoffeeVendingMachines/CoinDepot.cs @@ -29,7 +29,7 @@ public class CoinDepot public override string ToString() { - return $"{Coin}: {Count}"; + return $"{Coin} x{Count}"; } public bool Withdraw() diff --git a/CoffeeVendingMachines/Model.cs b/CoffeeVendingMachines/Model.cs index 7119c36..d0340b1 100644 --- a/CoffeeVendingMachines/Model.cs +++ b/CoffeeVendingMachines/Model.cs @@ -2,10 +2,10 @@ namespace CoffeeVendingMachines; public enum CoinType { - Cent05, - Cent10, - Cent20, - Cent50, - Euro01, - Euro02 + Cent05 = 005, + Cent10 = 010, + Cent20 = 020, + Cent50 = 050, + Euro01 = 100, + Euro02 = 200 } \ No newline at end of file diff --git a/CoffeeVendingMachines/Product.cs b/CoffeeVendingMachines/Product.cs index 47d021a..c962494 100644 --- a/CoffeeVendingMachines/Product.cs +++ b/CoffeeVendingMachines/Product.cs @@ -5,17 +5,20 @@ public class Product public const int FallbackPrice = 50; private readonly int _price; private int _stock; - public readonly bool InStock; - public readonly string Name; + public bool InStock => _stock > 0; + public string Name { get; } public int NumberSold { get; private set; } - public int Price { get; private init; } + public int Price => _price; public Product (string name, int price = FallbackPrice, int stock = 0) { Name = name; _price = price; _stock = stock; - InStock = _stock > 0; + if(price <= 0 || price % 5 != 0) + { + _price = FallbackPrice; + } } public bool AddSale() @@ -32,6 +35,6 @@ public class Product public override string ToString() { - return $"{Name} € {Price} [{_stock} in stock | {NumberSold} sold]"; + return $"{Name,-10} € {(decimal)Price/100:0.00} [{_stock} in stock | {NumberSold} sold]"; } }