Refactor Reader classes: Extract common parsing logic to StringParsingHelper
Created StringParsingHelper utility class (107 lines) to consolidate repetitive parsing: - ParseInt32, ParseDouble, ParsePercent methods with error handling - TryParseKeyValue methods for extracting values from key=value strings - ExtractAfterPrefix for removing fixed prefixes Benefits: - Eliminated duplicate parsing code across ReportReader and PlateReader - Consistent error handling and debug logging - Cleaner, more maintainable parsing methods - Reduced PlateReader from 338 lines to 277 lines (18% reduction) - Reduced ReportReader from 378 lines to 339 lines (10% reduction) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -142,30 +142,18 @@ namespace PepLib.IO
|
||||
|
||||
private void ParsePostedFiles(string data)
|
||||
{
|
||||
if (data.Length < 14)
|
||||
return;
|
||||
|
||||
Plate.PostedFiles = data.Remove(0, 14).Trim();
|
||||
Plate.PostedFiles = StringParsingHelper.ExtractAfterPrefix(data, "POSTED FILES=");
|
||||
}
|
||||
|
||||
private void ParseHeatLot(string data)
|
||||
{
|
||||
if (data.Length < 9)
|
||||
return;
|
||||
|
||||
Plate.HeatLot = data.Remove(0, 9).Trim();
|
||||
Plate.HeatLot = StringParsingHelper.ExtractAfterPrefix(data, "HEAT LOT=");
|
||||
}
|
||||
|
||||
private void ParseSpacing(string data)
|
||||
{
|
||||
var parts = data.Split('=');
|
||||
|
||||
if (parts.Length != 2)
|
||||
return;
|
||||
|
||||
double spacing;
|
||||
double.TryParse(parts[1], out spacing);
|
||||
|
||||
if (StringParsingHelper.TryParseDoubleFromKeyValue(data, '=', out spacing))
|
||||
Plate.PartSpacing = spacing;
|
||||
}
|
||||
|
||||
@@ -176,37 +164,18 @@ namespace PepLib.IO
|
||||
if (parts.Length != 5)
|
||||
return;
|
||||
|
||||
var leftSplit = parts[1].Split('=');
|
||||
if (leftSplit.Length == 2)
|
||||
{
|
||||
double x;
|
||||
double.TryParse(leftSplit[1], out x);
|
||||
Plate.EdgeSpacing.Left = x;
|
||||
}
|
||||
double value;
|
||||
if (StringParsingHelper.TryParseDoubleFromKeyValue(parts[1], '=', out value))
|
||||
Plate.EdgeSpacing.Left = value;
|
||||
|
||||
var bottomSplit = parts[2].Split('=');
|
||||
if (bottomSplit.Length == 2)
|
||||
{
|
||||
double x;
|
||||
double.TryParse(bottomSplit[1], out x);
|
||||
Plate.EdgeSpacing.Bottom = x;
|
||||
}
|
||||
if (StringParsingHelper.TryParseDoubleFromKeyValue(parts[2], '=', out value))
|
||||
Plate.EdgeSpacing.Bottom = value;
|
||||
|
||||
var rightSplit = parts[3].Split('=');
|
||||
if (rightSplit.Length == 2)
|
||||
{
|
||||
double x;
|
||||
double.TryParse(rightSplit[1], out x);
|
||||
Plate.EdgeSpacing.Right = x;
|
||||
}
|
||||
if (StringParsingHelper.TryParseDoubleFromKeyValue(parts[3], '=', out value))
|
||||
Plate.EdgeSpacing.Right = value;
|
||||
|
||||
var topSplit = parts[4].Split('=');
|
||||
if (topSplit.Length == 2)
|
||||
{
|
||||
double x;
|
||||
double.TryParse(topSplit[1], out x);
|
||||
Plate.EdgeSpacing.Top = x;
|
||||
}
|
||||
if (StringParsingHelper.TryParseDoubleFromKeyValue(parts[4], '=', out value))
|
||||
Plate.EdgeSpacing.Top = value;
|
||||
}
|
||||
|
||||
private void ParsePlateSize(string data)
|
||||
@@ -265,73 +234,43 @@ namespace PepLib.IO
|
||||
|
||||
private void ParseMaterial(string data)
|
||||
{
|
||||
var parts = data.Split('=');
|
||||
|
||||
if (parts.Length != 2)
|
||||
return;
|
||||
|
||||
int material;
|
||||
int.TryParse(parts[1], out material);
|
||||
|
||||
if (StringParsingHelper.TryParseInt32FromKeyValue(data, '=', out material))
|
||||
Plate.Material.Id = material;
|
||||
}
|
||||
|
||||
private void ParseGrade(string data)
|
||||
{
|
||||
var parts = data.Split('=');
|
||||
|
||||
if (parts.Length != 2)
|
||||
return;
|
||||
|
||||
Plate.Material.Grade = parts[1].Trim();
|
||||
string value;
|
||||
if (StringParsingHelper.TryParseKeyValue(data, '=', out value))
|
||||
Plate.Material.Grade = value;
|
||||
}
|
||||
|
||||
private void ParseDescription(string data)
|
||||
{
|
||||
var parts = data.Split('=');
|
||||
|
||||
if (parts.Length != 2)
|
||||
return;
|
||||
|
||||
Plate.Description = parts[1].Trim();
|
||||
string value;
|
||||
if (StringParsingHelper.TryParseKeyValue(data, '=', out value))
|
||||
Plate.Description = value;
|
||||
}
|
||||
|
||||
private void ParseThickness(string data)
|
||||
{
|
||||
var parts = data.Split('=');
|
||||
|
||||
if (parts.Length != 2)
|
||||
return;
|
||||
|
||||
double thickness;
|
||||
double.TryParse(parts[1], out thickness);
|
||||
|
||||
if (StringParsingHelper.TryParseDoubleFromKeyValue(data, '=', out thickness))
|
||||
Plate.Thickness = thickness;
|
||||
}
|
||||
|
||||
private void ParseDensity(string data)
|
||||
{
|
||||
var parts = data.Split('=');
|
||||
|
||||
if (parts.Length != 2)
|
||||
return;
|
||||
|
||||
double density;
|
||||
double.TryParse(parts[1], out density);
|
||||
|
||||
if (StringParsingHelper.TryParseDoubleFromKeyValue(data, '=', out density))
|
||||
Plate.Material.Density = density;
|
||||
}
|
||||
|
||||
private void ParseTorchCount(string data)
|
||||
{
|
||||
var parts = data.Split('=');
|
||||
|
||||
if (parts.Length != 2)
|
||||
return;
|
||||
|
||||
int torchCount;
|
||||
int.TryParse(parts[1], out torchCount);
|
||||
|
||||
if (StringParsingHelper.TryParseInt32FromKeyValue(data, '=', out torchCount))
|
||||
Plate.TorchCount = torchCount;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,7 +170,7 @@ namespace PepLib.IO
|
||||
break;
|
||||
|
||||
case "Thickness":
|
||||
plt.Thickness = ParseDouble(value);
|
||||
plt.Thickness = StringParsingHelper.ParseDouble(value);
|
||||
break;
|
||||
|
||||
case "Plate Size":
|
||||
@@ -178,7 +178,7 @@ namespace PepLib.IO
|
||||
break;
|
||||
|
||||
case "Material":
|
||||
plt.MaterialNumber = ParseInt32(value);
|
||||
plt.MaterialNumber = StringParsingHelper.ParseInt32(value);
|
||||
break;
|
||||
|
||||
case "Grade":
|
||||
@@ -194,23 +194,23 @@ namespace PepLib.IO
|
||||
break;
|
||||
|
||||
case "Plate Util":
|
||||
plt.PlateUtilization = ParsePercent(value);
|
||||
plt.PlateUtilization = StringParsingHelper.ParsePercent(value);
|
||||
break;
|
||||
|
||||
case "Material Util":
|
||||
plt.MaterialUtilization = ParsePercent(value);
|
||||
plt.MaterialUtilization = StringParsingHelper.ParsePercent(value);
|
||||
break;
|
||||
|
||||
case "Total Area1":
|
||||
plt.Area1 = ParseDouble(value);
|
||||
plt.Area1 = StringParsingHelper.ParseDouble(value);
|
||||
break;
|
||||
|
||||
case "Total Area2":
|
||||
plt.Area2 = ParseDouble(value);
|
||||
plt.Area2 = StringParsingHelper.ParseDouble(value);
|
||||
break;
|
||||
|
||||
case "Bubble pierces":
|
||||
plt.BubblePierceCount = ParseInt32(value);
|
||||
plt.BubblePierceCount = StringParsingHelper.ParseInt32(value);
|
||||
break;
|
||||
|
||||
case "Total cutting time":
|
||||
@@ -218,11 +218,11 @@ namespace PepLib.IO
|
||||
break;
|
||||
|
||||
case "Cutting feedrate":
|
||||
Report.CutFeedrate = ParseInt32(value);
|
||||
Report.CutFeedrate = StringParsingHelper.ParseInt32(value);
|
||||
break;
|
||||
|
||||
case "Rapid feedrate":
|
||||
Report.RapidFeedrate = ParseInt32(value);
|
||||
Report.RapidFeedrate = StringParsingHelper.ParseInt32(value);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -248,35 +248,35 @@ namespace PepLib.IO
|
||||
break;
|
||||
|
||||
case "Qty Req":
|
||||
dwg.QtyRequired = ParseInt32(value);
|
||||
dwg.QtyRequired = StringParsingHelper.ParseInt32(value);
|
||||
break;
|
||||
|
||||
case "Qty Nstd":
|
||||
dwg.QtyNested = ParseInt32(value);
|
||||
dwg.QtyNested = StringParsingHelper.ParseInt32(value);
|
||||
break;
|
||||
|
||||
case "# of Pierces":
|
||||
dwg.PierceCount = ParseInt32(value);
|
||||
dwg.PierceCount = StringParsingHelper.ParseInt32(value);
|
||||
break;
|
||||
|
||||
case "Intersections":
|
||||
dwg.IntersectionCount = ParseInt32(value);
|
||||
dwg.IntersectionCount = StringParsingHelper.ParseInt32(value);
|
||||
break;
|
||||
|
||||
case "Area1*":
|
||||
dwg.Area1 = ParseDouble(value);
|
||||
dwg.Area1 = StringParsingHelper.ParseDouble(value);
|
||||
break;
|
||||
|
||||
case "Area2**":
|
||||
dwg.Area2 = ParseDouble(value);
|
||||
dwg.Area2 = StringParsingHelper.ParseDouble(value);
|
||||
break;
|
||||
|
||||
case "% of Material":
|
||||
dwg.PercentOfMaterial = ParsePercent(value);
|
||||
dwg.PercentOfMaterial = StringParsingHelper.ParsePercent(value);
|
||||
break;
|
||||
|
||||
case "% of Time":
|
||||
dwg.PercentOfCutTime = ParsePercent(value);
|
||||
dwg.PercentOfCutTime = StringParsingHelper.ParsePercent(value);
|
||||
dwg.TotalCutTime =
|
||||
TimeSpan.FromTicks((long)(Report.TotalCutTime.Ticks * dwg.PercentOfCutTime / 100.0));
|
||||
break;
|
||||
@@ -327,45 +327,6 @@ namespace PepLib.IO
|
||||
report.TotalCutTime = new TimeSpan(hrs, min, sec);
|
||||
}
|
||||
|
||||
private static double ParsePercent(string s, double defaultValue = 0.0)
|
||||
{
|
||||
var t = s.TrimEnd('%', ' ');
|
||||
double f;
|
||||
|
||||
if (!double.TryParse(t, out f))
|
||||
{
|
||||
Debug.WriteLine("Failed to convert \"" + s + "\" from percent string to double");
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
private static double ParseDouble(string s, double defaultValue = 0.0)
|
||||
{
|
||||
double f;
|
||||
|
||||
if (!double.TryParse(s, out f))
|
||||
{
|
||||
Debug.WriteLine("Failed to convert \"" + s + "\" from string to double");
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
private static int ParseInt32(string s, int defaultValue = 0)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!int.TryParse(s, out i))
|
||||
{
|
||||
Debug.WriteLine("Failed to convert \"" + s + "\" from string to int");
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
private enum Section
|
||||
{
|
||||
|
||||
107
PepLib/IO/StringParsingHelper.cs
Normal file
107
PepLib/IO/StringParsingHelper.cs
Normal file
@@ -0,0 +1,107 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace PepLib.IO
|
||||
{
|
||||
internal static class StringParsingHelper
|
||||
{
|
||||
public static int ParseInt32(string value, int defaultValue = 0)
|
||||
{
|
||||
int result;
|
||||
if (!int.TryParse(value, out result))
|
||||
{
|
||||
Debug.WriteLine($"Failed to convert \"{value}\" from string to int");
|
||||
return defaultValue;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static double ParseDouble(string value, double defaultValue = 0.0)
|
||||
{
|
||||
double result;
|
||||
if (!double.TryParse(value, out result))
|
||||
{
|
||||
Debug.WriteLine($"Failed to convert \"{value}\" from string to double");
|
||||
return defaultValue;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static double ParsePercent(string value, double defaultValue = 0.0)
|
||||
{
|
||||
var trimmed = value.TrimEnd('%', ' ');
|
||||
double result;
|
||||
if (!double.TryParse(trimmed, out result))
|
||||
{
|
||||
Debug.WriteLine($"Failed to convert \"{value}\" from percent string to double");
|
||||
return defaultValue;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static bool TrySplitKeyValue(string data, char separator, out string key, out string value)
|
||||
{
|
||||
var parts = data.Split(separator);
|
||||
if (parts.Length == 2)
|
||||
{
|
||||
key = parts[0].Trim();
|
||||
value = parts[1].Trim();
|
||||
return true;
|
||||
}
|
||||
|
||||
key = null;
|
||||
value = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static string ExtractAfterPrefix(string data, string prefix)
|
||||
{
|
||||
if (data.Length < prefix.Length)
|
||||
return string.Empty;
|
||||
|
||||
return data.Remove(0, prefix.Length).Trim();
|
||||
}
|
||||
|
||||
public static bool TryParseKeyValue(string data, char separator, out string value, Action<string> onError = null)
|
||||
{
|
||||
var parts = data.Split(separator);
|
||||
if (parts.Length == 2)
|
||||
{
|
||||
value = parts[1].Trim();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (onError != null)
|
||||
onError($"Expected 2 parts when splitting '{data}' by '{separator}', got {parts.Length}");
|
||||
|
||||
value = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool TryParseInt32FromKeyValue(string data, char separator, out int result, int defaultValue = 0)
|
||||
{
|
||||
string value;
|
||||
if (TryParseKeyValue(data, separator, out value))
|
||||
{
|
||||
result = ParseInt32(value, defaultValue);
|
||||
return true;
|
||||
}
|
||||
|
||||
result = defaultValue;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool TryParseDoubleFromKeyValue(string data, char separator, out double result, double defaultValue = 0.0)
|
||||
{
|
||||
string value;
|
||||
if (TryParseKeyValue(data, separator, out value))
|
||||
{
|
||||
result = ParseDouble(value, defaultValue);
|
||||
return true;
|
||||
}
|
||||
|
||||
result = defaultValue;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -97,6 +97,7 @@
|
||||
<Compile Include="Size.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="IO\ReportReader.cs" />
|
||||
<Compile Include="IO\StringParsingHelper.cs" />
|
||||
<Compile Include="Spacing.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Report.cs" />
|
||||
|
||||
Reference in New Issue
Block a user