namespace CutList.Core { /// /// Represents an item to be placed in a bin. /// Enforces business rules for valid items. /// public class BinItem { private string _name = string.Empty; private double _length; public BinItem(string? name, double length) { if (length <= 0) throw new ArgumentException("Item length must be greater than zero", nameof(length)); _name = name ?? string.Empty; _length = length; } /// /// Parameterless constructor for serialization only. /// Use the parameterized constructor for creating valid instances. /// public BinItem() { } public string Name { get => _name; set => _name = value ?? string.Empty; } public double Length { get => _length; set { if (value <= 0) throw new ArgumentException("Item length must be greater than zero", nameof(value)); _length = value; } } /// /// Checks if this item can fit in the given available length. /// public bool CanFitIn(double availableLength) { return Length <= availableLength; } /// /// Checks if this item can fit in the given available length with spacing. /// public bool CanFitInWithSpacing(double availableLength, double spacing) { return Length + spacing <= availableLength; } public override string ToString() { return $"{Name} ({Length}\")"; } public override bool Equals(object? obj) { if (obj is BinItem other) { return Name == other.Name && Length.IsEqualTo(other.Length); } return false; } public override int GetHashCode() { unchecked { // Prime multiplier reduces collisions in hash-based collections const int HashMultiplier = 23; int hash = 17; hash = hash * HashMultiplier + (Name?.GetHashCode() ?? 0); hash = hash * HashMultiplier + Length.GetHashCode(); return hash; } } } }