diff --git a/Adaptation/.vscode/tasks.json b/Adaptation/.vscode/tasks.json index bd1ac8e..49a1bc8 100644 --- a/Adaptation/.vscode/tasks.json +++ b/Adaptation/.vscode/tasks.json @@ -86,6 +86,18 @@ ], "problemMatcher": "$msCompile" }, + { + "label": "Project", + "type": "shell", + "command": "code ../MET08DDUPSFS6420.csproj", + "problemMatcher": [] + }, + { + "label": "Git Config", + "type": "shell", + "command": "code ../.git/config", + "problemMatcher": [] + }, { "label": "Kanbn Console", "type": "npm", diff --git a/Adaptation/FileHandlers/pcl/Complete.cs b/Adaptation/FileHandlers/pcl/Complete.cs deleted file mode 100644 index 55983fe..0000000 --- a/Adaptation/FileHandlers/pcl/Complete.cs +++ /dev/null @@ -1,57 +0,0 @@ -using Adaptation.Shared; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.IO; -using System.Linq; -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace Adaptation.FileHandlers.pcl; - -#nullable enable - -internal class Complete -{ - - public Complete(Header header, Wafer[] wafers) - { - Header = header; - Wafers = wafers; - } - - public Header Header { get; } - public Wafer[] Wafers { get; } - - internal static Complete? Get(Logistics logistics, List fileInfoCollection, ReadOnlyDictionary pages) - { - Complete? result; - Constant constant = new(); - string headerFileName = pages.ElementAt(pages.Count - 1).Key; - Header? header = Header.Get(pages, constant, headerFileName); - if (header is null) - result = null; - else - { - ReadOnlyCollection wafers = Wafer.Get(pages, constant, headerFileName); - if (wafers.Count == 0) - result = null; - else - { - result = new(header, wafers.ToArray()); - FileInfo fileInfo = new($"{logistics.ReportFullPath}.json"); - string json = JsonSerializer.Serialize(result, CompleteSourceGenerationContext.Default.Complete); - File.WriteAllText(fileInfo.FullName, json); - File.SetLastWriteTime(fileInfo.FullName, logistics.DateTimeFromSequence); - fileInfoCollection.Add(fileInfo); - } - } - return result; - } - -} - -[JsonSourceGenerationOptions(WriteIndented = true)] -[JsonSerializable(typeof(Complete))] -internal partial class CompleteSourceGenerationContext : JsonSerializerContext -{ -} \ No newline at end of file diff --git a/Adaptation/FileHandlers/pcl/FileRead.cs b/Adaptation/FileHandlers/pcl/FileRead.cs index ca1d11f..b8e6601 100644 --- a/Adaptation/FileHandlers/pcl/FileRead.cs +++ b/Adaptation/FileHandlers/pcl/FileRead.cs @@ -114,10 +114,10 @@ public class FileRead : Shared.FileRead, IFileRead else { ReadOnlyDictionary pages = Convert.PDF(_Logistics, _GhostPCLFileName, results.Item4); - Complete? complete = Complete.Get(_Logistics, results.Item4, pages); - if (complete is null) + Run? run = Run.Get(_Logistics, results.Item4, pages); + if (run is null) throw new Exception(string.Concat("A) No Data - ", dateTime.Ticks)); - IProcessData iProcessData = new ProcessData(this, _Logistics, results.Item4, pages, complete); + IProcessData iProcessData = new ProcessData(this, _Logistics, results.Item4, pages, run); if (iProcessData is not ProcessData processData) throw new Exception(string.Concat("B) No Data - ", dateTime.Ticks)); string mid; diff --git a/Adaptation/FileHandlers/pcl/Header.cs b/Adaptation/FileHandlers/pcl/Header.cs index f0ab878..15b0382 100644 --- a/Adaptation/FileHandlers/pcl/Header.cs +++ b/Adaptation/FileHandlers/pcl/Header.cs @@ -13,7 +13,7 @@ public class Header public Header(string date, string recipe, string id, - WaferSummary[] waferSummary, + ReadOnlyCollection waferSummary, string lPDCountMin, string lPDCM2Min, string areaCountMin, @@ -96,7 +96,7 @@ public class Header public string Date { get; } public string Recipe { get; } public string Id { get; } - public WaferSummary[] WaferSummary { get; } + public ReadOnlyCollection WaferSummary { get; } public string LPDCountMin { get; } public string LPDCM2Min { get; } public string AreaCountMin { get; } @@ -273,7 +273,7 @@ public class Header result = new(date: date, recipe: recipe, id: id, - waferSummary: collection.ToArray(), + waferSummary: collection.AsReadOnly(), lPDCountMin: toEol1[0].Trim(), lPDCM2Min: toEol1[1].Trim(), areaCountMin: toEol1[2].Trim(), diff --git a/Adaptation/FileHandlers/pcl/ProcessData.cs b/Adaptation/FileHandlers/pcl/ProcessData.cs index 41f9ce5..91f7157 100644 --- a/Adaptation/FileHandlers/pcl/ProcessData.cs +++ b/Adaptation/FileHandlers/pcl/ProcessData.cs @@ -73,7 +73,7 @@ public class ProcessData : IProcessData List Shared.Properties.IProcessData.Details => _Details; - internal ProcessData(IFileRead fileRead, Logistics logistics, List fileInfoCollection, ReadOnlyDictionary pages, Complete complete) + internal ProcessData(IFileRead fileRead, Logistics logistics, List fileInfoCollection, ReadOnlyDictionary pages, Run run) { _Details = new List(); _I = 0; @@ -82,7 +82,7 @@ public class ProcessData : IProcessData Date = GetDateTime(logistics); MesEntity = logistics.MesEntity; _Log = LogManager.GetLogger(typeof(ProcessData)); - Parse(fileRead, logistics, fileInfoCollection, pages, complete); + Parse(fileRead, logistics, fileInfoCollection, pages, run); } private static DateTime GetDateTime(Logistics logistics) => @@ -381,7 +381,7 @@ public class ProcessData : IProcessData return result; } - private void Set(ILogistics logistics, Complete complete) + private void Set(ILogistics logistics, Run run) { string lot; string rds; @@ -391,8 +391,8 @@ public class ProcessData : IProcessData string employee; ScanPast("Recipe ID:"); _ = GetBefore("LotID:"); - lot = complete.Header.Id; - recipe = complete.Header.Recipe; + lot = run.Header.Id; + recipe = run.Header.Recipe; Descriptor descriptor = GetDescriptor(lot); lot = descriptor.Lot; psn = descriptor.PSN; @@ -408,7 +408,7 @@ public class ProcessData : IProcessData UniqueId = string.Format("{0}_{1}_{2}", logistics.JobID, lot, Path.GetFileNameWithoutExtension(logistics.ReportFullPath)); } - private void ParseLotSummary(ILogistics logistics, ReadOnlyDictionary pages, Complete complete, string headerFileName, Dictionary> slots) + private void ParseLotSummary(ILogistics logistics, ReadOnlyDictionary pages, Run run, string headerFileName, Dictionary> slots) { _I = 0; ParseErrorText = string.Empty; @@ -418,7 +418,7 @@ public class ProcessData : IProcessData _Data = value; ScanPast("Date:"); _ = GetToEOL(); - Set(logistics, complete); + Set(logistics, run); // determine number of wafers and their slot numbers _Log.Debug(_Data.Substring(_I)); string slot; @@ -597,7 +597,7 @@ public class ProcessData : IProcessData #nullable enable - private void Parse(IFileRead fileRead, Logistics logistics, List fileInfoCollection, ReadOnlyDictionary pages, Complete complete) + private void Parse(IFileRead fileRead, Logistics logistics, List fileInfoCollection, ReadOnlyDictionary pages, Run run) { if (fileRead is null) throw new ArgumentNullException(nameof(fileRead)); @@ -607,7 +607,7 @@ public class ProcessData : IProcessData List> pageMapping = new(); _Log.Debug($"****ParseData - Parsing lot summary"); string headerFileName = pages.ElementAt(pages.Count - 1).Key; - ParseLotSummary(logistics, pages, complete, headerFileName, slots); + ParseLotSummary(logistics, pages, run, headerFileName, slots); string sourcePath = Path.GetDirectoryName(logistics.ReportFullPath) ?? throw new Exception(); string sourceFileNameWithoutExtension = Path.GetFileNameWithoutExtension(logistics.ReportFullPath); foreach (FileInfo fileInfo in fileInfoCollection) diff --git a/Adaptation/FileHandlers/pcl/Row.cs b/Adaptation/FileHandlers/pcl/Row.cs new file mode 100644 index 0000000..ff90603 --- /dev/null +++ b/Adaptation/FileHandlers/pcl/Row.cs @@ -0,0 +1,189 @@ +using System.Text.Json.Serialization; + +namespace Adaptation.FileHandlers.pcl; + +#nullable enable + +internal class Row +{ + + public Row(Run run, int i) + { + Date = run.Header.Date; + Recipe = run.Header.Recipe; + Id = run.Header.Id; + // + WaferId = run.Header.WaferSummary[i].Id; + LPDCount = run.Header.WaferSummary[i].LPDCount; + LPDCM2 = run.Header.WaferSummary[i].LPDCM2; + AreaCount = run.Header.WaferSummary[i].AreaCount; + AreaTotal = run.Header.WaferSummary[i].AreaTotal; + ScratchCount = run.Header.WaferSummary[i].ScratchCount; + ScratchTotal = run.Header.WaferSummary[i].ScratchTotal; + SumOfDefects = run.Header.WaferSummary[i].SumOfDefects; + HazeRegion = run.Header.WaferSummary[i].HazeRegion; + HazeAverage = run.Header.WaferSummary[i].HazeAverage; + Grade = run.Header.WaferSummary[i].Grade; + // + LPDCountMin = run.Header.LPDCountMin; + LPDCM2Min = run.Header.LPDCM2Min; + AreaCountMin = run.Header.AreaCountMin; + AreaTotalMin = run.Header.AreaTotalMin; + ScratchCountMin = run.Header.ScratchCountMin; + ScratchTotalMin = run.Header.ScratchTotalMin; + SumOfDefectsMin = run.Header.SumOfDefectsMin; + HazeRegionMin = run.Header.HazeRegionMin; + HazeAverageMin = run.Header.HazeAverageMin; + LPDCountMax = run.Header.LPDCountMax; + LPDCM2Max = run.Header.LPDCM2Max; + AreaCountMax = run.Header.AreaCountMax; + AreaTotalMax = run.Header.AreaTotalMax; + ScratchCountMax = run.Header.ScratchCountMax; + ScratchTotalMax = run.Header.ScratchTotalMax; + SumOfDefectsMax = run.Header.SumOfDefectsMax; + HazeRegionMax = run.Header.HazeRegionMax; + HazeAverageMax = run.Header.HazeAverageMax; + LPDCountAvg = run.Header.LPDCountAvg; + LPDCM2Avg = run.Header.LPDCM2Avg; + AreaCountAvg = run.Header.AreaCountAvg; + AreaTotalAvg = run.Header.AreaTotalAvg; + ScratchCountAvg = run.Header.ScratchCountAvg; + ScratchTotalAvg = run.Header.ScratchTotalAvg; + SumOfDefectsAvg = run.Header.SumOfDefectsAvg; + HazeRegionAvg = run.Header.HazeRegionAvg; + HazeAverageAvg = run.Header.HazeAverageAvg; + LPDCountStdDev = run.Header.LPDCountStdDev; + LPDCM2StdDev = run.Header.LPDCM2StdDev; + AreaCountStdDev = run.Header.AreaCountStdDev; + AreaTotalStdDev = run.Header.AreaTotalStdDev; + ScratchCountStdDev = run.Header.ScratchCountStdDev; + ScratchTotalStdDev = run.Header.ScratchTotalStdDev; + SumOfDefectsStdDev = run.Header.SumOfDefectsStdDev; + HazeRegionStdDev = run.Header.HazeRegionStdDev; + HazeAverageStdDev = run.Header.HazeAverageStdDev; + // + WaferDate = run.Wafers[i].Date; + Comments = run.Wafers[i].Comments; + Sort = run.Wafers[i].Sort; + WaferLPDCount = run.Wafers[i].LPDCount; + WaferLPDCM2 = run.Wafers[i].LPDCM2; + Bin1 = run.Wafers[i].Bin1; + Bin2 = run.Wafers[i].Bin2; + Bin3 = run.Wafers[i].Bin3; + Bin4 = run.Wafers[i].Bin4; + Bin5 = run.Wafers[i].Bin5; + Bin6 = run.Wafers[i].Bin6; + Bin7 = run.Wafers[i].Bin7; + Bin8 = run.Wafers[i].Bin8; + Mean = run.Wafers[i].Mean; + StdDev = run.Wafers[i].StdDev; + WaferAreaCount = run.Wafers[i].AreaCount; + WaferAreaTotal = run.Wafers[i].AreaTotal; + WaferScratchCount = run.Wafers[i].ScratchCount; + WaferScratchTotal = run.Wafers[i].ScratchTotal; + WaferSumOfDefects = run.Wafers[i].SumOfDefects; + WaferHazeRegion = run.Wafers[i].HazeRegion; + WaferHazeAverage = run.Wafers[i].HazeAverage; + HazePeak = run.Wafers[i].HazePeak; + Laser = run.Wafers[i].Laser; + Gain = run.Wafers[i].Gain; + Diameter = run.Wafers[i].Diameter; + Thresh = run.Wafers[i].Thresh; + Exclusion = run.Wafers[i].Exclusion; + HazeRng = run.Wafers[i].HazeRng; + Thruput = run.Wafers[i].Thruput; + WaferRecipe = run.Wafers[i].Recipe; + } + + public string Date { get; } + public string Recipe { get; } + public string Id { get; } + // + public string WaferId { get; } + public string LPDCount { get; } + public string LPDCM2 { get; } + public string AreaCount { get; } + public string AreaTotal { get; } + public string ScratchCount { get; } + public string ScratchTotal { get; } + public string SumOfDefects { get; } + public string HazeRegion { get; } + public string HazeAverage { get; } + public string Grade { get; } + // + public string LPDCountMin { get; } + public string LPDCM2Min { get; } + public string AreaCountMin { get; } + public string AreaTotalMin { get; } + public string ScratchCountMin { get; } + public string ScratchTotalMin { get; } + public string SumOfDefectsMin { get; } + public string HazeRegionMin { get; } + public string HazeAverageMin { get; } + public string LPDCountMax { get; } + public string LPDCM2Max { get; } + public string AreaCountMax { get; } + public string AreaTotalMax { get; } + public string ScratchCountMax { get; } + public string ScratchTotalMax { get; } + public string SumOfDefectsMax { get; } + public string HazeRegionMax { get; } + public string HazeAverageMax { get; } + public string LPDCountAvg { get; } + public string LPDCM2Avg { get; } + public string AreaCountAvg { get; } + public string AreaTotalAvg { get; } + public string ScratchCountAvg { get; } + public string ScratchTotalAvg { get; } + public string SumOfDefectsAvg { get; } + public string HazeRegionAvg { get; } + public string HazeAverageAvg { get; } + public string LPDCountStdDev { get; } + public string LPDCM2StdDev { get; } + public string AreaCountStdDev { get; } + public string AreaTotalStdDev { get; } + public string ScratchCountStdDev { get; } + public string ScratchTotalStdDev { get; } + public string SumOfDefectsStdDev { get; } + public string HazeRegionStdDev { get; } + public string HazeAverageStdDev { get; } + // + public string WaferDate { get; } + public string Comments { get; } + public string Sort { get; } + public string WaferLPDCount { get; } + public string WaferLPDCM2 { get; } + public string Bin1 { get; } + public string Bin2 { get; } + public string Bin3 { get; } + public string Bin4 { get; } + public string Bin5 { get; } + public string Bin6 { get; } + public string Bin7 { get; } + public string Bin8 { get; } + public string Mean { get; } + public string StdDev { get; } + public string WaferAreaCount { get; } + public string WaferAreaTotal { get; } + public string WaferScratchCount { get; } + public string WaferScratchTotal { get; } + public string WaferSumOfDefects { get; } + public string WaferHazeRegion { get; } + public string WaferHazeAverage { get; } + public string HazePeak { get; } + public string Laser { get; } + public string Gain { get; } + public string Diameter { get; } + public string Thresh { get; } + public string Exclusion { get; } + public string HazeRng { get; } + public string Thruput { get; } + public string WaferRecipe { get; } + +} + +[JsonSourceGenerationOptions(WriteIndented = true)] +[JsonSerializable(typeof(Row))] +internal partial class RowSourceGenerationContext : JsonSerializerContext +{ +} \ No newline at end of file diff --git a/Adaptation/FileHandlers/pcl/Run.cs b/Adaptation/FileHandlers/pcl/Run.cs new file mode 100644 index 0000000..0038ed9 --- /dev/null +++ b/Adaptation/FileHandlers/pcl/Run.cs @@ -0,0 +1,147 @@ +using Adaptation.Shared; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Adaptation.FileHandlers.pcl; + +#nullable enable + +internal class Run +{ + + public Run(Header header, ReadOnlyCollection wafers) + { + Header = header; + Wafers = wafers; + } + + public Header Header { get; } + public ReadOnlyCollection Wafers { get; } + + private static void WriteJson(Logistics logistics, List fileInfoCollection, Run result) + { + FileInfo fileInfo = new($"{logistics.ReportFullPath}.json"); + string json = JsonSerializer.Serialize(result, RunSourceGenerationContext.Default.Run); + File.WriteAllText(fileInfo.FullName, json); + File.SetLastWriteTime(fileInfo.FullName, logistics.DateTimeFromSequence); + fileInfoCollection.Add(fileInfo); + } + + private static ReadOnlyCollection GetLines(JsonElement[]? jsonElements) + { + List results = new(); + int columns = 0; + StringBuilder stringBuilder = new(); + for (int i = 0; i < jsonElements?.Length;) + { + foreach (JsonProperty jsonProperty in jsonElements[0].EnumerateObject()) + { + columns += 1; + _ = stringBuilder.Append('"').Append(jsonProperty.Name).Append('"').Append('\t'); + } + break; + } + if (jsonElements?.Length != 0) + _ = stringBuilder.Remove(stringBuilder.Length - 1, 1); + results.Add(stringBuilder.ToString()); + for (int i = 0; i < jsonElements?.Length; i++) + { + _ = stringBuilder.Clear(); + foreach (JsonProperty jsonProperty in jsonElements[i].EnumerateObject()) + { + if (jsonProperty.Value.ValueKind == JsonValueKind.Object) + _ = stringBuilder.Append('\t'); + else if (jsonProperty.Value.ValueKind != JsonValueKind.String) + _ = stringBuilder.Append(jsonProperty.Value).Append('\t'); + else + _ = stringBuilder.Append('"').Append(jsonProperty.Value).Append('"').Append('\t'); + } + _ = stringBuilder.Remove(stringBuilder.Length - 1, 1); + results.Add(stringBuilder.ToString()); + } + return results.AsReadOnly(); + } + + private static ReadOnlyCollection GetLines(JsonElement jsonElement) => + GetLines(new JsonElement[] { jsonElement }); + + private static void WriteTabSeparatedValues(Logistics logistics, List fileInfoCollection, Run run) + { + List results = new(); + Row row; + FileInfo fileInfo = new($"{logistics.ReportFullPath}.tsv"); + for (int i = 0; i < run.Wafers.Count; i++) + { + row = new(run, i); + results.Add(row); + } + string json = JsonSerializer.Serialize(results); + JsonElement[]? jsonElements = JsonSerializer.Deserialize(json); + ReadOnlyCollection lines = GetLines(jsonElements); + File.WriteAllText(fileInfo.FullName, string.Join(Environment.NewLine, lines)); + File.SetLastWriteTime(fileInfo.FullName, logistics.DateTimeFromSequence); + fileInfoCollection.Add(fileInfo); + } + + private static void WriteException(Logistics logistics, Exception ex) + { + FileInfo fileInfo = new($"{logistics.ReportFullPath}.{nameof(Exception)}.txt"); + File.WriteAllText(fileInfo.FullName, $"{ex.Message}{Environment.NewLine}{ex.StackTrace}"); + } + + internal static Run? Get(Logistics logistics, List fileInfoCollection, ReadOnlyDictionary pages) + { + Run? result; + Constant constant = new(); + string headerFileName = pages.ElementAt(pages.Count - 1).Key; + Header? header = Header.Get(pages, constant, headerFileName); + if (header is null) + result = null; + else + { + ReadOnlyCollection wafers = Wafer.Get(pages, constant, headerFileName); + if (wafers.Count == 0) + result = null; + else + { + result = new(header, wafers); + WriteJson(logistics, fileInfoCollection, result); + for (int i = 0; i < wafers.Count; i++) + { + if (wafers[i].Id != header.WaferSummary[i].Id) + { + header = null; + break; + } + } + if (header is null || wafers.Count != header.WaferSummary.Count) + result = null; + else + { + try + { + WriteTabSeparatedValues(logistics, fileInfoCollection, result); + } + catch (Exception ex) + { + WriteException(logistics, ex); + } + } + } + } + return result; + } + +} + +[JsonSourceGenerationOptions(WriteIndented = true)] +[JsonSerializable(typeof(Run))] +internal partial class RunSourceGenerationContext : JsonSerializerContext +{ +} \ No newline at end of file diff --git a/Adaptation/MET08DDUPSFS6420.Tests.csproj b/Adaptation/MET08DDUPSFS6420.Tests.csproj index e613f7f..69757fe 100644 --- a/Adaptation/MET08DDUPSFS6420.Tests.csproj +++ b/Adaptation/MET08DDUPSFS6420.Tests.csproj @@ -35,7 +35,7 @@ - + NU1701 NU1701 @@ -44,41 +44,39 @@ NU1701 NU1701 NU1701 - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + NU1701 - - - + + + - - - - - - - + + NU1701 - NU1701 - NU1701 - NU1701 + + + + + diff --git a/MET08DDUPSFS6420.csproj b/MET08DDUPSFS6420.csproj index baf83e4..57591fb 100644 --- a/MET08DDUPSFS6420.csproj +++ b/MET08DDUPSFS6420.csproj @@ -109,7 +109,9 @@ - + + + @@ -117,10 +119,7 @@ - - - - + @@ -129,6 +128,8 @@ + +