diff --git a/OpenNest.Posts.Cincinnati/SpeedClassifier.cs b/OpenNest.Posts.Cincinnati/SpeedClassifier.cs new file mode 100644 index 0000000..6c7e66c --- /dev/null +++ b/OpenNest.Posts.Cincinnati/SpeedClassifier.cs @@ -0,0 +1,31 @@ +namespace OpenNest.Posts.Cincinnati +{ + public sealed class SpeedClassifier + { + public double FastThreshold { get; set; } = 0.5; + public double SlowThreshold { get; set; } = 0.1; + + public string Classify(double contourLength, double sheetDiagonal) + { + var ratio = contourLength / sheetDiagonal; + if (ratio > FastThreshold) return "FAST"; + if (ratio <= SlowThreshold) return "SLOW"; + return "MEDIUM"; + } + + public string FormatCutDist(double contourLength, double sheetDiagonal) + { + return $"CutDist={FormatValue(contourLength)}/{FormatValue(sheetDiagonal)}"; + } + + private static string FormatValue(double value) + { + // Cincinnati convention: no leading zero for values < 1 (e.g., ".8702" not "0.8702") + var rounded = System.Math.Round(value, 4); + var str = rounded.ToString("0.####"); + if (rounded > 0 && rounded < 1 && str.StartsWith("0.")) + return str.Substring(1); + return str; + } + } +} diff --git a/OpenNest.Tests/Cincinnati/SpeedClassifierTests.cs b/OpenNest.Tests/Cincinnati/SpeedClassifierTests.cs new file mode 100644 index 0000000..e88ef09 --- /dev/null +++ b/OpenNest.Tests/Cincinnati/SpeedClassifierTests.cs @@ -0,0 +1,26 @@ +using OpenNest.Posts.Cincinnati; + +namespace OpenNest.Tests.Cincinnati; + +public class SpeedClassifierTests +{ + [Theory] + [InlineData(20.0, 10.0, "FAST")] + [InlineData(5.0, 10.0, "MEDIUM")] + [InlineData(0.5, 10.0, "SLOW")] + public void Classify_ReturnsExpectedClass(double contourLength, double sheetDiagonal, string expected) + { + var classifier = new SpeedClassifier(); + Assert.Equal(expected, classifier.Classify(contourLength, sheetDiagonal)); + } + + [Theory] + [InlineData(0.8702, 3.927, "CutDist=.8702/3.927")] + [InlineData(18.9722, 3.927, "CutDist=18.9722/3.927")] + [InlineData(0.0, 10.0, "CutDist=0/10")] + public void FormatCutDist_IncludesLengthAndDiagonal(double contour, double diag, string expected) + { + var classifier = new SpeedClassifier(); + Assert.Equal(expected, classifier.FormatCutDist(contour, diag)); + } +}