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