129 lines
3.8 KiB
C#
129 lines
3.8 KiB
C#
namespace Supermarket;
|
|
|
|
public abstract class Product
|
|
{
|
|
public const char Separator = ';';
|
|
|
|
public const string Invalid = "Invalid!";
|
|
|
|
/// <summary>
|
|
/// The constructor of Product
|
|
/// </summary>
|
|
/// <param name="productName">The product name</param>
|
|
/// <param name="barcode">The bar code</param>
|
|
/// <param name="quantity">The quantity</param>
|
|
protected Product(string productName, string barcode, int quantity)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(productName))
|
|
{
|
|
productName = Invalid;
|
|
}
|
|
ProductName = productName;
|
|
Barcode = IsBarcodeValid(barcode) ? barcode : Invalid;
|
|
Quantity = quantity > 0 ? quantity : 0;
|
|
}
|
|
|
|
/// <summary>
|
|
/// The product name
|
|
/// </summary>
|
|
public string ProductName { get; }
|
|
|
|
/// <summary>
|
|
/// The bar code of the product
|
|
/// </summary>
|
|
public string Barcode { get; }
|
|
|
|
/// <summary>
|
|
/// The quantity of the product
|
|
/// </summary>
|
|
public int Quantity { get; }
|
|
|
|
/// <summary>
|
|
/// The CSV column names
|
|
/// </summary>
|
|
protected virtual string[] CsvColumnNames => [nameof(Barcode), nameof(ProductName), nameof(Quantity)];
|
|
|
|
/// <summary>
|
|
/// The CSV column values
|
|
/// </summary>
|
|
protected virtual string[] CsvColumnValues => [Barcode, ProductName, Quantity.ToString()];
|
|
|
|
/// <summary>
|
|
/// The CSV header
|
|
/// </summary>
|
|
/// <returns>The formatted CSV header</returns>
|
|
public string GetCsvHeader() => string.Join(Separator, CsvColumnNames);
|
|
|
|
/// <summary>
|
|
/// The CSV line
|
|
/// </summary>
|
|
/// <returns>The formatted CSV line with values</returns>
|
|
public string ToCsv() => ToCsvLine(CsvColumnValues, Separator);
|
|
|
|
/// <summary>
|
|
/// The CSV line generator
|
|
/// </summary>
|
|
/// <param name="values">The values</param>
|
|
/// <param name="separator">The separator</param>
|
|
/// <returns>The formatted CSV line</returns>
|
|
protected static string ToCsvLine(string[] values, char separator) => String.Join(separator, values);
|
|
|
|
/// <summary>
|
|
/// Checks if the bar code is valid
|
|
/// </summary>
|
|
/// <param name="barcode">The bar code to check</param>
|
|
/// <returns>True if the bar code is valid, false otherwise</returns>
|
|
public static bool IsBarcodeValid(string? barcode)
|
|
{
|
|
if (string.IsNullOrEmpty(barcode) || barcode.Length != 8)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if(barcode.Length is > 8 or < 8)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
const int evenWeight = 3;
|
|
const int oddWeight = 1;
|
|
int weight = 0;
|
|
|
|
for (int i = 0; i < barcode.Length; i++)
|
|
{
|
|
if (!char.IsDigit(barcode[i]))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Skip check digit
|
|
if (i == 7)
|
|
{
|
|
break;
|
|
}
|
|
|
|
int digit = barcode[i] - '0';
|
|
weight += i % 2 == 0 ? digit * evenWeight : digit * oddWeight;
|
|
}
|
|
|
|
int calculatedCheckDigit = (10 - (weight % 10)) % 10;
|
|
|
|
return calculatedCheckDigit == barcode[^1] - '0';
|
|
}
|
|
|
|
/// <summary>
|
|
/// Appends new values to an existing array
|
|
/// </summary>
|
|
/// <param name="existingArray">The array to append to</param>
|
|
/// <param name="newValues">The array of values to append</param>
|
|
/// <typeparam name="T">The type</typeparam>
|
|
/// <returns>The complete array</returns>
|
|
protected static T[] AppendToArray<T>(T[] existingArray, params T[] newValues)
|
|
{
|
|
// we are allowed to use Lists, so why not? :)
|
|
List<T> result = new(existingArray.Length + newValues.Length);
|
|
result.AddRange(existingArray);
|
|
result.AddRange(newValues);
|
|
return result.ToArray();
|
|
}
|
|
}
|