using System;
namespace SawCut
{
///
/// Represents a type of bin with quantity and priority.
/// Enforces business rules for valid bin configurations.
///
public class MultiBin
{
private int _quantity;
private double _length;
private int _priority;
public MultiBin(double length, int quantity = 1, int priority = 25)
{
if (length <= 0)
throw new ArgumentException("Bin length must be greater than zero", nameof(length));
if (quantity < -1 || quantity == 0)
throw new ArgumentException("Quantity must be positive or -1 for unlimited", nameof(quantity));
_length = length;
_quantity = quantity;
_priority = priority;
}
///
/// Parameterless constructor for serialization only.
/// Use the parameterized constructor for creating valid instances.
///
public MultiBin()
{
_quantity = 1;
_priority = 25;
}
///
/// Quantity of bins available. Use -1 for unlimited bins.
///
public int Quantity
{
get => _quantity;
set
{
if (value < -1 || value == 0)
throw new ArgumentException("Quantity must be positive or -1 for unlimited", nameof(value));
_quantity = value;
}
}
public double Length
{
get => _length;
set
{
if (value <= 0)
throw new ArgumentException("Bin length must be greater than zero", nameof(value));
_length = value;
}
}
///
/// Lower value priority will be used first. Default is 25.
///
public int Priority
{
get => _priority;
set => _priority = value;
}
///
/// Checks if this bin type has unlimited quantity.
///
public bool IsUnlimited => Quantity == -1;
///
/// Checks if an item of the given length can fit in this bin.
///
public bool CanFitItem(double itemLength)
{
return itemLength <= Length && itemLength > 0;
}
///
/// Calculates the waste for a single bin if the given length is used.
///
public double CalculateWaste(double usedLength)
{
if (usedLength < 0 || usedLength > Length)
throw new ArgumentException("Used length must be between 0 and bin length", nameof(usedLength));
return Length - usedLength;
}
public override string ToString()
{
var quantityStr = IsUnlimited ? "Unlimited" : Quantity.ToString();
return $"Bin {Length}\" (Qty: {quantityStr}, Priority: {Priority})";
}
public override bool Equals(object? obj)
{
if (obj is MultiBin other)
{
return Quantity == other.Quantity &&
Length.IsEqualTo(other.Length) &&
Priority == other.Priority;
}
return false;
}
public override int GetHashCode()
{
unchecked
{
int hash = 17;
hash = hash * 23 + Quantity.GetHashCode();
hash = hash * 23 + Length.GetHashCode();
hash = hash * 23 + Priority.GetHashCode();
return hash;
}
}
}
}