ex-int-04-shipping-cost/ShippingCosts/Program.cs
github-classroom[bot] 5db225db88
Initial commit
2025-04-29 15:01:53 +00:00

128 lines
3.8 KiB
C#

using System.Globalization;
using System.Numerics;
using System.Text;
using ShippingCosts.Contracts;
using ShippingCosts.Implementations;
using Spectre.Console;
Console.OutputEncoding = Encoding.UTF8;
ICountryDistanceProvider countryDistanceProvider = new CountryDistanceProvider();
var shippingServices = new IShippingCostCalculator[]
{
new SelfPickup(),
new LPSShippingCostCalculator(countryDistanceProvider),
new LuxuryShippingCostCalculator(countryDistanceProvider)
};
Clear();
WriteLine("Please enter the dimensions of the package you want to ship.");
var box = AskForBoxMeasurements();
Clear();
var selectedService = AskForShippingService();
Clear();
string? targetCountry = AskForCountryName(countryDistanceProvider);
Clear();
if (targetCountry is null)
{
WriteLine("Sorry to see you go! We hope you'll ship with us again soon.");
return;
}
decimal cost = selectedService.CalculateShippingCosts(targetCountry, box)!.Value;
WriteLine($"The shipping costs for your package are {cost.ToString("C", CultureInfo.CurrentCulture)}.");
Console.ReadKey();
#region Helper methods
static void WriteLine(string text) => AnsiConsole.MarkupLine($"[blue]{text}[/]");
static void Clear()
{
AnsiConsole.Clear();
AnsiConsole.WriteLine();
AnsiConsole.Write(new FigletText("Shipping Cost Calculator")
.Color(Color.Blue)
.Centered());
}
static IMeasuredBox AskForBoxMeasurements()
{
int width = AskForPositiveValue<int>("Enter the package width in mm:");
int height = AskForPositiveValue<int>("Enter the package height in mm:");
int depth = AskForPositiveValue<int>("Enter the package depth in mm:");
double weight = AskForPositiveValue<double>("Enter the package weight in kg:");
return new Package
{
Depth = depth,
Height = height,
Weight = weight,
Width = width
};
static T AskForPositiveValue<T>(string prompt) where T : INumber<T>
{
T value;
do
{
value = AnsiConsole.Ask<T>(prompt);
if (value <= T.Zero)
{
AnsiConsole.MarkupLine("[red]Invalid input. Please enter a value greater than 0.[/]");
}
} while (value <= T.Zero);
return value;
}
}
IShippingCostCalculator AskForShippingService()
{
var services = new Dictionary<string, IShippingCostCalculator>();
foreach (var shippingService in shippingServices)
{
services.Add(shippingService.CarrierName, shippingService);
}
SelectionPrompt<string> prompt = new SelectionPrompt<string>()
.Title("Please choose a shipping service/type:")
.AddChoices(services.Keys);
string selection = AnsiConsole.Prompt(prompt);
return services[selection];
}
static string? AskForCountryName(ICountryDistanceProvider countryDistanceProvider)
{
string countryName;
const string Abort = "x";
do
{
countryName = AnsiConsole.Ask<string>($"Enter the country name to ship to (or type '{Abort}' to abort):");
if (countryName.Trim().Equals(Abort, StringComparison.OrdinalIgnoreCase))
{
AnsiConsole.MarkupLine("[yellow]Aborted by user.[/]");
return null;
}
countryName = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(countryName.ToLower());
if (!countryDistanceProvider.IsPossibleCountry(countryName))
{
AnsiConsole.MarkupLine("[red]Shipping to the provided country is not possible. " +
$"Please try again or type '{Abort}' to cancel.[/]");
}
} while (string.IsNullOrWhiteSpace(countryName) || !countryDistanceProvider.IsPossibleCountry(countryName));
return countryName;
}
#endregion