Compare commits

...

4 Commits

Author SHA1 Message Date
0ed6d17774 process-data-standard-format with HeaderId and SubgroupId 2025-04-28 17:15:42 -07:00
46844029b1 Now will default to typed when OI is null for the Reactor 2025-04-22 08:52:34 -07:00
e81ae34f8f process-data-standard-format with pipes 2025-04-21 13:19:06 -07:00
5a3469baa1 UniqueId replacement for attachments
Write input PDSF in output after EOF

GetPropertyValue for MoveMatchingFiles

MoveMatchingFile

ProcessDataStandardFormat over Tuple

MoveMatchingFiles to use ProcessDataStandardFormatMapping

MID Logic
2025-04-14 10:00:36 -07:00
32 changed files with 2211 additions and 1559 deletions

View File

@ -92,6 +92,26 @@
"command": "code ../MET08DDUPSP1TBI.csproj",
"problemMatcher": []
},
{
"label": "Readme",
"type": "shell",
"command": "code ../README.md",
"problemMatcher": []
},
{
"label": "File-Folder-Helper AOT s X Day-Helper-2025-03-20",
"type": "shell",
"command": "L:/DevOps/Mesa_FI/File-Folder-Helper/bin/Release/net8.0/win-x64/publish/File-Folder-Helper.exe",
"args": [
"s",
"X",
"L:/DevOps/EAF-Mesa-Integration/met08ddupsp1tbi",
"Day-Helper-2025-03-20",
"false",
"4"
],
"problemMatcher": []
},
{
"label": "Git Config",
"type": "shell",

View File

@ -14,7 +14,7 @@ namespace Adaptation.FileHandlers.APC;
public class FileRead : Shared.FileRead, IFileRead
{
public FileRead(ISMTP smtp, Dictionary<string, string> fileParameter, string cellInstanceName, int? connectionCount, string cellInstanceConnectionName, FileConnectorConfiguration fileConnectorConfiguration, string equipmentTypeName, string parameterizedModelObjectDefinitionType, IList<ModelObjectParameterDefinition> modelObjectParameters, string equipmentDictionaryName, Dictionary<string, List<long>> dummyRuns, Dictionary<long, List<string>> staticRuns, bool useCyclicalForDescription, bool isEAFHosted) :
public FileRead(ISMTP smtp, Dictionary<string, string> fileParameter, string cellInstanceName, int? connectionCount, string cellInstanceConnectionName, FileConnectorConfiguration fileConnectorConfiguration, string equipmentTypeName, string parameterizedModelObjectDefinitionType, IList<ModelObjectParameterDefinition> modelObjectParameters, string equipmentDictionaryName, Dictionary<string, List<long>> dummyRuns, Dictionary<long, List<Shared.Metrology.WS.Results>> staticRuns, bool useCyclicalForDescription, bool isEAFHosted) :
base(new Description(), false, smtp, fileParameter, cellInstanceName, connectionCount, cellInstanceConnectionName, fileConnectorConfiguration, equipmentTypeName, parameterizedModelObjectDefinitionType, modelObjectParameters, equipmentDictionaryName, dummyRuns, staticRuns, useCyclicalForDescription, isEAFHosted: connectionCount is null)
{
_MinFileLength = 10;
@ -120,15 +120,15 @@ public class FileRead : Shared.FileRead, IFileRead
private Tuple<string, Test[], JsonElement[], List<FileInfo>> GetExtractResult(string reportFullPath, DateTime dateTime)
{
Tuple<string, Test[], JsonElement[], List<FileInfo>> results;
Tuple<string, string[], string[]> pdsf = ProcessDataStandardFormat.GetLogisticsColumnsAndBody(reportFullPath);
_Logistics = new Logistics(reportFullPath, pdsf.Item1);
ProcessDataStandardFormat processDataStandardFormat = ProcessDataStandardFormat.GetProcessDataStandardFormat(reportFullPath);
_Logistics = new Logistics(reportFullPath, processDataStandardFormat);
SetFileParameterLotIDToLogisticsMID();
JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(pdsf);
JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(processDataStandardFormat);
List<Shared.Properties.IDescription> descriptions = GetDuplicatorDescriptions(jsonElements);
Test[] tests = (from l in descriptions select (Test)l.Test).ToArray();
if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0)
FileCopy(reportFullPath, dateTime, descriptions);
results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(pdsf.Item1, tests, jsonElements, new List<FileInfo>());
results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(string.Join(Environment.NewLine, processDataStandardFormat.Logistics[0]), tests, jsonElements, new List<FileInfo>());
return results;
}

View File

@ -18,7 +18,7 @@ public class FileRead : Shared.FileRead, IFileRead
private readonly string _JobIdParentDirectory;
private readonly string _JobIdArchiveParentDirectory;
public FileRead(ISMTP smtp, Dictionary<string, string> fileParameter, string cellInstanceName, int? connectionCount, string cellInstanceConnectionName, FileConnectorConfiguration fileConnectorConfiguration, string equipmentTypeName, string parameterizedModelObjectDefinitionType, IList<ModelObjectParameterDefinition> modelObjectParameters, string equipmentDictionaryName, Dictionary<string, List<long>> dummyRuns, Dictionary<long, List<string>> staticRuns, bool useCyclicalForDescription, bool isEAFHosted) :
public FileRead(ISMTP smtp, Dictionary<string, string> fileParameter, string cellInstanceName, int? connectionCount, string cellInstanceConnectionName, FileConnectorConfiguration fileConnectorConfiguration, string equipmentTypeName, string parameterizedModelObjectDefinitionType, IList<ModelObjectParameterDefinition> modelObjectParameters, string equipmentDictionaryName, Dictionary<string, List<long>> dummyRuns, Dictionary<long, List<Shared.Metrology.WS.Results>> staticRuns, bool useCyclicalForDescription, bool isEAFHosted) :
base(new Description(), false, smtp, fileParameter, cellInstanceName, connectionCount, cellInstanceConnectionName, fileConnectorConfiguration, equipmentTypeName, parameterizedModelObjectDefinitionType, modelObjectParameters, equipmentDictionaryName, dummyRuns, staticRuns, useCyclicalForDescription, isEAFHosted: connectionCount is null)
{
_MinFileLength = 10;
@ -120,9 +120,10 @@ public class FileRead : Shared.FileRead, IFileRead
if (dateTime == DateTime.MinValue)
throw new ArgumentNullException(nameof(dateTime));
string logisticsSequence = _Logistics.Sequence.ToString();
string day = $"{_Logistics.DateTimeFromSequence:yyyy-MM-dd}";
string weekOfYear = _Calendar.GetWeekOfYear(_Logistics.DateTimeFromSequence, CalendarWeekRule.FirstDay, DayOfWeek.Sunday).ToString("00");
string weekDirectory = $"{_Logistics.DateTimeFromSequence:yyyy}_Week_{weekOfYear}{@"\"}{_Logistics.DateTimeFromSequence:yyyy-MM-dd}";
string destinationArchiveDirectory = Path.Combine(_JobIdArchiveParentDirectory, _Logistics.JobID, weekDirectory);
string weekDirectory = $"{_Logistics.DateTimeFromSequence:yyyy}_Week_{weekOfYear}";
string destinationArchiveDirectory = Path.Combine(_JobIdArchiveParentDirectory, _Logistics.JobID, weekDirectory, day);
if (!Directory.Exists(destinationArchiveDirectory))
_ = Directory.CreateDirectory(destinationArchiveDirectory);
string jobIdDirectory = Path.Combine(_JobIdParentDirectory, _Logistics.JobID);
@ -144,15 +145,15 @@ public class FileRead : Shared.FileRead, IFileRead
private Tuple<string, Test[], JsonElement[], List<FileInfo>> GetExtractResult(string reportFullPath, DateTime dateTime)
{
Tuple<string, Test[], JsonElement[], List<FileInfo>> results;
Tuple<string, string[], string[]> pdsf = ProcessDataStandardFormat.GetLogisticsColumnsAndBody(reportFullPath);
_Logistics = new Logistics(reportFullPath, pdsf.Item1);
ProcessDataStandardFormat processDataStandardFormat = ProcessDataStandardFormat.GetProcessDataStandardFormat(reportFullPath);
_Logistics = new Logistics(reportFullPath, processDataStandardFormat);
SetFileParameterLotIDToLogisticsMID();
JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(pdsf);
JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(processDataStandardFormat);
List<Shared.Properties.IDescription> descriptions = GetDuplicatorDescriptions(jsonElements);
Test[] tests = (from l in descriptions select (Test)l.Test).ToArray();
if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0)
MoveArchive(reportFullPath, dateTime);
results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(pdsf.Item1, tests, jsonElements, new List<FileInfo>());
results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(string.Join(Environment.NewLine, processDataStandardFormat.Logistics[0]), tests, jsonElements, new List<FileInfo>());
return results;
}

View File

@ -9,7 +9,7 @@ namespace Adaptation.FileHandlers;
public class CellInstanceConnectionName
{
internal static IFileRead Get(ISMTP smtp, Dictionary<string, string> fileParameter, string cellInstanceName, string cellInstanceConnectionName, FileConnectorConfiguration fileConnectorConfiguration, string equipmentTypeName, string parameterizedModelObjectDefinitionType, IList<ModelObjectParameterDefinition> modelObjectParameters, string equipmentDictionaryName, Dictionary<string, List<long>> dummyRuns, Dictionary<long, List<string>> staticRuns, bool useCyclicalForDescription, int? connectionCount)
internal static IFileRead Get(ISMTP smtp, Dictionary<string, string> fileParameter, string cellInstanceName, string cellInstanceConnectionName, FileConnectorConfiguration fileConnectorConfiguration, string equipmentTypeName, string parameterizedModelObjectDefinitionType, IList<ModelObjectParameterDefinition> modelObjectParameters, string equipmentDictionaryName, Dictionary<string, List<long>> dummyRuns, Dictionary<long, List<Shared.Metrology.WS.Results>> staticRuns, bool useCyclicalForDescription, int? connectionCount)
{
IFileRead result = cellInstanceConnectionName switch
{

View File

@ -23,7 +23,7 @@ public class FileRead : Shared.FileRead, IFileRead
private int _LastDummyRunIndex;
private readonly string[] _CellNames;
public FileRead(ISMTP smtp, Dictionary<string, string> fileParameter, string cellInstanceName, int? connectionCount, string cellInstanceConnectionName, FileConnectorConfiguration fileConnectorConfiguration, string equipmentTypeName, string parameterizedModelObjectDefinitionType, IList<ModelObjectParameterDefinition> modelObjectParameters, string equipmentDictionaryName, Dictionary<string, List<long>> dummyRuns, Dictionary<long, List<string>> staticRuns, bool useCyclicalForDescription, bool isEAFHosted) :
public FileRead(ISMTP smtp, Dictionary<string, string> fileParameter, string cellInstanceName, int? connectionCount, string cellInstanceConnectionName, FileConnectorConfiguration fileConnectorConfiguration, string equipmentTypeName, string parameterizedModelObjectDefinitionType, IList<ModelObjectParameterDefinition> modelObjectParameters, string equipmentDictionaryName, Dictionary<string, List<long>> dummyRuns, Dictionary<long, List<Shared.Metrology.WS.Results>> staticRuns, bool useCyclicalForDescription, bool isEAFHosted) :
base(new Description(), false, smtp, fileParameter, cellInstanceName, connectionCount, cellInstanceConnectionName, fileConnectorConfiguration, equipmentTypeName, parameterizedModelObjectDefinitionType, modelObjectParameters, equipmentDictionaryName, dummyRuns, staticRuns, useCyclicalForDescription, isEAFHosted: connectionCount is null)
{
_MinFileLength = 10;

View File

@ -18,7 +18,7 @@ public class FileRead : Shared.FileRead, IFileRead
private string _LastLines;
private readonly string _IQSFile;
public FileRead(ISMTP smtp, Dictionary<string, string> fileParameter, string cellInstanceName, int? connectionCount, string cellInstanceConnectionName, FileConnectorConfiguration fileConnectorConfiguration, string equipmentTypeName, string parameterizedModelObjectDefinitionType, IList<ModelObjectParameterDefinition> modelObjectParameters, string equipmentDictionaryName, Dictionary<string, List<long>> dummyRuns, Dictionary<long, List<string>> staticRuns, bool useCyclicalForDescription, bool isEAFHosted) :
public FileRead(ISMTP smtp, Dictionary<string, string> fileParameter, string cellInstanceName, int? connectionCount, string cellInstanceConnectionName, FileConnectorConfiguration fileConnectorConfiguration, string equipmentTypeName, string parameterizedModelObjectDefinitionType, IList<ModelObjectParameterDefinition> modelObjectParameters, string equipmentDictionaryName, Dictionary<string, List<long>> dummyRuns, Dictionary<long, List<WS.Results>> staticRuns, bool useCyclicalForDescription, bool isEAFHosted) :
base(new Description(), false, smtp, fileParameter, cellInstanceName, connectionCount, cellInstanceConnectionName, fileConnectorConfiguration, equipmentTypeName, parameterizedModelObjectDefinitionType, modelObjectParameters, equipmentDictionaryName, dummyRuns, staticRuns, useCyclicalForDescription, isEAFHosted: connectionCount is null)
{
_MinFileLength = 10;
@ -148,17 +148,17 @@ public class FileRead : Shared.FileRead, IFileRead
private Tuple<string, Test[], JsonElement[], List<FileInfo>> GetExtractResult(string reportFullPath, DateTime dateTime)
{
Tuple<string, Test[], JsonElement[], List<FileInfo>> results;
Tuple<string, string[], string[]> pdsf = ProcessDataStandardFormat.GetLogisticsColumnsAndBody(reportFullPath);
_Logistics = new Logistics(reportFullPath, pdsf.Item1);
ProcessDataStandardFormat processDataStandardFormat = ProcessDataStandardFormat.GetProcessDataStandardFormat(reportFullPath);
_Logistics = new Logistics(reportFullPath, processDataStandardFormat);
SetFileParameterLotIDToLogisticsMID();
JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(pdsf);
JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(processDataStandardFormat);
List<txt.Description> descriptions = txt.ProcessData.GetDescriptions(jsonElements);
Test[] tests = (from l in descriptions select (Test)l.Test).ToArray();
if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0)
SaveIQSFile(reportFullPath, dateTime, descriptions, tests);
if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0)
FileCopy(reportFullPath, dateTime, descriptions);
results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(pdsf.Item1, tests, jsonElements, new List<FileInfo>());
results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(string.Join(Environment.NewLine, processDataStandardFormat.Logistics[0]), tests, jsonElements, new List<FileInfo>());
return results;
}

View File

@ -17,7 +17,7 @@ public class FileRead : Shared.FileRead, IFileRead
private long? _TickOffset;
public FileRead(ISMTP smtp, Dictionary<string, string> fileParameter, string cellInstanceName, int? connectionCount, string cellInstanceConnectionName, FileConnectorConfiguration fileConnectorConfiguration, string equipmentTypeName, string parameterizedModelObjectDefinitionType, IList<ModelObjectParameterDefinition> modelObjectParameters, string equipmentDictionaryName, Dictionary<string, List<long>> dummyRuns, Dictionary<long, List<string>> staticRuns, bool useCyclicalForDescription, bool isEAFHosted) :
public FileRead(ISMTP smtp, Dictionary<string, string> fileParameter, string cellInstanceName, int? connectionCount, string cellInstanceConnectionName, FileConnectorConfiguration fileConnectorConfiguration, string equipmentTypeName, string parameterizedModelObjectDefinitionType, IList<ModelObjectParameterDefinition> modelObjectParameters, string equipmentDictionaryName, Dictionary<string, List<long>> dummyRuns, Dictionary<long, List<Shared.Metrology.WS.Results>> staticRuns, bool useCyclicalForDescription, bool isEAFHosted) :
base(new Description(), false, smtp, fileParameter, cellInstanceName, connectionCount, cellInstanceConnectionName, fileConnectorConfiguration, equipmentTypeName, parameterizedModelObjectDefinitionType, modelObjectParameters, equipmentDictionaryName, dummyRuns, staticRuns, useCyclicalForDescription, isEAFHosted: connectionCount is null)
{
_MinFileLength = 10;

View File

@ -5,17 +5,71 @@ using Adaptation.Shared.Duplicator;
using Adaptation.Shared.Methods;
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.Threading;
namespace Adaptation.FileHandlers.MoveMatchingFiles;
#nullable enable
public class FileRead : Shared.FileRead, IFileRead
{
public FileRead(ISMTP smtp, Dictionary<string, string> fileParameter, string cellInstanceName, int? connectionCount, string cellInstanceConnectionName, FileConnectorConfiguration fileConnectorConfiguration, string equipmentTypeName, string parameterizedModelObjectDefinitionType, IList<ModelObjectParameterDefinition> modelObjectParameters, string equipmentDictionaryName, Dictionary<string, List<long>> dummyRuns, Dictionary<long, List<string>> staticRuns, bool useCyclicalForDescription, bool isEAFHosted) :
internal class PreWith
{
internal string MatchingFile { get; private set; }
internal string CheckFile { get; private set; }
internal string ErrFile { get; private set; }
internal string CheckDirectory { get; private set; }
internal string NoWaitDirectory { get; private set; }
internal PreWith(string matchingFile, string checkFile, string errFile, string checkDirectory, string noWaitDirectory)
{
MatchingFile = matchingFile;
CheckFile = checkFile;
ErrFile = errFile;
CheckDirectory = checkDirectory;
NoWaitDirectory = noWaitDirectory;
}
}
internal class Pre
{
internal string MatchingFile { get; private set; }
internal string CheckFile { get; private set; }
internal Pre(string matchingFile, string checkFile)
{
MatchingFile = matchingFile;
CheckFile = checkFile;
}
}
internal class Post
{
internal string ErrFile { get; private set; }
internal string CheckFile { get; private set; }
internal Post(string checkFile, string errFile)
{
ErrFile = errFile;
CheckFile = checkFile;
}
}
private readonly ProcessDataStandardFormatMapping _ProcessDataStandardFormatMapping;
public FileRead(ISMTP smtp, Dictionary<string, string> fileParameter, string cellInstanceName, int? connectionCount, string cellInstanceConnectionName, FileConnectorConfiguration fileConnectorConfiguration, string equipmentTypeName, string parameterizedModelObjectDefinitionType, IList<ModelObjectParameterDefinition> modelObjectParameters, string equipmentDictionaryName, Dictionary<string, List<long>> dummyRuns, Dictionary<long, List<Shared.Metrology.WS.Results>> staticRuns, bool useCyclicalForDescription, bool isEAFHosted) :
base(new Description(), false, smtp, fileParameter, cellInstanceName, connectionCount, cellInstanceConnectionName, fileConnectorConfiguration, equipmentTypeName, parameterizedModelObjectDefinitionType, modelObjectParameters, equipmentDictionaryName, dummyRuns, staticRuns, useCyclicalForDescription, isEAFHosted: connectionCount is null)
{
_MinFileLength = 10;
@ -27,6 +81,12 @@ public class FileRead : Shared.FileRead, IFileRead
throw new Exception(cellInstanceConnectionName);
if (!_IsDuplicator)
throw new Exception(cellInstanceConnectionName);
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<string, Test[], JsonElement[], List<FileInfo>> extractResults, Exception exception)
@ -41,7 +101,8 @@ public class FileRead : Shared.FileRead, IFileRead
Move(extractResults);
}
void IFileRead.WaitForThread() => WaitForThread(thread: null, threadExceptions: null);
void IFileRead.WaitForThread() =>
WaitForThread(thread: null, threadExceptions: null);
string IFileRead.GetEventDescription()
{
@ -88,7 +149,7 @@ public class FileRead : Shared.FileRead, IFileRead
DateTime dateTime = DateTime.Now;
results = GetExtractResult(reportFullPath, dateTime);
if (results.Item3 is null)
results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(results.Item1, Array.Empty<Test>(), JsonSerializer.Deserialize<JsonElement[]>("[]"), results.Item4);
results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(results.Item1, Array.Empty<Test>(), JsonSerializer.Deserialize<JsonElement[]>("[]") ?? throw new Exception(), results.Item4);
if (results.Item3.Length > 0 && _IsEAFHosted)
WritePDSF(this, results.Item3);
UpdateLastTicksDuration(DateTime.Now.Ticks - dateTime.Ticks);
@ -104,7 +165,69 @@ public class FileRead : Shared.FileRead, IFileRead
return results;
}
private static List<string> GetSearchDirectories(int numberLength, string parentDirectory)
private static ProcessDataStandardFormatMapping GetProcessDataStandardFormatMapping(string processDataStandardFormatMappingOldColumnNames, string processDataStandardFormatMappingNewColumnNames, string processDataStandardFormatMappingColumnIndices)
{
ProcessDataStandardFormatMapping result;
string[] segmentsB;
List<string> distinct = new();
Dictionary<string, string> keyValuePairs = new();
string args4 = "Time,HeaderUniqueId,UniqueId,Date,SP101";
string args5 = ",SP101";
string args6 = ",SP101";
string args7 = "Test|EventId,Recipe|Session,|SP101";
// string args8 = "Time,A_LOGISTICS,B_LOGISTICS,Test,Count,Index,MesEntity,Date,Employee,Lot,PSN,Reactor,Recipe,Grade,HeaderUniqueId,RDS,Session,Side,SrcDest,UniqueId,WaferID,DcnAllMax,DcnAllMean,DcnAllMin,DcnAllStdDev,DcnAreaCountMax,DcnAreaCountMean,DcnAreaCountMin,DcnAreaCountStdDev,DcnAreaMax,DcnAreaMean,DcnAreaMin,DcnAreaStdDev,DcnBin1Max,DcnBin1Mean,DcnBin1Min,DcnBin1StdDev,DcnBin2Max,DcnBin2Mean,DcnBin2Min,DcnBin2StdDev,DcnBin3Max,DcnBin3Mean,DcnBin3Min,DcnBin3StdDev,DcnBin4Max,DcnBin4Mean,DcnBin4Min,DcnBin4StdDev,DcnBin5Max,DcnBin5Mean,DcnBin5Min,DcnBin5StdDev,DcnBin6Max,DcnBin6Mean,DcnBin6Min,DcnBin6StdDev,DcnBin7Max,DcnBin7Mean,DcnBin7Min,DcnBin7StdDev,DcnBin8Max,DcnBin8Mean,DcnBin8Min,DcnBin8StdDev,DcnHazeAvgMax,DcnHazeAvgMean,DcnHazeAvgMin,DcnHazeAvgStdDev,DcnHazeMedianMax,DcnHazeMedianMean,DcnHazeMedianMin,DcnHazeMedianStdDev,DcnHazeStdDevMax,DcnHazeStdDevMean,DcnHazeStdDevMin,DcnHazeStdDevStdDev,DcnLpdESMax,DcnLpdESMean,DcnLpdESMin,DcnLpdESStdDev,DcnLpdMax,DcnLpdMean,DcnLpdMin,DcnLpdNMax,DcnLpdNMean,DcnLpdNMin,DcnLpdNStdDev,DcnLpdStdDev,DcnMicroScrMax,DcnMicroScrMean,DcnMicroScrMin,DcnMicroScrStdDev,DcnScrMax,DcnScrMean,DcnScrMin,DcnScrStdDev,DcnSlipMax,DcnSlipMean,DcnSlipMin,DcnSlipStdDev,DnnAllMax,DnnAllMean,DnnAllMin,DnnAllStdDev,DnnAreaCountMax,DnnAreaCountMean,DnnAreaCountMin,DnnAreaCountStdDev,DnnAreaMax,DnnAreaMean,DnnAreaMin,DnnAreaStdDev,DnnBin1Max,DnnBin1Mean,DnnBin1Min,DnnBin1StdDev,DnnBin2Max,DnnBin2Mean,DnnBin2Min,DnnBin2StdDev,DnnBin3Max,DnnBin3Mean,DnnBin3Min,DnnBin3StdDev,DnnBin4Max,DnnBin4Mean,DnnBin4Min,DnnBin4StdDev,DnnBin5Max,DnnBin5Mean,DnnBin5Min,DnnBin5StdDev,DnnBin6Max,DnnBin6Mean,DnnBin6Min,DnnBin6StdDev,DnnBin7Max,DnnBin7Mean,DnnBin7Min,DnnBin7StdDev,DnnBin8Max,DnnBin8Mean,DnnBin8Min,DnnBin8StdDev,DnnHazeAvgMax,DnnHazeAvgMean,DnnHazeAvgMin,DnnHazeAvgStdDev,DnnHazeMedianMax,DnnHazeMedianMean,DnnHazeMedianMin,DnnHazeMedianStdDev,DnnHazeStdDevMax,DnnHazeStdDevMean,DnnHazeStdDevMin,DnnHazeStdDevStdDev,DnnLpdESMax,DnnLpdESMean,DnnLpdESMin,DnnLpdESStdDev,DnnLpdMax,DnnLpdMean,DnnLpdMin,DnnLpdNMax,DnnLpdNMean,DnnLpdNMin,DnnLpdNStdDev,DnnLpdStdDev,DnnMicroScrMax,DnnMicroScrMean,DnnMicroScrMin,DnnMicroScrStdDev,DnnScrMax,DnnScrMean,DnnScrMin,DnnScrStdDev,DnnSlipMax,DnnSlipMean,DnnSlipMin,DnnSlipStdDev,DwnAllMax,DwnAllMean,DwnAllMin,DwnAllStdDev,DwnAreaCountMax,DwnAreaCountMean,DwnAreaCountMin,DwnAreaCountStdDev,DwnAreaMax,DwnAreaMean,DwnAreaMin,DwnAreaStdDev,DwnBin1Max,DwnBin1Mean,DwnBin1Min,DwnBin1StdDev,DwnBin2Max,DwnBin2Mean,DwnBin2Min,DwnBin2StdDev,DwnBin3Max,DwnBin3Mean,DwnBin3Min,DwnBin3StdDev,DwnBin4Max,DwnBin4Mean,DwnBin4Min,DwnBin4StdDev,DwnBin5Max,DwnBin5Mean,DwnBin5Min,DwnBin5StdDev,DwnBin6Max,DwnBin6Mean,DwnBin6Min,DwnBin6StdDev,DwnBin7Max,DwnBin7Mean,DwnBin7Min,DwnBin7StdDev,DwnBin8Max,DwnBin8Mean,DwnBin8Min,DwnBin8StdDev,DwnHazeAvgMax,DwnHazeAvgMean,DwnHazeAvgMin,DwnHazeAvgStdDev,DwnHazeMedianMax,DwnHazeMedianMean,DwnHazeMedianMin,DwnHazeMedianStdDev,DwnHazeStdDevMax,DwnHazeStdDevMean,DwnHazeStdDevMin,DwnHazeStdDevStdDev,DwnLpdESMax,DwnLpdESMean,DwnLpdESMin,DwnLpdESStdDev,DwnLpdMax,DwnLpdMean,DwnLpdMin,DwnLpdNMax,DwnLpdNMean,DwnLpdNMin,DwnLpdNStdDev,DwnLpdStdDev,DwnMicroScrMax,DwnMicroScrMean,DwnMicroScrMin,DwnMicroScrStdDev,DwnScrMax,DwnScrMean,DwnScrMin,DwnScrStdDev,DwnSlipMax,DwnSlipMean,DwnSlipMin,DwnSlipStdDev,DcnAll,DcnArea,DcnAreaCount,DcnBin1,DcnBin2,DcnBin3,DcnBin4,DcnBin5,DcnBin6,DcnBin7,DcnBin8,DcnHazeAvg,DcnHazeMedian,DcnHazeStdDev,DcnLpd,DcnLpdES,DcnLpdN,DcnMicroScr,DcnScr,DcnSlip,DnnAll,DnnArea,DnnAreaCount,DnnBin1,DnnBin2,DnnBin3,DnnBin4,DnnBin5,DnnBin6,DnnBin7,DnnBin8,DnnHazeAvg,DnnHazeMedian,DnnHazeStdDev,DnnLpd,DnnLpdES,DnnLpdN,DnnMicroScr,DnnScr,DnnSlip,DwnAll,DwnArea,DwnAreaCount,DwnBin1,DwnBin2,DwnBin3,DwnBin4,DwnBin5,DwnBin6,DwnBin7,DwnBin8,DwnHazeAvg,DwnHazeMedian,DwnHazeStdDev,DwnLpd,DwnLpdES,DwnLpdN,DwnMicroScr,DwnScr,DwnSlip";
// string args9 = "Time,A_LOGISTICS,B_LOGISTICS,Count,Sequence,MesEntity,Index,Lot,Session,DcnAllMin,DcnLpdMin,DcnLpdNMin,DcnLpdESMin,DcnMicroScrMin,DcnScrMin,DcnSlipMin,DcnAreaCountMin,DcnAreaMin,DcnHazeAvgMin,DcnHazeMedianMin,DcnHazeStdDevMin,DcnBin1Min,DcnBin2Min,DcnBin3Min,DcnBin4Min,DcnBin5Min,DcnBin6Min,DcnBin7Min,DcnBin8Min,DcnAllMax,DcnLpdMax,DcnLpdNMax,DcnLpdESMax,DcnMicroScrMax,DcnScrMax,DcnSlipMax,DcnAreaCountMax,DcnAreaMax,DcnHazeAvgMax,DcnHazeMedianMax,DcnHazeStdDevMax,DcnBin1Max,DcnBin2Max,DcnBin3Max,DcnBin4Max,DcnBin5Max,DcnBin6Max,DcnBin7Max,DcnBin8Max,DcnAllMean,DcnLpdMean,DcnLpdNMean,DcnLpdESMean,DcnMicroScrMean,DcnScrMean,DcnSlipMean,DcnAreaCountMean,DcnAreaMean,DcnHazeAvgMean,DcnHazeMedianMean,DcnHazeStdDevMean,DcnBin1Mean,DcnBin2Mean,DcnBin3Mean,DcnBin4Mean,DcnBin5Mean,DcnBin6Mean,DcnBin7Mean,DcnBin8Mean,DcnAllStdDev,DcnLpdStdDev,DcnLpdNStdDev,DcnLpdESStdDev,DcnMicroScrStdDev,DcnScrStdDev,DcnSlipStdDev,DcnAreaCountStdDev,DcnAreaStdDev,DcnHazeAvgStdDev,DcnHazeMedianStdDev,DcnHazeStdDevStdDev,DcnBin1StdDev,DcnBin2StdDev,DcnBin3StdDev,DcnBin4StdDev,DcnBin5StdDev,DcnBin6StdDev,DcnBin7StdDev,DcnBin8StdDev,DwnAllMin,DwnLpdMin,DwnLpdNMin,DwnLpdESMin,DwnMicroScrMin,DwnScrMin,DwnSlipMin,DwnAreaCountMin,DwnAreaMin,DwnHazeAvgMin,DwnHazeMedianMin,DwnHazeStdDevMin,DwnBin1Min,DwnBin2Min,DwnBin3Min,DwnBin4Min,DwnBin5Min,DwnBin6Min,DwnBin7Min,DwnBin8Min,DwnAllMax,DwnLpdMax,DwnLpdNMax,DwnLpdESMax,DwnMicroScrMax,DwnScrMax,DwnSlipMax,DwnAreaCountMax,DwnAreaMax,DwnHazeAvgMax,DwnHazeMedianMax,DwnHazeStdDevMax,DwnBin1Max,DwnBin2Max,DwnBin3Max,DwnBin4Max,DwnBin5Max,DwnBin6Max,DwnBin7Max,DwnBin8Max,DwnAllMean,DwnLpdMean,DwnLpdNMean,DwnLpdESMean,DwnMicroScrMean,DwnScrMean,DwnSlipMean,DwnAreaCountMean,DwnAreaMean,DwnHazeAvgMean,DwnHazeMedianMean,DwnHazeStdDevMean,DwnBin1Mean,DwnBin2Mean,DwnBin3Mean,DwnBin4Mean,DwnBin5Mean,DwnBin6Mean,DwnBin7Mean,DwnBin8Mean,DwnAllStdDev,DwnLpdStdDev,DwnLpdNStdDev,DwnLpdESStdDev,DwnMicroScrStdDev,DwnScrStdDev,DwnSlipStdDev,DwnAreaCountStdDev,DwnAreaStdDev,DwnHazeAvgStdDev,DwnHazeMedianStdDev,DwnHazeStdDevStdDev,DwnBin1StdDev,DwnBin2StdDev,DwnBin3StdDev,DwnBin4StdDev,DwnBin5StdDev,DwnBin6StdDev,DwnBin7StdDev,DwnBin8StdDev,DnnAllMin,DnnLpdMin,DnnLpdNMin,DnnLpdESMin,DnnMicroScrMin,DnnScrMin,DnnSlipMin,DnnAreaCountMin,DnnAreaMin,DnnHazeAvgMin,DnnHazeMedianMin,DnnHazeStdDevMin,DnnBin1Min,DnnBin2Min,DnnBin3Min,DnnBin4Min,DnnBin5Min,DnnBin6Min,DnnBin7Min,DnnBin8Min,DnnAllMax,DnnLpdMax,DnnLpdNMax,DnnLpdESMax,DnnMicroScrMax,DnnScrMax,DnnSlipMax,DnnAreaCountMax,DnnAreaMax,DnnHazeAvgMax,DnnHazeMedianMax,DnnHazeStdDevMax,DnnBin1Max,DnnBin2Max,DnnBin3Max,DnnBin4Max,DnnBin5Max,DnnBin6Max,DnnBin7Max,DnnBin8Max,DnnAllMean,DnnLpdMean,DnnLpdNMean,DnnLpdESMean,DnnMicroScrMean,DnnScrMean,DnnSlipMean,DnnAreaCountMean,DnnAreaMean,DnnHazeAvgMean,DnnHazeMedianMean,DnnHazeStdDevMean,DnnBin1Mean,DnnBin2Mean,DnnBin3Mean,DnnBin4Mean,DnnBin5Mean,DnnBin6Mean,DnnBin7Mean,DnnBin8Mean,DnnAllStdDev,DnnLpdStdDev,DnnLpdNStdDev,DnnLpdESStdDev,DnnMicroScrStdDev,DnnScrStdDev,DnnSlipStdDev,DnnAreaCountStdDev,DnnAreaStdDev,DnnHazeAvgStdDev,DnnHazeMedianStdDev,DnnHazeStdDevStdDev,DnnBin1StdDev,DnnBin2StdDev,DnnBin3StdDev,DnnBin4StdDev,DnnBin5StdDev,DnnBin6StdDev,DnnBin7StdDev,DnnBin8StdDev,Side,WaferID,Grade,SrcDest,DcnAll,DcnLpd,DcnLpdN,DcnLpdES,DcnMicroScr,DcnScr,DcnSlip,DcnAreaCount,DcnArea,DcnHazeAvg,DcnHazeMedian,DcnHazeStdDev,DcnBin1,DcnBin2,DcnBin3,DcnBin4,DcnBin5,DcnBin6,DcnBin7,DcnBin8,DwnAll,DwnLpd,DwnLpdN,DwnLpdES,DwnMicroScr,DwnScr,DwnSlip,DwnAreaCount,DwnArea,DwnHazeAvg,DwnHazeMedian,DwnHazeStdDev,DwnBin1,DwnBin2,DwnBin3,DwnBin4,DwnBin5,DwnBin6,DwnBin7,DwnBin8,DnnAll,DnnLpd,DnnLpdN,DnnLpdES,DnnMicroScr,DnnScr,DnnSlip,DnnAreaCount,DnnArea,DnnHazeAvg,DnnHazeMedian,DnnHazeStdDev,DnnBin1,DnnBin2,DnnBin3,DnnBin4,DnnBin5,DnnBin6,DnnBin7,DnnBin8,RDS,PSN,Reactor,Layer,Zone,Employee,InferredLot,Date,EventId";
// string args10 = "0,1,2,319,3,6,5,320,318,7,314,315,8,251,-1,313,8,249,252,-1,250,29,49,9,69,36,56,16,76,37,57,17,77,41,61,21,81,42,62,22,82,43,63,23,83,44,64,24,84,45,65,25,85,46,66,26,86,47,67,27,87,48,68,28,88,38,58,18,78,39,59,19,79,40,60,20,80,32,52,12,72,30,50,10,31,51,11,71,70,33,53,13,73,34,54,14,74,35,55,15,75,189,209,169,229,196,216,176,236,197,217,177,237,201,221,181,241,202,222,182,242,203,223,183,243,204,224,184,244,205,225,185,245,206,226,186,246,207,227,187,247,208,228,188,248,198,218,178,238,199,219,179,239,200,220,180,240,192,212,172,232,190,210,170,191,211,171,231,230,193,213,173,233,194,214,174,234,195,215,175,235,109,129,89,149,116,136,96,156,117,137,97,157,121,141,101,161,122,142,102,162,123,143,103,163,124,144,104,164,125,145,105,165,126,146,106,166,127,147,107,167,128,148,108,168,118,138,98,158,119,139,99,159,120,140,100,160,112,132,92,152,110,130,90,111,131,91,151,150,113,133,93,153,114,134,94,154,115,135,95,155,253,261,260,265,266,267,268,269,270,271,272,262,263,264,254,256,255,257,258,259,293,301,300,305,306,307,308,309,310,311,312,302,303,304,294,296,295,297,298,299,273,281,280,285,286,287,288,289,290,291,292,282,283,284,274,276,275,277,278,279";
string[] segments = args7.Split(',');
ReadOnlyCollection<string> ignoreColumns = new(args4.Split(','));
ReadOnlyCollection<string> backfillColumns = new(args5.Split(','));
ReadOnlyCollection<string> indexOnlyColumns = new(args6.Split(','));
ReadOnlyCollection<string> newColumnNames = new(processDataStandardFormatMappingNewColumnNames.Split(','));
ReadOnlyCollection<string> oldColumnNames = new(processDataStandardFormatMappingOldColumnNames.Split(','));
ReadOnlyCollection<int> columnIndices = new(processDataStandardFormatMappingColumnIndices.Split(',').Select(int.Parse).ToArray());
foreach (string segment in segments)
{
segmentsB = segment.Split('|');
if (segmentsB.Length != 2)
continue;
if (distinct.Contains(segmentsB[0]))
continue;
distinct.Add(segmentsB[0]);
keyValuePairs.Add(segmentsB[0], segmentsB[1]);
}
result = new(backfillColumns: backfillColumns,
columnIndices: columnIndices,
newColumnNames: newColumnNames,
ignoreColumns: ignoreColumns,
indexOnlyColumns: indexOnlyColumns,
keyValuePairs: new(keyValuePairs),
oldColumnNames: oldColumnNames);
return result;
}
private static ReadOnlyCollection<PreWith> GetPreWithCollection(ReadOnlyCollection<Pre> preCollection)
{
List<PreWith> results = new();
string errFile;
PreWith preWith;
string? checkDirectory;
string noWaitDirectory;
foreach (Pre pre in preCollection)
{
errFile = string.Concat(pre.CheckFile, ".err");
checkDirectory = Path.GetDirectoryName(pre.CheckFile);
if (string.IsNullOrEmpty(checkDirectory))
continue;
if (!Directory.Exists(checkDirectory))
_ = Directory.CreateDirectory(checkDirectory);
noWaitDirectory = Path.Combine(checkDirectory, "NoWaitDirectory");
preWith = new(pre.MatchingFile, pre.CheckFile, errFile, checkDirectory, noWaitDirectory);
results.Add(preWith);
}
return results.AsReadOnly();
}
private static ReadOnlyCollection<string> GetSearchDirectories(int numberLength, string parentDirectory)
{
List<string> results = new();
string[] directories = Directory.GetDirectories(parentDirectory, "*", SearchOption.TopDirectoryOnly);
@ -115,10 +238,142 @@ public class FileRead : Shared.FileRead, IFileRead
results.Add(directory);
}
results.Sort();
return results.AsReadOnly();
}
private static void CreatePointerFile(int numberLength, string parentDirectory, ReadOnlyCollection<string> matchingFiles)
{
string checkFile;
string writeFile;
string? directoryName;
int parentDirectoryLength = parentDirectory.Length;
foreach (string matchingFile in matchingFiles)
{
directoryName = Path.GetDirectoryName(matchingFile);
if (directoryName is null)
continue;
checkFile = $"{matchingFile[0]}{directoryName.Substring(parentDirectoryLength + numberLength + 1)}";
writeFile = Path.Combine(parentDirectory, $"{directoryName.Substring(parentDirectory.Length + 1, numberLength)}.txt");
if (File.Exists(writeFile))
continue;
File.AppendAllLines(writeFile, new string[] { parentDirectory, matchingFile, directoryName, checkFile });
}
}
private static ReadOnlyCollection<Pre> GetPreCollection(int numberLength, string parentDirectory, ReadOnlyCollection<string> matchingFiles)
{
List<Pre> results = new();
Pre pre;
string checkFile;
int parentDirectoryLength = parentDirectory.Length;
foreach (string matchingFile in matchingFiles)
{
checkFile = $"{matchingFile[0]}{matchingFile.Substring(parentDirectoryLength + numberLength + 1)}";
pre = new(matchingFile, checkFile);
results.Add(pre);
}
return results.AsReadOnly();
}
private void MoveCollection(DateTime dateTime, ProcessDataStandardFormat? processDataStandardFormat, ReadOnlyCollection<PreWith> preWithCollection)
{
ReadOnlyCollection<Post> postCollection = GetPostCollection(dateTime, processDataStandardFormat, preWithCollection);
if (postCollection.Count != 0)
{
Thread.Sleep(500);
StringBuilder stringBuilder = new();
foreach (Post post in postCollection)
{
if (File.Exists(post.ErrFile))
_ = stringBuilder.AppendLine(File.ReadAllText(post.ErrFile));
if (File.Exists(post.CheckFile))
_ = stringBuilder.AppendLine($"<{post.CheckFile}> was not consumed by the end!");
}
if (stringBuilder.Length > 0)
throw new Exception(stringBuilder.ToString());
}
}
private ReadOnlyCollection<Post> GetPostCollection(DateTime dateTime, ProcessDataStandardFormat? processDataStandardFormat, ReadOnlyCollection<PreWith> preWithCollection)
{
List<Post> results = new();
Post post;
long preWait;
foreach (PreWith preWith in preWithCollection)
{
if (!_IsEAFHosted)
continue;
if (processDataStandardFormat is null)
File.Move(preWith.MatchingFile, preWith.CheckFile);
else
{
if (!_StaticRuns.TryGetValue(_Logistics.Sequence, out List<Shared.Metrology.WS.Results>? wsResults))
wsResults = null;
ProcessDataStandardFormat.Write(preWith.CheckFile, processDataStandardFormat, wsResults);
File.Delete(preWith.MatchingFile);
}
if (Directory.Exists(preWith.NoWaitDirectory))
{
post = new(preWith.CheckFile, preWith.ErrFile);
results.Add(post);
continue;
}
if (_FileConnectorConfiguration?.FileHandleWaitTime is null)
preWait = DateTime.Now.AddMilliseconds(1234).Ticks;
else
preWait = DateTime.Now.AddMilliseconds(_FileConnectorConfiguration.FileHandleWaitTime.Value).Ticks;
for (short i = 0; i < short.MaxValue; i++)
{
if (DateTime.Now.Ticks > preWait)
break;
Thread.Sleep(500);
}
for (int i = 0; i < int.MaxValue; i++)
{
if (File.Exists(preWith.ErrFile))
throw new Exception(File.ReadAllText(preWith.ErrFile));
if (!File.Exists(preWith.CheckFile))
break;
if (new TimeSpan(DateTime.Now.Ticks - dateTime.Ticks).TotalSeconds > _BreakAfterSeconds)
throw new Exception($"Not all files were consumed after {_BreakAfterSeconds} second(s)!");
Thread.Sleep(500);
}
}
return results.AsReadOnly();
}
private Tuple<string, Test[], JsonElement[], List<FileInfo>> GetExtractResult(string reportFullPath, DateTime dateTime)
{
Tuple<string, Test[], JsonElement[], List<FileInfo>> results = new(string.Empty, Array.Empty<Test>(), Array.Empty<JsonElement>(), new List<FileInfo>());
ProcessDataStandardFormat? processDataStandardFormat = ProcessDataStandardFormat.GetProcessDataStandardFormat(reportFullPath, _ProcessDataStandardFormatMapping);
if (processDataStandardFormat is not null)
_Logistics = new Logistics(reportFullPath, processDataStandardFormat);
else
{
processDataStandardFormat = ProcessDataStandardFormat.GetProcessDataStandardFormat(reportFullPath);
_Logistics = new Logistics(reportFullPath, processDataStandardFormat);
processDataStandardFormat = null;
}
if (!_IsEAFHosted && processDataStandardFormat is not null)
ProcessDataStandardFormat.Write(".pdsf", processDataStandardFormat, wsResults: null);
SetFileParameterLotIDToLogisticsMID();
int numberLength = 2;
long ticks = dateTime.Ticks;
string parentParentDirectory = GetParentParent(reportFullPath);
ReadOnlyCollection<string> searchDirectories = GetSearchDirectories(numberLength, parentParentDirectory);
ReadOnlyCollection<string> matchingFiles = GetMatchingFiles(ticks, reportFullPath, searchDirectories);
if (matchingFiles.Count != searchDirectories.Count)
throw new Exception($"Didn't find all files after {_BreakAfterSeconds} second(s)!");
try
{ CreatePointerFile(numberLength, parentParentDirectory, matchingFiles); }
catch (Exception) { }
ReadOnlyCollection<Pre> preCollection = GetPreCollection(numberLength, parentParentDirectory, matchingFiles);
ReadOnlyCollection<PreWith> preWithCollection = GetPreWithCollection(preCollection);
MoveCollection(dateTime, processDataStandardFormat, preWithCollection);
return results;
}
private List<string> GetMatchingFiles(long ticks, string reportFullPath, List<string> searchDirectories)
private ReadOnlyCollection<string> GetMatchingFiles(long ticks, string reportFullPath, ReadOnlyCollection<string> searchDirectories)
{
List<string> results = new();
string[] found;
@ -137,129 +392,7 @@ public class FileRead : Shared.FileRead, IFileRead
break;
}
}
return results;
}
private static List<(string matchingFile, string checkFile)> GetCollection(int numberLength, string parentDirectory, List<string> matchingFiles)
{
List<(string matchingFile, string checkFile)> results = new();
string checkFile;
int parentDirectoryLength = parentDirectory.Length;
foreach (string matchingFile in matchingFiles)
{
checkFile = $"{matchingFile[0]}{matchingFile.Substring(parentDirectoryLength + numberLength + 1)}";
results.Add(new(matchingFile, checkFile));
}
return results;
}
private static List<(string, string, string, string, string)> GetCollection(List<(string matchingFile, string checkFile)> collection)
{
List<(string, string, string, string, string)> results = new();
string errFile;
string checkDirectory;
string noWaitDirectory;
foreach ((string matchingFile, string checkFile) in collection)
{
errFile = string.Concat(checkFile, ".err");
checkDirectory = Path.GetDirectoryName(checkFile);
if (!Directory.Exists(checkDirectory))
_ = Directory.CreateDirectory(checkDirectory);
noWaitDirectory = Path.Combine(checkDirectory, "NoWaitDirectory");
results.Add(new(matchingFile, checkFile, errFile, checkDirectory, noWaitDirectory));
}
return results;
}
private void MoveCollection(DateTime dateTime, List<(string matchingFile, string checkFile)> collection)
{
long preWait;
List<(string checkFile, string errFile)> postCollection = new();
foreach ((string matchingFile, string checkFile, string errFile, string checkDirectory, string noWaitDirectory) in GetCollection(collection))
{
File.Move(matchingFile, checkFile);
if (Directory.Exists(noWaitDirectory))
{
postCollection.Add(new(checkFile, errFile));
continue;
}
if (_FileConnectorConfiguration?.FileHandleWaitTime is null)
preWait = DateTime.Now.AddMilliseconds(1234).Ticks;
else
preWait = DateTime.Now.AddMilliseconds(_FileConnectorConfiguration.FileHandleWaitTime.Value).Ticks;
for (short i = 0; i < short.MaxValue; i++)
{
if (DateTime.Now.Ticks > preWait)
break;
Thread.Sleep(500);
}
for (int i = 0; i < int.MaxValue; i++)
{
if (File.Exists(errFile))
throw new Exception(File.ReadAllText(errFile));
if (!File.Exists(checkFile))
break;
if (new TimeSpan(DateTime.Now.Ticks - dateTime.Ticks).TotalSeconds > _BreakAfterSeconds)
throw new Exception($"Not all files were consumed after {_BreakAfterSeconds} second(s)!");
Thread.Sleep(500);
}
}
if (postCollection.Count != 0)
{
Thread.Sleep(500);
StringBuilder stringBuilder = new();
foreach ((string checkFile, string errFile) in postCollection)
{
if (File.Exists(errFile))
_ = stringBuilder.AppendLine(File.ReadAllText(errFile));
if (File.Exists(checkFile))
_ = stringBuilder.AppendLine($"<{checkFile}> was not consumed by the end!");
}
if (stringBuilder.Length > 0)
throw new Exception(stringBuilder.ToString());
}
}
private static void CreatePointerFile(int numberLength, string parentDirectory, List<string> matchingFiles)
{
#nullable enable
string checkFile;
string writeFile;
string? directoryName;
int parentDirectoryLength = parentDirectory.Length;
foreach (string matchingFile in matchingFiles)
{
directoryName = Path.GetDirectoryName(matchingFile);
if (directoryName is null)
continue;
checkFile = $"{matchingFile[0]}{directoryName.Substring(parentDirectoryLength + numberLength + 1)}";
writeFile = Path.Combine(parentDirectory, $"{directoryName.Substring(parentDirectory.Length + 1, numberLength)}.txt");
if (File.Exists(writeFile))
continue;
File.AppendAllLines(writeFile, new string[] { parentDirectory, matchingFile, directoryName, checkFile });
}
#nullable disable
}
private Tuple<string, Test[], JsonElement[], List<FileInfo>> GetExtractResult(string reportFullPath, DateTime dateTime)
{
Tuple<string, Test[], JsonElement[], List<FileInfo>> results = new(string.Empty, null, null, new List<FileInfo>());
Tuple<string, string[], string[]> pdsf = ProcessDataStandardFormat.GetLogisticsColumnsAndBody(reportFullPath);
_Logistics = new Logistics(reportFullPath, pdsf.Item1);
SetFileParameterLotIDToLogisticsMID();
int numberLength = 2;
long ticks = dateTime.Ticks;
string parentParentDirectory = GetParentParent(reportFullPath);
List<string> searchDirectories = GetSearchDirectories(numberLength, parentParentDirectory);
List<string> matchingFiles = GetMatchingFiles(ticks, reportFullPath, searchDirectories);
if (matchingFiles.Count != searchDirectories.Count)
throw new Exception($"Didn't find all files after {_BreakAfterSeconds} second(s)!");
try
{ CreatePointerFile(numberLength, parentParentDirectory, matchingFiles); }
catch (Exception) { }
List<(string matchingFile, string checkFile)> collection = GetCollection(numberLength, parentParentDirectory, matchingFiles);
MoveCollection(dateTime, collection);
return results;
return results.AsReadOnly();
}
}

View File

@ -22,7 +22,7 @@ public class FileRead : Shared.FileRead, IFileRead
private readonly string _OpenInsightFilePattern;
private readonly string _OpenInsightApiECDirectory;
public FileRead(ISMTP smtp, Dictionary<string, string> fileParameter, string cellInstanceName, int? connectionCount, string cellInstanceConnectionName, FileConnectorConfiguration fileConnectorConfiguration, string equipmentTypeName, string parameterizedModelObjectDefinitionType, IList<ModelObjectParameterDefinition> modelObjectParameters, string equipmentDictionaryName, Dictionary<string, List<long>> dummyRuns, Dictionary<long, List<string>> staticRuns, bool useCyclicalForDescription, bool isEAFHosted) :
public FileRead(ISMTP smtp, Dictionary<string, string> fileParameter, string cellInstanceName, int? connectionCount, string cellInstanceConnectionName, FileConnectorConfiguration fileConnectorConfiguration, string equipmentTypeName, string parameterizedModelObjectDefinitionType, IList<ModelObjectParameterDefinition> modelObjectParameters, string equipmentDictionaryName, Dictionary<string, List<long>> dummyRuns, Dictionary<long, List<WS.Results>> staticRuns, bool useCyclicalForDescription, bool isEAFHosted) :
base(new Description(), false, smtp, fileParameter, cellInstanceName, connectionCount, cellInstanceConnectionName, fileConnectorConfiguration, equipmentTypeName, parameterizedModelObjectDefinitionType, modelObjectParameters, equipmentDictionaryName, dummyRuns, staticRuns, useCyclicalForDescription, isEAFHosted: connectionCount is null)
{
_MinFileLength = 10;
@ -168,7 +168,7 @@ public class FileRead : Shared.FileRead, IFileRead
return new Tuple<string, string>(result.ToString(), x.Date);
}
private void SaveOpenInsightFile(string reportFullPath, DateTime dateTime, string logistics, List<txt.Description> descriptions, Test[] tests)
private void SaveOpenInsightFile(string reportFullPath, DateTime dateTime, ProcessDataStandardFormat processDataStandardFormat, List<txt.Description> descriptions, Test[] tests)
{
bool isDummyRun = false;
List<(Shared.Properties.IScopeInfo, string)> collection = new();
@ -195,20 +195,20 @@ public class FileRead : Shared.FileRead, IFileRead
bool save = string.IsNullOrEmpty(_LastLines) || check != _LastLines;
if (save && !string.IsNullOrEmpty(check))
{
long? subGroupId;
long? subgroupId;
_LastLines = check;
long breakAfter = dateTime.AddSeconds(_BreakAfterSeconds).Ticks;
long preWait = _FileConnectorConfiguration?.FileHandleWaitTime is null ? dateTime.AddMilliseconds(1234).Ticks : dateTime.AddMilliseconds(_FileConnectorConfiguration.FileHandleWaitTime.Value).Ticks;
if (string.IsNullOrEmpty(descriptions[0].Reactor) || string.IsNullOrEmpty(descriptions[0].PSN))
subGroupId = null;
subgroupId = null;
else
(subGroupId, int? _, string _) = FromIQS.GetCommandText(_IqsConnectionString, _Logistics, descriptions[0], breakAfter, preWait);
if (subGroupId is null)
(subgroupId, int? _, string _) = FromIQS.GetCommandText(_IqsConnectionString, _Logistics, descriptions[0], breakAfter, preWait);
if (subgroupId is null)
collection.Add(new(new ScopeInfo(tests[0], _OpenInsightFilePattern), lines.Item1));
else
collection.Add(new(new ScopeInfo(tests[0], $"{subGroupId.Value} {_OpenInsightFilePattern}"), lines.Item1));
collection.Add(new(new ScopeInfo(tests[0], $"{subgroupId.Value} {_OpenInsightFilePattern}"), lines.Item1));
string weekOfYear = _Calendar.GetWeekOfYear(_Logistics.DateTimeFromSequence, CalendarWeekRule.FirstDay, DayOfWeek.Sunday).ToString("00");
FromIQS.Save(_OpenInsightApiECDirectory, _Logistics, reportFullPath, logistics, descriptions.First(), lines.Item1, subGroupId, weekOfYear);
FromIQS.Save(_OpenInsightApiECDirectory, _Logistics, reportFullPath, processDataStandardFormat, descriptions.First(), lines.Item1, subgroupId, weekOfYear);
}
if (!Directory.Exists(duplicateDirectory))
_ = Directory.CreateDirectory(duplicateDirectory);
@ -220,15 +220,15 @@ public class FileRead : Shared.FileRead, IFileRead
private Tuple<string, Test[], JsonElement[], List<FileInfo>> GetExtractResult(string reportFullPath, DateTime dateTime)
{
Tuple<string, Test[], JsonElement[], List<FileInfo>> results;
Tuple<string, string[], string[]> pdsf = ProcessDataStandardFormat.GetLogisticsColumnsAndBody(reportFullPath);
_Logistics = new Logistics(reportFullPath, pdsf.Item1);
ProcessDataStandardFormat processDataStandardFormat = ProcessDataStandardFormat.GetProcessDataStandardFormat(reportFullPath);
_Logistics = new Logistics(reportFullPath, processDataStandardFormat);
SetFileParameterLotIDToLogisticsMID();
JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(pdsf);
JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(processDataStandardFormat);
List<txt.Description> descriptions = txt.ProcessData.GetDescriptions(jsonElements);
Test[] tests = (from l in descriptions select (Test)l.Test).ToArray();
if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0)
SaveOpenInsightFile(reportFullPath, dateTime, pdsf.Item1, descriptions, tests);
results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(pdsf.Item1, tests, jsonElements, new List<FileInfo>());
SaveOpenInsightFile(reportFullPath, dateTime, processDataStandardFormat, descriptions, tests);
results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(string.Join(Environment.NewLine, processDataStandardFormat.Logistics[0]), tests, jsonElements, new List<FileInfo>());
return results;
}

View File

@ -325,7 +325,7 @@ public class FromIQS
return new(result, count, commandText);
}
private static string GetJson(Logistics logistics, string logisticLines, txt.Description description)
private static string GetJson(Logistics logistics, ProcessDataStandardFormat processDataStandardFormat, txt.Description description)
{
string result;
StringBuilder stringBuilder = new();
@ -345,7 +345,7 @@ public class FromIQS
string safeValue;
string[] segments;
string serializerValue;
foreach (string line in logisticLines.Split(new string[] { Environment.NewLine }, StringSplitOptions.None))
foreach (string line in processDataStandardFormat.Logistics)
{
segments = line.Split('\t');
if (segments.Length < 2)
@ -376,11 +376,11 @@ public class FromIQS
return result;
}
internal static void Save(string openInsightApiECDirectory, Logistics logistics, string reportFullPath, string logisticLines, txt.Description description, string lines, long? subGroupId, string weekOfYear)
internal static void Save(string openInsightApiECDirectory, Logistics logistics, string reportFullPath, ProcessDataStandardFormat processDataStandardFormat, txt.Description description, string lines, long? subGroupId, string weekOfYear)
{
string checkFile;
string fileName = Path.GetFileName(reportFullPath);
string json = GetJson(logistics, logisticLines, description);
string json = GetJson(logistics, processDataStandardFormat, description);
string? ecPathRoot = Path.GetPathRoot(openInsightApiECDirectory);
bool ecExists = ecPathRoot is not null && Directory.Exists(ecPathRoot);
string weekYear = $"{logistics.DateTimeFromSequence:yyyy}_Week_{weekOfYear}";
@ -396,6 +396,9 @@ public class FromIQS
checkFile = Path.Combine(ecDirectory, $"{logistics.DateTimeFromSequence.Ticks}.json");
if (ecExists && !File.Exists(checkFile))
File.WriteAllText(checkFile, json);
checkFile = Path.Combine(ecDirectory, $"{logistics.DateTimeFromSequence.Ticks}.lbl");
if (ecExists && !File.Exists(checkFile))
File.WriteAllText(checkFile, processDataStandardFormat.Body[processDataStandardFormat.Body.Count - 1]);
}
private static string GetCommandText(string[] iqsCopyValues)

View File

@ -19,7 +19,7 @@ public class FileRead : Shared.FileRead, IFileRead
private readonly string _OpenInsightMetrologyViewerAPI;
private readonly string _OpenInsightMetrologyViewerFileShare;
public FileRead(ISMTP smtp, Dictionary<string, string> fileParameter, string cellInstanceName, int? connectionCount, string cellInstanceConnectionName, FileConnectorConfiguration fileConnectorConfiguration, string equipmentTypeName, string parameterizedModelObjectDefinitionType, IList<ModelObjectParameterDefinition> modelObjectParameters, string equipmentDictionaryName, Dictionary<string, List<long>> dummyRuns, Dictionary<long, List<string>> staticRuns, bool useCyclicalForDescription, bool isEAFHosted) :
public FileRead(ISMTP smtp, Dictionary<string, string> fileParameter, string cellInstanceName, int? connectionCount, string cellInstanceConnectionName, FileConnectorConfiguration fileConnectorConfiguration, string equipmentTypeName, string parameterizedModelObjectDefinitionType, IList<ModelObjectParameterDefinition> modelObjectParameters, string equipmentDictionaryName, Dictionary<string, List<long>> dummyRuns, Dictionary<long, List<WS.Results>> staticRuns, bool useCyclicalForDescription, bool isEAFHosted) :
base(new Description(), false, smtp, fileParameter, cellInstanceName, connectionCount, cellInstanceConnectionName, fileConnectorConfiguration, equipmentTypeName, parameterizedModelObjectDefinitionType, modelObjectParameters, equipmentDictionaryName, dummyRuns, staticRuns, useCyclicalForDescription, isEAFHosted: connectionCount is null)
{
_MinFileLength = 10;
@ -121,16 +121,16 @@ public class FileRead : Shared.FileRead, IFileRead
_ = Directory.CreateDirectory(checkDirectory);
File.Copy(reportFullPath, Path.Combine(checkDirectory, Path.GetFileName(reportFullPath)), overwrite: true);
(string jsonResults, WS.Results wsResults) = WS.SendData(_OpenInsightMetrologyViewerAPI, _Logistics.Sequence, directory, wsRequest);
if (!wsResults.Success)
throw new Exception(wsResults.ToString());
_Log.Debug(wsResults.HeaderID);
if (wsResults.Success is null || !wsResults.Success.Value)
throw new Exception(jsonResults);
_Log.Debug(wsResults.HeaderId);
lock (_StaticRuns)
{
if (!_StaticRuns.ContainsKey(_Logistics.Sequence))
_StaticRuns.Add(_Logistics.Sequence, new());
_StaticRuns[_Logistics.Sequence].Add(jsonResults);
_StaticRuns[_Logistics.Sequence].Add(wsResults);
}
checkDirectory = Path.Combine(directory, $"-{wsResults.HeaderID}");
checkDirectory = Path.Combine(directory, $"-{wsResults.HeaderId}");
if (!Directory.Exists(checkDirectory))
_ = Directory.CreateDirectory(checkDirectory);
File.Copy(reportFullPath, Path.Combine(checkDirectory, Path.GetFileName(reportFullPath)), overwrite: true);
@ -139,15 +139,15 @@ public class FileRead : Shared.FileRead, IFileRead
private Tuple<string, Test[], JsonElement[], List<FileInfo>> GetExtractResult(string reportFullPath, DateTime dateTime)
{
Tuple<string, Test[], JsonElement[], List<FileInfo>> results;
Tuple<string, string[], string[]> pdsf = ProcessDataStandardFormat.GetLogisticsColumnsAndBody(reportFullPath);
_Logistics = new Logistics(reportFullPath, pdsf.Item1);
ProcessDataStandardFormat processDataStandardFormat = ProcessDataStandardFormat.GetProcessDataStandardFormat(reportFullPath);
_Logistics = new Logistics(reportFullPath, processDataStandardFormat);
SetFileParameterLotIDToLogisticsMID();
JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(pdsf);
JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(processDataStandardFormat);
List<txt.Description> descriptions = txt.ProcessData.GetDescriptions(jsonElements);
Test[] tests = (from l in descriptions select (Test)l.Test).ToArray();
if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0)
SendData(reportFullPath, dateTime, descriptions);
results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(pdsf.Item1, tests, jsonElements, new List<FileInfo>());
results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(string.Join(Environment.NewLine, processDataStandardFormat.Logistics[0]), tests, jsonElements, new List<FileInfo>());
return results;
}

View File

@ -6,7 +6,6 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text.Json;
namespace Adaptation.FileHandlers.OpenInsightMetrologyViewer;
@ -607,8 +606,12 @@ public class WSRequest
Details.Add(detail);
}
Date = logistics.DateTimeFromSequence.ToString();
if (UniqueID is null && Details.Count != 0)
UniqueID = Details[0].HeaderUniqueID;
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}";
}
}
/// <summary>
@ -632,29 +635,30 @@ public class WSRequest
return result;
}
internal static long GetHeaderId(IFileRead fileRead, Logistics logistics, string openInsightMetrologyViewerAPI, string openInsightMetrologyViewerFileShare, int weekOfYear, string json, List<txt.Description> descriptions)
internal static long GetHeaderId(IFileRead fileRead, Logistics logistics, string openInsightMetrologyViewerAPI, string openInsightMetrologyViewerFileShare, int weekOfYear, WS.Results results, List<txt.Description> descriptions)
{
long result;
if (string.IsNullOrEmpty(json))
if (results is not null && results.HeaderId is not null)
result = results.HeaderId.Value;
else
{
WSRequest wsRequest = new(fileRead, logistics, descriptions);
string directory = Path.Combine(openInsightMetrologyViewerFileShare, logistics.DateTimeFromSequence.Year.ToString(), $"WW{weekOfYear:00}");
(json, WS.Results wsResults) = WS.SendData(openInsightMetrologyViewerAPI, logistics.Sequence, directory, wsRequest);
if (!wsResults.Success)
(_, WS.Results wsResults) = WS.SendData(openInsightMetrologyViewerAPI, logistics.Sequence, directory, wsRequest);
if (wsResults.Success is null || !wsResults.Success.Value)
throw new Exception(wsResults.ToString());
result = wsResults.HeaderId.Value;
}
WS.Results metrologyWSRequest = JsonSerializer.Deserialize<WS.Results>(json, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
result = metrologyWSRequest.HeaderID;
return result;
}
#pragma warning disable IDE0060
internal static void PostOpenInsightMetrologyViewerAttachments(IFileRead fileRead, Logistics logistics, string openInsightMetrologyViewerAPI, string ghostPCLFileName, List<txt.Description> descriptions, string matchDirectory, string subGroupId, long headerId, string headerIdDirectory)
internal static void PostOpenInsightMetrologyViewerAttachments(IFileRead fileRead, Logistics logistics, string openInsightMetrologyViewerAPI, string ghostPCLFileName, List<txt.Description> descriptions, string matchDirectory, WS.Results results, string headerIdDirectory)
#pragma warning restore IDE0060
{
string[] summaryFiles = Directory.GetFiles(matchDirectory, "*.txt", SearchOption.TopDirectoryOnly);
if (summaryFiles.Length != 1)
throw new Exception($"Invalid source file count for <{headerId}>!");
throw new Exception($"Invalid source file count for <{results.HeaderId}>!");
string[] prnFiles = Directory.GetFiles(matchDirectory, "WaferMap*.prn", SearchOption.TopDirectoryOnly);
List<string> pdfFiles = new();
foreach (string prnFile in prnFiles.OrderBy(l => l))
@ -664,7 +668,7 @@ public class WSRequest
List<WS.Attachment> dataAttachments = new();
List<WS.Attachment> headerAttachments = new()
{
new WS.Attachment(subGroupId, headerId, headerIdDirectory, descriptions[0].HeaderUniqueId, "Data.txt", summaryFiles[0])
new WS.Attachment(results, headerIdDirectory, $"{logistics.JobID}_{logistics.MID}_{logistics.DateTimeFromSequence:yyyyMMddHHmmssffff}", "Data.txt", summaryFiles[0])
};
int count;
if (pdfFiles.Count < descriptions.Count)
@ -674,7 +678,7 @@ public class WSRequest
for (int i = 0; i < count; i++)
{
if (!string.IsNullOrEmpty(pdfFiles[i]))
dataAttachments.Add(new WS.Attachment(subGroupId, headerId, headerIdDirectory, descriptions[i].UniqueId, "Image.pdf", pdfFiles[i]));
dataAttachments.Add(new WS.Attachment(results, headerIdDirectory, $"{logistics.JobID}_{logistics.MID}_{logistics.DateTimeFromSequence:yyyyMMddHHmmssffff}_Item-{i + 1}", "Image.pdf", pdfFiles[i]));
}
if (dataAttachments.Count == 0 || dataAttachments.Count != descriptions.Count)
throw new Exception($"Invalid attachment count! {dataAttachments.Count} != {descriptions.Count}");

View File

@ -19,7 +19,7 @@ public class FileRead : Shared.FileRead, IFileRead
private readonly string _OpenInsightMetrologyViewerAPI;
private readonly string _OpenInsightMetrologyViewerFileShare;
public FileRead(ISMTP smtp, Dictionary<string, string> fileParameter, string cellInstanceName, int? connectionCount, string cellInstanceConnectionName, FileConnectorConfiguration fileConnectorConfiguration, string equipmentTypeName, string parameterizedModelObjectDefinitionType, IList<ModelObjectParameterDefinition> modelObjectParameters, string equipmentDictionaryName, Dictionary<string, List<long>> dummyRuns, Dictionary<long, List<string>> staticRuns, bool useCyclicalForDescription, bool isEAFHosted) :
public FileRead(ISMTP smtp, Dictionary<string, string> fileParameter, string cellInstanceName, int? connectionCount, string cellInstanceConnectionName, FileConnectorConfiguration fileConnectorConfiguration, string equipmentTypeName, string parameterizedModelObjectDefinitionType, IList<ModelObjectParameterDefinition> modelObjectParameters, string equipmentDictionaryName, Dictionary<string, List<long>> dummyRuns, Dictionary<long, List<Shared.Metrology.WS.Results>> staticRuns, bool useCyclicalForDescription, bool isEAFHosted) :
base(new Description(), false, smtp, fileParameter, cellInstanceName, connectionCount, cellInstanceConnectionName, fileConnectorConfiguration, equipmentTypeName, parameterizedModelObjectDefinitionType, modelObjectParameters, equipmentDictionaryName, dummyRuns, staticRuns, useCyclicalForDescription, isEAFHosted: connectionCount is null)
{
_MinFileLength = 10;
@ -141,30 +141,25 @@ public class FileRead : Shared.FileRead, IFileRead
private void PostOpenInsightMetrologyViewerAttachments(List<txt.Description> descriptions)
{
string? json;
string? subGroupId;
Shared.Metrology.WS.Results? results;
string jobIdDirectory = Path.Combine(Path.GetDirectoryName(_FileConnectorConfiguration.AlternateTargetFolder) ?? throw new Exception(), _Logistics.JobID);
if (!Directory.Exists(jobIdDirectory))
_ = Directory.CreateDirectory(jobIdDirectory);
string[] matchDirectories = GetInProcessDirectory(jobIdDirectory);
if (!_StaticRuns.TryGetValue(_Logistics.Sequence, out List<string>? values))
(json, subGroupId) = (null, null);
if (!_StaticRuns.TryGetValue(_Logistics.Sequence, out List<Shared.Metrology.WS.Results>? wsResults))
results = null;
else
{
if (values.Count != 1)
throw new Exception($"{nameof(_StaticRuns)} {values.Count} != 1 {_Logistics.Sequence}!");
string[] segments = values[0].Split(new string[] { "|" }, StringSplitOptions.None);
json = segments[0];
subGroupId = segments.Length > 1 ? segments[1] : null;
lock (_StaticRuns)
_ = _StaticRuns.Remove(_Logistics.Sequence);
if (wsResults is null || wsResults.Count != 1)
throw new NullReferenceException($"{nameof(wsResults)} {wsResults?.Count} != 1 {_Logistics.Sequence}!");
results = wsResults[0];
}
int weekOfYear = _Calendar.GetWeekOfYear(_Logistics.DateTimeFromSequence, CalendarWeekRule.FirstDay, DayOfWeek.Sunday);
long headerId = !_IsEAFHosted ? -1 : OpenInsightMetrologyViewer.WSRequest.GetHeaderId(this, _Logistics, _OpenInsightMetrologyViewerAPI, _OpenInsightMetrologyViewerFileShare, weekOfYear, json, descriptions);
long headerId = !_IsEAFHosted ? -1 : OpenInsightMetrologyViewer.WSRequest.GetHeaderId(this, _Logistics, _OpenInsightMetrologyViewerAPI, _OpenInsightMetrologyViewerFileShare, weekOfYear, results, descriptions);
string? headerIdDirectory = GetHeaderIdDirectory(headerId);
if (string.IsNullOrEmpty(headerIdDirectory))
throw new Exception($"Didn't find header id directory <{headerId}>");
OpenInsightMetrologyViewer.WSRequest.PostOpenInsightMetrologyViewerAttachments(this, _Logistics, _OpenInsightMetrologyViewerAPI, _GhostPCLFileName, descriptions, matchDirectories[0], subGroupId, headerId, headerIdDirectory);
OpenInsightMetrologyViewer.WSRequest.PostOpenInsightMetrologyViewerAttachments(this, _Logistics, _OpenInsightMetrologyViewerAPI, _GhostPCLFileName, descriptions, matchDirectories[0], results, headerIdDirectory);
}
private Tuple<string, Test[], JsonElement[], List<FileInfo>> GetExtractResult(string reportFullPath, DateTime dateTime)
@ -172,15 +167,15 @@ public class FileRead : Shared.FileRead, IFileRead
if (dateTime == DateTime.MinValue)
throw new ArgumentNullException(nameof(dateTime));
Tuple<string, Test[], JsonElement[], List<FileInfo>> results;
Tuple<string, string[], string[]> pdsf = ProcessDataStandardFormat.GetLogisticsColumnsAndBody(reportFullPath);
_Logistics = new Logistics(reportFullPath, pdsf.Item1);
ProcessDataStandardFormat processDataStandardFormat = ProcessDataStandardFormat.GetProcessDataStandardFormat(reportFullPath);
_Logistics = new Logistics(reportFullPath, processDataStandardFormat);
SetFileParameterLotIDToLogisticsMID();
JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(pdsf);
JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(processDataStandardFormat);
List<txt.Description> descriptions = txt.ProcessData.GetDescriptions(jsonElements);
Test[] tests = (from l in descriptions select (Test)l.Test).ToArray();
if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0)
PostOpenInsightMetrologyViewerAttachments(descriptions);
results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(pdsf.Item1, tests, jsonElements, new List<FileInfo>());
results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(string.Join(Environment.NewLine, processDataStandardFormat.Logistics[0]), tests, jsonElements, new List<FileInfo>());
return results;
}

View File

@ -17,7 +17,7 @@ public class FileRead : Shared.FileRead, IFileRead
private readonly string _JobIdParentDirectory;
private readonly string _JobIdProcessParentDirectory;
public FileRead(ISMTP smtp, Dictionary<string, string> fileParameter, string cellInstanceName, int? connectionCount, string cellInstanceConnectionName, FileConnectorConfiguration fileConnectorConfiguration, string equipmentTypeName, string parameterizedModelObjectDefinitionType, IList<ModelObjectParameterDefinition> modelObjectParameters, string equipmentDictionaryName, Dictionary<string, List<long>> dummyRuns, Dictionary<long, List<string>> staticRuns, bool useCyclicalForDescription, bool isEAFHosted) :
public FileRead(ISMTP smtp, Dictionary<string, string> fileParameter, string cellInstanceName, int? connectionCount, string cellInstanceConnectionName, FileConnectorConfiguration fileConnectorConfiguration, string equipmentTypeName, string parameterizedModelObjectDefinitionType, IList<ModelObjectParameterDefinition> modelObjectParameters, string equipmentDictionaryName, Dictionary<string, List<long>> dummyRuns, Dictionary<long, List<Shared.Metrology.WS.Results>> staticRuns, bool useCyclicalForDescription, bool isEAFHosted) :
base(new Description(), false, smtp, fileParameter, cellInstanceName, connectionCount, cellInstanceConnectionName, fileConnectorConfiguration, equipmentTypeName, parameterizedModelObjectDefinitionType, modelObjectParameters, equipmentDictionaryName, dummyRuns, staticRuns, useCyclicalForDescription, isEAFHosted: connectionCount is null)
{
_MinFileLength = 10;
@ -129,23 +129,50 @@ 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);
File.Copy(reportFullPath, Path.Combine(sequenceDirectory, Path.GetFileName(reportFullPath)), overwrite: true);
File.WriteAllText(jsonFileName, json);
lock (_StaticRuns)
_ = _StaticRuns.Remove(_Logistics.Sequence);
}
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<string, Test[], JsonElement[], List<FileInfo>> GetExtractResult(string reportFullPath, DateTime dateTime)
{
Tuple<string, Test[], JsonElement[], List<FileInfo>> results;
Tuple<string, string[], string[]> pdsf = ProcessDataStandardFormat.GetLogisticsColumnsAndBody(reportFullPath);
_Logistics = new Logistics(reportFullPath, pdsf.Item1);
ProcessDataStandardFormat processDataStandardFormat = ProcessDataStandardFormat.GetProcessDataStandardFormat(reportFullPath);
_Logistics = new Logistics(reportFullPath, processDataStandardFormat);
SetFileParameterLotIDToLogisticsMID();
JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(pdsf);
JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(processDataStandardFormat);
List<txt.Description> descriptions = txt.ProcessData.GetDescriptions(jsonElements);
Test[] tests = (from l in descriptions select (Test)l.Test).ToArray();
results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(pdsf.Item1, tests, jsonElements, new List<FileInfo>());
results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(string.Join(Environment.NewLine, processDataStandardFormat.Logistics[0]), tests, jsonElements, new List<FileInfo>());
if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0)
DirectoryMove(reportFullPath, dateTime, descriptions);
else if (!_IsEAFHosted)

View File

@ -14,7 +14,7 @@ namespace Adaptation.FileHandlers.SPaCe;
public class FileRead : Shared.FileRead, IFileRead
{
public FileRead(ISMTP smtp, Dictionary<string, string> fileParameter, string cellInstanceName, int? connectionCount, string cellInstanceConnectionName, FileConnectorConfiguration fileConnectorConfiguration, string equipmentTypeName, string parameterizedModelObjectDefinitionType, IList<ModelObjectParameterDefinition> modelObjectParameters, string equipmentDictionaryName, Dictionary<string, List<long>> dummyRuns, Dictionary<long, List<string>> staticRuns, bool useCyclicalForDescription, bool isEAFHosted) :
public FileRead(ISMTP smtp, Dictionary<string, string> fileParameter, string cellInstanceName, int? connectionCount, string cellInstanceConnectionName, FileConnectorConfiguration fileConnectorConfiguration, string equipmentTypeName, string parameterizedModelObjectDefinitionType, IList<ModelObjectParameterDefinition> modelObjectParameters, string equipmentDictionaryName, Dictionary<string, List<long>> dummyRuns, Dictionary<long, List<Shared.Metrology.WS.Results>> staticRuns, bool useCyclicalForDescription, bool isEAFHosted) :
base(new Description(), false, smtp, fileParameter, cellInstanceName, connectionCount, cellInstanceConnectionName, fileConnectorConfiguration, equipmentTypeName, parameterizedModelObjectDefinitionType, modelObjectParameters, equipmentDictionaryName, dummyRuns, staticRuns, useCyclicalForDescription, isEAFHosted: connectionCount is null)
{
_MinFileLength = 10;
@ -117,15 +117,15 @@ public class FileRead : Shared.FileRead, IFileRead
private Tuple<string, Test[], JsonElement[], List<FileInfo>> GetExtractResult(string reportFullPath, DateTime dateTime)
{
Tuple<string, Test[], JsonElement[], List<FileInfo>> results;
Tuple<string, string[], string[]> pdsf = ProcessDataStandardFormat.GetLogisticsColumnsAndBody(reportFullPath);
_Logistics = new Logistics(reportFullPath, pdsf.Item1);
ProcessDataStandardFormat processDataStandardFormat = ProcessDataStandardFormat.GetProcessDataStandardFormat(reportFullPath);
_Logistics = new Logistics(reportFullPath, processDataStandardFormat);
SetFileParameterLotIDToLogisticsMID();
JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(pdsf);
JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(processDataStandardFormat);
List<Shared.Properties.IDescription> descriptions = GetDuplicatorDescriptions(jsonElements);
Test[] tests = (from l in descriptions select (Test)l.Test).ToArray();
if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0)
FileCopy(reportFullPath, dateTime, descriptions);
results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(pdsf.Item1, tests, jsonElements, new List<FileInfo>());
results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(string.Join(Environment.NewLine, processDataStandardFormat.Logistics[0]), tests, jsonElements, new List<FileInfo>());
return results;
}

View File

@ -23,7 +23,7 @@ public class FileRead : Shared.FileRead, IFileRead
private long? _TickOffset;
public FileRead(ISMTP smtp, Dictionary<string, string> fileParameter, string cellInstanceName, int? connectionCount, string cellInstanceConnectionName, FileConnectorConfiguration fileConnectorConfiguration, string equipmentTypeName, string parameterizedModelObjectDefinitionType, IList<ModelObjectParameterDefinition> modelObjectParameters, string equipmentDictionaryName, Dictionary<string, List<long>> dummyRuns, Dictionary<long, List<string>> staticRuns, bool useCyclicalForDescription, bool isEAFHosted) :
public FileRead(ISMTP smtp, Dictionary<string, string> fileParameter, string cellInstanceName, int? connectionCount, string cellInstanceConnectionName, FileConnectorConfiguration fileConnectorConfiguration, string equipmentTypeName, string parameterizedModelObjectDefinitionType, IList<ModelObjectParameterDefinition> modelObjectParameters, string equipmentDictionaryName, Dictionary<string, List<long>> dummyRuns, Dictionary<long, List<Shared.Metrology.WS.Results>> staticRuns, bool useCyclicalForDescription, bool isEAFHosted) :
base(new Description(), false, smtp, fileParameter, cellInstanceName, connectionCount, cellInstanceConnectionName, fileConnectorConfiguration, equipmentTypeName, parameterizedModelObjectDefinitionType, modelObjectParameters, equipmentDictionaryName, dummyRuns, staticRuns, useCyclicalForDescription, isEAFHosted: connectionCount is null)
{ // cSpell:restore
_MinFileLength = 10;

View File

@ -84,12 +84,18 @@ public partial class Job
else
common = Get(input);
}
if (IsValid(common.RDSNumber))
bool isValid = IsValid(common.RDSNumber);
if (isValid)
commonB = GetWithValidRDS(lsl2SQLConnectionString, common.Layer, common.PSN, common.RDSNumber, common.ReactorNumber, common.Zone);
else if (workOrder.IsWorkOrder || common.RDSNumber.HasValue)
commonB = Get(lsl2SQLConnectionString, common.Layer, common.PSN, common.ReactorNumber, workOrder.SlotNumber, workOrder.WorkOrderNumber, workOrder.WorkOrderCassette, common.Zone);
else
commonB = new(hyphen, hyphen, common.RDSNumber, common.PSN, common.ReactorNumber, hyphen);
commonB = new(comment: hyphen,
layer: hyphen,
rdsNumber: common.RDSNumber,
psn: common.PSN,
reactorNumber: common.ReactorNumber,
zone: hyphen);
Qty = "1";
Status = hyphen; // INFO
CreationUser = hyphen; // ?
@ -107,7 +113,7 @@ public partial class Job
ProductName = !string.IsNullOrEmpty(commonB.PSN) ? commonB.PSN : hyphen; // PRODUCT
ProcessSpecName = !string.IsNullOrEmpty(commonB.Zone) ? commonB.Zone : hyphen; // WAFER_POS
BasicType = !string.IsNullOrEmpty(commonB.Comment) ? commonB.Comment : hyphen; // BASIC_TYPE
LotName = commonB.RDSNumber is not null ? commonB.RDSNumber.Value.ToString() : hyphen; // MID
LotName = commonB.RDSNumber is not null ? commonB.RDSNumber.Value.ToString() : input.MID; // MID
ProcessType = commonB.ReactorNumber is not null ? commonB.ReactorNumber.Value.ToString() : hyphen; // PROCESS_JOBID
Items.Add(new Item { Name = "0", Type = "NA", Number = (0 + 1).ToString(), Qty = "1", CarrierName = hyphen });
}
@ -237,9 +243,10 @@ public partial class Job
{
string? psn;
string? rds;
int rdsCheck;
string? zone;
int rdsNumber;
string? layer;
int? rdsNumber;
string? reactor;
string? employee;
int? reactorNumber;
@ -250,11 +257,9 @@ public partial class Job
string[] segments = mid.Split(new char[] { '-' });
// bool hasRDS = Regex.IsMatch(mid, "[-]?([QP][0-9]{4,}|[0-9]{5,})[-]?");
(reactor, rds) = GetReactorAndRDS(input.MID, mid, segments);
if (string.IsNullOrEmpty(rds))
rdsNumber = 0;
else
_ = int.TryParse(rds, out rdsNumber);
if (IsInvalid(rdsNumber) || !int.TryParse(reactor, out int reactorCheck))
rdsNumber = string.IsNullOrEmpty(rds) || !int.TryParse(rds, out rdsCheck) ? null : rdsCheck;
bool isInvalid = IsInvalid(rdsNumber);
if (isInvalid || !int.TryParse(reactor, out int reactorCheck))
{
psn = null;
zone = null;
@ -597,7 +602,11 @@ public partial class Job
string comment;
const int zero = 0;
const string hyphen = "-";
string commandText = GetCommandText(rds: null, workOrderNumber, workOrderCassette, slotNumber, reactorNumber);
string commandText = GetCommandText(rds: null,
workOrderNumber: workOrderNumber,
workOrderCassette: workOrderCassette,
slot: slotNumber,
reactor: reactorNumber);
string json = GetRunJson(lsl2SQLConnectionString, commandText);
if (string.IsNullOrEmpty(json))
{
@ -640,7 +649,12 @@ public partial class Job
comment = $"{loadLockSideFull} - {runs[zero].ReactorType}";
}
}
return new(comment, layer, rdsNumber, psn, reactorNumber, zone);
return new(comment: comment,
layer: layer,
rdsNumber: rdsNumber,
psn: psn,
reactorNumber: reactorNumber,
zone: zone);
}
private static CommonB GetWithValidRDS(string lsl2SQLConnectionString, string layer, string psn, int? rdsNumber, int? reactorNumber, string zone)
@ -648,7 +662,11 @@ public partial class Job
string comment;
const int zero = 0;
const string hyphen = "-";
string commandText = GetCommandText(rdsNumber, workOrderNumber: null, workOrderCassette: null, slot: null, reactor: null);
string commandText = GetCommandText(rds: rdsNumber,
workOrderNumber: null,
workOrderCassette: null,
slot: null,
reactor: null);
string json = GetRunJson(lsl2SQLConnectionString, commandText);
if (string.IsNullOrEmpty(json))
{
@ -675,7 +693,7 @@ public partial class Job
zone = runs[zero].Zone;
if (string.IsNullOrEmpty(layer))
layer = runs[zero].EpiLayer;
reactorNumber = runs[zero].Reactor;
reactorNumber = runs[zero].Reactor is null ? reactorNumber : runs[zero].Reactor.Value;
string loadLockSide = runs[zero].LoadLockSide;
string loadLockSideFull = loadLockSide switch
{
@ -686,7 +704,12 @@ public partial class Job
comment = $"{loadLockSideFull} - {runs[zero].ReactorType}";
}
}
return new(comment, layer, rdsNumber, psn, reactorNumber, zone);
return new(comment: comment,
layer: layer,
rdsNumber: rdsNumber,
psn: psn,
reactorNumber: reactorNumber,
zone: zone);
}
}

View File

@ -24,7 +24,7 @@ public class Run
public string PartNo { get; set; }
[JsonPropertyName("reactor")]
public int Reactor { get; set; }
public int? Reactor { get; set; }
[JsonPropertyName("ps_no")]
public string PSN { get; set; }

View File

@ -15,7 +15,7 @@ public class FileRead : Shared.FileRead, IFileRead
private long? _TickOffset;
public FileRead(ISMTP smtp, Dictionary<string, string> fileParameter, string cellInstanceName, int? connectionCount, string cellInstanceConnectionName, FileConnectorConfiguration fileConnectorConfiguration, string equipmentTypeName, string parameterizedModelObjectDefinitionType, IList<ModelObjectParameterDefinition> modelObjectParameters, string equipmentDictionaryName, Dictionary<string, List<long>> dummyRuns, Dictionary<long, List<string>> staticRuns, bool useCyclicalForDescription, bool isEAFHosted) :
public FileRead(ISMTP smtp, Dictionary<string, string> fileParameter, string cellInstanceName, int? connectionCount, string cellInstanceConnectionName, FileConnectorConfiguration fileConnectorConfiguration, string equipmentTypeName, string parameterizedModelObjectDefinitionType, IList<ModelObjectParameterDefinition> modelObjectParameters, string equipmentDictionaryName, Dictionary<string, List<long>> dummyRuns, Dictionary<long, List<Shared.Metrology.WS.Results>> staticRuns, bool useCyclicalForDescription, bool isEAFHosted) :
base(new Description(), true, smtp, fileParameter, cellInstanceName, connectionCount, cellInstanceConnectionName, fileConnectorConfiguration, equipmentTypeName, parameterizedModelObjectDefinitionType, modelObjectParameters, equipmentDictionaryName, dummyRuns, staticRuns, useCyclicalForDescription, isEAFHosted: connectionCount is null)
{
_MinFileLength = 10;

View File

@ -955,8 +955,6 @@ public class ProcessData : IProcessData
{
// NOTE: get the UniqueID during DataCalculation in order to retrieve the SPCToolID from the cell component Tag field.
// id
//runData.UniqueID = string.Format("{0}_{1}", sp1Header.UniqueId, i + 1);
//runData.HeaderUniqueID = sp1Header.UniqueId;
// General Wafer Info
Side = dcnTotals[i].Side,
@ -1029,7 +1027,6 @@ public class ProcessData : IProcessData
DnnBin6 = dnnTotals[i].Bin6 ?? string.Empty,
DnnBin7 = dnnTotals[i].Bin7 ?? string.Empty,
DnnBin8 = dnnTotals[i].Bin8 ?? string.Empty,
//result.HeaderUniqueID = string.Concat(MesEntity, "_", Lot, "_Summary_", Date);
HeaderUniqueID = UniqueID
};
result.UniqueID = string.Concat(result.HeaderUniqueID, "_", result.WaferID.PadLeft(2, '0'));

View File

@ -25,7 +25,7 @@ stages:
nugetSource: "https://artifactory.intra.infineon.com/artifactory/api/nuget/ngt-fi-package-main-vir/"
jobs:
- job: SetupEnviroment
- job: SetupEnvironment
steps:
- script: |
echo $(Build.BuildId)
@ -51,7 +51,7 @@ stages:
- job: BuildDebug
dependsOn:
- SetupEnviroment
- SetupEnvironment
steps:
- script: |
set configuration=Debug
@ -66,7 +66,7 @@ stages:
- job: BuildRelease
dependsOn:
- SetupEnviroment
- SetupEnvironment
steps:
- script: |
set configuration=Release
@ -98,7 +98,7 @@ stages:
- job: TestDebug
dependsOn:
- SetupEnviroment
- SetupEnvironment
- BuildDebug
- BuildRelease
steps:
@ -168,7 +168,7 @@ stages:
nugetSource: "https://artifactory.intra.infineon.com/artifactory/api/nuget/ngt-fi-package-main-vir/"
jobs:
- job: SetupEnviroment
- job: SetupEnvironment
steps:
- script: |
echo $(Build.BuildId)
@ -194,7 +194,7 @@ stages:
- job: BuildRelease
dependsOn:
- SetupEnviroment
- SetupEnvironment
steps:
- script: |
set configuration=Release
@ -226,7 +226,7 @@ stages:
- job: TestRelease
dependsOn:
- SetupEnviroment
- SetupEnvironment
- BuildRelease
steps:
- script: |

File diff suppressed because it is too large Load Diff

View File

@ -35,6 +35,9 @@ public class Logistics : ILogistics
public long Sequence => _Sequence;
public double TotalSecondsSinceLastWriteTimeFromSequence => _TotalSecondsSinceLastWriteTimeFromSequence;
private static string DefaultMesEntity(DateTime dateTime) =>
string.Concat(dateTime.Ticks, "_MES_ENTITY");
public Logistics(IFileRead fileRead)
{
DateTime dateTime = DateTime.Now;
@ -84,13 +87,13 @@ public class Logistics : ILogistics
_Logistics2 = new List<Logistics2>();
}
public Logistics(string reportFullPath, string logistics)
internal Logistics(string reportFullPath, ProcessDataStandardFormat processDataStandardFormat)
{
string key;
DateTime dateTime;
string[] segments;
_FileInfo = new(reportFullPath);
_Logistics1 = logistics.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries).ToList();
_Logistics1 = processDataStandardFormat.Logistics.ToList();
if (Logistics1.Count == 0 || !Logistics1[0].StartsWith("LOGISTICS_1"))
{
_NullData = null;
@ -190,8 +193,6 @@ public class Logistics : ILogistics
}
}
private static string DefaultMesEntity(DateTime dateTime) => string.Concat(dateTime.Ticks, "_MES_ENTITY");
internal void Update(string mid, string processJobID)
{
_MID = mid;

View File

@ -6,23 +6,25 @@ public partial class WS
public class Attachment
{
public string SubGroupId { get; set; }
public long HeaderId { get; set; }
public string HeaderIdDirectory { get; set; }
public string UniqueId { get; set; }
public string DestinationFileName { get; set; }
public string SourceFileName { get; set; }
public string AttachmentId { get; set; }
#nullable enable
public Attachment(string subGroupId, long headerId, string headerIdDirectory, string uniqueId, string destinationFileName, string sourceFileName)
public long HeaderId { get; set; }
public string UniqueId { get; set; }
public string SubGroupId { get; set; }
public string AttachmentId { get; set; }
public string SourceFileName { get; set; }
public string HeaderIdDirectory { get; set; }
public string DestinationFileName { get; set; }
public Attachment(Results? results, string headerIdDirectory, string uniqueId, string destinationFileName, string sourceFileName)
{
SubGroupId = subGroupId;
HeaderId = headerId;
HeaderIdDirectory = headerIdDirectory;
UniqueId = uniqueId;
DestinationFileName = destinationFileName;
SourceFileName = sourceFileName;
HeaderIdDirectory = headerIdDirectory;
DestinationFileName = destinationFileName;
AttachmentId = System.Guid.NewGuid().ToString();
HeaderId = results?.HeaderId is null ? -1 : results.HeaderId.Value;
SubGroupId = results?.SubgroupId is null ? string.Empty : results.SubgroupId.Value.ToString();
}
}

View File

@ -1,27 +1,75 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Adaptation.Shared.Metrology;
public partial class WS
{
// this class represents the response from the Inbound API endpoint
public class Results
{
// true or false if data was written to the database
public bool Success { get; set; }
// if true, contains ID of the Header record in the database
public long HeaderID { get; set; }
#nullable enable
// if false, this collection will contain a list of errors
public List<string> Errors { get; set; }
[JsonConstructor]
public Results(List<string>? errors,
long? headerId,
long? subgroupId,
bool? success,
List<string>? warnings)
{
Errors = errors;
Success = success;
HeaderId = headerId;
Warnings = warnings;
SubgroupId = subgroupId;
}
// this collection will contain a list of warnings, they will not prevent data from being saved
public List<string> Warnings { get; set; }
[JsonPropertyName("errors")] public List<string>? Errors { get; set; }
[JsonPropertyName("headerID")] public long? HeaderId { get; set; }
[JsonPropertyName("subgroupId")] public long? SubgroupId { get; set; }
[JsonPropertyName("success")] public bool? Success { get; set; }
[JsonPropertyName("warnings")] public List<string>? Warnings { get; set; }
public override string ToString()
{
string result = JsonSerializer.Serialize(this, ResultsSourceGenerationContext.Default.Results);
return result;
}
internal static Results Get(Results results, long? subgroupId) =>
new(results.Errors, results.HeaderId, subgroupId, results.Success, results.Warnings);
internal static Results Get(string resultsJson, Exception e)
{
Results results;
Exception? exception = e;
List<string> errors = new();
StringBuilder stringBuilder = new();
while (exception is not null)
{
_ = stringBuilder.AppendLine(exception.Message);
exception = exception.InnerException;
}
errors.Add(resultsJson);
errors.Add(stringBuilder.ToString());
results = new(errors: errors,
headerId: null,
subgroupId: null,
success: false,
warnings: new());
return results;
}
// this is just a helper function to make displaying the results easier
public override string ToString() => JsonSerializer.Serialize(this, GetType());
}
}
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(WS.Results))]
internal partial class ResultsSourceGenerationContext : JsonSerializerContext
{
}

View File

@ -10,9 +10,11 @@ namespace Adaptation.Shared.Metrology;
public partial class WS
{
#nullable enable
public static (string, Results) SendData(string url, long sequence, string directory, object payload, int timeoutSeconds = 120)
{
Results results = new();
Results? wsResults = null;
string resultsJson = string.Empty;
try
{
@ -30,29 +32,20 @@ public partial class WS
};
HttpResponseMessage httpResponseMessage = httpClient.SendAsync(httpRequestMessage, HttpCompletionOption.ResponseContentRead).Result;
resultsJson = httpResponseMessage.Content.ReadAsStringAsync().Result;
results = JsonSerializer.Deserialize<Results>(resultsJson, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
string checkDirectory = Path.Combine(directory, $"-{results.HeaderID}");
wsResults = JsonSerializer.Deserialize(resultsJson, ResultsSourceGenerationContext.Default.Results);
if (wsResults is null)
throw new NullReferenceException(nameof(wsResults));
string checkDirectory = Path.Combine(directory, $"-{wsResults.HeaderId}");
if (!Directory.Exists(checkDirectory))
_ = Directory.CreateDirectory(checkDirectory);
File.WriteAllText(Path.Combine(checkDirectory, $"{sequence}.json"), json);
}
if (!results.Success)
results.Errors.Add(results.ToString());
if (wsResults.Success is null || !wsResults.Success.Value)
wsResults.Errors?.Add(wsResults.ToString());
}
catch (Exception e)
{
Exception exception = e;
StringBuilder stringBuilder = new();
while (exception is not null)
{
_ = stringBuilder.AppendLine(exception.Message);
exception = exception.InnerException;
}
results.Errors ??= new List<string>();
results.Errors.Add(resultsJson);
results.Errors.Add(stringBuilder.ToString());
}
return new(resultsJson, results);
{ wsResults ??= Results.Get(resultsJson, e); }
return new(resultsJson, wsResults);
}
public static void AttachFile(string url, Attachment attachment, int timeoutSeconds = 60)
@ -69,16 +62,20 @@ public partial class WS
}
}
public static void AttachFiles(string url, List<Attachment> headerAttachments = null, List<Attachment> dataAttachments = null)
public static void AttachFiles(string url, List<Attachment>? headerAttachments = null, List<Attachment>? dataAttachments = null)
{
string directory;
try
{
string? directoryName;
if (headerAttachments is not null)
{
foreach (Attachment attachment in headerAttachments)
{
directory = Path.Combine(Path.GetDirectoryName(attachment.HeaderIdDirectory), attachment.AttachmentId) ?? throw new Exception();
directoryName = Path.GetDirectoryName(attachment.HeaderIdDirectory);
if (string.IsNullOrEmpty(directoryName))
continue;
directory = Path.Combine(directoryName, attachment.AttachmentId) ?? throw new Exception();
if (!Directory.Exists(directory))
_ = Directory.CreateDirectory(directory);
File.Copy(attachment.SourceFileName, Path.Combine(directory, attachment.DestinationFileName), overwrite: true);
@ -88,7 +85,10 @@ public partial class WS
{
foreach (Attachment attachment in dataAttachments)
{
directory = Path.Combine(Path.GetDirectoryName(attachment.HeaderIdDirectory.Replace("Header", "Data")), attachment.AttachmentId) ?? throw new Exception();
directoryName = Path.GetDirectoryName(attachment.HeaderIdDirectory.Replace("Header", "Data"));
if (string.IsNullOrEmpty(directoryName))
continue;
directory = Path.Combine(directoryName, attachment.AttachmentId) ?? throw new Exception();
if (!Directory.Exists(directory))
_ = Directory.CreateDirectory(directory);
File.Copy(attachment.SourceFileName, Path.Combine(directory, attachment.DestinationFileName), overwrite: true);
@ -108,7 +108,7 @@ public partial class WS
}
catch (Exception e)
{
Exception exception = e;
Exception? exception = e;
StringBuilder stringBuilder = new();
while (exception is not null)
{

View File

@ -1,18 +1,22 @@
using Adaptation.Shared.Methods;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Adaptation.Shared;
public class ProcessDataStandardFormat
#nullable enable
internal class ProcessDataStandardFormat
{
public enum SearchFor
internal enum SearchFor
{
EquipmentIntegration = 1,
BusinessIntegration = 2,
@ -20,325 +24,47 @@ public class ProcessDataStandardFormat
Archive = 4
}
public static string GetPDSFText(IFileRead fileRead, Logistics logistics, JsonElement[] jsonElements, string logisticsText)
internal long? Sequence { get; private set; }
internal ReadOnlyCollection<string> Body { get; private set; }
internal ReadOnlyCollection<string> Footer { get; private set; }
internal ReadOnlyCollection<string> Header { get; private set; }
internal ReadOnlyCollection<string> Columns { get; private set; }
internal ProcessDataStandardFormat? InputPDSF { get; private set; }
internal ReadOnlyCollection<string> Logistics { get; private set; }
internal ProcessDataStandardFormat(ReadOnlyCollection<string> body,
ReadOnlyCollection<string> columns,
ReadOnlyCollection<string> footer,
ReadOnlyCollection<string> header,
ProcessDataStandardFormat? inputPDSF,
ReadOnlyCollection<string> logistics,
long? sequence)
{
string result;
if (jsonElements.Length == 0)
result = string.Empty;
else
{
int columns = 0;
List<string> lines;
string endOffset = "E#######T";
string dataOffset = "D#######T";
string headerOffset = "H#######T";
string format = "MM/dd/yyyy HH:mm:ss";
StringBuilder stringBuilder = new();
lines = new string[] { "HEADER_TAG\tHEADER_VALUE", "FORMAT\t2.00", "NUMBER_PASSES\t0001", string.Concat("HEADER_OFFSET\t", headerOffset), string.Concat("DATA_OFFSET\t", dataOffset), string.Concat("END_OFFSET\t", endOffset) }.ToList();
_ = stringBuilder.Append("\"Time\"").Append('\t');
_ = stringBuilder.Append("\"A_LOGISTICS\"").Append('\t');
_ = stringBuilder.Append("\"B_LOGISTICS\"").Append('\t');
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;
}
_ = stringBuilder.Remove(stringBuilder.Length - 1, 1);
lines.Add(stringBuilder.ToString());
for (int i = 0; i < jsonElements.Length; i++)
{
_ = stringBuilder.Clear();
_ = stringBuilder.Append("0.1").Append('\t');
_ = stringBuilder.Append('1').Append('\t');
_ = stringBuilder.Append('2').Append('\t');
foreach (JsonProperty jsonProperty in jsonElements[i].EnumerateObject())
_ = stringBuilder.Append(jsonProperty.Value).Append('\t');
_ = stringBuilder.Remove(stringBuilder.Length - 1, 1);
lines.Add(stringBuilder.ToString());
}
lines.Add(string.Concat("NUM_DATA_ROWS ", jsonElements.Length.ToString().PadLeft(9, '0')));
lines.Add(string.Concat("NUM_DATA_COLUMNS ", (columns + 3).ToString().PadLeft(9, '0')));
lines.Add("DELIMITER ;");
lines.Add(string.Concat("START_TIME_FORMAT ", format));
lines.Add(string.Concat("START_TIME ", logistics.DateTimeFromSequence.ToString(format))); //12/26/2019 15:22:44
lines.Add(string.Concat("LOGISTICS_COLUMN", '\t', "A_LOGISTICS"));
lines.Add(string.Concat("LOGISTICS_COLUMN", '\t', "B_LOGISTICS"));
if (!string.IsNullOrEmpty(logisticsText))
lines.Add(logisticsText);
else
{
lines.Add(string.Concat("LOGISTICS_1", '\t', "A_CHAMBER=;A_INFO=", fileRead.EventName, ";A_INFO2=", fileRead.EquipmentType, ";A_JOBID=", fileRead.CellInstanceName, ";A_MES_ENTITY=", fileRead.MesEntity, ";A_MID=", logistics.MID, ";A_NULL_DATA=", fileRead.NullData, ";A_PPID=NO_PPID;A_PROCESS_JOBID=", logistics.ProcessJobID, ";A_PRODUCT=;A_SEQUENCE=", logistics.Sequence, ";A_WAFER_ID=;"));
lines.Add(string.Concat("LOGISTICS_2", '\t', "B_CHAMBER=;B_INFO=", fileRead.EventName, ";B_INFO2=", fileRead.EquipmentType, ";B_JOBID=", fileRead.CellInstanceName, ";B_MES_ENTITY=", fileRead.MesEntity, ";B_MID=", logistics.MID, ";B_NULL_DATA=", fileRead.NullData, ";B_PPID=NO_PPID;B_PROCESS_JOBID=", logistics.ProcessJobID, ";B_PRODUCT=;B_SEQUENCE=", logistics.Sequence, ";B_WAFER_ID=;"));
lines.Add("END_HEADER");
}
_ = stringBuilder.Clear();
foreach (string line in lines)
_ = stringBuilder.AppendLine(line);
result = stringBuilder.ToString();
result = result.Replace(headerOffset, result.IndexOf("NUM_DATA_ROWS").ToString().PadLeft(9, '0')).
Replace(dataOffset, result.IndexOf('"').ToString().PadLeft(9, '0')).
Replace(endOffset, result.Length.ToString().PadLeft(9, '0'));
}
return result;
Body = body;
Columns = columns;
Footer = footer;
Header = header;
InputPDSF = inputPDSF;
Logistics = logistics;
Sequence = sequence;
}
public static Tuple<string, string[], string[]> GetLogisticsColumnsAndBody(string reportFullPath, string[] lines = null)
{
string segment;
List<string> body = new();
StringBuilder logistics = new();
lines ??= File.ReadAllLines(reportFullPath);
string[] segments;
if (lines.Length < 7)
segments = Array.Empty<string>();
else
segments = lines[6].Trim().Split('\t');
List<string> columns = new();
for (int c = 0; c < segments.Length; c++)
{
segment = segments[c].Substring(1, segments[c].Length - 2);
if (!columns.Contains(segment))
columns.Add(segment);
else
{
for (short i = 1; i < short.MaxValue; i++)
{
segment = string.Concat(segment, "_", i);
if (!columns.Contains(segment))
{
columns.Add(segment);
break;
}
}
}
}
bool lookForLogistics = false;
for (int r = 7; r < lines.Length; r++)
{
if (lines[r].StartsWith("NUM_DATA_ROWS"))
lookForLogistics = true;
if (!lookForLogistics)
{
body.Add(lines[r]);
continue;
}
if (lines[r].StartsWith("LOGISTICS_1"))
{
for (int i = r; i < lines.Length; i++)
{
if (lines[r].StartsWith("END_HEADER"))
break;
_ = logistics.AppendLine(lines[i]);
}
break;
}
}
return new Tuple<string, string[], string[]>(logistics.ToString(), columns.ToArray(), body.ToArray());
}
internal static string EquipmentIntegration(bool addSpaces = true, char separator = ' ') =>
GetString(SearchFor.EquipmentIntegration, addSpaces, separator);
public static JsonElement[] GetArray(Tuple<string, string[], string[]> pdsf, bool lookForNumbers = false)
{
JsonElement[] results;
string logistics = pdsf.Item1;
string[] columns = pdsf.Item2;
string[] bodyLines = pdsf.Item3;
if (bodyLines.Length == 0 || !bodyLines[0].Contains('\t'))
results = JsonSerializer.Deserialize<JsonElement[]>("[]");
else
{
string value;
string[] segments;
List<string> lines = new();
StringBuilder stringBuilder = new();
foreach (string bodyLine in bodyLines)
{
_ = stringBuilder.Clear();
_ = stringBuilder.Append('{');
segments = bodyLine.Trim().Split('\t');
if (!lookForNumbers)
{
for (int c = 1; c < segments.Length; c++)
{
value = segments[c].Replace("\"", "\\\"").Replace("\\", "\\\\");
_ = stringBuilder.Append('"').Append(columns[c]).Append("\":\"").Append(value).Append("\",");
}
}
else
{
for (int c = 1; c < segments.Length; c++)
{
value = segments[c].Replace("\"", "\\\"").Replace("\\", "\\\\");
if (string.IsNullOrEmpty(value))
_ = stringBuilder.Append('"').Append(columns[c]).Append("\":").Append(value).Append("null,");
else if (value.All(char.IsDigit))
_ = stringBuilder.Append('"').Append(columns[c]).Append("\":").Append(value).Append(',');
else
_ = stringBuilder.Append('"').Append(columns[c]).Append("\":\"").Append(value).Append("\",");
}
}
_ = stringBuilder.Remove(stringBuilder.Length - 1, 1);
_ = stringBuilder.AppendLine("}");
lines.Add(stringBuilder.ToString());
}
string json = $"[{string.Join(",", lines)}]";
results = JsonSerializer.Deserialize<JsonElement[]>(json);
}
return results;
}
internal static string BusinessIntegration(bool addSpaces = true, char separator = ' ') =>
GetString(SearchFor.BusinessIntegration, addSpaces, separator);
public static Dictionary<string, List<string>> GetDictionary(Tuple<string, string[], string[]> pdsf)
{
Dictionary<string, List<string>> results = new();
string[] segments;
string[] columns = pdsf.Item2;
string[] bodyLines = pdsf.Item3;
foreach (string column in columns)
results.Add(column, new List<string>());
foreach (string bodyLine in bodyLines)
{
segments = bodyLine.Split('\t');
for (int c = 1; c < segments.Length; c++)
{
if (c >= columns.Length)
continue;
results[columns[c]].Add(segments[c]);
}
}
return results;
}
internal static string SystemExport(bool addSpaces = true, char separator = ' ') =>
GetString(SearchFor.SystemExport, addSpaces, separator);
public static Tuple<string, Dictionary<Test, Dictionary<string, List<string>>>> GetTestDictionary(Tuple<string, string[], string[]> pdsf)
{
Dictionary<Test, Dictionary<string, List<string>>> results = new();
List<string> collection;
string testColumn = nameof(Test);
Dictionary<string, List<string>> keyValuePairs = GetDictionary(pdsf);
if (!keyValuePairs.TryGetValue(testColumn, out collection))
throw new Exception();
int min;
int max;
Test testKey;
List<string> vs;
string columnKey;
Dictionary<Test, List<int>> tests = new();
for (int i = 0; i < collection.Count; i++)
{
if (Enum.TryParse(collection[i], out Test test))
{
if (!results.ContainsKey(test))
{
tests.Add(test, new List<int>());
results.Add(test, new Dictionary<string, List<string>>());
}
tests[test].Add(i);
}
}
foreach (KeyValuePair<Test, List<int>> testKeyValuePair in tests)
{
testKey = testKeyValuePair.Key;
min = testKeyValuePair.Value.Min();
max = testKeyValuePair.Value.Max() + 1;
foreach (KeyValuePair<string, List<string>> keyValuePair in keyValuePairs)
results[testKey].Add(keyValuePair.Key, new List<string>());
foreach (KeyValuePair<string, List<string>> keyValuePair in keyValuePairs)
{
vs = keyValuePair.Value;
columnKey = keyValuePair.Key;
for (int i = min; i < max; i++)
{
if (vs.Count > i)
results[testKey][columnKey].Add(vs[i]);
else
results[testKey][columnKey].Add(string.Empty);
}
}
}
return new Tuple<string, Dictionary<Test, Dictionary<string, List<string>>>>(pdsf.Item1, results);
}
internal static string Archive(bool addSpaces = true, char separator = ' ') =>
GetString(SearchFor.Archive, addSpaces, separator);
private static string GetString(SearchFor searchFor, bool addSpaces, char separator = ' ')
{
if (!addSpaces)
return string.Concat(((int)searchFor).ToString().PadLeft(2, '0'), searchFor);
else
return string.Concat(((int)searchFor).ToString().PadLeft(2, '0'), separator, searchFor.ToString().Replace("In", string.Concat(separator, "In")).Replace("Ex", string.Concat(separator, "Ex")));
}
internal static ProcessDataStandardFormat GetEmpty() =>
new(new(Array.Empty<string>()), new(Array.Empty<string>()), new(Array.Empty<string>()), new(Array.Empty<string>()), null, new(new string[] { "LOGISTICS_1" }), null);
public static string EquipmentIntegration(bool addSpaces = true, char separator = ' ') => GetString(SearchFor.EquipmentIntegration, addSpaces, separator);
public static string BusinessIntegration(bool addSpaces = true, char separator = ' ') => GetString(SearchFor.BusinessIntegration, addSpaces, separator);
public static string SystemExport(bool addSpaces = true, char separator = ' ') => GetString(SearchFor.SystemExport, addSpaces, separator);
public static string Archive(bool addSpaces = true, char separator = ' ') => GetString(SearchFor.Archive, addSpaces, separator);
public static string GetLines(Logistics logistics, Properties.IScopeInfo scopeInfo, List<string> names, Dictionary<string, List<string>> keyValuePairs, string dateFormat, string timeFormat, List<string> pairedParameterNames, bool useDateTimeFromSequence = true, string format = "", List<string> ignoreParameterNames = null)
{
StringBuilder result = new();
ignoreParameterNames ??= new List<string>();
if (useDateTimeFromSequence && !string.IsNullOrEmpty(format))
throw new Exception();
else if (!useDateTimeFromSequence && string.IsNullOrEmpty(format))
throw new Exception();
string nullData;
const string columnDate = "Date";
const string columnTime = "Time";
const string firstDuplicate = "_1";
_ = result.AppendLine(scopeInfo.Header);
StringBuilder line = new();
if (logistics.NullData is null)
nullData = string.Empty;
else
nullData = logistics.NullData.ToString();
int count = (from l in keyValuePairs select l.Value.Count).Min();
for (int r = 0; r < count; r++)
{
_ = line.Clear();
_ = line.Append('!');
foreach (KeyValuePair<string, List<string>> keyValuePair in keyValuePairs)
{
if (!names.Contains(keyValuePair.Key))
continue;
if (ignoreParameterNames.Contains(keyValuePair.Key))
continue;
if (pairedParameterNames.Contains(keyValuePair.Key))
{
if (string.IsNullOrEmpty(keyValuePair.Value[r]) || keyValuePair.Value[r] == nullData)
continue;
else
_ = result.Append(line).Append(keyValuePair.Key).Append(';').AppendLine(keyValuePair.Value[r]);
}
else
{
if (useDateTimeFromSequence && keyValuePair.Key == columnDate)
_ = line.Append(logistics.DateTimeFromSequence.ToString(dateFormat));
else if (useDateTimeFromSequence && keyValuePair.Key == columnTime)
_ = line.Append(logistics.DateTimeFromSequence.ToString(timeFormat));
else if (!useDateTimeFromSequence && keyValuePair.Key == columnDate && keyValuePair.Value[r].Length == format.Length)
_ = line.Append(DateTime.ParseExact(keyValuePair.Value[r], format, CultureInfo.InvariantCulture).ToString(dateFormat));
else if (!useDateTimeFromSequence && keyValuePair.Key == columnTime && keyValuePairs.ContainsKey(string.Concat(keyValuePair.Key, firstDuplicate)) && keyValuePairs[string.Concat(keyValuePair.Key, firstDuplicate)][r].Length == format.Length)
_ = line.Append(DateTime.ParseExact(keyValuePairs[string.Concat(keyValuePair.Key, firstDuplicate)][r], format, CultureInfo.InvariantCulture).ToString(timeFormat));
else if (string.IsNullOrEmpty(keyValuePair.Value[r]) || keyValuePair.Value[r] == nullData)
_ = line.Append(nullData);
else
_ = line.Append(keyValuePair.Value[r]);
_ = line.Append(';');
}
}
if (pairedParameterNames.Count == 0)
{
_ = line.Remove(line.Length - 1, 1);
_ = result.AppendLine(line.ToString());
}
}
return result.ToString();
}
public static List<string> PDSFToFixedWidth(string reportFullPath)
internal static List<string> PDSFToFixedWidth(string reportFullPath)
{
List<string> results = new();
if (!File.Exists(reportFullPath))
@ -407,4 +133,590 @@ public class ProcessDataStandardFormat
return results;
}
internal static ProcessDataStandardFormat GetProcessDataStandardFormat(string reportFullPath, string[]? lines = null, int columnsLine = 6)
{
ProcessDataStandardFormat result;
string segment;
string[] segments;
bool addToFooter = false;
List<string> body = new();
List<string> header = new();
List<string> footer = new();
List<string> columns = new();
ReadOnlyCollection<string> logistics;
lines ??= File.ReadAllLines(reportFullPath);
if (lines.Length < columnsLine + 1)
segments = Array.Empty<string>();
else
{
segments = lines[columnsLine].Trim().Split('\t');
for (int i = 0; i < columnsLine; i++)
header.Add(lines[i]);
}
for (int c = 0; c < segments.Length; c++)
{
segment = segments[c].Substring(1, segments[c].Length - 2);
if (!columns.Contains(segment))
columns.Add(segment);
else
{
for (short i = 1; i < short.MaxValue; i++)
{
segment = string.Concat(segment, "_", i);
if (!columns.Contains(segment))
{
columns.Add(segment);
break;
}
}
}
}
for (int r = columnsLine + 1; r < lines.Length; r++)
{
if (lines[r].StartsWith("NUM_DATA_ROWS"))
addToFooter = true;
if (!addToFooter)
body.Add(lines[r]);
else
{
footer.Add(lines[r]);
if (lines[r].StartsWith("END_HEADER"))
break;
}
}
string? linesOne = lines.Length > 0 && body.Count == 0 && columns.Count == 0 ? lines[1] : null;
logistics = GetLogistics(footer, linesOne: linesOne);
result = new(body: body.AsReadOnly(),
columns: columns.AsReadOnly(),
footer: footer.AsReadOnly(),
header: header.AsReadOnly(),
inputPDSF: null,
logistics: logistics,
sequence: null);
return result;
}
private static ReadOnlyCollection<string> GetLogistics(List<string> footer, string? linesOne)
{
List<string> results = new();
bool foundLogistics1 = false;
foreach (string line in footer)
{
if (line.StartsWith("END_HEADER"))
break;
if (line.StartsWith("LOGISTICS_1"))
foundLogistics1 = true;
if (foundLogistics1 && line.StartsWith("LOGISTICS_"))
results.Add(line);
}
if (!string.IsNullOrEmpty(linesOne) && results.Count == 0)
results.Add(linesOne);
return results.AsReadOnly();
}
internal static ProcessDataStandardFormat? GetProcessDataStandardFormat(string reportFullPath, ProcessDataStandardFormatMapping pdsfMapping)
{
ProcessDataStandardFormat? result;
const int columnsLine = 6;
FileInfo fileInfo = new(reportFullPath);
ProcessDataStandardFormat processDataStandardFormat = GetProcessDataStandardFormat(fileInfo.LastWriteTime, pdsfMapping.NewColumnNames.Count, columnsLine, fileInfo.FullName, lines: null);
JsonElement[]? jsonElements = GetArray(pdsfMapping.NewColumnNames.Count, processDataStandardFormat, lookForNumbers: false);
if (jsonElements is null || jsonElements.Length == 0 || pdsfMapping.OldColumnNames.Count != pdsfMapping.ColumnIndices.Count)
result = null;
else
{
result = GetProcessDataStandardFormat(pdsfMapping, jsonElements, processDataStandardFormat);
if (result.Sequence is null || result.Columns.Count == 0 || result.Body.Count == 0 || result.Logistics.Count == 0)
result = null;
}
return result;
}
private static ProcessDataStandardFormat GetProcessDataStandardFormat(DateTime lastWriteTime, int expectedColumns, int columnsLine, string path, string[]? lines)
{
ProcessDataStandardFormat result;
long sequence;
string[] segments;
bool addToFooter = false;
List<string> body = new();
List<string> header = new();
List<string> footer = new();
ReadOnlyCollection<string> logistics;
lines ??= File.ReadAllLines(path);
if (lines.Length <= columnsLine)
segments = Array.Empty<string>();
else
{
segments = lines[columnsLine].Split('\t');
if (segments.Length != expectedColumns)
segments = Array.Empty<string>();
for (int i = 0; i < columnsLine; i++)
header.Add(lines[i]);
}
string[] columns = segments.Select(l => l.Trim('"')).ToArray();
for (int r = columnsLine + 1; r < lines.Length; r++)
{
if (lines[r].StartsWith("NUM_DATA_ROWS"))
addToFooter = true;
if (!addToFooter)
body.Add(lines[r]);
else
{
footer.Add(lines[r]);
if (lines[r].StartsWith("END_HEADER"))
break;
}
}
logistics = GetLogistics(footer, linesOne: null);
if (logistics.Count == 0)
sequence = lastWriteTime.Ticks;
else
{
segments = logistics[0].Split(new string[] { "SEQUENCE=" }, StringSplitOptions.None);
sequence = segments.Length < 2 || !long.TryParse(segments[1].Split(';')[0], out long s) ? lastWriteTime.Ticks : s;
}
result = new(body: body.AsReadOnly(),
columns: new(columns),
footer: footer.AsReadOnly(),
header: header.AsReadOnly(),
inputPDSF: null,
logistics: logistics,
sequence: sequence);
return result;
}
private static JsonElement[]? GetArray(int expectedColumns, ProcessDataStandardFormat processDataStandardFormat, bool lookForNumbers)
{
JsonElement[]? results;
if (processDataStandardFormat.Body.Count == 0 || !processDataStandardFormat.Body[0].Contains('\t'))
results = JsonSerializer.Deserialize("[]", JsonElementCollectionSourceGenerationContext.Default.JsonElementArray) ?? throw new Exception();
else
{
string value;
string[] segments;
List<string> lines = new();
StringBuilder stringBuilder = new();
foreach (string bodyLine in processDataStandardFormat.Body)
{
_ = stringBuilder.Clear();
_ = stringBuilder.Append('{');
segments = bodyLine.Split('\t');
if (segments.Length != expectedColumns)
continue;
if (!lookForNumbers)
{
for (int c = 0; c < segments.Length; c++)
{
value = segments[c].Replace("\"", "\\\"").Replace("\\", "\\\\");
_ = stringBuilder.Append('"').Append(processDataStandardFormat.Columns[c]).Append("\":\"").Append(value).Append("\",");
}
}
else
{
for (int c = 0; c < segments.Length; c++)
{
value = segments[c].Replace("\"", "\\\"").Replace("\\", "\\\\");
if (string.IsNullOrEmpty(value))
_ = stringBuilder.Append('"').Append(processDataStandardFormat.Columns[c]).Append("\":").Append(value).Append("null,");
else if (value.All(char.IsDigit))
_ = stringBuilder.Append('"').Append(processDataStandardFormat.Columns[c]).Append("\":").Append(value).Append(',');
else
_ = stringBuilder.Append('"').Append(processDataStandardFormat.Columns[c]).Append("\":\"").Append(value).Append("\",");
}
}
_ = stringBuilder.Remove(stringBuilder.Length - 1, 1);
_ = stringBuilder.AppendLine("}");
lines.Add(stringBuilder.ToString());
}
string json = $"[{string.Join(",", lines)}]";
results = JsonSerializer.Deserialize(json, JsonElementCollectionSourceGenerationContext.Default.JsonElementArray);
}
return results;
}
private static ProcessDataStandardFormat GetProcessDataStandardFormat(ProcessDataStandardFormatMapping processDataStandardFormatMapping, JsonElement[] jsonElements, ProcessDataStandardFormat processDataStandardFormat)
{
ProcessDataStandardFormat result;
int column;
string value;
JsonProperty jsonProperty;
List<string> values = new();
List<string> results = new();
JsonProperty[] jsonProperties;
List<string> unknownColumns = new();
for (int i = 0; i < jsonElements.Length; i++)
{
values.Clear();
if (jsonElements[i].ValueKind != JsonValueKind.Object)
{
unknownColumns.Add(string.Empty);
break;
}
jsonProperties = jsonElements[i].EnumerateObject().ToArray();
if (jsonProperties.Length != processDataStandardFormatMapping.NewColumnNames.Count)
continue;
for (int c = 0; c < processDataStandardFormatMapping.ColumnIndices.Count; c++)
{
column = processDataStandardFormatMapping.ColumnIndices[c];
if (column == -1)
value = processDataStandardFormatMapping.OldColumnNames[c];
else
{
jsonProperty = jsonProperties[column];
value = jsonProperty.Value.ToString();
}
values.Add(value);
}
results.Add(string.Join("\t", values));
}
result = new(body: new(results),
columns: processDataStandardFormatMapping.OldColumnNames,
footer: processDataStandardFormat.Footer,
header: processDataStandardFormat.Header,
inputPDSF: processDataStandardFormat,
logistics: processDataStandardFormat.Logistics,
sequence: processDataStandardFormat.Sequence);
return result;
}
internal static void Write(string path, ProcessDataStandardFormat processDataStandardFormat, List<Metrology.WS.Results>? wsResults)
{
List<string> results = new();
if (processDataStandardFormat.Sequence is null)
throw new NullReferenceException(nameof(processDataStandardFormat.Sequence));
string endOffset = "E#######T";
string dataOffset = "D#######T";
string headerOffset = "H#######T";
string format = "MM/dd/yyyy HH:mm:ss";
string startTime = new DateTime(processDataStandardFormat.Sequence.Value).ToString(format);
results.Add("HEADER_TAG\tHEADER_VALUE");
results.Add("FORMAT\t2.00");
results.Add("NUMBER_PASSES\t0001");
results.Add($"HEADER_OFFSET\t{headerOffset}");
results.Add($"DATA_OFFSET\t{dataOffset}");
results.Add($"END_OFFSET\t{endOffset}");
results.Add($"\"{string.Join("\"\t\"", processDataStandardFormat.Columns)}\"");
results.AddRange(processDataStandardFormat.Body);
results.Add($"NUM_DATA_ROWS\t{processDataStandardFormat.Body.Count.ToString().PadLeft(9, '0')}");
results.Add($"NUM_DATA_COLUMNS\t{processDataStandardFormat.Columns.Count.ToString().PadLeft(9, '0')}");
results.Add("DELIMITER\t;");
results.Add($"START_TIME_FORMAT\t{format}");
results.Add($"START_TIME\t{startTime}");
results.Add("LOGISTICS_COLUMN\tA_LOGISTICS");
results.Add("LOGISTICS_COLUMN\tB_LOGISTICS");
if (wsResults is null || wsResults.Count != 1)
results.AddRange(processDataStandardFormat.Logistics);
else
{
string[] segments;
foreach (string logistics in processDataStandardFormat.Logistics)
{
segments = logistics.Split(new string[] { "\t" }, StringSplitOptions.None);
if (segments.Length != 2 || string.IsNullOrEmpty(segments[1]))
results.Add(logistics);
else
results.Add($"{segments[0]}\t{segments[1][0]}_HeaderId={wsResults[0].HeaderId};{segments[1][0]}_SubgroupId={wsResults[0].SubgroupId};{segments[1]}");
}
}
results.Add("EOF");
if (processDataStandardFormat.InputPDSF is not null)
{
List<char> hyphens = new();
results.AddRange(processDataStandardFormat.InputPDSF.Header.Select(l => l.Replace('\t', '|')));
results.Add(string.Empty);
results.Add($"|{string.Join("|", processDataStandardFormat.InputPDSF.Columns)}|");
for (int i = 0; i < processDataStandardFormat.InputPDSF.Columns.Count; i++)
hyphens.Add('-');
results.Add($"|{string.Join("|", hyphens)}|");
results.AddRange(processDataStandardFormat.InputPDSF.Body.Select(l => l.Replace('\t', '|')));
results.Add(string.Empty);
results.AddRange(processDataStandardFormat.InputPDSF.Footer.Select(l => l.Replace('\t', '|')));
}
File.WriteAllText(path, string.Join(Environment.NewLine, results));
}
internal static Dictionary<string, List<string>> GetDictionary(ProcessDataStandardFormat processDataStandardFormat)
{
Dictionary<string, List<string>> results = new();
string[] segments;
foreach (string column in processDataStandardFormat.Columns)
results.Add(column, new List<string>());
foreach (string bodyLine in processDataStandardFormat.Body)
{
segments = bodyLine.Split('\t');
for (int c = 1; c < segments.Length; c++)
{
if (c >= processDataStandardFormat.Columns.Count)
continue;
results[processDataStandardFormat.Columns[c]].Add(segments[c]);
}
}
return results;
}
internal static JsonElement[] GetArray(ProcessDataStandardFormat processDataStandardFormat, bool lookForNumbers = false)
{
JsonElement[] results;
if (processDataStandardFormat.Body.Count == 0 || !processDataStandardFormat.Body[0].Contains('\t'))
results = JsonSerializer.Deserialize("[]", JsonElementCollectionSourceGenerationContext.Default.JsonElementArray) ?? throw new Exception();
else
{
string value;
string[] segments;
List<string> lines = new();
StringBuilder stringBuilder = new();
foreach (string bodyLine in processDataStandardFormat.Body)
{
_ = stringBuilder.Clear();
_ = stringBuilder.Append('{');
segments = bodyLine.Trim().Split('\t');
if (!lookForNumbers)
{
for (int c = 1; c < segments.Length; c++)
{
value = segments[c].Replace("\"", "\\\"").Replace("\\", "\\\\");
_ = stringBuilder.Append('"').Append(processDataStandardFormat.Columns[c]).Append("\":\"").Append(value).Append("\",");
}
}
else
{
for (int c = 1; c < segments.Length; c++)
{
value = segments[c].Replace("\"", "\\\"").Replace("\\", "\\\\");
if (string.IsNullOrEmpty(value))
_ = stringBuilder.Append('"').Append(processDataStandardFormat.Columns[c]).Append("\":").Append(value).Append("null,");
else if (value.All(char.IsDigit))
_ = stringBuilder.Append('"').Append(processDataStandardFormat.Columns[c]).Append("\":").Append(value).Append(',');
else
_ = stringBuilder.Append('"').Append(processDataStandardFormat.Columns[c]).Append("\":\"").Append(value).Append("\",");
}
}
_ = stringBuilder.Remove(stringBuilder.Length - 1, 1);
_ = stringBuilder.AppendLine("}");
lines.Add(stringBuilder.ToString());
}
string json = $"[{string.Join(",", lines)}]";
results = JsonSerializer.Deserialize<JsonElement[]>(json) ?? throw new Exception();
}
return results;
}
internal static string GetPDSFText(IFileRead fileRead, Logistics logistics, JsonElement[] jsonElements, string logisticsText)
{
string result;
if (jsonElements.Length == 0)
result = string.Empty;
else
{
int columns = 0;
List<string> lines;
string endOffset = "E#######T";
string dataOffset = "D#######T";
string headerOffset = "H#######T";
string format = "MM/dd/yyyy HH:mm:ss";
StringBuilder stringBuilder = new();
lines = new string[] { "HEADER_TAG\tHEADER_VALUE", "FORMAT\t2.00", "NUMBER_PASSES\t0001", string.Concat("HEADER_OFFSET\t", headerOffset), string.Concat("DATA_OFFSET\t", dataOffset), string.Concat("END_OFFSET\t", endOffset) }.ToList();
_ = stringBuilder.Append("\"Time\"").Append('\t');
_ = stringBuilder.Append("\"A_LOGISTICS\"").Append('\t');
_ = stringBuilder.Append("\"B_LOGISTICS\"").Append('\t');
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;
}
_ = stringBuilder.Remove(stringBuilder.Length - 1, 1);
lines.Add(stringBuilder.ToString());
for (int i = 0; i < jsonElements.Length; i++)
{
_ = stringBuilder.Clear();
_ = stringBuilder.Append("0.1").Append('\t');
_ = stringBuilder.Append('1').Append('\t');
_ = stringBuilder.Append('2').Append('\t');
foreach (JsonProperty jsonProperty in jsonElements[i].EnumerateObject())
_ = stringBuilder.Append(jsonProperty.Value).Append('\t');
_ = stringBuilder.Remove(stringBuilder.Length - 1, 1);
lines.Add(stringBuilder.ToString());
}
lines.Add(string.Concat("NUM_DATA_ROWS ", jsonElements.Length.ToString().PadLeft(9, '0')));
lines.Add(string.Concat("NUM_DATA_COLUMNS ", (columns + 3).ToString().PadLeft(9, '0')));
lines.Add("DELIMITER ;");
lines.Add(string.Concat("START_TIME_FORMAT ", format));
lines.Add(string.Concat("START_TIME ", logistics.DateTimeFromSequence.ToString(format))); //12/26/2019 15:22:44
lines.Add(string.Concat("LOGISTICS_COLUMN", '\t', "A_LOGISTICS"));
lines.Add(string.Concat("LOGISTICS_COLUMN", '\t', "B_LOGISTICS"));
if (!string.IsNullOrEmpty(logisticsText))
lines.Add(logisticsText);
else
{
lines.Add(string.Concat("LOGISTICS_1", '\t', "A_CHAMBER=;A_INFO=", fileRead.EventName, ";A_INFO2=", fileRead.EquipmentType, ";A_JOBID=", fileRead.CellInstanceName, ";A_MES_ENTITY=", fileRead.MesEntity, ";A_MID=", logistics.MID, ";A_NULL_DATA=", fileRead.NullData, ";A_PPID=NO_PPID;A_PROCESS_JOBID=", logistics.ProcessJobID, ";A_PRODUCT=;A_SEQUENCE=", logistics.Sequence, ";A_WAFER_ID=;"));
lines.Add(string.Concat("LOGISTICS_2", '\t', "B_CHAMBER=;B_INFO=", fileRead.EventName, ";B_INFO2=", fileRead.EquipmentType, ";B_JOBID=", fileRead.CellInstanceName, ";B_MES_ENTITY=", fileRead.MesEntity, ";B_MID=", logistics.MID, ";B_NULL_DATA=", fileRead.NullData, ";B_PPID=NO_PPID;B_PROCESS_JOBID=", logistics.ProcessJobID, ";B_PRODUCT=;B_SEQUENCE=", logistics.Sequence, ";B_WAFER_ID=;"));
lines.Add("END_HEADER");
}
_ = stringBuilder.Clear();
foreach (string line in lines)
_ = stringBuilder.AppendLine(line);
result = stringBuilder.ToString();
result = result.Replace(headerOffset, result.IndexOf("NUM_DATA_ROWS").ToString().PadLeft(9, '0')).
Replace(dataOffset, result.IndexOf('"').ToString().PadLeft(9, '0')).
Replace(endOffset, result.Length.ToString().PadLeft(9, '0'));
}
return result;
}
internal static Tuple<string, Dictionary<Test, Dictionary<string, List<string>>>> GetTestDictionary(ProcessDataStandardFormat processDataStandardFormat)
{
Dictionary<Test, Dictionary<string, List<string>>> results = new();
List<string>? collection;
string testColumn = nameof(Test);
Dictionary<string, List<string>> keyValuePairs = GetDictionary(processDataStandardFormat);
if (!keyValuePairs.TryGetValue(testColumn, out collection))
throw new Exception();
int min;
int max;
Test testKey;
List<string> vs;
string columnKey;
Dictionary<Test, List<int>> tests = new();
for (int i = 0; i < collection.Count; i++)
{
if (Enum.TryParse(collection[i], out Test test))
{
if (!results.ContainsKey(test))
{
tests.Add(test, new List<int>());
results.Add(test, new Dictionary<string, List<string>>());
}
tests[test].Add(i);
}
}
foreach (KeyValuePair<Test, List<int>> testKeyValuePair in tests)
{
testKey = testKeyValuePair.Key;
min = testKeyValuePair.Value.Min();
max = testKeyValuePair.Value.Max() + 1;
foreach (KeyValuePair<string, List<string>> keyValuePair in keyValuePairs)
results[testKey].Add(keyValuePair.Key, new List<string>());
foreach (KeyValuePair<string, List<string>> keyValuePair in keyValuePairs)
{
vs = keyValuePair.Value;
columnKey = keyValuePair.Key;
for (int i = min; i < max; i++)
{
if (vs.Count > i)
results[testKey][columnKey].Add(vs[i]);
else
results[testKey][columnKey].Add(string.Empty);
}
}
}
return new Tuple<string, Dictionary<Test, Dictionary<string, List<string>>>>(processDataStandardFormat.Logistics[0], results);
}
internal static string GetLines(Logistics logistics, Properties.IScopeInfo scopeInfo, List<string> names, Dictionary<string, List<string>> keyValuePairs, string dateFormat, string timeFormat, List<string> pairedParameterNames, bool useDateTimeFromSequence = true, string format = "", List<string>? ignoreParameterNames = null)
{
StringBuilder result = new();
ignoreParameterNames ??= new List<string>();
if (useDateTimeFromSequence && !string.IsNullOrEmpty(format))
throw new Exception();
else if (!useDateTimeFromSequence && string.IsNullOrEmpty(format))
throw new Exception();
string? nullData;
const string columnDate = "Date";
const string columnTime = "Time";
const string firstDuplicate = "_1";
_ = result.AppendLine(scopeInfo.Header);
StringBuilder line = new();
if (logistics.NullData is null)
nullData = string.Empty;
else
nullData = logistics.NullData.ToString();
int count = (from l in keyValuePairs select l.Value.Count).Min();
for (int r = 0; r < count; r++)
{
_ = line.Clear();
_ = line.Append('!');
foreach (KeyValuePair<string, List<string>> keyValuePair in keyValuePairs)
{
if (!names.Contains(keyValuePair.Key))
continue;
if (ignoreParameterNames.Contains(keyValuePair.Key))
continue;
if (pairedParameterNames.Contains(keyValuePair.Key))
{
if (string.IsNullOrEmpty(keyValuePair.Value[r]) || keyValuePair.Value[r] == nullData)
continue;
else
_ = result.Append(line).Append(keyValuePair.Key).Append(';').AppendLine(keyValuePair.Value[r]);
}
else
{
if (useDateTimeFromSequence && keyValuePair.Key == columnDate)
_ = line.Append(logistics.DateTimeFromSequence.ToString(dateFormat));
else if (useDateTimeFromSequence && keyValuePair.Key == columnTime)
_ = line.Append(logistics.DateTimeFromSequence.ToString(timeFormat));
else if (!useDateTimeFromSequence && keyValuePair.Key == columnDate && keyValuePair.Value[r].Length == format.Length)
_ = line.Append(DateTime.ParseExact(keyValuePair.Value[r], format, CultureInfo.InvariantCulture).ToString(dateFormat));
else if (!useDateTimeFromSequence && keyValuePair.Key == columnTime && keyValuePairs.ContainsKey(string.Concat(keyValuePair.Key, firstDuplicate)) && keyValuePairs[string.Concat(keyValuePair.Key, firstDuplicate)][r].Length == format.Length)
_ = line.Append(DateTime.ParseExact(keyValuePairs[string.Concat(keyValuePair.Key, firstDuplicate)][r], format, CultureInfo.InvariantCulture).ToString(timeFormat));
else if (string.IsNullOrEmpty(keyValuePair.Value[r]) || keyValuePair.Value[r] == nullData)
_ = line.Append(nullData);
else
_ = line.Append(keyValuePair.Value[r]);
_ = line.Append(';');
}
}
if (pairedParameterNames.Count == 0)
{
_ = line.Remove(line.Length - 1, 1);
_ = result.AppendLine(line.ToString());
}
}
return result.ToString();
}
private static string GetString(SearchFor searchFor, bool addSpaces, char separator = ' ')
{
if (!addSpaces)
return string.Concat(((int)searchFor).ToString().PadLeft(2, '0'), searchFor);
else
return string.Concat(((int)searchFor).ToString().PadLeft(2, '0'), separator, searchFor.ToString().Replace("In", string.Concat(separator, "In")).Replace("Ex", string.Concat(separator, "Ex")));
}
private static int? TryGetPropertyIndex(JsonProperty[] jsonProperties, string propertyName)
{
int? result = null;
for (int i = 0; i < jsonProperties.Length; i++)
{
if (jsonProperties[i].Name != propertyName)
continue;
result = i;
break;
}
if (result is null)
{
for (int i = 0; i < jsonProperties.Length; i++)
{
if (jsonProperties[i].Name[0] != propertyName[0])
continue;
if (jsonProperties[i].Name.Length != propertyName.Length)
continue;
if (jsonProperties[i].Name != propertyName)
continue;
result = i;
break;
}
}
return result;
}
}
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(JsonElement[]))]
internal partial class JsonElementCollectionSourceGenerationContext : JsonSerializerContext
{
}

View File

@ -0,0 +1,33 @@
using System.Collections.ObjectModel;
namespace Adaptation.Shared;
public class ProcessDataStandardFormatMapping
{
public ReadOnlyCollection<string> BackfillColumns { get; private set; }
public ReadOnlyCollection<int> ColumnIndices { get; private set; }
public ReadOnlyCollection<string> IgnoreColumns { get; private set; }
public ReadOnlyCollection<string> IndexOnlyColumns { get; private set; }
public ReadOnlyDictionary<string, string> KeyValuePairs { get; private set; }
public ReadOnlyCollection<string> NewColumnNames { get; private set; }
public ReadOnlyCollection<string> OldColumnNames { get; private set; }
public ProcessDataStandardFormatMapping(ReadOnlyCollection<string> backfillColumns,
ReadOnlyCollection<int> columnIndices,
ReadOnlyCollection<string> ignoreColumns,
ReadOnlyCollection<string> indexOnlyColumns,
ReadOnlyDictionary<string, string> keyValuePairs,
ReadOnlyCollection<string> newColumnNames,
ReadOnlyCollection<string> oldColumnNames)
{
BackfillColumns = backfillColumns;
ColumnIndices = columnIndices;
IgnoreColumns = ignoreColumns;
IndexOnlyColumns = indexOnlyColumns;
KeyValuePairs = keyValuePairs;
NewColumnNames = newColumnNames;
OldColumnNames = oldColumnNames;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -259,4 +259,29 @@ public class Job : LoggingUnitTesting, IDisposable
NonThrowTryCatch();
}
#if !Always
[Ignore]
#endif
[TestMethod]
public void TestJobH()
{
FileHandlers.TIBCO.Transport.Job job;
MethodBase methodBase = new StackFrame().GetMethod();
string metrologyFileShare = FileHandlers.TIBCO.FileRead.MetrologyFileShare;
string barcodeHostFileShare = FileHandlers.TIBCO.FileRead.BarcodeHostFileShare;
string lsl2SQLConnectionString = FileHandlers.TIBCO.FileRead.LSL2SQLConnectionString;
LoggingUnitTesting.Logger.LogInformation(string.Concat(methodBase.Name, " - Getting configuration"));
HttpClient httpClient = new() { BaseAddress = new(FileHandlers.TIBCO.FileRead.OpenInsightApplicationProgrammingInterface) };
string mid = """
{"Area": "Si", "EquipmentType": "MET08DDUPSFS6420", "MesEntity": "TENCOR1", "Sequence": "638765945581765554", "MID": "AK1PL2", "Recipe": "8INCLEAN"}
""";
job = new(lsl2SQLConnectionString, metrologyFileShare, barcodeHostFileShare, httpClient, mid);
Assert.IsFalse(string.IsNullOrEmpty(job.ProcessType));
Assert.IsFalse(string.IsNullOrEmpty(job.LotName));
Assert.IsFalse(string.IsNullOrEmpty(job.ProductName));
Assert.IsFalse(string.IsNullOrEmpty(job.Equipment));
LoggingUnitTesting.Logger.LogInformation(string.Concat(methodBase.Name, " - Exit"));
NonThrowTryCatch();
}
}

View File

@ -37,7 +37,7 @@ public partial class FileRead : FileReaderHandler, ISMTP
private FilePathGenerator _FilePathGeneratorForTarget;
private readonly List<EquipmentParameter> _EquipmentParameters;
private static readonly Dictionary<string, List<long>> _DummyRuns;
private static readonly Dictionary<long, List<string>> _StaticRuns;
private static readonly Dictionary<long, List<Adaptation.Shared.Metrology.WS.Results>> _StaticRuns;
static FileRead()
{

View File

@ -177,6 +177,7 @@
<Compile Include="Adaptation\Shared\Metrology\WS.Results.cs" />
<Compile Include="Adaptation\Shared\ParameterType.cs" />
<Compile Include="Adaptation\Shared\ProcessDataStandardFormat.cs" />
<Compile Include="Adaptation\Shared\ProcessDataStandardFormatMapping.cs" />
<Compile Include="Adaptation\Shared\Properties\IDescription.cs" />
<Compile Include="Adaptation\Shared\Properties\IFileRead.cs" />
<Compile Include="Adaptation\Shared\Properties\ILogistics.cs" />