From 954cdf7a26adbded87afc5e4c2fa4dbf3955c47d Mon Sep 17 00:00:00 2001 From: Mike Phares Date: Wed, 16 Apr 2025 06:32:13 -0700 Subject: [PATCH] UniqueId replacement for attachments Write input PDSF in output after EOF GetPropertyValue for MoveMatchingFiles MoveMatchingFile --- .../MoveMatchingFiles/FileRead.cs | 21 ++++++++++------ .../OpenInsightMetrologyViewer/WSRequest.cs | 20 ++++++++++----- Adaptation/FileHandlers/Processed/FileRead.cs | 25 +++++++++++++++++++ Adaptation/Shared/FileRead.cs | 2 +- .../Shared/ProcessDataStandardFormat.cs | 16 +++++++++--- 5 files changed, 66 insertions(+), 18 deletions(-) diff --git a/Adaptation/FileHandlers/MoveMatchingFiles/FileRead.cs b/Adaptation/FileHandlers/MoveMatchingFiles/FileRead.cs index bf09839..e64ee10 100644 --- a/Adaptation/FileHandlers/MoveMatchingFiles/FileRead.cs +++ b/Adaptation/FileHandlers/MoveMatchingFiles/FileRead.cs @@ -81,7 +81,12 @@ public class FileRead : Shared.FileRead, IFileRead throw new Exception(cellInstanceConnectionName); if (!_IsDuplicator) throw new Exception(cellInstanceConnectionName); - _ProcessDataStandardFormatMapping = GetProcessDataStandardFormatMapping(); + string processDataStandardFormatMappingOldColumnNames = GetPropertyValue(cellInstanceConnectionName, modelObjectParameters, "Process.Data.Standard.Format.Mapping.Old.Column.Names"); + string processDataStandardFormatMappingNewColumnNames = GetPropertyValue(cellInstanceConnectionName, modelObjectParameters, "Process.Data.Standard.Format.Mapping.New.Column.Names"); + string processDataStandardFormatMappingColumnIndices = GetPropertyValue(cellInstanceConnectionName, modelObjectParameters, "Process.Data.Standard.Format.Mapping.Column.Indices"); + _ProcessDataStandardFormatMapping = GetProcessDataStandardFormatMapping(processDataStandardFormatMappingOldColumnNames, + processDataStandardFormatMappingNewColumnNames, + processDataStandardFormatMappingColumnIndices); } void IFileRead.Move(Tuple> extractResults, Exception exception) @@ -160,7 +165,7 @@ public class FileRead : Shared.FileRead, IFileRead return results; } - private static ProcessDataStandardFormatMapping GetProcessDataStandardFormatMapping() + private static ProcessDataStandardFormatMapping GetProcessDataStandardFormatMapping(string processDataStandardFormatMappingOldColumnNames, string processDataStandardFormatMappingNewColumnNames, string processDataStandardFormatMappingColumnIndices) { ProcessDataStandardFormatMapping result; string[] segmentsB; @@ -170,16 +175,16 @@ public class FileRead : Shared.FileRead, IFileRead string args5 = ""; string args6 = ""; string args7 = "Test|EventId,Lot|Id,Slot|WaferId,AreaTotal|WaferAreaTotal,HazeAverage|WaferHazeAverage,HazeRegion|WaferHazeRegion,ScratchTotal|WaferScratchTotal"; - string args8 = "Time,A_LOGISTICS,B_LOGISTICS,Test,Count,Index,MesEntity,Date,Employee,Lot,PSN,Reactor,Recipe,Comments,Diameter,Exclusion,Gain,HeaderUniqueId,Laser,ParseErrorText,RDS,Slot,UniqueId,AreaCount,AreaCountAvg,AreaCountMax,AreaCountMin,AreaCountStdDev,AreaTotal,AreaTotalAvg,AreaTotalMax,AreaTotalMin,AreaTotalStdDev,Bin1,Bin2,Bin3,Bin4,Bin5,Bin6,Bin7,Bin8,HazeAverage,HazeAverageAvg,HazeAverageMax,HazeAverageMin,HazeAverageStdDev,HazePeak,HazeRegion,HazeRegionAvg,HazeRegionMax,HazeRegionMin,HazeRegionStdDev,HazeRng,LPDCM2,LPDCM2Avg,LPDCM2Max,LPDCM2Min,LPDCM2StdDev,LPDCount,LPDCountAvg,LPDCountMax,LPDCountMin,LPDCountStdDev,Mean,ScratchCount,ScratchCountAvg,ScratchCountMax,ScratchCountMin,ScratchCountStdDev,ScratchTotal,ScratchTotalAvg,ScratchTotalMax,ScratchTotalMin,ScratchTotalStdDev,Sort,StdDev,SumOfDefects,SumOfDefectsAvg,SumOfDefectsMax,SumOfDefectsMin,SumOfDefectsStdDev,Thresh,Thruput"; - string args9 = "Time,A_LOGISTICS,B_LOGISTICS,Count,Sequence,MesEntity,Index,Date,Recipe,Id,WaferId,LPDCount,LPDCM2,AreaCount,AreaTotal,ScratchCount,ScratchTotal,SumOfDefects,HazeRegion,HazeAverage,Grade,LPDCountMin,LPDCM2Min,AreaCountMin,AreaTotalMin,ScratchCountMin,ScratchTotalMin,SumOfDefectsMin,HazeRegionMin,HazeAverageMin,LPDCountMax,LPDCM2Max,AreaCountMax,AreaTotalMax,ScratchCountMax,ScratchTotalMax,SumOfDefectsMax,HazeRegionMax,HazeAverageMax,LPDCountAvg,LPDCM2Avg,AreaCountAvg,AreaTotalAvg,ScratchCountAvg,ScratchTotalAvg,SumOfDefectsAvg,HazeRegionAvg,HazeAverageAvg,LPDCountStdDev,LPDCM2StdDev,AreaCountStdDev,AreaTotalStdDev,ScratchCountStdDev,ScratchTotalStdDev,SumOfDefectsStdDev,HazeRegionStdDev,HazeAverageStdDev,WaferDate,Comments,Sort,WaferLPDCount,WaferLPDCM2,Bin1,Bin2,Bin3,Bin4,Bin5,Bin6,Bin7,Bin8,Mean,StdDev,WaferAreaCount,WaferAreaTotal,WaferScratchCount,WaferScratchTotal,WaferSumOfDefects,WaferHazeRegion,WaferHazeAverage,HazePeak,Laser,Gain,Diameter,Thresh,Exclusion,HazeRng,Thruput,WaferRecipe,RDS,PSN,Reactor,Layer,Zone,Employee,InferredLot,EventId"; - string args10 = "0,1,2,95,3,6,5,7,93,9,89,90,8,58,82,84,81,-1,80,-1,88,10,-1,13,41,32,23,50,73,42,33,24,51,62,63,64,65,66,67,68,69,78,47,38,29,56,79,77,46,37,28,55,85,12,40,31,22,49,11,39,30,21,48,70,15,43,34,25,52,75,44,35,26,53,59,71,17,45,36,27,54,83,86"; + // string args8 = "Time,A_LOGISTICS,B_LOGISTICS,Test,Count,Index,MesEntity,Date,Employee,Lot,PSN,Reactor,Recipe,Comments,Diameter,Exclusion,Gain,HeaderUniqueId,Laser,ParseErrorText,RDS,Slot,UniqueId,AreaCount,AreaCountAvg,AreaCountMax,AreaCountMin,AreaCountStdDev,AreaTotal,AreaTotalAvg,AreaTotalMax,AreaTotalMin,AreaTotalStdDev,Bin1,Bin2,Bin3,Bin4,Bin5,Bin6,Bin7,Bin8,HazeAverage,HazeAverageAvg,HazeAverageMax,HazeAverageMin,HazeAverageStdDev,HazePeak,HazeRegion,HazeRegionAvg,HazeRegionMax,HazeRegionMin,HazeRegionStdDev,HazeRng,LPDCM2,LPDCM2Avg,LPDCM2Max,LPDCM2Min,LPDCM2StdDev,LPDCount,LPDCountAvg,LPDCountMax,LPDCountMin,LPDCountStdDev,Mean,ScratchCount,ScratchCountAvg,ScratchCountMax,ScratchCountMin,ScratchCountStdDev,ScratchTotal,ScratchTotalAvg,ScratchTotalMax,ScratchTotalMin,ScratchTotalStdDev,Sort,StdDev,SumOfDefects,SumOfDefectsAvg,SumOfDefectsMax,SumOfDefectsMin,SumOfDefectsStdDev,Thresh,Thruput"; + // string args9 = "Time,A_LOGISTICS,B_LOGISTICS,Count,Sequence,MesEntity,Index,Date,Recipe,Id,WaferId,LPDCount,LPDCM2,AreaCount,AreaTotal,ScratchCount,ScratchTotal,SumOfDefects,HazeRegion,HazeAverage,Grade,LPDCountMin,LPDCM2Min,AreaCountMin,AreaTotalMin,ScratchCountMin,ScratchTotalMin,SumOfDefectsMin,HazeRegionMin,HazeAverageMin,LPDCountMax,LPDCM2Max,AreaCountMax,AreaTotalMax,ScratchCountMax,ScratchTotalMax,SumOfDefectsMax,HazeRegionMax,HazeAverageMax,LPDCountAvg,LPDCM2Avg,AreaCountAvg,AreaTotalAvg,ScratchCountAvg,ScratchTotalAvg,SumOfDefectsAvg,HazeRegionAvg,HazeAverageAvg,LPDCountStdDev,LPDCM2StdDev,AreaCountStdDev,AreaTotalStdDev,ScratchCountStdDev,ScratchTotalStdDev,SumOfDefectsStdDev,HazeRegionStdDev,HazeAverageStdDev,WaferDate,Comments,Sort,WaferLPDCount,WaferLPDCM2,Bin1,Bin2,Bin3,Bin4,Bin5,Bin6,Bin7,Bin8,Mean,StdDev,WaferAreaCount,WaferAreaTotal,WaferScratchCount,WaferScratchTotal,WaferSumOfDefects,WaferHazeRegion,WaferHazeAverage,HazePeak,Laser,Gain,Diameter,Thresh,Exclusion,HazeRng,Thruput,WaferRecipe,RDS,PSN,Reactor,Layer,Zone,Employee,InferredLot,EventId"; + // string args10 = "0,1,2,95,3,6,5,7,93,9,89,90,8,58,82,84,81,-1,80,-1,88,10,-1,13,41,32,23,50,73,42,33,24,51,62,63,64,65,66,67,68,69,78,47,38,29,56,79,77,46,37,28,55,85,12,40,31,22,49,11,39,30,21,48,70,15,43,34,25,52,75,44,35,26,53,59,71,17,45,36,27,54,83,86"; string[] segments = args7.Split(','); ReadOnlyCollection ignoreColumns = new(args4.Split(',')); - ReadOnlyCollection newColumnNames = new(args9.Split(',')); - ReadOnlyCollection oldColumnNames = new(args8.Split(',')); ReadOnlyCollection backfillColumns = new(args5.Split(',')); ReadOnlyCollection indexOnlyColumns = new(args6.Split(',')); - ReadOnlyCollection columnIndices = new(args10.Split(',').Select(int.Parse).ToArray()); + ReadOnlyCollection newColumnNames = new(processDataStandardFormatMappingNewColumnNames.Split(',')); + ReadOnlyCollection oldColumnNames = new(processDataStandardFormatMappingOldColumnNames.Split(',')); + ReadOnlyCollection columnIndices = new(processDataStandardFormatMappingColumnIndices.Split(',').Select(int.Parse).ToArray()); foreach (string segment in segments) { segmentsB = segment.Split('|'); diff --git a/Adaptation/FileHandlers/OpenInsightMetrologyViewer/WSRequest.cs b/Adaptation/FileHandlers/OpenInsightMetrologyViewer/WSRequest.cs index d63378b..9e9aa1a 100644 --- a/Adaptation/FileHandlers/OpenInsightMetrologyViewer/WSRequest.cs +++ b/Adaptation/FileHandlers/OpenInsightMetrologyViewer/WSRequest.cs @@ -199,6 +199,12 @@ public class WSRequest if (string.IsNullOrEmpty(Details[i].Bin8)) Details[i].Bin8 = null; } + UniqueId = $"{logistics.JobID}_{logistics.MID}_{logistics.DateTimeFromSequence:yyyyMMddHHmmssffff}"; + for (int i = 0; i < Details.Count; i++) + { + Details[i].HeaderUniqueId = UniqueId; + Details[i].UniqueId = $"{logistics.JobID}_{logistics.MID}_{logistics.DateTimeFromSequence:yyyyMMddHHmmssffff}_Item-{i + 1}"; + } } private static void UpdateDataPDF(List descriptions, string checkFileName) @@ -306,6 +312,7 @@ public class WSRequest #pragma warning restore IDE0060 { string checkFileName; + pcl.Description description; string[] pclFiles = Directory.GetFiles(matchDirectory, "*.pcl", SearchOption.TopDirectoryOnly); if (pclFiles.Length != 1) throw new Exception($"Invalid source file count for <{headerId}>!"); @@ -318,18 +325,19 @@ public class WSRequest else { UpdateDataPDF(descriptions, checkFileName); - headerAttachments.Add(new WS.Attachment(subGroupId, headerId, headerIdDirectory, descriptions[0].HeaderUniqueId, "Data.pdf", checkFileName)); + headerAttachments.Add(new WS.Attachment(subGroupId, headerId, headerIdDirectory, $"{logistics.JobID}_{logistics.MID}_{logistics.DateTimeFromSequence:yyyyMMddHHmmssffff}", "Data.pdf", checkFileName)); } - foreach (pcl.Description description in descriptions) + for (int i = 0; i < descriptions.Count; i++) { - checkFileName = Path.Combine(matchDirectory, $"{sourceFileNameNoExt}_{description.Slot.Replace('*', 's')}_image.pdf"); + description = descriptions[i]; + checkFileName = Path.Combine(matchDirectory, $"{sourceFileNameNoExt}_s{description.Slot}_image.pdf"); if (File.Exists(checkFileName)) - dataAttachments.Add(new WS.Attachment(subGroupId, headerId, headerIdDirectory, description.UniqueId, "Image.pdf", checkFileName)); + dataAttachments.Add(new WS.Attachment(subGroupId, headerId, headerIdDirectory, $"{logistics.JobID}_{logistics.MID}_{logistics.DateTimeFromSequence:yyyyMMddHHmmssffff}_Item-{i + 1}", "Image.pdf", checkFileName)); else { - checkFileName = Path.Combine(matchDirectory, $"{sourceFileNameNoExt}_{description.Slot.Replace('*', 's')}_data.pdf"); + checkFileName = Path.Combine(matchDirectory, $"{sourceFileNameNoExt}_s{description.Slot}_data.pdf"); if (File.Exists(checkFileName)) - dataAttachments.Add(new WS.Attachment(subGroupId, headerId, headerIdDirectory, description.UniqueId, "Image.pdf", checkFileName)); + dataAttachments.Add(new WS.Attachment(subGroupId, headerId, headerIdDirectory, $"{logistics.JobID}_{logistics.MID}_{logistics.DateTimeFromSequence:yyyyMMddHHmmssffff}_Item-{i + 1}", "Image.pdf", checkFileName)); } } if (dataAttachments.Count == 0 || dataAttachments.Count != descriptions.Count) diff --git a/Adaptation/FileHandlers/Processed/FileRead.cs b/Adaptation/FileHandlers/Processed/FileRead.cs index 576c8fa..9d09b8b 100644 --- a/Adaptation/FileHandlers/Processed/FileRead.cs +++ b/Adaptation/FileHandlers/Processed/FileRead.cs @@ -129,6 +129,7 @@ public class FileRead : Shared.FileRead, IFileRead string destinationJobIdDirectory = Path.Combine(_JobIdProcessParentDirectory, _Logistics.JobID, directoryName); string sequenceDirectory = Path.Combine(destinationJobIdDirectory, logisticsSequence); string jsonFileName = Path.Combine(sequenceDirectory, $"{Path.GetFileNameWithoutExtension(reportFullPath)}.json"); + MoveMatchingFile(jobIdDirectory, matchDirectories[0]); Directory.Move(matchDirectories[0], destinationJobIdDirectory); if (!Directory.Exists(sequenceDirectory)) _ = Directory.CreateDirectory(sequenceDirectory); @@ -136,6 +137,30 @@ public class FileRead : Shared.FileRead, IFileRead File.WriteAllText(jsonFileName, json); } + private static void MoveMatchingFile(string jobIdDirectory, string matchDirectory) + { + string checkFile; + string jobIdDirectoryFileName; + string matchDirectoryFileName; + string[] jobIdDirectoryFiles = Directory.GetFiles(jobIdDirectory, "*", SearchOption.TopDirectoryOnly); + string[] matchDirectoryFiles = Directory.GetFiles(matchDirectory, "*", SearchOption.TopDirectoryOnly); + foreach (string jobIdDirectoryFile in jobIdDirectoryFiles) + { + jobIdDirectoryFileName = Path.GetFileName(jobIdDirectoryFile); + foreach (string matchDirectoryFile in matchDirectoryFiles) + { + matchDirectoryFileName = Path.GetFileName(matchDirectoryFile); + if (jobIdDirectoryFileName.StartsWith(matchDirectoryFileName)) + { + checkFile = Path.Combine(matchDirectory, jobIdDirectoryFileName); + if (File.Exists(checkFile)) + continue; + File.Move(jobIdDirectoryFile, checkFile); + } + } + } + } + private Tuple> GetExtractResult(string reportFullPath, DateTime dateTime) { Tuple> results; diff --git a/Adaptation/Shared/FileRead.cs b/Adaptation/Shared/FileRead.cs index 7c2fe14..2bf54ea 100644 --- a/Adaptation/Shared/FileRead.cs +++ b/Adaptation/Shared/FileRead.cs @@ -383,7 +383,7 @@ public class FileRead : Properties.IFileRead else { string logisticsSequence = _Logistics.Sequence.ToString(); - results = Directory.GetDirectories(jobIdDirectory, string.Concat(_Logistics.MID, '*', logisticsSequence, '*'), SearchOption.TopDirectoryOnly); + results = Directory.GetDirectories(jobIdDirectory, $"*{logisticsSequence}*", SearchOption.TopDirectoryOnly); } if ((results is null) || results.Length != 1) throw new Exception("Didn't find directory by logistics sequence"); diff --git a/Adaptation/Shared/ProcessDataStandardFormat.cs b/Adaptation/Shared/ProcessDataStandardFormat.cs index 1c5a4c7..059d613 100644 --- a/Adaptation/Shared/ProcessDataStandardFormat.cs +++ b/Adaptation/Shared/ProcessDataStandardFormat.cs @@ -28,14 +28,17 @@ internal class ProcessDataStandardFormat internal ReadOnlyCollection Body { get; private set; } internal ReadOnlyCollection Columns { get; private set; } internal ReadOnlyCollection Logistics { get; private set; } + internal ReadOnlyCollection InputLines { get; private set; } internal ProcessDataStandardFormat(ReadOnlyCollection body, ReadOnlyCollection columns, + ReadOnlyCollection inputLines, ReadOnlyCollection logistics, long? sequence) { Body = body; Columns = columns; + InputLines = inputLines; Logistics = logistics; Sequence = sequence; } @@ -53,7 +56,7 @@ internal class ProcessDataStandardFormat GetString(SearchFor.Archive, addSpaces, separator); internal static ProcessDataStandardFormat GetEmpty() => - new(new(Array.Empty()), new(Array.Empty()), new(Array.Empty()), null); + new(new(Array.Empty()), new(Array.Empty()), new(Array.Empty()), new(Array.Empty()), null); internal static List PDSFToFixedWidth(string reportFullPath) { @@ -169,15 +172,18 @@ internal class ProcessDataStandardFormat { for (int i = r; i < lines.Length; i++) { - if (lines[i].StartsWith("END_HEADER")) + if (!lines[i].StartsWith("LOGISTICS_") || lines[i].StartsWith("END_HEADER")) break; logistics.Add(lines[i]); } break; } } + if (lines.Length > 0 && body.Count == 0 && columns.Count == 0 && logistics.Count == 0) + logistics.Add(lines[1]); result = new(body: body.AsReadOnly(), columns: columns.AsReadOnly(), + inputLines: lines.ToList().AsReadOnly(), logistics: logistics.AsReadOnly(), sequence: null); return result; @@ -232,7 +238,7 @@ internal class ProcessDataStandardFormat { for (int i = r; i < lines.Length; i++) { - if (lines[i].StartsWith("END_HEADER")) + if (!lines[i].StartsWith("LOGISTICS_") || lines[i].StartsWith("END_HEADER")) break; logistics.Add(lines[i]); } @@ -248,6 +254,7 @@ internal class ProcessDataStandardFormat } result = new(body: body.AsReadOnly(), columns: new(columns), + inputLines: lines.ToList().AsReadOnly(), logistics: logistics.AsReadOnly(), sequence: sequence); return result; @@ -339,6 +346,7 @@ internal class ProcessDataStandardFormat } result = new(body: new(results), columns: processDataStandardFormatMapping.OldColumnNames, + inputLines: processDataStandardFormat.InputLines, logistics: processDataStandardFormat.Logistics, sequence: processDataStandardFormat.Sequence); return result; @@ -370,6 +378,8 @@ internal class ProcessDataStandardFormat results.Add("LOGISTICS_COLUMN\tA_LOGISTICS"); results.Add("LOGISTICS_COLUMN\tB_LOGISTICS"); results.AddRange(processDataStandardFormat.Logistics); + results.Add("EOF"); + results.AddRange(processDataStandardFormat.InputLines.Select(l => l.Replace('\t', '|'))); File.WriteAllText(path, string.Join(Environment.NewLine, results)); }