433 lines
18 KiB
C#
433 lines
18 KiB
C#
using Microsoft.Extensions.Logging;
|
|
#if HgCV
|
|
using System.Collections.ObjectModel;
|
|
using System.Text.Json;
|
|
using System.Text.Json.Serialization;
|
|
#endif
|
|
|
|
namespace File_Folder_Helper.ADO2024.PI3;
|
|
|
|
internal static partial class Helper20241030
|
|
{
|
|
|
|
#if HgCV
|
|
|
|
private record Complete(Header Header, Summary Summary, ReadOnlyCollection<Point> Points)
|
|
{
|
|
|
|
internal static Complete? Get(int take, string site, string multiple, string summaryLine, string lastUnits, string lastUnitsB, ReadOnlyCollection<string> lines)
|
|
{
|
|
Complete? result;
|
|
Header? header = Header.Get(lines, site, summaryLine);
|
|
if (header is null)
|
|
result = null;
|
|
else
|
|
{
|
|
Summary? summary = SummarySegment.Get(lines, site, summaryLine, lastUnits);
|
|
if (summary is null)
|
|
result = null;
|
|
else
|
|
{
|
|
ReadOnlyCollection<Point> points = Point.GetCollection(lines, take, site, multiple, summaryLine, lastUnitsB) ?? throw new NullReferenceException(nameof(summary));
|
|
if (points.Count == 0)
|
|
result = null;
|
|
else
|
|
result = new(header, summary, points);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
}
|
|
|
|
[JsonSourceGenerationOptions(WriteIndented = true)]
|
|
[JsonSerializable(typeof(Complete))]
|
|
private partial class CompleteSourceGenerationContext : JsonSerializerContext
|
|
{
|
|
}
|
|
|
|
private record Header([property: JsonPropertyName("Operator")] string Operator,
|
|
[property: JsonPropertyName("Start Voltage")] string StartVoltage,
|
|
[property: JsonPropertyName("Wafer")] string Wafer,
|
|
[property: JsonPropertyName("Stop Voltage")] string StopVoltage,
|
|
[property: JsonPropertyName("Lot")] string Lot,
|
|
[property: JsonPropertyName("Ramp Rate")] string RampRate,
|
|
[property: JsonPropertyName("Plan")] string Plan,
|
|
[property: JsonPropertyName("G limit")] string GLimit,
|
|
[property: JsonPropertyName("Date")] string Date,
|
|
[property: JsonPropertyName("Time")] string Time,
|
|
[property: JsonPropertyName("Setup File")] string SetupFile,
|
|
[property: JsonPropertyName("Wafer size")] string WaferSize,
|
|
[property: JsonPropertyName("Folder")] string Folder,
|
|
[property: JsonPropertyName("Ccomp")] string Ccomp,
|
|
[property: JsonPropertyName("Pattern")] string Pattern,
|
|
[property: JsonPropertyName("Area")] string Area,
|
|
[property: JsonPropertyName("Cond Type")] string CondType,
|
|
[property: JsonPropertyName("Rho Method")] string RhoMethod,
|
|
[property: JsonPropertyName("Model")] string Model)
|
|
{
|
|
|
|
private static string[] GetRemove() =>
|
|
[
|
|
" L L",
|
|
" O O",
|
|
" G G",
|
|
" C C",
|
|
" O O",
|
|
" N N",
|
|
" C C",
|
|
" E E",
|
|
" N N",
|
|
" T T",
|
|
" R R",
|
|
" A A",
|
|
" T T",
|
|
" I I",
|
|
" O O",
|
|
" N N"
|
|
];
|
|
|
|
internal static Header Get() =>
|
|
new(string.Empty,
|
|
string.Empty,
|
|
string.Empty,
|
|
string.Empty,
|
|
string.Empty,
|
|
string.Empty,
|
|
string.Empty,
|
|
string.Empty,
|
|
string.Empty,
|
|
string.Empty,
|
|
string.Empty,
|
|
string.Empty,
|
|
string.Empty,
|
|
string.Empty,
|
|
string.Empty,
|
|
string.Empty,
|
|
string.Empty,
|
|
string.Empty,
|
|
string.Empty);
|
|
|
|
private static ReadOnlyCollection<JsonProperty> GetJsonProperties()
|
|
{
|
|
JsonProperty[] results;
|
|
string json;
|
|
Header header = Get();
|
|
json = JsonSerializer.Serialize(header);
|
|
JsonElement jsonElement = JsonSerializer.Deserialize<JsonElement>(json);
|
|
results = jsonElement.EnumerateObject().ToArray();
|
|
return new(results);
|
|
}
|
|
|
|
internal static Header? Get(ReadOnlyCollection<string> lines, string site, string summaryLine)
|
|
{
|
|
Header? result;
|
|
string json;
|
|
string check;
|
|
string[] segments;
|
|
string[] segmentsB;
|
|
string[] segmentsC;
|
|
bool found = false;
|
|
string[] remove = GetRemove();
|
|
Dictionary<string, string> keyValuePairs = [];
|
|
ReadOnlyCollection<JsonProperty> jsonProperties = GetJsonProperties();
|
|
foreach (string line in lines)
|
|
{
|
|
if (line.Contains(site))
|
|
found = true;
|
|
if (!found)
|
|
continue;
|
|
if (line == summaryLine)
|
|
break;
|
|
foreach (JsonProperty jsonProperty in jsonProperties)
|
|
{
|
|
segments = line.Split([$"{jsonProperty.Name}:", $"{jsonProperty.Name} :"], StringSplitOptions.None);
|
|
if (segments.Length < 2)
|
|
continue;
|
|
check = segments[1].Trim();
|
|
foreach (JsonProperty jsonPropertyB in jsonProperties)
|
|
{
|
|
segmentsB = check.Split([$"{jsonPropertyB.Name}:", $"{jsonPropertyB.Name} :"], StringSplitOptions.None);
|
|
if (segmentsB.Length > 1)
|
|
check = segmentsB[0].Trim();
|
|
}
|
|
foreach (string r in remove)
|
|
{
|
|
segmentsC = check.Split(r);
|
|
if (segmentsC.Length > 1)
|
|
check = segmentsC[0].Trim();
|
|
}
|
|
keyValuePairs.Add(jsonProperty.Name, check);
|
|
}
|
|
}
|
|
if (keyValuePairs.Count != jsonProperties.Count)
|
|
result = null;
|
|
else
|
|
{
|
|
json = JsonSerializer.Serialize(keyValuePairs);
|
|
result = JsonSerializer.Deserialize(json, HeaderSourceGenerationContext.Default.Header) ?? throw new NullReferenceException(nameof(result));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
}
|
|
|
|
[JsonSourceGenerationOptions(WriteIndented = true)]
|
|
[JsonSerializable(typeof(Header))]
|
|
private partial class HeaderSourceGenerationContext : JsonSerializerContext
|
|
{
|
|
}
|
|
|
|
private record Summary(SummarySegment? Mean, SummarySegment? StandardDeviationPercentage, SummarySegment? RadialGradient);
|
|
|
|
private record SummarySegment([property: JsonPropertyName("Navg")] string NAvg,
|
|
[property: JsonPropertyName("Nsl")] string Nsl,
|
|
[property: JsonPropertyName("Vd")] string Vd,
|
|
[property: JsonPropertyName("Flat Z")] string FlatZ,
|
|
[property: JsonPropertyName("Rhoavg")] string RhoAvg,
|
|
[property: JsonPropertyName("Rhosl")] string Rhosl,
|
|
[property: JsonPropertyName("Phase")] string Phase,
|
|
[property: JsonPropertyName("Grade")] string Grade,
|
|
[property: JsonPropertyName("@ Rs")] string Rs)
|
|
{
|
|
|
|
internal static SummarySegment Get() =>
|
|
new(string.Empty,
|
|
string.Empty,
|
|
string.Empty,
|
|
string.Empty,
|
|
string.Empty,
|
|
string.Empty,
|
|
string.Empty,
|
|
string.Empty,
|
|
string.Empty);
|
|
|
|
private static ReadOnlyCollection<JsonProperty> GetJsonProperties()
|
|
{
|
|
JsonProperty[] results;
|
|
string json;
|
|
SummarySegment summarySegment = Get();
|
|
json = JsonSerializer.Serialize(summarySegment);
|
|
JsonElement jsonElement = JsonSerializer.Deserialize<JsonElement>(json);
|
|
results = jsonElement.EnumerateObject().ToArray();
|
|
return new(results);
|
|
}
|
|
|
|
internal static Summary? Get(ReadOnlyCollection<string> lines, string site, string summaryLine, string lastUnits)
|
|
{
|
|
Summary? result;
|
|
string json;
|
|
string[] segments;
|
|
bool found = false;
|
|
string[] segmentsB;
|
|
Dictionary<string, string> keyValuePairs = [];
|
|
Dictionary<string, string> keyValuePairsB = [];
|
|
Dictionary<string, string> keyValuePairsC = [];
|
|
ReadOnlyCollection<JsonProperty> jsonProperties = GetJsonProperties();
|
|
foreach (string line in lines)
|
|
{
|
|
if (line == summaryLine)
|
|
found = true;
|
|
if (!found)
|
|
continue;
|
|
if (line.Contains(site))
|
|
break;
|
|
if (line.Contains(lastUnits))
|
|
break;
|
|
foreach (JsonProperty jsonProperty in jsonProperties)
|
|
{
|
|
segments = line.Split([$"{jsonProperty.Name}:", $"{jsonProperty.Name} :"], StringSplitOptions.None);
|
|
if (segments.Length < 2 || (!line.StartsWith(jsonProperty.Name) && !line.StartsWith($"@ {jsonProperty.Name}")))
|
|
continue;
|
|
segmentsB = segments[1].Trim().Split(' ');
|
|
if (segmentsB.Length < 3)
|
|
continue;
|
|
keyValuePairs.Add(jsonProperty.Name, segmentsB[0]);
|
|
keyValuePairsB.Add(jsonProperty.Name, segmentsB[1]);
|
|
keyValuePairsC.Add(jsonProperty.Name, segmentsB[2]);
|
|
}
|
|
}
|
|
if (keyValuePairs.Count != jsonProperties.Count || keyValuePairsB.Count != jsonProperties.Count || keyValuePairsC.Count != jsonProperties.Count)
|
|
result = null;
|
|
else
|
|
{
|
|
json = JsonSerializer.Serialize(keyValuePairs);
|
|
SummarySegment? mean = JsonSerializer.Deserialize(json, SummarySegmentSourceGenerationContext.Default.SummarySegment);
|
|
json = JsonSerializer.Serialize(keyValuePairsB);
|
|
SummarySegment? standardDeviationPercentage = JsonSerializer.Deserialize(json, SummarySegmentSourceGenerationContext.Default.SummarySegment);
|
|
json = JsonSerializer.Serialize(keyValuePairsC);
|
|
SummarySegment? radialGradient = JsonSerializer.Deserialize(json, SummarySegmentSourceGenerationContext.Default.SummarySegment);
|
|
result = new(mean, standardDeviationPercentage, radialGradient);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
}
|
|
|
|
[JsonSourceGenerationOptions(WriteIndented = true)]
|
|
[JsonSerializable(typeof(SummarySegment))]
|
|
private partial class SummarySegmentSourceGenerationContext : JsonSerializerContext
|
|
{
|
|
}
|
|
|
|
private record Point([property: JsonPropertyName("Site")] string Site,
|
|
[property: JsonPropertyName("X")] string X,
|
|
[property: JsonPropertyName("Y")] string Y,
|
|
[property: JsonPropertyName("Navg")] string NAvg,
|
|
[property: JsonPropertyName("Rhoavg")] string RhoAvg,
|
|
[property: JsonPropertyName("Nsl")] string Nsl,
|
|
[property: JsonPropertyName("Rhosl")] string Rhosl,
|
|
[property: JsonPropertyName("Vd")] string Vd,
|
|
[property: JsonPropertyName("Phase")] string Phase,
|
|
[property: JsonPropertyName("Flat Z")] string FlatZ,
|
|
[property: JsonPropertyName("Grade")] string Grade,
|
|
[property: JsonPropertyName("X Left")] string XLeft,
|
|
[property: JsonPropertyName("X Right")] string XRight,
|
|
[property: JsonPropertyName("Bottom Y")] string BottomY,
|
|
[property: JsonPropertyName("Top Y")] string TopY)
|
|
{
|
|
|
|
internal static Point Get() =>
|
|
new(string.Empty,
|
|
string.Empty,
|
|
string.Empty,
|
|
string.Empty,
|
|
string.Empty,
|
|
string.Empty,
|
|
string.Empty,
|
|
string.Empty,
|
|
string.Empty,
|
|
string.Empty,
|
|
string.Empty,
|
|
string.Empty,
|
|
string.Empty,
|
|
string.Empty,
|
|
string.Empty);
|
|
|
|
internal static ReadOnlyCollection<Point> GetCollection(ReadOnlyCollection<string> lines, int take, string site, string multiple, string summaryLine, string lastUnitsB)
|
|
{
|
|
List<Point> results = [];
|
|
string s;
|
|
string line;
|
|
Point point;
|
|
string[] segments;
|
|
string[] segmentsB;
|
|
bool found = false;
|
|
bool foundB = false;
|
|
string[] segmentsC;
|
|
List<string> sites = [];
|
|
for (int i = 0; i < lines.Count; i++)
|
|
{
|
|
line = lines[i];
|
|
segmentsC = line.Split(site, StringSplitOptions.RemoveEmptyEntries);
|
|
if (segmentsC.Length > 1)
|
|
{
|
|
foreach (string segment in segmentsC)
|
|
sites.Add(segment.Trim());
|
|
}
|
|
if (line == summaryLine)
|
|
{
|
|
sites.RemoveAt(0);
|
|
found = true;
|
|
}
|
|
if (!found)
|
|
continue;
|
|
if (!foundB && line.Contains(multiple))
|
|
foundB = true;
|
|
if (line != lastUnitsB)
|
|
continue;
|
|
if (foundB)
|
|
{
|
|
foundB = false;
|
|
continue;
|
|
}
|
|
for (int j = 0; j < sites.Count; j++)
|
|
{
|
|
s = sites[j];
|
|
if (i + take > lines.Count)
|
|
break;
|
|
segments = s.Split(["(", ",", ")"], StringSplitOptions.None);
|
|
if (segments.Length < 2)
|
|
break;
|
|
segmentsB = lines[i + 10].Split(' ');
|
|
if (segmentsB.Length < 2)
|
|
break;
|
|
point = new(segments[0].Trim(),
|
|
segments[1].Trim(),
|
|
segments[2].Trim(),
|
|
NAvg: lines[i + 2].Trim(),
|
|
Nsl: lines[i + 3].Trim(),
|
|
Vd: lines[i + 4].Trim(),
|
|
FlatZ: lines[i + 5].Trim(),
|
|
RhoAvg: lines[i + 6].Trim(),
|
|
Rhosl: lines[i + 7].Trim(),
|
|
Phase: lines[i + 8].Trim(),
|
|
Grade: lines[i + 9].Trim(),
|
|
XLeft: segmentsB[0],
|
|
XRight: segmentsB[1],
|
|
BottomY: lines[i + 11].Trim(),
|
|
TopY: lines[i + 12].Trim());
|
|
results.Add(point);
|
|
i += take;
|
|
}
|
|
sites.Clear();
|
|
}
|
|
return new(results);
|
|
}
|
|
|
|
}
|
|
|
|
[JsonSourceGenerationOptions(WriteIndented = true)]
|
|
[JsonSerializable(typeof(Point))]
|
|
private partial class PointSourceGenerationContext : JsonSerializerContext
|
|
{
|
|
}
|
|
|
|
internal static void GetComplete(ILogger<Worker> logger, List<string> args)
|
|
{
|
|
string searchPattern = args[2];
|
|
string sourceDirectory = Path.GetFullPath(args[0]);
|
|
string[] files = Directory.GetFiles(sourceDirectory, searchPattern, SearchOption.TopDirectoryOnly);
|
|
if (files.Length != 1)
|
|
logger.LogError("No files found in {sourceDirectory} with search pattern {searchPattern}", sourceDirectory, searchPattern);
|
|
else
|
|
{
|
|
const int take = 12;
|
|
string[] lines = File.ReadAllLines(files[0]);
|
|
ReadOnlyCollection<string> collection = new(lines);
|
|
if (collection.Count < take)
|
|
logger.LogError("File {files[0]} has less than {take} lines", files[0], take);
|
|
else
|
|
{
|
|
const string site = "Site: ";
|
|
const string multiple = "MULTIPLE";
|
|
const string summaryLine = "SUMMARY A A";
|
|
const string lastUnits = "Flat Z: Grade : % Flat Z: Grade : %";
|
|
const string lastUnitsB = "Flat Z: Grade : % Flat Z: Grade : % Flat Z: Grade : %";
|
|
Complete? complete = Complete.Get(take, site, multiple, summaryLine, lastUnits, lastUnitsB, collection);
|
|
if (complete is null)
|
|
logger.LogError("Could not get Complete from {files[0]}", files[0]);
|
|
else
|
|
{
|
|
string json = JsonSerializer.Serialize(complete, CompleteSourceGenerationContext.Default.Complete);
|
|
File.WriteAllText($"{files[0]}.json", json);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#else
|
|
|
|
internal static void GetComplete(ILogger<Worker> logger, List<string> args)
|
|
{
|
|
string searchPattern = args[2];
|
|
string sourceDirectory = Path.GetFullPath(args[0]);
|
|
string[] files = Directory.GetFiles(sourceDirectory, searchPattern, SearchOption.TopDirectoryOnly);
|
|
if (files.Length != 1)
|
|
logger.LogError("No files found in {sourceDirectory} with search pattern {searchPattern}", sourceDirectory, searchPattern);
|
|
logger.LogError("GetComplete is not available in HgCV {args[1]}", args[1]);
|
|
}
|
|
|
|
#endif
|
|
|
|
} |