namespace DeliveryFeeCalculation.Programs
{
public static class DeliveryFeeConstants
{
public const decimal MinDistanceFee = 5m;
public const decimal MedDistanceFee = 8m;
public const decimal MaxDistanceFee = 10m;
public const decimal RainingFee = 2m;
public const int MinDistanceLimitKm = 5;
public const int MedDistanceLimitKm = 10;
}
public class DeliveryFeeCalculator
{
public void CalculateAndShowFee()
{
ShowMenu();
decimal distance = GetDistance();
bool isRaining = GetWeather();
decimal deliveryFee = CalculateFee(distance, isRaining);
Console.WriteLine($"\nYOUR DELIVERYFEE FOR THIS CONDITIONS IS ${deliveryFee:F2}.");
}
/// <summary>
/// Calculates delivery fee based on distance and whether it is raining.
/// This method is the "business logic" and should be easy to test.
/// </summary>
/// <param name="distanceKm">Delivery distance in kilometers.</param>
/// <param name="isRaining">True if it is raining, false otherwise.</param>
/// <returns>The total delivery fee.</returns>
public decimal CalculateFee(decimal distanceKm, bool isRaining)
{
decimal deliveryFee = 0m;
if (distanceKm <= DeliveryFeeConstants.MinDistanceLimitKm)
{
deliveryFee = DeliveryFeeConstants.MinDistanceFee;
}
else if (distanceKm < DeliveryFeeConstants.MedDistanceLimitKm)
{
deliveryFee = DeliveryFeeConstants.MedDistanceFee;
}
else
{
deliveryFee = DeliveryFeeConstants. MaxDistanceFee;
}
if (isRaining)
{
deliveryFee += DeliveryFeeConstants.RainingFee;
}
return deliveryFee;
}
/// <summary>
/// Requests the delivery distance from the user.
/// </summary>
/// <returns>The distance in kilometers.</returns>
public static decimal GetDistance()
{
decimal distance;
Console.WriteLine("\nHow far is the restaurant from your house?");
//loop to ensure input is a valid, positive number
while (!decimal.TryParse(Console.ReadLine(), out distance) || distance <= 0)
{
Console.WriteLine("\nInvalid input.Please enter an integer (ex. 2):");
}
return distance;
}
/// <summary>
/// Ask the user about the weather condition.
/// </summary>
/// <returns>True if it is raining.</returns>
public static bool GetWeather()
{
string answer;
Console.WriteLine("\nIs it raining now? (Y/N)*");
//loop to ensure a valid answer ('Y' or 'N')
while (true)
{
answer = (Console.ReadLine() ?? "").Trim().ToUpper();
if (answer == "Y") return true;
if (answer == "N") return false;
Console.WriteLine("Invalid answer. Please enter 'Y' for Yes or 'N' for No:");
}
}
/// <summary>
/// Displays the menu with fee details.
/// </summary>
public static void ShowMenu()
{
Console.WriteLine("TO COMPLETE YOUR PURCHASE, LET´S CALCULATE YOUR DELIVERY FEE. \nFOR THIS, ENTER SOME DETAILS.");
Console.WriteLine("\nDETAILS OF THE FEE:" +
$"\n${DeliveryFeeConstants.MinDistanceFee:F2} = Distance <= {DeliveryFeeConstants.MinDistanceLimitKm}KM." +
$"\n${DeliveryFeeConstants.MedDistanceFee:F2} = Distance > {DeliveryFeeConstants.MinDistanceLimitKm}KM e <= {DeliveryFeeConstants.MedDistanceLimitKm}KM." +
$"\n${DeliveryFeeConstants.MaxDistanceFee
:F2} = Distance > {DeliveryFeeConstants.MedDistanceLimitKm}KM." +
$"\n${DeliveryFeeConstants.RainingFee:F2} = Additional Rain.");
}
}
}