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 Points) { internal static Complete? Get(int take, string site, string multiple, string summaryLine, string lastUnits, string lastUnitsB, ReadOnlyCollection 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 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 GetJsonProperties() { JsonProperty[] results; string json; Header header = Get(); json = JsonSerializer.Serialize(header); JsonElement jsonElement = JsonSerializer.Deserialize(json); results = jsonElement.EnumerateObject().ToArray(); return new(results); } internal static Header? Get(ReadOnlyCollection lines, string site, string summaryLine) { Header? result; string json; string check; string[] segments; string[] segmentsB; string[] segmentsC; bool found = false; string[] remove = GetRemove(); Dictionary keyValuePairs = []; ReadOnlyCollection 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 GetJsonProperties() { JsonProperty[] results; string json; SummarySegment summarySegment = Get(); json = JsonSerializer.Serialize(summarySegment); JsonElement jsonElement = JsonSerializer.Deserialize(json); results = jsonElement.EnumerateObject().ToArray(); return new(results); } internal static Summary? Get(ReadOnlyCollection lines, string site, string summaryLine, string lastUnits) { Summary? result; string json; string[] segments; bool found = false; string[] segmentsB; Dictionary keyValuePairs = []; Dictionary keyValuePairsB = []; Dictionary keyValuePairsC = []; ReadOnlyCollection 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 GetCollection(ReadOnlyCollection lines, int take, string site, string multiple, string summaryLine, string lastUnitsB) { List results = []; string s; string line; Point point; string[] segments; string[] segmentsB; bool found = false; bool foundB = false; string[] segmentsC; List 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 logger, List 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 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 logger, List 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 }