Removed Bugs from cs files & almost completed CoffeeVendingMachine.cs
This commit is contained in:
parent
bc7f2da775
commit
66cc7055fa
4 changed files with 273 additions and 41 deletions
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ public class CoinDepot
|
|||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{Coin}: {Count}";
|
||||
return $"{Coin} x{Count}";
|
||||
}
|
||||
|
||||
public bool Withdraw()
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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]";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue