Move BinFileSaver from CutList/Services to CutList.Core namespace for reuse by MCP server. Add GenerateReport() method that returns formatted text instead of only writing to file. Refactor to use TextWriter base class for flexibility. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
142 lines
4.3 KiB
C#
142 lines
4.3 KiB
C#
using CutList.Core.Formatting;
|
|
using System.Diagnostics;
|
|
|
|
namespace CutList.Core
|
|
{
|
|
public class BinFileSaver
|
|
{
|
|
private readonly IEnumerable<Bin> _bins;
|
|
|
|
private int PaddingWidthOfItemLength { get; set; }
|
|
|
|
public bool OpenFileAfterSave { get; set; }
|
|
|
|
public BinFileSaver(IEnumerable<Bin> bins)
|
|
{
|
|
_bins = bins ?? throw new ArgumentNullException(nameof(bins));
|
|
}
|
|
|
|
public void SaveBinsToFile(string file)
|
|
{
|
|
using (var writer = new StreamWriter(file))
|
|
{
|
|
writer.AutoFlush = true;
|
|
WriteToWriter(writer);
|
|
}
|
|
|
|
if (OpenFileAfterSave)
|
|
{
|
|
OpenFile(file);
|
|
}
|
|
}
|
|
|
|
public string GenerateReport()
|
|
{
|
|
using var writer = new StringWriter();
|
|
WriteToWriter(writer);
|
|
return writer.ToString();
|
|
}
|
|
|
|
private void WriteToWriter(TextWriter writer)
|
|
{
|
|
PaddingWidthOfItemLength = _bins
|
|
.SelectMany(b => b.Items)
|
|
.Select(i => FormatHelper.ConvertToMixedFraction(i.Length).Length)
|
|
.DefaultIfEmpty(0)
|
|
.Max();
|
|
|
|
WriteHeader(writer);
|
|
|
|
var id = 1;
|
|
foreach (var bin in _bins)
|
|
{
|
|
WriteBinSummary(writer, bin, id++);
|
|
}
|
|
|
|
WriteFinalSummary(writer);
|
|
}
|
|
|
|
private void OpenFile(string file)
|
|
{
|
|
try
|
|
{
|
|
Process.Start("notepad.exe", file);
|
|
}
|
|
catch
|
|
{
|
|
Process.Start(file);
|
|
}
|
|
}
|
|
|
|
private void WriteHeader(TextWriter writer)
|
|
{
|
|
var totalBars = _bins.Count();
|
|
var totalItems = _bins.Sum(b => b.Items.Count);
|
|
|
|
writer.WriteLine("CUT LIST");
|
|
writer.WriteLine($"Date: {DateTime.Now:g}");
|
|
writer.WriteLine($"Total stock bars needed: {totalBars}");
|
|
writer.WriteLine($"Total pieces to cut: {totalItems}");
|
|
writer.WriteLine();
|
|
}
|
|
|
|
private void WriteBinSummary(TextWriter writer, Bin bin, int id)
|
|
{
|
|
var stockLength = FormatHelper.ConvertToMixedFraction(bin.Length);
|
|
var dropLength = FormatHelper.ConvertToMixedFraction(bin.RemainingLength);
|
|
|
|
writer.WriteLine(new string('─', 50));
|
|
writer.WriteLine($"BAR #{id} - Start with {stockLength}\" stock");
|
|
writer.WriteLine();
|
|
writer.WriteLine(" Cut these pieces:");
|
|
|
|
WriteBinItems(writer, bin);
|
|
|
|
writer.WriteLine();
|
|
writer.WriteLine($" Remaining drop: {dropLength}\"");
|
|
writer.WriteLine();
|
|
}
|
|
|
|
private void WriteBinItems(TextWriter writer, Bin bin)
|
|
{
|
|
var groups = bin.Items
|
|
.GroupBy(i => new { i.Name, i.Length })
|
|
.OrderBy(g => g.Key.Name)
|
|
.ThenBy(g => g.Key.Length);
|
|
|
|
var lengthHeader = "LENGTH".PadLeft(PaddingWidthOfItemLength + 1);
|
|
writer.WriteLine($" QTY {lengthHeader} LABEL");
|
|
|
|
foreach (var group in groups)
|
|
{
|
|
var first = group.First();
|
|
var count = group.Count();
|
|
var length = FormatHelper
|
|
.ConvertToMixedFraction(first.Length)
|
|
.PadLeft(PaddingWidthOfItemLength) + "\"";
|
|
|
|
writer.WriteLine($" {count,3} {length} {first.Name}");
|
|
}
|
|
}
|
|
|
|
private void WriteFinalSummary(TextWriter writer)
|
|
{
|
|
var totalBars = _bins.Count();
|
|
var totalItems = _bins.Sum(b => b.Items.Count);
|
|
var totalStock = _bins.Sum(b => b.Length);
|
|
var totalDrop = _bins.Sum(b => b.RemainingLength);
|
|
|
|
string fmt(double v) => FormatHelper.ConvertToMixedFraction(v);
|
|
|
|
writer.WriteLine(new string('═', 50));
|
|
writer.WriteLine("SUMMARY");
|
|
writer.WriteLine($" Stock bars needed: {totalBars}");
|
|
writer.WriteLine($" Total pieces to cut: {totalItems}");
|
|
writer.WriteLine($" Total material used: {fmt(totalStock)}\"");
|
|
writer.WriteLine($" Total drop/waste: {fmt(totalDrop)}\"");
|
|
writer.WriteLine(new string('═', 50));
|
|
}
|
|
|
|
}
|
|
}
|