128 lines
3.8 KiB
C#
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
|