Removed Bugs from cs files & almost completed CoffeeVendingMachine.cs

This commit is contained in:
MarcUs7i 2024-11-18 08:45:15 +01:00
parent bc7f2da775
commit 66cc7055fa
4 changed files with 273 additions and 41 deletions

View file

@ -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();
/// <summary>
/// Creates a new coffee vending machine.
/// </summary>
/// <param name="coinDepots"></param>
/// <param name="products"></param>
/// <param name="location"></param>
public CoffeeVendingMachine(CoinDepot[] coinDepots, Product[] products, string location)
{
//TODO
Location = location;
_currentChangeCoins = coinDepots;
_products = products;
_currentInputCoins = CreateCoinDepots(6);
}
public CoffeeVendingMachine(string location)
/// <summary>
/// Creates a new coffee vending machine with default products.
/// </summary>
/// <param name="location"></param>
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 [];
}
/// <summary>
/// Inserts the given coin into the machine.
/// </summary>
/// <param name="coin"></param>
/// <returns>True if the coin was inserted, false otherwise.</returns>
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)
/// <summary>
/// Withdraws the change from the machine.
/// </summary>
/// <param name="productName"></param>
/// <param name="change"></param>
/// <param name="remainder"></param>
/// <returns>True if the change was withdrawn, false otherwise.</returns>
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;
}
/// <summary>
/// Withdraws the input coins from the machine.
/// </summary>
/// <returns>The withdrawn coins.</returns>
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 +
"|=======================================|";
}
/// <summary>
/// Adds the input coins to the change coins.
/// </summary>
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)
/// <summary>
/// Creates the coin depots.
/// </summary>
/// <param name="count"></param>
/// <returns>The created coin depots.</returns>
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;
}
/// <summary>
/// Creates the default products.
/// </summary>
/// <returns>The default products.</returns>
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;
}
/// <summary>
/// Gets the depot by the given coin type.
/// </summary>
/// <param name="coinDepots"></param>
/// <param name="coinType"></param>
/// <returns>The depot with the given coin type or null if not found.</returns>
private static CoinDepot? GetDepotByType(CoinDepot[] coinDepots, CoinType coinType)
{
//TODO
foreach (var coinDepot in coinDepots)
{
if (coinDepot.Coin == coinType)
{
return coinDepot;
}
}
return null;
}
/// <summary>
/// Prepares the change coins for the given amount.
/// </summary>
/// <param name="amount"></param>
/// <param name="changeCoins"></param>
/// <returns>The remaining amount that could not be changed.</returns>
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;
}
/// <summary>
/// Sums the value of all coins in the coin depots.
/// </summary>
/// <param name="coinDepots"></param>
/// <returns>The sum of all coins in the coin depots.</returns>
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;
}
/// <summary>
/// Tries to find a product by its name.
/// </summary>
/// <param name="productName"></param>
/// <param name="product"></param>
/// <returns>True if the product was found, false otherwise.</returns>
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;
}
/// <summary>
/// Gets the available products.
/// </summary>
/// <returns>The available products.</returns>
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;
}
}

View file

@ -29,7 +29,7 @@ public class CoinDepot
public override string ToString()
{
return $"{Coin}: {Count}";
return $"{Coin} x{Count}";
}
public bool Withdraw()

View file

@ -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
}

View file

@ -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]";
}
}